diff --git a/baselibs.conf b/baselibs.conf deleted file mode 100644 index 99bee94..0000000 --- a/baselibs.conf +++ /dev/null @@ -1,11 +0,0 @@ -gdb - +/usr/bin/gdb -> /usr/bin/gdb - # kill package for i586 32bit - targetarch x86_64 block! - prereq -glibc-x86 -gdbserver - +/usr/bin/gdbserver -> /usr/bin/gdbserver - provides "gdb-:/usr/bin/gdbserver" - # kill package for i586 32bit - targetarch x86_64 block! - prereq -glibc-x86 diff --git a/cell-combined.diff b/cell-combined.diff deleted file mode 100644 index 1db94c7..0000000 --- a/cell-combined.diff +++ /dev/null @@ -1,5626 +0,0 @@ ---- gdb/Makefile.in -+++ gdb/Makefile.in -@@ -502,7 +502,7 @@ ALL_TARGET_OBS = \ - sh64-tdep.o sh-linux-tdep.o shnbsd-tdep.o sh-tdep.o \ - sparc-linux-tdep.o sparcnbsd-tdep.o sparcobsd-tdep.o \ - sparc-sol2-tdep.o sparc-tdep.o \ -- spu-tdep.o \ -+ spu-tdep.o spu-multiarch.o solib-spu.o \ - v850-tdep.o \ - vaxnbsd-tdep.o vaxobsd-tdep.o vax-tdep.o \ - xstormy16-tdep.o \ -@@ -1342,7 +1342,7 @@ ALLDEPFILES = \ - sparc64-tdep.c sparc64fbsd-nat.c sparc64fbsd-tdep.c \ - sparc64nbsd-nat.c sparc64nbsd-tdep.c sparc64obsd-tdep.c \ - sparcnbsd-nat.c sparcnbsd-tdep.c sparcobsd-tdep.c \ -- spu-linux-nat.c spu-tdep.c \ -+ spu-linux-nat.c spu-tdep.c spu-multiarch.c solib-spu.c \ - v850-tdep.c \ - vax-nat.c vax-tdep.c vaxbsd-nat.c vaxnbsd-tdep.c \ - windows-nat.c windows-tdep.c \ ---- gdb/arch-utils.c -+++ gdb/arch-utils.c -@@ -326,15 +326,24 @@ set_endian (char *ignore_args, int from_ - } - - /* Given SELECTED, a currently selected BFD architecture, and -- FROM_TARGET, a BFD architecture reported by the target description, -- return what architecture to use. Either may be NULL; if both are -- specified, we use the more specific. If the two are obviously -- incompatible, warn the user. */ -+ TARGET_DESC, the current target description, return what -+ architecture to use. -+ -+ SELECTED may be NULL, in which case we return the architecture -+ associated with TARGET_DESC. If SELECTED specifies a variant -+ of the architecture associtated with TARGET_DESC, return the -+ more specific of the two. -+ -+ If SELECTED is a different architecture, but it is accepted as -+ compatible by the target, we can use the target architecture. -+ -+ If SELECTED is obviously incompatible, warn the user. */ - - static const struct bfd_arch_info * --choose_architecture_for_target (const struct bfd_arch_info *selected, -- const struct bfd_arch_info *from_target) -+choose_architecture_for_target (const struct target_desc *target_desc, -+ const struct bfd_arch_info *selected) - { -+ const struct bfd_arch_info *from_target = tdesc_architecture (target_desc); - const struct bfd_arch_info *compat1, *compat2; - - if (selected == NULL) -@@ -364,6 +373,11 @@ choose_architecture_for_target (const st - - if (compat1 == NULL && compat2 == NULL) - { -+ /* BFD considers the architectures incompatible. Check our target -+ description whether it accepts SELECTED as compatible anyway. */ -+ if (tdesc_compatible_p (target_desc, selected)) -+ return from_target; -+ - warning (_("Selected architecture %s is not compatible " - "with reported target architecture %s"), - selected->printable_name, from_target->printable_name); -@@ -692,7 +706,7 @@ gdbarch_info_fill (struct gdbarch_info * - /* From the target. */ - if (info->target_desc != NULL) - info->bfd_arch_info = choose_architecture_for_target -- (info->bfd_arch_info, tdesc_architecture (info->target_desc)); -+ (info->target_desc, info->bfd_arch_info); - /* From the default. */ - if (info->bfd_arch_info == NULL) - info->bfd_arch_info = default_bfd_arch; -@@ -720,6 +734,27 @@ gdbarch_info_fill (struct gdbarch_info * - gdb_assert (info->bfd_arch_info != NULL); - } - -+ -+/* restore_current_gdbarch() will be used by the cleanup machinery -+ to restore the current_gdbarch value saved in a call to -+ save_current_gdbarch(). */ -+ -+static void -+restore_current_gdbarch (void *arg) -+{ -+ current_gdbarch = arg; -+} -+ -+/* Save the value of current so that it may be restored by a -+ later call to do_cleanups(). Returns the struct cleanup pointer -+ needed for later doing the cleanup. */ -+ -+struct cleanup * -+save_current_gdbarch (void) -+{ -+ return make_cleanup (restore_current_gdbarch, current_gdbarch); -+} -+ - /* */ - - extern initialize_file_ftype _initialize_gdbarch_utils; /* -Wmissing-prototypes */ ---- gdb/arch-utils.h -+++ gdb/arch-utils.h -@@ -139,4 +139,9 @@ extern void gdbarch_info_fill (struct gd - - extern struct gdbarch *gdbarch_from_bfd (bfd *abfd); - -+/* Save value of current_gdbarch so that it may be restored by -+ a later call to do_cleanups(). Returns the struct cleanup -+ pointer needed for later doing the cleanup. */ -+struct cleanup *save_current_gdbarch (void); -+ - #endif ---- gdb/avr-tdep.c -+++ gdb/avr-tdep.c -@@ -278,7 +278,8 @@ avr_convert_saddr_to_raw (CORE_ADDR x) - /* Convert from address to pointer and vice-versa. */ - - static void --avr_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr) -+avr_address_to_pointer (struct gdbarch *gdbarch, -+ struct type *type, gdb_byte *buf, CORE_ADDR addr) - { - /* Is it a code address? */ - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC -@@ -296,7 +297,8 @@ avr_address_to_pointer (struct type *typ - } - - static CORE_ADDR --avr_pointer_to_address (struct type *type, const gdb_byte *buf) -+avr_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, const gdb_byte *buf) - { - CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type)); - ---- gdb/breakpoint.c -+++ gdb/breakpoint.c -@@ -1134,7 +1134,7 @@ Note: automatically using hardware break - bpt->overlay_target_info = bpt->target_info; - bpt->overlay_target_info.placed_address = addr; - val = target_insert_breakpoint (&bpt->overlay_target_info); -- if (val != 0) -+ if (val > 0) - fprintf_unfiltered (tmp_error_stream, - "Overlay breakpoint %d failed: in ROM?", - bpt->owner->number); -@@ -1157,6 +1157,14 @@ Note: automatically using hardware break - } - } - -+ if (val < 0) -+ { -+ /* The target could not insert the breakpoint right away due -+ to a temporary issue. No error, but do not mark the bp -+ as 'inserted'. */ -+ return 0; -+ } -+ - if (val) - { - /* Can't set the breakpoint. */ -@@ -1626,6 +1634,14 @@ remove_breakpoint (struct bp_location *b - } - } - -+ if (val < 0) -+ { -+ /* The target could not remove the breakpoint right away due -+ to a temporary issue. No error, but keep the bp marked -+ as 'inserted'. */ -+ return 0; -+ } -+ - /* In some cases, we might not be able to remove a breakpoint - in a shared library that has already been removed, but we - have not yet processed the shlib unload event. */ -@@ -7553,6 +7569,37 @@ breakpoint_re_set (void) - - create_overlay_event_breakpoint ("_ovly_debug_event"); - } -+ -+/* Update breakpoint location list after an object file was relocated. */ -+void -+breakpoint_relocate (struct objfile *objfile, struct section_offsets *delta) -+{ -+ struct bp_location *b; -+ struct obj_section *s; -+ -+ /* Update the breakpoint addresses so that breakpoint_re_set has a chance -+ to identify the previous locations (to carry over enabled state). */ -+ ALL_BP_LOCATIONS (b) -+ { -+ if (b->inserted || b->loc_type == bp_loc_other) -+ continue; -+ -+ ALL_OBJFILE_OSECTIONS (objfile, s) -+ { -+ CORE_ADDR offset = ANOFFSET (delta, s->the_bfd_section->index); -+ -+ if (b->address >= obj_section_addr (s) - offset -+ && b->address < obj_section_endaddr (s) - offset) -+ { -+ b->address += offset; -+ break; -+ } -+ } -+ } -+ -+ /* Now reset all breakpoints. */ -+ breakpoint_re_set (); -+} - - /* Reset the thread number of this breakpoint: - ---- gdb/breakpoint.h -+++ gdb/breakpoint.h -@@ -670,6 +670,8 @@ extern int breakpoint_thread_match (CORE - - extern void until_break_command (char *, int, int); - -+extern void breakpoint_relocate (struct objfile *, struct section_offsets *); -+ - extern void breakpoint_re_set (void); - - extern void breakpoint_re_set_thread (struct breakpoint *); ---- gdb/cli/cli-dump.c -+++ gdb/cli/cli-dump.c -@@ -428,7 +428,7 @@ add_dump_command (char *name, void (*fun - - /* Opaque data for restore_section_callback. */ - struct callback_data { -- long load_offset; -+ CORE_ADDR load_offset; - CORE_ADDR load_start; - CORE_ADDR load_end; - }; -@@ -533,8 +533,8 @@ restore_binary_file (char *filename, str - printf_filtered - ("Restoring binary file %s into memory (0x%lx to 0x%lx)\n", - filename, -- (unsigned long) data->load_start + data->load_offset, -- (unsigned long) data->load_start + data->load_offset + len); -+ (unsigned long) (data->load_start + data->load_offset), -+ (unsigned long) (data->load_start + data->load_offset + len)); - - /* Now set the file pos to the requested load start pos. */ - if (fseek (file, data->load_start, SEEK_SET) != 0) -@@ -584,7 +584,7 @@ restore_command (char *args, int from_tt - /* Parse offset (optional). */ - if (args != NULL && *args != '\0') - data.load_offset = -- parse_and_eval_long (scan_expression_with_cleanup (&args, NULL)); -+ parse_and_eval_address (scan_expression_with_cleanup (&args, NULL)); - if (args != NULL && *args != '\0') - { - /* Parse start address (optional). */ ---- gdb/configure.tgt -+++ gdb/configure.tgt -@@ -354,7 +354,8 @@ powerpc-*-aix* | rs6000-*-*) - powerpc-*-linux* | powerpc64-*-linux*) - # Target: PowerPC running Linux - gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \ -- solib.o solib-svr4.o corelow.o symfile-mem.o" -+ solib.o solib-svr4.o solib-spu.o spu-multiarch.o \ -+ corelow.o symfile-mem.o" - gdb_sim=../sim/ppc/libsim.a - build_gdbserver=yes - ;; ---- gdb/corelow.c -+++ gdb/corelow.c -@@ -560,6 +560,33 @@ core_files_info (struct target_ops *t) - print_section_info (t, core_bfd); - } - -+struct spuid_list -+{ -+ gdb_byte *buf; -+ ULONGEST offset; -+ LONGEST len; -+ ULONGEST pos; -+ ULONGEST written; -+}; -+ -+static void -+add_to_spuid_list (bfd *abfd, asection *asect, void *list_p) -+{ -+ struct spuid_list *list = list_p; -+ int fd, pos = 0; -+ -+ sscanf (bfd_section_name (abfd, asect), "SPU/%d/regs%n", &fd, &pos); -+ if (pos == 0) -+ return; -+ -+ if (list->pos >= list->offset && list->pos + 4 <= list->offset + list->len) -+ { -+ store_unsigned_integer (list->buf + list->pos - list->offset, 4, fd); -+ list->written += 4; -+ } -+ list->pos += 4; -+} -+ - static LONGEST - core_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, -@@ -652,6 +679,53 @@ core_xfer_partial (struct target_ops *op - } - /* FALL THROUGH */ - -+ case TARGET_OBJECT_SPU: -+ if (readbuf && annex) -+ { -+ /* When the SPU contexts are stored in core file, BFD -+ represents this with a fake section called "SPU/". */ -+ -+ struct bfd_section *section; -+ bfd_size_type size; -+ char *contents; -+ -+ char sectionstr[100]; -+ xsnprintf (sectionstr, sizeof sectionstr, "SPU/%s", annex); -+ -+ section = bfd_get_section_by_name (core_bfd, sectionstr); -+ if (section == NULL) -+ return -1; -+ -+ size = bfd_section_size (core_bfd, section); -+ if (offset >= size) -+ return 0; -+ size -= offset; -+ if (size > len) -+ size = len; -+ if (size > 0 -+ && !bfd_get_section_contents (core_bfd, section, readbuf, -+ (file_ptr) offset, size)) -+ { -+ warning (_("Couldn't read SPU section in core file.")); -+ return -1; -+ } -+ -+ return size; -+ } -+ else if (readbuf) -+ { -+ /* NULL annex requests list of all present spuids. */ -+ struct spuid_list list; -+ list.buf = readbuf; -+ list.offset = offset; -+ list.len = len; -+ list.pos = 0; -+ list.written = 0; -+ bfd_map_over_sections (core_bfd, add_to_spuid_list, &list); -+ return list.written; -+ } -+ return -1; -+ - default: - if (ops->beneath != NULL) - return ops->beneath->to_xfer_partial (ops->beneath, object, annex, -@@ -691,8 +765,8 @@ core_file_thread_alive (ptid_t tid) - static const struct target_desc * - core_read_description (struct target_ops *target) - { -- if (gdbarch_core_read_description_p (current_gdbarch)) -- return gdbarch_core_read_description (current_gdbarch, target, core_bfd); -+ if (core_gdbarch && gdbarch_core_read_description_p (core_gdbarch)) -+ return gdbarch_core_read_description (core_gdbarch, target, core_bfd); - - return NULL; - } ---- gdb/doc/gdb.texinfo -+++ gdb/doc/gdb.texinfo -@@ -16910,6 +16910,33 @@ and local store addresses and transfer s - - @end table - -+When @value{GDBN} is debugging a combined PowerPC/SPU application -+on the Cell Broadband Engine, it provides in addition the following -+special commands: -+ -+@table @code -+@item set spu stop-on-load @var{arg} -+@kindex set spu -+Set whether to stop for new SPE threads. When set to @code{on}, @value{GDBN} -+will give control to the user when a new SPE thread enters its @code{main} -+function. The default is @code{off}. -+ -+@item show spu stop-on-load -+@kindex show spu -+Show whether to stop for new SPE threads. -+ -+@item set spu auto-flush-cache @var{arg} -+Set whether to automatically flush the software-managed cache. When set to -+@code{on}, @value{GDBN} will automatically cause the SPE software-managed -+cache to be flushed whenever SPE execution stops. This provides a consistent -+view of PowerPC memory that is accessed via the cache. If an application -+does not use the software-managed cache, this option has no effect. -+ -+@item show spu auto-flush-cache -+Show whether to automatically flush the software-managed cache. -+ -+@end table -+ - @node PowerPC - @subsection PowerPC - @cindex PowerPC architecture -@@ -29271,6 +29298,7 @@ are explained further below. - - - @r{[}@var{architecture}@r{]} -+ @r{[}@var{compatible}@dots{}@r{]} - @r{[}@var{feature}@dots{}@r{]} - - @end smallexample -@@ -29322,9 +29350,33 @@ An @samp{} element has thi - @var{arch} - @end smallexample - --@var{arch} is an architecture name from the same selection --accepted by @code{set architecture} (@pxref{Targets, ,Specifying a --Debugging Target}). -+@var{arch} is one of the architectures from the set accepted by -+@code{set architecture} (@pxref{Targets, ,Specifying a Debugging Target}). -+ -+@subsection Compatible Architecture -+@cindex -+ -+A @samp{} element has this form: -+ -+@smallexample -+ @var{arch} -+@end smallexample -+ -+@var{arch} is one of the architectures from the set accepted by -+@code{set architecture} (@pxref{Targets, ,Specifying a Debugging Target}). -+ -+A @samp{} element is used to specify that the target -+is able to run binaries in some other than the main target architecture -+given by the @samp{} element. For example, on the -+Cell Broadband Engine, the main architecture is @code{powerpc:common} -+or @code{powerpc:common64}, but the system is able to run binaries -+in the @code{spu} architecture as well. The way to describe this -+capability with @samp{} is as follows: -+ -+@smallexample -+ @code{powerpc:common} -+ @code{spu} -+@end smallexample - - @subsection Features - @cindex ---- gdb/features/Makefile -+++ gdb/features/Makefile -@@ -34,7 +34,7 @@ - WHICH = arm-with-iwmmxt mips-linux mips64-linux \ - rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \ - rs6000/powerpc-64l rs6000/powerpc-altivec64l rs6000/powerpc-vsx32l \ -- rs6000/powerpc-vsx64l -+ rs6000/powerpc-vsx64l rs6000/powerpc-cell32l rs6000/powerpc-cell64l - - # Record which registers should be sent to GDB by default after stop. - arm-with-iwmmxt-expedite = r11,sp,pc -@@ -42,6 +42,7 @@ mips-linux-expedite = r29,pc - mips64-linux-expedite = r29,pc - rs6000/powerpc-32l-expedite = r1,pc - rs6000/powerpc-altivec32l-expedite = r1,pc -+rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4 - rs6000/powerpc-vsx32l-expedite = r1,pc - rs6000/powerpc-isa205-32l-expedite = r1,pc - rs6000/powerpc-isa205-altivec32l-expedite = r1,pc -@@ -49,6 +50,7 @@ rs6000/powerpc-isa205-vsx32l-expedite = - rs6000/powerpc-e500l-expedite = r1,pc - rs6000/powerpc-64l-expedite = r1,pc - rs6000/powerpc-altivec64l-expedite = r1,pc -+rs6000/powerpc-cell64l-expedite = r1,pc,r0,orig_r3,r4 - rs6000/powerpc-vsx64l-expedite = r1,pc - rs6000/powerpc-isa205-64l-expedite = r1,pc - rs6000/powerpc-isa205-altivec64l-expedite = r1,pc ---- gdb/features/rs6000/powerpc-cell32l.c -+++ gdb/features/rs6000/powerpc-cell32l.c -@@ -0,0 +1,170 @@ -+/* THIS FILE IS GENERATED. Original: powerpc-cell32l.xml */ -+ -+#include "defs.h" -+#include "gdbtypes.h" -+#include "target-descriptions.h" -+ -+struct target_desc *tdesc_powerpc_cell32l; -+static void -+initialize_tdesc_powerpc_cell32l (void) -+{ -+ struct target_desc *result = allocate_target_description (); -+ struct tdesc_feature *feature; -+ struct type *field_type, *type; -+ -+ set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common")); -+ -+ tdesc_add_compatible (result, bfd_scan_arch ("spu:256K")); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.core"); -+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "pc", 64, 1, NULL, 32, "code_ptr"); -+ tdesc_create_reg (feature, "msr", 65, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "lr", 67, 1, NULL, 32, "code_ptr"); -+ tdesc_create_reg (feature, "ctr", 68, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32"); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu"); -+ tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "fpscr", 70, 1, "float", 32, "int"); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux"); -+ tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 32, "int"); -+ tdesc_create_reg (feature, "trap", 72, 1, NULL, 32, "int"); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec"); -+ field_type = tdesc_named_type (feature, "ieee_single"); -+ type = init_vector_type (field_type, 4); -+ TYPE_NAME (type) = xstrdup ("v4f"); -+ tdesc_record_type (feature, type); -+ -+ field_type = tdesc_named_type (feature, "int32"); -+ type = init_vector_type (field_type, 4); -+ TYPE_NAME (type) = xstrdup ("v4i32"); -+ tdesc_record_type (feature, type); -+ -+ field_type = tdesc_named_type (feature, "int16"); -+ type = init_vector_type (field_type, 8); -+ TYPE_NAME (type) = xstrdup ("v8i16"); -+ tdesc_record_type (feature, type); -+ -+ field_type = tdesc_named_type (feature, "int8"); -+ type = init_vector_type (field_type, 16); -+ TYPE_NAME (type) = xstrdup ("v16i8"); -+ tdesc_record_type (feature, type); -+ -+ type = init_composite_type (NULL, TYPE_CODE_UNION); -+ TYPE_NAME (type) = xstrdup ("vec128"); -+ field_type = tdesc_named_type (feature, "uint128"); -+ append_composite_type_field (type, xstrdup ("uint128"), field_type); -+ field_type = tdesc_named_type (feature, "v4f"); -+ append_composite_type_field (type, xstrdup ("v4_float"), field_type); -+ field_type = tdesc_named_type (feature, "v4i32"); -+ append_composite_type_field (type, xstrdup ("v4_int32"), field_type); -+ field_type = tdesc_named_type (feature, "v8i16"); -+ append_composite_type_field (type, xstrdup ("v8_int16"), field_type); -+ field_type = tdesc_named_type (feature, "v16i8"); -+ append_composite_type_field (type, xstrdup ("v16_int8"), field_type); -+ TYPE_VECTOR (type) = 1; -+ tdesc_record_type (feature, type); -+ -+ tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int"); -+ tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int"); -+ -+ tdesc_powerpc_cell32l = result; -+} ---- gdb/features/rs6000/powerpc-cell32l.xml -+++ gdb/features/rs6000/powerpc-cell32l.xml -@@ -0,0 +1,19 @@ -+ -+ -+ -+ -+ -+ -+ -+ powerpc:common -+ spu -+ -+ -+ -+ -+ ---- gdb/features/rs6000/powerpc-cell64l.c -+++ gdb/features/rs6000/powerpc-cell64l.c -@@ -0,0 +1,170 @@ -+/* THIS FILE IS GENERATED. Original: powerpc-cell64l.xml */ -+ -+#include "defs.h" -+#include "gdbtypes.h" -+#include "target-descriptions.h" -+ -+struct target_desc *tdesc_powerpc_cell64l; -+static void -+initialize_tdesc_powerpc_cell64l (void) -+{ -+ struct target_desc *result = allocate_target_description (); -+ struct tdesc_feature *feature; -+ struct type *field_type, *type; -+ -+ set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64")); -+ -+ tdesc_add_compatible (result, bfd_scan_arch ("spu:256K")); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.core"); -+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "pc", 64, 1, NULL, 64, "code_ptr"); -+ tdesc_create_reg (feature, "msr", 65, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32"); -+ tdesc_create_reg (feature, "lr", 67, 1, NULL, 64, "code_ptr"); -+ tdesc_create_reg (feature, "ctr", 68, 1, NULL, 64, "uint64"); -+ tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32"); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu"); -+ tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double"); -+ tdesc_create_reg (feature, "fpscr", 70, 1, "float", 32, "int"); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux"); -+ tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 64, "int"); -+ tdesc_create_reg (feature, "trap", 72, 1, NULL, 64, "int"); -+ -+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec"); -+ field_type = tdesc_named_type (feature, "ieee_single"); -+ type = init_vector_type (field_type, 4); -+ TYPE_NAME (type) = xstrdup ("v4f"); -+ tdesc_record_type (feature, type); -+ -+ field_type = tdesc_named_type (feature, "int32"); -+ type = init_vector_type (field_type, 4); -+ TYPE_NAME (type) = xstrdup ("v4i32"); -+ tdesc_record_type (feature, type); -+ -+ field_type = tdesc_named_type (feature, "int16"); -+ type = init_vector_type (field_type, 8); -+ TYPE_NAME (type) = xstrdup ("v8i16"); -+ tdesc_record_type (feature, type); -+ -+ field_type = tdesc_named_type (feature, "int8"); -+ type = init_vector_type (field_type, 16); -+ TYPE_NAME (type) = xstrdup ("v16i8"); -+ tdesc_record_type (feature, type); -+ -+ type = init_composite_type (NULL, TYPE_CODE_UNION); -+ TYPE_NAME (type) = xstrdup ("vec128"); -+ field_type = tdesc_named_type (feature, "uint128"); -+ append_composite_type_field (type, xstrdup ("uint128"), field_type); -+ field_type = tdesc_named_type (feature, "v4f"); -+ append_composite_type_field (type, xstrdup ("v4_float"), field_type); -+ field_type = tdesc_named_type (feature, "v4i32"); -+ append_composite_type_field (type, xstrdup ("v4_int32"), field_type); -+ field_type = tdesc_named_type (feature, "v8i16"); -+ append_composite_type_field (type, xstrdup ("v8_int16"), field_type); -+ field_type = tdesc_named_type (feature, "v16i8"); -+ append_composite_type_field (type, xstrdup ("v16_int8"), field_type); -+ TYPE_VECTOR (type) = 1; -+ tdesc_record_type (feature, type); -+ -+ tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128"); -+ tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int"); -+ tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int"); -+ -+ tdesc_powerpc_cell64l = result; -+} ---- gdb/features/rs6000/powerpc-cell64l.xml -+++ gdb/features/rs6000/powerpc-cell64l.xml -@@ -0,0 +1,19 @@ -+ -+ -+ -+ -+ -+ -+ -+ powerpc:common64 -+ spu -+ -+ -+ -+ -+ ---- gdb/findvar.c -+++ gdb/findvar.c -@@ -309,13 +309,15 @@ value_of_register_lazy (struct frame_inf - /* Given a pointer of type TYPE in target form in BUF, return the - address it represents. */ - CORE_ADDR --unsigned_pointer_to_address (struct type *type, const gdb_byte *buf) -+unsigned_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, const gdb_byte *buf) - { - return extract_unsigned_integer (buf, TYPE_LENGTH (type)); - } - - CORE_ADDR --signed_pointer_to_address (struct type *type, const gdb_byte *buf) -+signed_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, const gdb_byte *buf) - { - return extract_signed_integer (buf, TYPE_LENGTH (type)); - } -@@ -323,14 +325,15 @@ signed_pointer_to_address (struct type * - /* Given an address, store it as a pointer of type TYPE in target - format in BUF. */ - void --unsigned_address_to_pointer (struct type *type, gdb_byte *buf, -- CORE_ADDR addr) -+unsigned_address_to_pointer (struct gdbarch *gdbarch, struct type *type, -+ gdb_byte *buf, CORE_ADDR addr) - { - store_unsigned_integer (buf, TYPE_LENGTH (type), addr); - } - - void --address_to_signed_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr) -+address_to_signed_pointer (struct gdbarch *gdbarch, struct type *type, -+ gdb_byte *buf, CORE_ADDR addr) - { - store_signed_integer (buf, TYPE_LENGTH (type), addr); - } ---- gdb/frame-unwind.c -+++ gdb/frame-unwind.c -@@ -126,7 +126,7 @@ default_frame_sniffer (const struct fram - struct value * - frame_unwind_got_optimized (struct frame_info *frame, int regnum) - { -- struct gdbarch *gdbarch = get_frame_arch (frame); -+ struct gdbarch *gdbarch = frame_arch_unwind (frame); - struct value *reg_val; - - reg_val = value_zero (register_type (gdbarch, regnum), not_lval); -@@ -149,7 +149,7 @@ frame_unwind_got_register (struct frame_ - struct value * - frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr) - { -- struct gdbarch *gdbarch = get_frame_arch (frame); -+ struct gdbarch *gdbarch = frame_arch_unwind (frame); - - return value_at_lazy (register_type (gdbarch, regnum), addr); - } -@@ -161,7 +161,7 @@ struct value * - frame_unwind_got_constant (struct frame_info *frame, int regnum, - ULONGEST val) - { -- struct gdbarch *gdbarch = get_frame_arch (frame); -+ struct gdbarch *gdbarch = frame_arch_unwind (frame); - struct value *reg_val; - - reg_val = value_zero (register_type (gdbarch, regnum), not_lval); -@@ -173,7 +173,7 @@ frame_unwind_got_constant (struct frame_ - struct value * - frame_unwind_got_bytes (struct frame_info *frame, int regnum, gdb_byte *buf) - { -- struct gdbarch *gdbarch = get_frame_arch (frame); -+ struct gdbarch *gdbarch = frame_arch_unwind (frame); - struct value *reg_val; - - reg_val = value_zero (register_type (gdbarch, regnum), not_lval); -@@ -189,7 +189,7 @@ struct value * - frame_unwind_got_address (struct frame_info *frame, int regnum, - CORE_ADDR addr) - { -- struct gdbarch *gdbarch = get_frame_arch (frame); -+ struct gdbarch *gdbarch = frame_arch_unwind (frame); - struct value *reg_val; - - reg_val = value_zero (register_type (gdbarch, regnum), not_lval); ---- gdb/frame-unwind.h -+++ gdb/frame-unwind.h -@@ -121,6 +121,13 @@ typedef struct value * (frame_prev_regis - typedef void (frame_dealloc_cache_ftype) (struct frame_info *self, - void *this_cache); - -+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner); -+ use THIS frame, and implicitly the NEXT frame's register unwind -+ method, return PREV frame's architecture. */ -+ -+typedef struct gdbarch *(frame_prev_arch_ftype) (struct frame_info *this_frame, -+ void **this_prologue_cache); -+ - struct frame_unwind - { - /* The frame's type. Should this instead be a collection of -@@ -133,6 +140,7 @@ struct frame_unwind - const struct frame_data *unwind_data; - frame_sniffer_ftype *sniffer; - frame_dealloc_cache_ftype *dealloc_cache; -+ frame_prev_arch_ftype *prev_arch; - }; - - /* Register a frame unwinder, _prepending_ it to the front of the ---- gdb/frame.c -+++ gdb/frame.c -@@ -41,6 +41,7 @@ - #include "objfiles.h" - #include "exceptions.h" - #include "gdbthread.h" -+#include "arch-utils.h" - - static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame); - -@@ -75,6 +76,13 @@ struct frame_info - void *prologue_cache; - const struct frame_unwind *unwind; - -+ /* Cached copy of the previous frame's architecture. */ -+ struct -+ { -+ int p; -+ struct gdbarch *arch; -+ } prev_arch; -+ - /* Cached copy of the previous frame's resume address. */ - struct { - int p; -@@ -190,6 +198,9 @@ fprint_frame_type (struct ui_file *file, - case SIGTRAMP_FRAME: - fprintf_unfiltered (file, "SIGTRAMP_FRAME"); - return; -+ case ARCH_FRAME: -+ fprintf_unfiltered (file, "ARCH_FRAME"); -+ return; - default: - fprintf_unfiltered (file, ""); - return; -@@ -251,6 +262,9 @@ get_frame_id (struct frame_info *fi) - } - if (!fi->this_id.p) - { -+ struct cleanup *old_chain = save_current_gdbarch (); -+ current_gdbarch = get_frame_arch (fi); -+ - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, "{ get_frame_id (fi=%d) ", - fi->level); -@@ -266,6 +280,8 @@ get_frame_id (struct frame_info *fi) - fprint_frame_id (gdb_stdlog, fi->this_id.value); - fprintf_unfiltered (gdb_stdlog, " }\n"); - } -+ -+ do_cleanups (old_chain); - } - return fi->this_id.value; - } -@@ -459,7 +475,7 @@ frame_pc_unwind (struct frame_info *this - if (!this_frame->prev_pc.p) - { - CORE_ADDR pc; -- if (gdbarch_unwind_pc_p (get_frame_arch (this_frame))) -+ if (gdbarch_unwind_pc_p (frame_arch_unwind (this_frame))) - { - /* The right way. The `pure' way. The one true way. This - method depends solely on the register-unwind code to -@@ -477,7 +493,7 @@ frame_pc_unwind (struct frame_info *this - frame. This is all in stark contrast to the old - FRAME_SAVED_PC which would try to directly handle all the - different ways that a PC could be unwound. */ -- pc = gdbarch_unwind_pc (get_frame_arch (this_frame), this_frame); -+ pc = gdbarch_unwind_pc (frame_arch_unwind (this_frame), this_frame); - } - else - internal_error (__FILE__, __LINE__, _("No unwind_pc method")); -@@ -650,19 +666,24 @@ get_frame_register (struct frame_info *f - struct value * - frame_unwind_register_value (struct frame_info *frame, int regnum) - { -+ struct gdbarch *gdbarch; - struct value *value; -+ struct cleanup *old_chain; - - gdb_assert (frame != NULL); -+ gdbarch = frame_arch_unwind (frame); - - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "\ - { frame_unwind_register_value (frame=%d,regnum=%d(%s),...) ", - frame->level, regnum, -- user_reg_map_regnum_to_name -- (get_frame_arch (frame), regnum)); -+ user_reg_map_regnum_to_name (gdbarch, regnum)); - } - -+ old_chain = save_current_gdbarch (); -+ current_gdbarch = gdbarch; -+ - /* Find the unwinder. */ - if (frame->unwind == NULL) - frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache); -@@ -695,7 +716,7 @@ frame_unwind_register_value (struct fram - - fprintf_unfiltered (gdb_stdlog, " bytes="); - fprintf_unfiltered (gdb_stdlog, "["); -- for (i = 0; i < register_size (get_frame_arch (frame), regnum); i++) -+ for (i = 0; i < register_size (gdbarch, regnum); i++) - fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); - fprintf_unfiltered (gdb_stdlog, "]"); - } -@@ -704,6 +725,7 @@ frame_unwind_register_value (struct fram - fprintf_unfiltered (gdb_stdlog, " }\n"); - } - -+ do_cleanups (old_chain); - return value; - } - -@@ -718,7 +740,7 @@ frame_unwind_register_signed (struct fra - { - gdb_byte buf[MAX_REGISTER_SIZE]; - frame_unwind_register (frame, regnum, buf); -- return extract_signed_integer (buf, register_size (get_frame_arch (frame), -+ return extract_signed_integer (buf, register_size (frame_arch_unwind (frame), - regnum)); - } - -@@ -733,7 +755,7 @@ frame_unwind_register_unsigned (struct f - { - gdb_byte buf[MAX_REGISTER_SIZE]; - frame_unwind_register (frame, regnum, buf); -- return extract_unsigned_integer (buf, register_size (get_frame_arch (frame), -+ return extract_unsigned_integer (buf, register_size (frame_arch_unwind (frame), - regnum)); - } - -@@ -1070,6 +1092,8 @@ select_frame (struct frame_info *fi) - source language of this frame, and switch to it if desired. */ - if (fi) - { -+ current_gdbarch = get_frame_arch (fi); -+ - /* We retrieve the frame's symtab by using the frame PC. However - we cannot use the frame PC as-is, because it usually points to - the instruction following the "call", which is sometimes the -@@ -1694,9 +1718,17 @@ enum frame_type - get_frame_type (struct frame_info *frame) - { - if (frame->unwind == NULL) -- /* Initialize the frame's unwinder because that's what -- provides the frame's type. */ -- frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache); -+ { -+ struct cleanup *old_chain = save_current_gdbarch (); -+ current_gdbarch = get_frame_arch (frame); -+ -+ /* Initialize the frame's unwinder because that's what -+ provides the frame's type. */ -+ frame->unwind = frame_unwind_find_by_frame (frame, -+ &frame->prologue_cache); -+ do_cleanups (old_chain); -+ } -+ - return frame->unwind->type; - } - -@@ -1731,17 +1763,48 @@ safe_frame_unwind_memory (struct frame_i - return !target_read_memory (addr, buf, len); - } - --/* Architecture method. */ -+/* Architecture methods. */ - - struct gdbarch * - get_frame_arch (struct frame_info *this_frame) - { -- /* In the future, this function will return a per-frame -- architecture instead of current_gdbarch. Calling the -- routine with a NULL value of this_frame is a bug! */ -- gdb_assert (this_frame); -+ return frame_arch_unwind (this_frame->next); -+} -+ -+struct gdbarch * -+frame_arch_unwind (struct frame_info *next_frame) -+{ -+ if (!next_frame->prev_arch.p) -+ { -+ struct gdbarch *arch; -+ struct cleanup *old_chain = save_current_gdbarch (); -+ -+ if (next_frame->level >= 0) -+ current_gdbarch = get_frame_arch (next_frame); -+ -+ if (next_frame->unwind == NULL) -+ next_frame->unwind -+ = frame_unwind_find_by_frame (next_frame, -+ &next_frame->prologue_cache); -+ -+ if (next_frame->unwind->prev_arch != NULL) -+ arch = next_frame->unwind->prev_arch (next_frame, -+ &next_frame->prologue_cache); -+ else -+ arch = get_frame_arch (next_frame); -+ -+ next_frame->prev_arch.arch = arch; -+ next_frame->prev_arch.p = 1; -+ if (frame_debug) -+ fprintf_unfiltered (gdb_stdlog, -+ "{ frame_arch_unwind (next_frame=%d) -> %s }\n", -+ next_frame->level, -+ gdbarch_bfd_arch_info (arch)->printable_name); -+ -+ do_cleanups (old_chain); -+ } - -- return current_gdbarch; -+ return next_frame->prev_arch.arch; - } - - /* Stack pointer methods. */ ---- gdb/frame.h -+++ gdb/frame.h -@@ -180,6 +180,8 @@ enum frame_type - /* In a signal handler, various OSs handle this in various ways. - The main thing is that the frame may be far from normal. */ - SIGTRAMP_FRAME, -+ /* Fake frame representing a cross-architecture call. */ -+ ARCH_FRAME, - /* Sentinel or registers frame. This frame obtains register values - direct from the inferior's registers. */ - SENTINEL_FRAME -@@ -523,6 +525,7 @@ extern int safe_frame_unwind_memory (str - /* Return this frame's architecture. */ - - extern struct gdbarch *get_frame_arch (struct frame_info *this_frame); -+extern struct gdbarch *frame_arch_unwind (struct frame_info *next_frame); - - - /* Values for the source flag to be used in print_frame_info_base(). */ ---- gdb/gcore.c -+++ gdb/gcore.c -@@ -35,7 +35,7 @@ - generate-core-file for programs with large resident data. */ - #define MAX_COPY_BYTES (1024 * 1024) - --static char *default_gcore_target (void); -+static const char *default_gcore_target (void); - static enum bfd_architecture default_gcore_arch (void); - static unsigned long default_gcore_mach (void); - static int gcore_memory_sections (bfd *); -@@ -125,7 +125,7 @@ default_gcore_mach (void) - return 0; - #else - -- const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (current_gdbarch); -+ const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch); - - if (bfdarch != NULL) - return bfdarch->mach; -@@ -139,8 +139,7 @@ default_gcore_mach (void) - static enum bfd_architecture - default_gcore_arch (void) - { -- const struct bfd_arch_info * bfdarch = gdbarch_bfd_arch_info -- (current_gdbarch); -+ const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch); - - if (bfdarch != NULL) - return bfdarch->arch; -@@ -150,10 +149,15 @@ default_gcore_arch (void) - return bfd_get_arch (exec_bfd); - } - --static char * -+static const char * - default_gcore_target (void) - { -- /* FIXME: This may only work for ELF targets. */ -+ /* The gdbarch may define a target to use for core files. */ -+ if (gdbarch_gcore_bfd_target_p (target_gdbarch)) -+ return gdbarch_gcore_bfd_target (target_gdbarch); -+ -+ /* Otherwise, try to fall back to the exec_bfd target. This will probably -+ not work for non-ELF targets. */ - if (exec_bfd == NULL) - return NULL; - else ---- gdb/gdbarch.c -+++ gdb/gdbarch.c -@@ -226,6 +226,7 @@ struct gdbarch - int core_reg_section_encodes_pid; - struct core_regset_section * core_regset_sections; - gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries; -+ const char * gcore_bfd_target; - int vtable_function_descriptors; - int vbit_in_delta; - gdbarch_skip_permanent_breakpoint_ftype *skip_permanent_breakpoint; -@@ -314,8 +315,8 @@ struct gdbarch startup_gdbarch = - 0, /* register_to_value */ - 0, /* value_to_register */ - 0, /* value_from_register */ -- 0, /* pointer_to_address */ -- 0, /* address_to_pointer */ -+ unsigned_pointer_to_address, /* pointer_to_address */ -+ unsigned_address_to_pointer, /* address_to_pointer */ - 0, /* integer_to_address */ - 0, /* return_value */ - 0, /* skip_prologue */ -@@ -360,6 +361,7 @@ struct gdbarch startup_gdbarch = - 0, /* core_reg_section_encodes_pid */ - 0, /* core_regset_sections */ - 0, /* core_xfer_shared_libraries */ -+ 0, /* gcore_bfd_target */ - 0, /* vtable_function_descriptors */ - 0, /* vbit_in_delta */ - 0, /* skip_permanent_breakpoint */ -@@ -613,6 +615,7 @@ verify_gdbarch (struct gdbarch *gdbarch) - /* Skip verify of regset_from_core_section, has predicate */ - /* Skip verify of core_reg_section_encodes_pid, invalid_p == 0 */ - /* Skip verify of core_xfer_shared_libraries, has predicate */ -+ /* Skip verify of gcore_bfd_target, has predicate */ - /* Skip verify of vtable_function_descriptors, invalid_p == 0 */ - /* Skip verify of vbit_in_delta, invalid_p == 0 */ - /* Skip verify of skip_permanent_breakpoint, has predicate */ -@@ -838,6 +841,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s - "gdbarch_dump: frame_red_zone_size = %s\n", - plongest (gdbarch->frame_red_zone_size)); - fprintf_unfiltered (file, -+ "gdbarch_dump: gdbarch_gcore_bfd_target_p() = %d\n", -+ gdbarch_gcore_bfd_target_p (gdbarch)); -+ fprintf_unfiltered (file, -+ "gdbarch_dump: gcore_bfd_target = %s\n", -+ gdbarch->gcore_bfd_target); -+ fprintf_unfiltered (file, - "gdbarch_dump: gdbarch_get_longjmp_target_p() = %d\n", - gdbarch_get_longjmp_target_p (gdbarch)); - fprintf_unfiltered (file, -@@ -2070,7 +2079,7 @@ gdbarch_pointer_to_address (struct gdbar - gdb_assert (gdbarch->pointer_to_address != NULL); - if (gdbarch_debug >= 2) - fprintf_unfiltered (gdb_stdlog, "gdbarch_pointer_to_address called\n"); -- return gdbarch->pointer_to_address (type, buf); -+ return gdbarch->pointer_to_address (gdbarch, type, buf); - } - - void -@@ -2087,7 +2096,7 @@ gdbarch_address_to_pointer (struct gdbar - gdb_assert (gdbarch->address_to_pointer != NULL); - if (gdbarch_debug >= 2) - fprintf_unfiltered (gdb_stdlog, "gdbarch_address_to_pointer called\n"); -- gdbarch->address_to_pointer (type, buf, addr); -+ gdbarch->address_to_pointer (gdbarch, type, buf, addr); - } - - void -@@ -2963,6 +2972,31 @@ set_gdbarch_core_xfer_shared_libraries ( - } - - int -+gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch) -+{ -+ gdb_assert (gdbarch != NULL); -+ return gdbarch->gcore_bfd_target != 0; -+} -+ -+const char * -+gdbarch_gcore_bfd_target (struct gdbarch *gdbarch) -+{ -+ gdb_assert (gdbarch != NULL); -+ /* Check variable changed from pre-default. */ -+ gdb_assert (gdbarch->gcore_bfd_target != 0); -+ if (gdbarch_debug >= 2) -+ fprintf_unfiltered (gdb_stdlog, "gdbarch_gcore_bfd_target called\n"); -+ return gdbarch->gcore_bfd_target; -+} -+ -+void -+set_gdbarch_gcore_bfd_target (struct gdbarch *gdbarch, -+ const char * gcore_bfd_target) -+{ -+ gdbarch->gcore_bfd_target = gcore_bfd_target; -+} -+ -+int - gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch) - { - gdb_assert (gdbarch != NULL); -@@ -3423,10 +3457,15 @@ gdbarch_data (struct gdbarch *gdbarch, s - (as all fields are valid), but be careful to also detect - recursive references. */ - { -+ struct cleanup *old_chain = save_current_gdbarch (); -+ current_gdbarch = gdbarch; -+ - gdb_assert (data->init_p); - data->init_p = 0; - gdbarch->data[data->index] = data->post_init (gdbarch); - data->init_p = 1; -+ -+ do_cleanups (old_chain); - } - else - /* The architecture initialization hasn't completed - punt - ---- gdb/gdbarch.h -+++ gdb/gdbarch.h -@@ -348,11 +348,11 @@ typedef struct value * (gdbarch_value_fr - extern struct value * gdbarch_value_from_register (struct gdbarch *gdbarch, struct type *type, int regnum, struct frame_info *frame); - extern void set_gdbarch_value_from_register (struct gdbarch *gdbarch, gdbarch_value_from_register_ftype *value_from_register); - --typedef CORE_ADDR (gdbarch_pointer_to_address_ftype) (struct type *type, const gdb_byte *buf); -+typedef CORE_ADDR (gdbarch_pointer_to_address_ftype) (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf); - extern CORE_ADDR gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf); - extern void set_gdbarch_pointer_to_address (struct gdbarch *gdbarch, gdbarch_pointer_to_address_ftype *pointer_to_address); - --typedef void (gdbarch_address_to_pointer_ftype) (struct type *type, gdb_byte *buf, CORE_ADDR addr); -+typedef void (gdbarch_address_to_pointer_ftype) (struct gdbarch *gdbarch, struct type *type, gdb_byte *buf, CORE_ADDR addr); - extern void gdbarch_address_to_pointer (struct gdbarch *gdbarch, struct type *type, gdb_byte *buf, CORE_ADDR addr); - extern void set_gdbarch_address_to_pointer (struct gdbarch *gdbarch, gdbarch_address_to_pointer_ftype *address_to_pointer); - -@@ -661,6 +661,13 @@ typedef LONGEST (gdbarch_core_xfer_share - extern LONGEST gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len); - extern void set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries); - -+/* BFD target to use when generating a core file. */ -+ -+extern int gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch); -+ -+extern const char * gdbarch_gcore_bfd_target (struct gdbarch *gdbarch); -+extern void set_gdbarch_gcore_bfd_target (struct gdbarch *gdbarch, const char * gcore_bfd_target); -+ - /* If the elements of C++ vtables are in-place function descriptors rather - than normal function pointers (which may point to code or a descriptor), - set this to one. */ ---- gdb/gdbarch.sh -+++ gdb/gdbarch.sh -@@ -466,8 +466,8 @@ f:void:value_to_register:struct frame_in - # (but not the value contents) filled in. - f:struct value *:value_from_register:struct type *type, int regnum, struct frame_info *frame:type, regnum, frame::default_value_from_register::0 - # --f:CORE_ADDR:pointer_to_address:struct type *type, const gdb_byte *buf:type, buf::unsigned_pointer_to_address::0 --f:void:address_to_pointer:struct type *type, gdb_byte *buf, CORE_ADDR addr:type, buf, addr::unsigned_address_to_pointer::0 -+m:CORE_ADDR:pointer_to_address:struct type *type, const gdb_byte *buf:type, buf::unsigned_pointer_to_address::0 -+m:void:address_to_pointer:struct type *type, gdb_byte *buf, CORE_ADDR addr:type, buf, addr::unsigned_address_to_pointer::0 - M:CORE_ADDR:integer_to_address:struct type *type, const gdb_byte *buf:type, buf - - # Return the return-value convention that will be used by FUNCTYPE -@@ -614,6 +614,9 @@ v:struct core_regset_section *:core_regs - # core file into buffer READBUF with length LEN. - M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len - -+# BFD target to use when generating a core file. -+V:const char *:gcore_bfd_target:::0:0:::gdbarch->gcore_bfd_target -+ - # If the elements of C++ vtables are in-place function descriptors rather - # than normal function pointers (which may point to code or a descriptor), - # set this to one. -@@ -1743,10 +1746,15 @@ gdbarch_data (struct gdbarch *gdbarch, s - (as all fields are valid), but be careful to also detect - recursive references. */ - { -+ struct cleanup *old_chain = save_current_gdbarch (); -+ current_gdbarch = gdbarch; -+ - gdb_assert (data->init_p); - data->init_p = 0; - gdbarch->data[data->index] = data->post_init (gdbarch); - data->init_p = 1; -+ -+ do_cleanups (old_chain); - } - else - /* The architecture initialization hasn't completed - punt - ---- gdb/gdbserver/Makefile.in -+++ gdb/gdbserver/Makefile.in -@@ -207,8 +207,8 @@ clean: - rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c reg-xtensa.c - rm -f arm-with-iwmmxt.c mips-linux.c mips64-linux.c - rm -f powerpc-32l.c powerpc-64l.c powerpc-e500l.c -- rm -f powerpc-altivec32l.c powerpc-vsx32l.c powerpc-altivec64l.c -- rm -f powerpc-vsx64l.c -+ rm -f powerpc-altivec32l.c powerpc-cell32l.c powerpc-vsx32l.c -+ rm -f powerpc-altivec64l.c powerpc-cell64l.c powerpc-vsx64l.c - rm -f powerpc-isa205-32l.c powerpc-isa205-64l.c - rm -f powerpc-isa205-altivec32l.c powerpc-isa205-vsx32l.c powerpc-isa205-altivec64l.c - rm -f powerpc-isa205-vsx64l.c -@@ -356,6 +356,9 @@ powerpc-32l.c : $(srcdir)/../regformats/ - powerpc-altivec32l.o : powerpc-altivec32l.c $(regdef_h) - powerpc-altivec32l.c : $(srcdir)/../regformats/rs6000/powerpc-altivec32l.dat $(regdat_sh) - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-altivec32l.dat powerpc-altivec32l.c -+powerpc-cell32l.o : powerpc-cell32l.c $(regdef_h) -+powerpc-cell32l.c : $(srcdir)/../regformats/rs6000/powerpc-cell32l.dat $(regdat_sh) -+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-cell32l.dat powerpc-cell32l.c - powerpc-vsx32l.o : powerpc-vsx32l.c $(regdef_h) - powerpc-vsx32l.c : $(srcdir)/../regformats/rs6000/powerpc-vsx32l.dat $(regdat_sh) - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-vsx32l.dat powerpc-vsx32l.c -@@ -377,6 +380,9 @@ powerpc-64l.c : $(srcdir)/../regformats/ - powerpc-altivec64l.o : powerpc-altivec64l.c $(regdef_h) - powerpc-altivec64l.c : $(srcdir)/../regformats/rs6000/powerpc-altivec64l.dat $(regdat_sh) - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-altivec64l.dat powerpc-altivec64l.c -+powerpc-cell64l.o : powerpc-cell64l.c $(regdef_h) -+powerpc-cell64l.c : $(srcdir)/../regformats/rs6000/powerpc-cell64l.dat $(regdat_sh) -+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-cell64l.dat powerpc-cell64l.c - powerpc-vsx64l.o : powerpc-vsx64l.c $(regdef_h) - powerpc-vsx64l.c : $(srcdir)/../regformats/rs6000/powerpc-vsx64l.dat $(regdat_sh) - $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-vsx64l.dat powerpc-vsx64l.c ---- gdb/gdbserver/configure.srv -+++ gdb/gdbserver/configure.srv -@@ -102,6 +102,7 @@ case "${target}" in - ;; - powerpc*-*-linux*) srv_regobj="powerpc-32l.o" - srv_regobj="${srv_regobj} powerpc-altivec32l.o" -+ srv_regobj="${srv_regobj} powerpc-cell32l.o" - srv_regobj="${srv_regobj} powerpc-vsx32l.o" - srv_regobj="${srv_regobj} powerpc-isa205-32l.o" - srv_regobj="${srv_regobj} powerpc-isa205-altivec32l.o" -@@ -109,6 +110,7 @@ case "${target}" in - srv_regobj="${srv_regobj} powerpc-e500l.o" - srv_regobj="${srv_regobj} powerpc-64l.o" - srv_regobj="${srv_regobj} powerpc-altivec64l.o" -+ srv_regobj="${srv_regobj} powerpc-cell64l.o" - srv_regobj="${srv_regobj} powerpc-vsx64l.o" - srv_regobj="${srv_regobj} powerpc-isa205-64l.o" - srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o" -@@ -116,6 +118,7 @@ case "${target}" in - srv_tgtobj="linux-low.o linux-ppc-low.o" - srv_xmlfiles="rs6000/powerpc-32l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml" -+ srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-vsx32l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-32l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-altivec32l.xml" -@@ -130,6 +133,7 @@ case "${target}" in - srv_xmlfiles="${srv_xmlfiles} rs6000/power-spe.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-64l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec64l.xml" -+ srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell64l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-vsx64l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-64l.xml" - srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-altivec64l.xml" ---- gdb/gdbserver/linux-low.c -+++ gdb/gdbserver/linux-low.c -@@ -36,8 +36,14 @@ - #include - #include - #include -+#include -+#include - #include - -+#ifndef SPUFS_MAGIC -+#define SPUFS_MAGIC 0x23c9b64e -+#endif -+ - #ifndef PTRACE_GETSIGINFO - # define PTRACE_GETSIGINFO 0x4202 - # define PTRACE_SETSIGINFO 0x4203 -@@ -2218,6 +2224,102 @@ linux_xfer_siginfo (const char *annex, u - return len; - } - -+ -+/* Enumerate spufs IDs for process PID. */ -+static int -+spu_enumerate_spu_ids (long pid, unsigned char *buf, CORE_ADDR offset, int len) -+{ -+ int pos = 0; -+ int written = 0; -+ char path[128]; -+ DIR *dir; -+ struct dirent *entry; -+ -+ sprintf (path, "/proc/%ld/fd", pid); -+ dir = opendir (path); -+ if (!dir) -+ return -1; -+ -+ rewinddir (dir); -+ while ((entry = readdir (dir)) != NULL) -+ { -+ struct stat st; -+ struct statfs stfs; -+ int fd; -+ -+ fd = atoi (entry->d_name); -+ if (!fd) -+ continue; -+ -+ sprintf (path, "/proc/%ld/fd/%d", pid, fd); -+ if (stat (path, &st) != 0) -+ continue; -+ if (!S_ISDIR (st.st_mode)) -+ continue; -+ -+ if (statfs (path, &stfs) != 0) -+ continue; -+ if (stfs.f_type != SPUFS_MAGIC) -+ continue; -+ -+ if (pos >= offset && pos + 4 <= offset + len) -+ { -+ *(unsigned int *)(buf + pos - offset) = fd; -+ written += 4; -+ } -+ pos += 4; -+ } -+ -+ closedir (dir); -+ return written; -+} -+ -+/* Implements the to_xfer_partial interface for the TARGET_OBJECT_SPU -+ object type, using the /proc file system */ -+static int -+linux_spu_qxfer_partial (const char *annex, unsigned char *readbuf, -+ unsigned const char *writebuf, -+ CORE_ADDR offset, int len) -+{ -+ char buf[128]; -+ int fd = 0; -+ int ret = 0; -+ -+ if (!writebuf && !readbuf) -+ return -1; -+ -+ if (!*annex) -+ { -+ if (!readbuf) -+ return -1; -+ else -+ return spu_enumerate_spu_ids (inferior_pid, readbuf, offset, len); -+ } -+ -+ sprintf (buf, "/proc/%ld/fd/%s", inferior_pid, annex); -+ if (debug_threads) -+ printf ("access [%s] |offset [%lld] | len [%d]\n", buf, offset, len); -+ -+ fd = open (buf, writebuf? O_WRONLY : O_RDONLY); -+ if (fd <= 0) -+ return -1; -+ -+ if (offset != 0 -+ && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) -+ { -+ close (fd); -+ return 0; -+ } -+ -+ if (writebuf) -+ ret = write (fd, writebuf, (size_t) len); -+ else -+ ret = read (fd, readbuf, (size_t) len); -+ -+ close (fd); -+ return ret; -+} -+ - static struct target_ops linux_target_ops = { - linux_create_inferior, - linux_attach, -@@ -2248,7 +2350,7 @@ static struct target_ops linux_target_op - #else - NULL, - #endif -- NULL, -+ linux_spu_qxfer_partial, - hostio_last_error_from_errno, - linux_qxfer_osdata, - linux_xfer_siginfo, ---- gdb/gdbserver/linux-ppc-low.c -+++ gdb/gdbserver/linux-ppc-low.c -@@ -28,6 +28,7 @@ - #define PPC_FEATURE_HAS_VSX 0x00000080 - #define PPC_FEATURE_HAS_ALTIVEC 0x10000000 - #define PPC_FEATURE_HAS_SPE 0x00800000 -+#define PPC_FEATURE_CELL 0x00010000 - #define PPC_FEATURE_ARCH_2_05 0x00001000 - - static unsigned long ppc_hwcap; -@@ -37,6 +38,8 @@ static unsigned long ppc_hwcap; - void init_registers_powerpc_32l (void); - /* Defined in auto-generated file powerpc-altivec32l.c. */ - void init_registers_powerpc_altivec32l (void); -+/* Defined in auto-generated file powerpc-cell32l.c. */ -+void init_registers_powerpc_cell32l (void); - /* Defined in auto-generated file powerpc-vsx32l.c. */ - void init_registers_powerpc_vsx32l (void); - /* Defined in auto-generated file powerpc-isa205-32l.c. */ -@@ -51,6 +54,8 @@ void init_registers_powerpc_e500l (void) - void init_registers_powerpc_64l (void); - /* Defined in auto-generated file powerpc-altivec64l.c. */ - void init_registers_powerpc_altivec64l (void); -+/* Defined in auto-generated file powerpc-cell64l.c. */ -+void init_registers_powerpc_cell64l (void); - /* Defined in auto-generated file powerpc-vsx64l.c. */ - void init_registers_powerpc_vsx64l (void); - /* Defined in auto-generated file powerpc-isa205-64l.c. */ -@@ -186,10 +191,72 @@ ppc_supply_ptrace_register (int regno, c - supply_register (regno, buf); - } - -+ -+#define INSTR_SC 0x44000002 -+#define NR_spu_run 0x0116 -+ -+/* If the PPU thread is currently stopped on a spu_run system call, -+ return to FD and ADDR the file handle and NPC parameter address -+ used with the system call. Return non-zero if successful. */ -+static int -+parse_spufs_run (int *fd, CORE_ADDR *addr) -+{ -+ CORE_ADDR curr_pc; -+ int curr_insn; -+ int curr_r0; -+ -+ if (register_size (0) == 4) -+ { -+ unsigned int pc, r0, r3, r4; -+ collect_register_by_name ("pc", &pc); -+ collect_register_by_name ("r0", &r0); -+ collect_register_by_name ("orig_r3", &r3); -+ collect_register_by_name ("r4", &r4); -+ curr_pc = (CORE_ADDR) pc; -+ curr_r0 = (int) r0; -+ *fd = (int) r3; -+ *addr = (CORE_ADDR) r4; -+ } -+ else -+ { -+ unsigned long pc, r0, r3, r4; -+ collect_register_by_name ("pc", &pc); -+ collect_register_by_name ("r0", &r0); -+ collect_register_by_name ("orig_r3", &r3); -+ collect_register_by_name ("r4", &r4); -+ curr_pc = (CORE_ADDR) pc; -+ curr_r0 = (int) r0; -+ *fd = (int) r3; -+ *addr = (CORE_ADDR) r4; -+ } -+ -+ /* Fetch instruction preceding current NIP. */ -+ if ((*the_target->read_memory) (curr_pc - 4, -+ (unsigned char *) &curr_insn, 4) != 0) -+ return 0; -+ /* It should be a "sc" instruction. */ -+ if (curr_insn != INSTR_SC) -+ return 0; -+ /* System call number should be NR_spu_run. */ -+ if (curr_r0 != NR_spu_run) -+ return 0; -+ -+ return 1; -+} -+ - static CORE_ADDR - ppc_get_pc (void) - { -- if (register_size (0) == 4) -+ CORE_ADDR addr; -+ int fd; -+ -+ if (parse_spufs_run (&fd, &addr)) -+ { -+ unsigned int pc; -+ (*the_target->read_memory) (addr, (unsigned char *) &pc, 4); -+ return ((CORE_ADDR)1 << 63) | ((CORE_ADDR)fd << 32) | (CORE_ADDR) (pc - 4); -+ } -+ else if (register_size (0) == 4) - { - unsigned int pc; - collect_register_by_name ("pc", &pc); -@@ -206,7 +273,15 @@ ppc_get_pc (void) - static void - ppc_set_pc (CORE_ADDR pc) - { -- if (register_size (0) == 4) -+ CORE_ADDR addr; -+ int fd; -+ -+ if (parse_spufs_run (&fd, &addr)) -+ { -+ unsigned int newpc = pc; -+ (*the_target->write_memory) (addr, (unsigned char *) &newpc, 4); -+ } -+ else if (register_size (0) == 4) - { - unsigned int newpc = pc; - supply_register_by_name ("pc", &newpc); -@@ -272,7 +347,9 @@ ppc_arch_setup (void) - if (msr < 0) - { - ppc_get_hwcap (&ppc_hwcap); -- if (ppc_hwcap & PPC_FEATURE_HAS_VSX) -+ if (ppc_hwcap & PPC_FEATURE_CELL) -+ init_registers_powerpc_cell64l (); -+ else if (ppc_hwcap & PPC_FEATURE_HAS_VSX) - { - if (ppc_hwcap & PPC_FEATURE_ARCH_2_05) - init_registers_powerpc_isa205_vsx64l (); -@@ -295,7 +372,9 @@ ppc_arch_setup (void) - init_registers_powerpc_32l (); - - ppc_get_hwcap (&ppc_hwcap); -- if (ppc_hwcap & PPC_FEATURE_HAS_VSX) -+ if (ppc_hwcap & PPC_FEATURE_CELL) -+ init_registers_powerpc_cell32l (); -+ else if (ppc_hwcap & PPC_FEATURE_HAS_VSX) - { - if (ppc_hwcap & PPC_FEATURE_ARCH_2_05) - init_registers_powerpc_isa205_vsx32l (); -@@ -339,11 +418,24 @@ ppc_breakpoint_at (CORE_ADDR where) - { - unsigned int insn; - -- (*the_target->read_memory) (where, (unsigned char *) &insn, 4); -- if (insn == ppc_breakpoint) -- return 1; -- /* If necessary, recognize more trap instructions here. GDB only uses the -- one. */ -+ if (where & ((CORE_ADDR)1 << 63)) -+ { -+ char mem_annex[32]; -+ sprintf (mem_annex, "%d/mem", (int)((where >> 32) & 0x7fffffff)); -+ (*the_target->qxfer_spu) (mem_annex, (unsigned char *) &insn, -+ NULL, where & 0xffffffff, 4); -+ if (insn == 0x3fff) -+ return 1; -+ } -+ else -+ { -+ (*the_target->read_memory) (where, (unsigned char *) &insn, 4); -+ if (insn == ppc_breakpoint) -+ return 1; -+ /* If necessary, recognize more trap instructions here. GDB only uses -+ the one. */ -+ } -+ - return 0; - } - ---- gdb/gdbserver/thread-db.c -+++ gdb/gdbserver/thread-db.c -@@ -386,6 +386,10 @@ thread_db_get_tls_address (struct thread - td_err_e err; - struct process_info *process; - -+ /* If the thread layer is not (yet) initialized, fail. */ -+ if (!all_symbols_looked_up) -+ return -1; -+ - process = get_thread_process (thread); - if (!process->thread_known) - find_one_thread (process->lwpid); ---- gdb/i386-nat.c -+++ gdb/i386-nat.c -@@ -641,14 +641,14 @@ i386_insert_hw_breakpoint (struct bp_tar - } - - /* Remove a hardware-assisted breakpoint at BP_TGT->placed_address. -- Return 0 on success, -1 on failure. */ -+ Return 0 on success, EBUSY on failure. */ - - int - i386_remove_hw_breakpoint (struct bp_target_info *bp_tgt) - { - unsigned len_rw = i386_length_and_rw_bits (1, hw_execute); - CORE_ADDR addr = bp_tgt->placed_address; -- int retval = i386_remove_aligned_watchpoint (addr, len_rw); -+ int retval = i386_remove_aligned_watchpoint (addr, len_rw) ? EBUSY : 0; - - if (maint_show_dr) - i386_show_dr ("remove_hwbp", addr, 1, hw_execute); ---- gdb/inferior.h -+++ gdb/inferior.h -@@ -156,13 +156,17 @@ extern CORE_ADDR read_pc (void); - - extern void write_pc (CORE_ADDR); - --extern CORE_ADDR unsigned_pointer_to_address (struct type *type, -+extern CORE_ADDR unsigned_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, - const gdb_byte *buf); --extern void unsigned_address_to_pointer (struct type *type, gdb_byte *buf, -+extern void unsigned_address_to_pointer (struct gdbarch *gdbarch, -+ struct type *type, gdb_byte *buf, - CORE_ADDR addr); --extern CORE_ADDR signed_pointer_to_address (struct type *type, -+extern CORE_ADDR signed_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, - const gdb_byte *buf); --extern void address_to_signed_pointer (struct type *type, gdb_byte *buf, -+extern void address_to_signed_pointer (struct gdbarch *gdbarch, -+ struct type *type, gdb_byte *buf, - CORE_ADDR addr); - - extern void wait_for_inferior (int treat_exec_as_sigtrap); ---- gdb/iq2000-tdep.c -+++ gdb/iq2000-tdep.c -@@ -87,7 +87,8 @@ insn_addr_from_ptr (CORE_ADDR ptr) /* ta - Convert a target pointer to an address in host (CORE_ADDR) format. */ - - static CORE_ADDR --iq2000_pointer_to_address (struct type * type, const gdb_byte * buf) -+iq2000_pointer_to_address (struct gdbarch *gdbarch, -+ struct type * type, const gdb_byte * buf) - { - enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type)); - CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type)); -@@ -104,7 +105,8 @@ iq2000_pointer_to_address (struct type * - Convert a host-format address (CORE_ADDR) into a target pointer. */ - - static void --iq2000_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr) -+iq2000_address_to_pointer (struct gdbarch *gdbarch, -+ struct type *type, gdb_byte *buf, CORE_ADDR addr) - { - enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type)); - ---- gdb/linux-nat.c -+++ gdb/linux-nat.c -@@ -53,6 +53,12 @@ - #include - #include "gdb_dirent.h" - #include "xml-support.h" -+#include /* for struct statfs */ -+#include /* for DIR etc. */ -+ -+#ifndef SPUFS_MAGIC -+#define SPUFS_MAGIC 0x23c9b64e -+#endif - - #ifdef HAVE_PERSONALITY - # include -@@ -3529,8 +3535,8 @@ linux_nat_do_thread_registers (bfd *obfd - gdb_gregset_t gregs; - gdb_fpregset_t fpregs; - unsigned long lwp = ptid_get_lwp (ptid); -- struct regcache *regcache = get_thread_regcache (ptid); -- struct gdbarch *gdbarch = get_regcache_arch (regcache); -+ struct gdbarch *gdbarch = target_gdbarch; -+ struct regcache *regcache = get_thread_arch_regcache (ptid, gdbarch); - const struct regset *regset; - int core_regset_p; - struct cleanup *old_chain; -@@ -3640,6 +3646,119 @@ linux_nat_corefile_thread_callback (stru - return 0; - } - -+/* Enumerate spufs IDs for process PID. */ -+ -+static void -+iterate_over_spus (int pid, void (*callback) (void *, int), void *data) -+{ -+ char path[128]; -+ DIR *dir; -+ struct dirent *entry; -+ -+ xsnprintf (path, sizeof path, "/proc/%d/fd", pid); -+ dir = opendir (path); -+ if (!dir) -+ return; -+ -+ rewinddir (dir); -+ while ((entry = readdir (dir)) != NULL) -+ { -+ struct stat st; -+ struct statfs stfs; -+ int fd; -+ -+ fd = atoi (entry->d_name); -+ if (!fd) -+ continue; -+ -+ xsnprintf (path, sizeof path, "/proc/%d/fd/%d", pid, fd); -+ if (stat (path, &st) != 0) -+ continue; -+ if (!S_ISDIR (st.st_mode)) -+ continue; -+ -+ if (statfs (path, &stfs) != 0) -+ continue; -+ if (stfs.f_type != SPUFS_MAGIC) -+ continue; -+ -+ callback (data, fd); -+ } -+ -+ closedir (dir); -+} -+ -+/* Generate corefile notes for SPU contexts. */ -+ -+struct linux_spu_corefile_data -+{ -+ bfd *obfd; -+ char *note_data; -+ int *note_size; -+}; -+ -+static void -+linux_spu_corefile_callback (void *data, int fd) -+{ -+ struct linux_spu_corefile_data *args = data; -+ int i; -+ -+ static const char *spu_files[] = -+ { -+ "object-id", -+ "mem", -+ "regs", -+ "fpcr", -+ "lslr", -+ "decr", -+ "decr_status", -+ "signal1", -+ "signal1_type", -+ "signal2", -+ "signal2_type", -+ "event_mask", -+ "event_status", -+ "mbox_info", -+ "ibox_info", -+ "wbox_info", -+ "dma_info", -+ "proxydma_info", -+ }; -+ -+ for (i = 0; i < sizeof (spu_files) / sizeof (spu_files[0]); i++) -+ { -+ char annex[32], note_name[32]; -+ gdb_byte *spu_data; -+ LONGEST spu_len; -+ -+ xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[i]); -+ spu_len = target_read_alloc (¤t_target, TARGET_OBJECT_SPU, -+ annex, &spu_data); -+ if (spu_len > 0) -+ { -+ xsnprintf (note_name, sizeof note_name, "SPU/%s", annex); -+ args->note_data = elfcore_write_note (args->obfd, args->note_data, -+ args->note_size, note_name, -+ NT_SPU, spu_data, spu_len); -+ xfree (spu_data); -+ } -+ } -+} -+ -+static char * -+linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size) -+{ -+ struct linux_spu_corefile_data args; -+ args.obfd = obfd; -+ args.note_data = note_data; -+ args.note_size = note_size; -+ -+ iterate_over_spus (PIDGET (inferior_ptid), -+ linux_spu_corefile_callback, &args); -+ -+ return args.note_data; -+} -+ - /* Fills the "to_make_corefile_note" target vector. Builds the note - section for a corefile, and returns it in a malloc buffer. */ - -@@ -3700,6 +3819,8 @@ linux_nat_make_corefile_notes (bfd *obfd - xfree (auxv); - } - -+ note_data = linux_spu_make_corefile_notes (obfd, note_data, note_size); -+ - make_cleanup (xfree, note_data); - return note_data; - } -@@ -4031,6 +4152,99 @@ linux_proc_xfer_partial (struct target_o - return ret; - } - -+ -+/* Enumerate spufs IDs for process PID. */ -+static LONGEST -+spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, LONGEST len) -+{ -+ LONGEST pos = 0; -+ LONGEST written = 0; -+ char path[128]; -+ DIR *dir; -+ struct dirent *entry; -+ -+ xsnprintf (path, sizeof path, "/proc/%d/fd", pid); -+ dir = opendir (path); -+ if (!dir) -+ return -1; -+ -+ rewinddir (dir); -+ while ((entry = readdir (dir)) != NULL) -+ { -+ struct stat st; -+ struct statfs stfs; -+ int fd; -+ -+ fd = atoi (entry->d_name); -+ if (!fd) -+ continue; -+ -+ xsnprintf (path, sizeof path, "/proc/%d/fd/%d", pid, fd); -+ if (stat (path, &st) != 0) -+ continue; -+ if (!S_ISDIR (st.st_mode)) -+ continue; -+ -+ if (statfs (path, &stfs) != 0) -+ continue; -+ if (stfs.f_type != SPUFS_MAGIC) -+ continue; -+ -+ if (pos >= offset && pos + 4 <= offset + len) -+ { -+ store_unsigned_integer (buf + pos - offset, 4, fd); -+ written += 4; -+ } -+ pos += 4; -+ } -+ -+ closedir (dir); -+ return written; -+} -+ -+/* Implement the to_xfer_partial interface for the TARGET_OBJECT_SPU -+ object type, using the /proc file system. */ -+static LONGEST -+linux_proc_xfer_spu (struct target_ops *ops, enum target_object object, -+ const char *annex, gdb_byte *readbuf, -+ const gdb_byte *writebuf, -+ ULONGEST offset, LONGEST len) -+{ -+ char buf[128]; -+ int fd = 0; -+ int ret = -1; -+ int pid = PIDGET (inferior_ptid); -+ -+ if (!annex) -+ { -+ if (!readbuf) -+ return -1; -+ else -+ return spu_enumerate_spu_ids (pid, readbuf, offset, len); -+ } -+ -+ xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex); -+ fd = open (buf, writebuf? O_WRONLY : O_RDONLY); -+ if (fd <= 0) -+ return -1; -+ -+ if (offset != 0 -+ && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) -+ { -+ close (fd); -+ return 0; -+ } -+ -+ if (writebuf) -+ ret = write (fd, writebuf, (size_t) len); -+ else if (readbuf) -+ ret = read (fd, readbuf, (size_t) len); -+ -+ close (fd); -+ return ret; -+} -+ -+ - /* Parse LINE as a signal set and add its set bits to SIGS. */ - - static void -@@ -4236,6 +4450,10 @@ linux_xfer_partial (struct target_ops *o - return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf, - offset, len); - -+ if (object == TARGET_OBJECT_SPU) -+ return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf, -+ offset, len); -+ - xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf, - offset, len); - if (xfer != 0) ---- gdb/m32c-tdep.c -+++ gdb/m32c-tdep.c -@@ -2401,7 +2401,8 @@ m32c_skip_trampoline_code (struct frame_ - programmer! :) */ - - static void --m32c_m16c_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr) -+m32c_m16c_address_to_pointer (struct gdbarch *gdbarch, -+ struct type *type, gdb_byte *buf, CORE_ADDR addr) - { - enum type_code target_code; - gdb_assert (TYPE_CODE (type) == TYPE_CODE_PTR || -@@ -2449,7 +2450,8 @@ m32c_m16c_address_to_pointer (struct typ - - - static CORE_ADDR --m32c_m16c_pointer_to_address (struct type *type, const gdb_byte *buf) -+m32c_m16c_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, const gdb_byte *buf) - { - CORE_ADDR ptr; - enum type_code target_code; ---- gdb/objfiles.c -+++ gdb/objfiles.c -@@ -672,7 +672,7 @@ objfile_relocate (struct objfile *objfil - } - - /* Relocate breakpoints as necessary, after things are relocated. */ -- breakpoint_re_set (); -+ breakpoint_relocate (objfile, delta); - } - - /* Many places in gdb want to test just to see if we have any partial ---- gdb/ppc-linux-nat.c -+++ gdb/ppc-linux-nat.c -@@ -60,6 +60,9 @@ - If they aren't, we can provide them ourselves (their values are fixed - because they are part of the kernel ABI). They are used in the AT_HWCAP - entry of the AUXV. */ -+#ifndef PPC_FEATURE_CELL -+#define PPC_FEATURE_CELL 0x00010000 -+#endif - #ifndef PPC_FEATURE_BOOKE - #define PPC_FEATURE_BOOKE 0x00008000 - #endif -@@ -1238,12 +1241,58 @@ fill_fpregset (const struct regcache *re - fpregsetp, sizeof (*fpregsetp)); - } - -+static int -+ppc_linux_target_wordsize (void) -+{ -+ int wordsize = 4; -+ -+ /* Check for 64-bit inferior process. This is the case when the host is -+ 64-bit, and in addition the top bit of the MSR register is set. */ -+#ifdef __powerpc64__ -+ long msr; -+ -+ int tid = TIDGET (inferior_ptid); -+ if (tid == 0) -+ tid = PIDGET (inferior_ptid); -+ -+ errno = 0; -+ msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0); -+ if (errno == 0 && msr < 0) -+ wordsize = 8; -+#endif -+ -+ return wordsize; -+} -+ -+static int -+ppc_linux_auxv_parse (struct target_ops *ops, gdb_byte **readptr, -+ gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) -+{ -+ int sizeof_auxv_field = ppc_linux_target_wordsize (); -+ gdb_byte *ptr = *readptr; -+ -+ if (endptr == ptr) -+ return 0; -+ -+ if (endptr - ptr < sizeof_auxv_field * 2) -+ return -1; -+ -+ *typep = extract_unsigned_integer (ptr, sizeof_auxv_field); -+ ptr += sizeof_auxv_field; -+ *valp = extract_unsigned_integer (ptr, sizeof_auxv_field); -+ ptr += sizeof_auxv_field; -+ -+ *readptr = ptr; -+ return 1; -+} -+ - static const struct target_desc * - ppc_linux_read_description (struct target_ops *ops) - { - int altivec = 0; - int vsx = 0; - int isa205 = 0; -+ int cell = 0; - - int tid = TIDGET (inferior_ptid); - if (tid == 0) -@@ -1291,26 +1340,24 @@ ppc_linux_read_description (struct targe - if (ppc_linux_get_hwcap () & PPC_FEATURE_ARCH_2_05) - isa205 = 1; - -- /* Check for 64-bit inferior process. This is the case when the host is -- 64-bit, and in addition the top bit of the MSR register is set. */ --#ifdef __powerpc64__ -- { -- long msr; -- errno = 0; -- msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0); -- if (errno == 0 && msr < 0) -- { -- if (vsx) -- return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l; -- else if (altivec) -- return isa205? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l; -+ if (ppc_linux_get_hwcap () & PPC_FEATURE_CELL) -+ cell = 1; - -- return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l; -- } -- } --#endif -+ if (ppc_linux_target_wordsize () == 8) -+ { -+ if (cell) -+ return tdesc_powerpc_cell64l; -+ else if (vsx) -+ return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l; -+ else if (altivec) -+ return isa205? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l; -+ -+ return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l; -+ } - -- if (vsx) -+ if (cell) -+ return tdesc_powerpc_cell32l; -+ else if (vsx) - return isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l; - else if (altivec) - return isa205? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l; -@@ -1342,6 +1389,7 @@ _initialize_ppc_linux_nat (void) - t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range; - - t->to_read_description = ppc_linux_read_description; -+ t->to_auxv_parse = ppc_linux_auxv_parse; - - /* Register the target. */ - linux_nat_add_target (t); ---- gdb/ppc-linux-tdep.c -+++ gdb/ppc-linux-tdep.c -@@ -38,12 +38,20 @@ - #include "trad-frame.h" - #include "frame-unwind.h" - #include "tramp-frame.h" -+#include "observer.h" -+#include "auxv.h" -+#include "elf/common.h" -+#include "exceptions.h" -+#include "arch-utils.h" -+#include "spu-tdep.h" - - #include "features/rs6000/powerpc-32l.c" - #include "features/rs6000/powerpc-altivec32l.c" -+#include "features/rs6000/powerpc-cell32l.c" - #include "features/rs6000/powerpc-vsx32l.c" - #include "features/rs6000/powerpc-isa205-32l.c" - #include "features/rs6000/powerpc-isa205-altivec32l.c" -+#include "features/rs6000/powerpc-cell64l.c" - #include "features/rs6000/powerpc-isa205-vsx32l.c" - #include "features/rs6000/powerpc-64l.c" - #include "features/rs6000/powerpc-altivec64l.c" -@@ -995,6 +1003,46 @@ static struct tramp_frame ppc64_linux_si - }; - - -+/* Address to use for displaced stepping. When debugging a stand-alone -+ SPU executable, entry_point_address () will point to an SPU local-store -+ address and is thus not usable as displaced stepping location. We use -+ the auxiliary vector to determine the PowerPC-side entry point address -+ instead. */ -+ -+static CORE_ADDR ppc_linux_entry_point_addr = 0; -+ -+static void -+ppc_linux_inferior_created (struct target_ops *target, int from_tty) -+{ -+ ppc_linux_entry_point_addr = 0; -+} -+ -+static CORE_ADDR -+ppc_linux_displaced_step_location (struct gdbarch *gdbarch) -+{ -+ if (ppc_linux_entry_point_addr == 0) -+ { -+ CORE_ADDR addr; -+ -+ /* Determine entry point from target auxiliary vector. */ -+ if (target_auxv_search (¤t_target, AT_ENTRY, &addr) <= 0) -+ error (_("Cannot find AT_ENTRY auxiliary vector entry.")); -+ -+ /* Make certain that the address points at real code, and not a -+ function descriptor. */ -+ addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, -+ ¤t_target); -+ -+ /* Inferior calls also use the entry point as a breakpoint location. -+ We don't want displaced stepping to interfere with those -+ breakpoints, so leave space. */ -+ ppc_linux_entry_point_addr = addr + 2 * PPC_INSN_SIZE; -+ } -+ -+ return ppc_linux_entry_point_addr; -+} -+ -+ - /* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable. */ - int - ppc_linux_trap_reg_p (struct gdbarch *gdbarch) -@@ -1028,11 +1076,18 @@ ppc_linux_write_pc (struct regcache *reg - regcache_cooked_write_unsigned (regcache, PPC_TRAP_REGNUM, -1); - } - -+static int -+ppc_linux_spu_section (bfd *abfd, asection *asect, void *user_data) -+{ -+ return strncmp (bfd_section_name (abfd, asect), "SPU/", 4) == 0; -+} -+ - static const struct target_desc * - ppc_linux_core_read_description (struct gdbarch *gdbarch, - struct target_ops *target, - bfd *abfd) - { -+ asection *cell = bfd_sections_find_if (abfd, ppc_linux_spu_section, NULL); - asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx"); - asection *vsx = bfd_get_section_by_name (abfd, ".reg-ppc-vsx"); - asection *section = bfd_get_section_by_name (abfd, ".reg"); -@@ -1042,7 +1097,9 @@ ppc_linux_core_read_description (struct - switch (bfd_section_size (abfd, section)) - { - case 48 * 4: -- if (vsx) -+ if (cell) -+ return tdesc_powerpc_cell32l; -+ else if (vsx) - return tdesc_powerpc_vsx32l; - else if (altivec) - return tdesc_powerpc_altivec32l; -@@ -1050,7 +1107,9 @@ ppc_linux_core_read_description (struct - return tdesc_powerpc_32l; - - case 48 * 8: -- if (vsx) -+ if (cell) -+ return tdesc_powerpc_cell64l; -+ else if (vsx) - return tdesc_powerpc_vsx64l; - else if (altivec) - return tdesc_powerpc_altivec64l; -@@ -1062,6 +1121,258 @@ ppc_linux_core_read_description (struct - } - } - -+ -+/* Cell/B.E. active SPE context tracking support. */ -+ -+static CORE_ADDR spe_context_lm_addr = 0; -+static CORE_ADDR spe_context_offset = 0; -+ -+static ptid_t spe_context_cache_ptid; -+static CORE_ADDR spe_context_cache_address; -+ -+/* Callback for new objfiles. We check whether we've loaded a version -+ of libspe2 that provides the __spe_current_active_context variable. */ -+static void -+ppc_linux_new_objfile (struct objfile *objfile) -+{ -+ struct minimal_symbol *sym; -+ -+ if (!objfile) -+ { -+ spe_context_lm_addr = 0; -+ spe_context_offset = 0; -+ spe_context_cache_ptid = minus_one_ptid; -+ spe_context_cache_address = 0; -+ return; -+ } -+ -+ sym = lookup_minimal_symbol ("__spe_current_active_context", NULL, objfile); -+ if (sym) -+ { -+ spe_context_lm_addr = svr4_fetch_objfile_link_map (objfile); -+ spe_context_offset = SYMBOL_VALUE_ADDRESS (sym); -+ spe_context_cache_ptid = minus_one_ptid; -+ spe_context_cache_address = 0; -+ return; -+ } -+} -+ -+/* Retrieve contents of the N'th element in the current thread's -+ linked SPE context list into ID and NPC. Return the address of -+ said context element, or 0 if not found. */ -+static CORE_ADDR -+ppc_linux_spe_context (int wordsize, int n, int *id, unsigned int *npc) -+{ -+ CORE_ADDR spe_context = 0; -+ gdb_byte buf[16]; -+ int i; -+ -+ /* Quick exit if we have not found __spe_current_active_context. */ -+ if (!spe_context_lm_addr) -+ return 0; -+ -+ /* Look up cached address of thread-local variable. */ -+ if (!ptid_equal (spe_context_cache_ptid, inferior_ptid)) -+ { -+ volatile struct gdb_exception ex; -+ struct target_ops *target; -+ -+ for (target = current_target.beneath; -+ target != NULL; -+ target = target->beneath) -+ { -+ if (target->to_get_thread_local_address != NULL) -+ break; -+ } -+ -+ if (target == NULL) -+ return 0; -+ -+ TRY_CATCH (ex, RETURN_MASK_ERROR) -+ { -+ spe_context_cache_address -+ = target->to_get_thread_local_address -+ (target, inferior_ptid, spe_context_lm_addr, spe_context_offset); -+ -+ spe_context_cache_ptid = inferior_ptid; -+ } -+ -+ if (ex.reason < 0) -+ return 0; -+ } -+ -+ /* Read variable value. */ -+ if (target_read_memory (spe_context_cache_address, buf, wordsize) == 0) -+ spe_context = extract_unsigned_integer (buf, wordsize); -+ -+ /* Cyle through to N'th linked list element. */ -+ for (i = 0; i < n && spe_context; i++) -+ if (target_read_memory (spe_context + align_up (12, wordsize), -+ buf, wordsize) == 0) -+ spe_context = extract_unsigned_integer (buf, wordsize); -+ else -+ spe_context = 0; -+ -+ /* Read current context. */ -+ if (spe_context -+ && target_read_memory (spe_context, buf, 12) != 0) -+ spe_context = 0; -+ -+ /* Extract data elements. */ -+ if (spe_context) -+ { -+ if (id) -+ *id = extract_signed_integer (buf, 4); -+ if (npc) -+ *npc = extract_unsigned_integer (buf + 4, 4); -+ } -+ -+ return spe_context; -+} -+ -+ -+/* Cell/B.E. cross-architecture unwinder support. */ -+ -+struct ppu2spu_cache -+{ -+ struct frame_id frame_id; -+ struct regcache *regcache; -+}; -+ -+static struct gdbarch * -+ppu2spu_prev_arch (struct frame_info *this_frame, void **this_cache) -+{ -+ struct ppu2spu_cache *cache = *this_cache; -+ return get_regcache_arch (cache->regcache); -+} -+ -+static void -+ppu2spu_this_id (struct frame_info *this_frame, -+ void **this_cache, struct frame_id *this_id) -+{ -+ struct ppu2spu_cache *cache = *this_cache; -+ *this_id = cache->frame_id; -+} -+ -+static struct value * -+ppu2spu_prev_register (struct frame_info *this_frame, -+ void **this_cache, int regnum) -+{ -+ struct ppu2spu_cache *cache = *this_cache; -+ struct gdbarch *gdbarch = get_regcache_arch (cache->regcache); -+ gdb_byte *buf; -+ -+ buf = alloca (register_size (gdbarch, regnum)); -+ regcache_cooked_read (cache->regcache, regnum, buf); -+ return frame_unwind_got_bytes (this_frame, regnum, buf); -+} -+ -+struct ppu2spu_data -+{ -+ int id; -+ unsigned int npc; -+ gdb_byte gprs[128*16]; -+}; -+ -+static int -+ppu2spu_unwind_register (void *src, int regnum, gdb_byte *buf) -+{ -+ struct ppu2spu_data *data = src; -+ -+ if (regnum >= 0 && regnum < SPU_NUM_GPRS) -+ memcpy (buf, data->gprs + 16*regnum, 16); -+ else if (regnum == SPU_ID_REGNUM) -+ store_unsigned_integer (buf, 4, data->id); -+ else if (regnum == SPU_PC_REGNUM) -+ store_unsigned_integer (buf, 4, data->npc); -+ else -+ return 0; -+ -+ return 1; -+} -+ -+static int -+ppu2spu_sniffer (const struct frame_unwind *self, -+ struct frame_info *this_frame, void **this_prologue_cache) -+{ -+ struct gdbarch *gdbarch = get_frame_arch (this_frame); -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); -+ struct ppu2spu_data data; -+ struct frame_info *fi; -+ CORE_ADDR base, func, backchain, spe_context; -+ gdb_byte buf[8]; -+ int n = 0; -+ -+ /* Count the number of SPU contexts already in the frame chain. */ -+ for (fi = get_next_frame (this_frame); fi; fi = get_next_frame (fi)) -+ if (get_frame_type (fi) == ARCH_FRAME -+ && gdbarch_bfd_arch_info (get_frame_arch (fi))->arch == bfd_arch_spu) -+ n++; -+ -+ base = get_frame_sp (this_frame); -+ func = get_frame_pc (this_frame); -+ if (target_read_memory (base, buf, tdep->wordsize)) -+ return 0; -+ backchain = extract_unsigned_integer (buf, tdep->wordsize); -+ -+ spe_context = ppc_linux_spe_context (tdep->wordsize, n, &data.id, &data.npc); -+ if (spe_context && base <= spe_context && spe_context < backchain) -+ { -+ struct gdbarch *spu_gdbarch; -+ char annex[32]; -+ -+ /* Find gdbarch for SPU. */ -+ struct gdbarch_info info; -+ gdbarch_info_init (&info); -+ info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu); -+ info.byte_order = BFD_ENDIAN_BIG; -+ info.osabi = GDB_OSABI_LINUX; -+ info.tdep_info = (void *) &data.id; -+ spu_gdbarch = gdbarch_find_by_info (info); -+ if (!spu_gdbarch) -+ return 0; -+ -+ xsnprintf (annex, sizeof annex, "%d/regs", data.id); -+ if (target_read (¤t_target, TARGET_OBJECT_SPU, annex, -+ data.gprs, 0, sizeof data.gprs) -+ == sizeof data.gprs) -+ { -+ struct ppu2spu_cache *cache -+ = FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache); -+ -+ struct regcache *regcache = regcache_xmalloc (spu_gdbarch); -+ struct cleanup *cleanups = make_cleanup_regcache_xfree (regcache); -+ regcache_save (regcache, ppu2spu_unwind_register, &data); -+ discard_cleanups (cleanups); -+ -+ cache->frame_id = frame_id_build (base, func); -+ cache->regcache = regcache; -+ *this_prologue_cache = cache; -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+static void -+ppu2spu_dealloc_cache (struct frame_info *self, void *this_cache) -+{ -+ struct ppu2spu_cache *cache = this_cache; -+ regcache_xfree (cache->regcache); -+} -+ -+static const struct frame_unwind ppu2spu_unwind = { -+ ARCH_FRAME, -+ ppu2spu_this_id, -+ ppu2spu_prev_register, -+ NULL, -+ ppu2spu_sniffer, -+ ppu2spu_dealloc_cache, -+ ppu2spu_prev_arch, -+}; -+ -+ - static void - ppc_linux_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -@@ -1102,6 +1413,12 @@ ppc_linux_init_abi (struct gdbarch_info - /* Trampolines. */ - tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sigaction_tramp_frame); - tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sighandler_tramp_frame); -+ -+ /* BFD target for core files. */ -+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE) -+ set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpcle"); -+ else -+ set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc"); - } - - if (tdep->wordsize == 8) -@@ -1119,6 +1436,12 @@ ppc_linux_init_abi (struct gdbarch_info - /* Trampolines. */ - tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sigaction_tramp_frame); - tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame); -+ -+ /* BFD target for core files. */ -+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE) -+ set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpcle"); -+ else -+ set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); - } - set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section); - set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description); -@@ -1158,6 +1481,22 @@ ppc_linux_init_abi (struct gdbarch_info - PPC_TRAP_REGNUM, "trap"); - } - } -+ -+ /* Enable Cell/B.E. if supported by the target. */ -+ if (tdesc_compatible_p (info.target_desc, -+ bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu))) -+ { -+ /* Cell/B.E. multi-architecture support. */ -+ set_spu_solib_ops (gdbarch); -+ -+ /* Cell/B.E. cross-architecture unwinder support. */ -+ frame_unwind_prepend_unwinder (gdbarch, &ppu2spu_unwind); -+ -+ /* The default displaced_step_at_entry_point doesn't work for -+ SPU stand-alone executables. */ -+ set_gdbarch_displaced_step_location (gdbarch, -+ ppc_linux_displaced_step_location); -+ } - } - - void -@@ -1172,15 +1511,23 @@ _initialize_ppc_linux_tdep (void) - gdbarch_register_osabi (bfd_arch_rs6000, bfd_mach_rs6k, GDB_OSABI_LINUX, - ppc_linux_init_abi); - -+ /* Attach to inferior_created observer. */ -+ observer_attach_inferior_created (ppc_linux_inferior_created); -+ -+ /* Add ourselves to objfile event chain. */ -+ observer_attach_new_objfile (ppc_linux_new_objfile); -+ - /* Initialize the Linux target descriptions. */ - initialize_tdesc_powerpc_32l (); - initialize_tdesc_powerpc_altivec32l (); -+ initialize_tdesc_powerpc_cell32l (); - initialize_tdesc_powerpc_vsx32l (); - initialize_tdesc_powerpc_isa205_32l (); - initialize_tdesc_powerpc_isa205_altivec32l (); - initialize_tdesc_powerpc_isa205_vsx32l (); - initialize_tdesc_powerpc_64l (); - initialize_tdesc_powerpc_altivec64l (); -+ initialize_tdesc_powerpc_cell64l (); - initialize_tdesc_powerpc_vsx64l (); - initialize_tdesc_powerpc_isa205_64l (); - initialize_tdesc_powerpc_isa205_altivec64l (); ---- gdb/ppc-linux-tdep.h -+++ gdb/ppc-linux-tdep.h -@@ -41,6 +41,7 @@ int ppc_linux_trap_reg_p (struct gdbarch - /* Linux target descriptions. */ - extern struct target_desc *tdesc_powerpc_32l; - extern struct target_desc *tdesc_powerpc_altivec32l; -+extern struct target_desc *tdesc_powerpc_cell32l; - extern struct target_desc *tdesc_powerpc_vsx32l; - extern struct target_desc *tdesc_powerpc_isa205_32l; - extern struct target_desc *tdesc_powerpc_isa205_altivec32l; -@@ -48,6 +49,7 @@ extern struct target_desc *tdesc_powerpc - extern struct target_desc *tdesc_powerpc_e500l; - extern struct target_desc *tdesc_powerpc_64l; - extern struct target_desc *tdesc_powerpc_altivec64l; -+extern struct target_desc *tdesc_powerpc_cell64l; - extern struct target_desc *tdesc_powerpc_vsx64l; - extern struct target_desc *tdesc_powerpc_isa205_64l; - extern struct target_desc *tdesc_powerpc_isa205_altivec64l; ---- gdb/printcmd.c -+++ gdb/printcmd.c -@@ -388,7 +388,7 @@ print_scalar_formatted (const void *vala - /* If we are printing it as unsigned, truncate it in case it is actually - a negative signed value (e.g. "print/u (short)-1" should print 65535 - (if shorts are 16 bits) instead of 4294967295). */ -- if (options->format != 'd') -+ if (options->format != 'd' || TYPE_UNSIGNED (type)) - { - if (len < sizeof (LONGEST)) - val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1; ---- gdb/proc-service.c -+++ gdb/proc-service.c -@@ -258,7 +258,7 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwp - struct regcache *regcache; - - inferior_ptid = BUILD_LWP (lwpid, ph->pid); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - target_fetch_registers (regcache, -1); - fill_gregset (regcache, (gdb_gregset_t *) gregset, -1); -@@ -277,7 +277,7 @@ ps_lsetregs (gdb_ps_prochandle_t ph, lwp - struct regcache *regcache; - - inferior_ptid = BUILD_LWP (lwpid, ph->pid); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - supply_gregset (regcache, (const gdb_gregset_t *) gregset); - target_store_registers (regcache, -1); -@@ -297,7 +297,7 @@ ps_lgetfpregs (gdb_ps_prochandle_t ph, l - struct regcache *regcache; - - inferior_ptid = BUILD_LWP (lwpid, ph->pid); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - target_fetch_registers (regcache, -1); - fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1); -@@ -317,7 +317,7 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, l - struct regcache *regcache; - - inferior_ptid = BUILD_LWP (lwpid, ph->pid); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset); - target_store_registers (regcache, -1); ---- gdb/regcache.c -+++ gdb/regcache.c -@@ -29,6 +29,7 @@ - #include "gdb_string.h" - #include "gdbcmd.h" /* For maintenanceprintlist. */ - #include "observer.h" -+#include "arch-utils.h" - - /* - * DATA STRUCTURE -@@ -410,36 +411,60 @@ regcache_invalidate (struct regcache *re - - - /* Global structure containing the current regcache. */ --/* FIXME: cagney/2002-05-11: The two global arrays registers[] and -- deprecated_register_valid[] currently point into this structure. */ --static struct regcache *current_regcache; - - /* NOTE: this is a write-through cache. There is no "dirty" bit for - recording if the register values have been changed (eg. by the - user). Therefore all registers must be written back to the - target when appropriate. */ - --struct regcache *get_thread_regcache (ptid_t ptid) -+struct regcache_list - { -- /* NOTE: uweigand/2007-05-05: We need to detect the thread's -- current architecture at this point. */ -- struct gdbarch *thread_gdbarch = current_gdbarch; -+ struct regcache *regcache; -+ struct regcache_list *next; -+}; -+ -+static struct regcache_list *current_regcache; -+ -+struct regcache * -+get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch) -+{ -+ struct regcache_list *list; -+ struct regcache *new_regcache; - -- if (current_regcache && ptid_equal (current_regcache->ptid, ptid) -- && get_regcache_arch (current_regcache) == thread_gdbarch) -- return current_regcache; -+ for (list = current_regcache; list; list = list->next) -+ if (ptid_equal (list->regcache->ptid, ptid) -+ && get_regcache_arch (list->regcache) == gdbarch) -+ return list->regcache; - -- if (current_regcache) -- regcache_xfree (current_regcache); -+ new_regcache = regcache_xmalloc (gdbarch); -+ new_regcache->readonly_p = 0; -+ new_regcache->ptid = ptid; - -- current_regcache = regcache_xmalloc (thread_gdbarch); -- current_regcache->readonly_p = 0; -- current_regcache->ptid = ptid; -+ list = xmalloc (sizeof (struct regcache_list)); -+ list->regcache = new_regcache; -+ list->next = current_regcache; -+ current_regcache = list; - -- return current_regcache; -+ return new_regcache; - } - --struct regcache *get_current_regcache (void) -+static ptid_t current_thread_ptid; -+static struct gdbarch *current_thread_arch; -+ -+struct regcache * -+get_thread_regcache (ptid_t ptid) -+{ -+ if (!current_thread_arch || !ptid_equal (current_thread_ptid, ptid)) -+ { -+ current_thread_ptid = ptid; -+ current_thread_arch = target_thread_architecture (ptid); -+ } -+ -+ return get_thread_arch_regcache (ptid, current_thread_arch); -+} -+ -+struct regcache * -+get_current_regcache (void) - { - return get_thread_regcache (inferior_ptid); - } -@@ -458,9 +483,11 @@ regcache_observer_target_changed (struct - static void - regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) - { -- if (current_regcache != NULL -- && ptid_equal (current_regcache->ptid, old_ptid)) -- current_regcache->ptid = new_ptid; -+ struct regcache_list *list; -+ -+ for (list = current_regcache; list; list = list->next) -+ if (ptid_equal (list->regcache->ptid, old_ptid)) -+ list->regcache->ptid = new_ptid; - } - - /* Low level examining and depositing of registers. -@@ -477,11 +504,20 @@ regcache_thread_ptid_changed (ptid_t old - void - registers_changed (void) - { -- int i; -+ struct regcache_list *list, *next; -+ -+ for (list = current_regcache; list; list = next) -+ { -+ next = list->next; -+ regcache_xfree (list->regcache); -+ xfree (list); -+ } - -- regcache_xfree (current_regcache); - current_regcache = NULL; - -+ current_thread_ptid = null_ptid; -+ current_thread_arch = NULL; -+ - /* Need to forget about any frames we have cached, too. */ - reinit_frame_cache (); - -@@ -509,6 +545,8 @@ regcache_raw_read (struct regcache *regc - { - struct cleanup *old_chain = save_inferior_ptid (); - inferior_ptid = regcache->ptid; -+ save_current_gdbarch (); -+ current_gdbarch = get_regcache_arch (regcache); - target_fetch_registers (regcache, regnum); - do_cleanups (old_chain); - } -@@ -667,6 +705,8 @@ regcache_raw_write (struct regcache *reg - - old_chain = save_inferior_ptid (); - inferior_ptid = regcache->ptid; -+ save_current_gdbarch (); -+ current_gdbarch = get_regcache_arch (regcache); - - target_prepare_to_store (regcache); - memcpy (register_buffer (regcache, regnum), buf, ---- gdb/regcache.h -+++ gdb/regcache.h -@@ -26,6 +26,7 @@ struct gdbarch; - - extern struct regcache *get_current_regcache (void); - extern struct regcache *get_thread_regcache (ptid_t ptid); -+extern struct regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *); - - void regcache_xfree (struct regcache *regcache); - struct cleanup *make_cleanup_regcache_xfree (struct regcache *regcache); ---- gdb/regformats/rs6000/powerpc-cell32l.dat -+++ gdb/regformats/rs6000/powerpc-cell32l.dat -@@ -0,0 +1,111 @@ -+# DO NOT EDIT: generated from rs6000/powerpc-cell32l.xml -+name:powerpc_cell32l -+xmltarget:powerpc-cell32l.xml -+expedite:r1,pc,r0,orig_r3,r4 -+32:r0 -+32:r1 -+32:r2 -+32:r3 -+32:r4 -+32:r5 -+32:r6 -+32:r7 -+32:r8 -+32:r9 -+32:r10 -+32:r11 -+32:r12 -+32:r13 -+32:r14 -+32:r15 -+32:r16 -+32:r17 -+32:r18 -+32:r19 -+32:r20 -+32:r21 -+32:r22 -+32:r23 -+32:r24 -+32:r25 -+32:r26 -+32:r27 -+32:r28 -+32:r29 -+32:r30 -+32:r31 -+64:f0 -+64:f1 -+64:f2 -+64:f3 -+64:f4 -+64:f5 -+64:f6 -+64:f7 -+64:f8 -+64:f9 -+64:f10 -+64:f11 -+64:f12 -+64:f13 -+64:f14 -+64:f15 -+64:f16 -+64:f17 -+64:f18 -+64:f19 -+64:f20 -+64:f21 -+64:f22 -+64:f23 -+64:f24 -+64:f25 -+64:f26 -+64:f27 -+64:f28 -+64:f29 -+64:f30 -+64:f31 -+32:pc -+32:msr -+32:cr -+32:lr -+32:ctr -+32:xer -+32:fpscr -+32:orig_r3 -+32:trap -+128:vr0 -+128:vr1 -+128:vr2 -+128:vr3 -+128:vr4 -+128:vr5 -+128:vr6 -+128:vr7 -+128:vr8 -+128:vr9 -+128:vr10 -+128:vr11 -+128:vr12 -+128:vr13 -+128:vr14 -+128:vr15 -+128:vr16 -+128:vr17 -+128:vr18 -+128:vr19 -+128:vr20 -+128:vr21 -+128:vr22 -+128:vr23 -+128:vr24 -+128:vr25 -+128:vr26 -+128:vr27 -+128:vr28 -+128:vr29 -+128:vr30 -+128:vr31 -+32:vscr -+32:vrsave ---- gdb/regformats/rs6000/powerpc-cell64l.dat -+++ gdb/regformats/rs6000/powerpc-cell64l.dat -@@ -0,0 +1,111 @@ -+# DO NOT EDIT: generated from rs6000/powerpc-cell64l.xml -+name:powerpc_cell64l -+xmltarget:powerpc-cell64l.xml -+expedite:r1,pc,r0,orig_r3,r4 -+64:r0 -+64:r1 -+64:r2 -+64:r3 -+64:r4 -+64:r5 -+64:r6 -+64:r7 -+64:r8 -+64:r9 -+64:r10 -+64:r11 -+64:r12 -+64:r13 -+64:r14 -+64:r15 -+64:r16 -+64:r17 -+64:r18 -+64:r19 -+64:r20 -+64:r21 -+64:r22 -+64:r23 -+64:r24 -+64:r25 -+64:r26 -+64:r27 -+64:r28 -+64:r29 -+64:r30 -+64:r31 -+64:f0 -+64:f1 -+64:f2 -+64:f3 -+64:f4 -+64:f5 -+64:f6 -+64:f7 -+64:f8 -+64:f9 -+64:f10 -+64:f11 -+64:f12 -+64:f13 -+64:f14 -+64:f15 -+64:f16 -+64:f17 -+64:f18 -+64:f19 -+64:f20 -+64:f21 -+64:f22 -+64:f23 -+64:f24 -+64:f25 -+64:f26 -+64:f27 -+64:f28 -+64:f29 -+64:f30 -+64:f31 -+64:pc -+64:msr -+32:cr -+64:lr -+64:ctr -+32:xer -+32:fpscr -+64:orig_r3 -+64:trap -+128:vr0 -+128:vr1 -+128:vr2 -+128:vr3 -+128:vr4 -+128:vr5 -+128:vr6 -+128:vr7 -+128:vr8 -+128:vr9 -+128:vr10 -+128:vr11 -+128:vr12 -+128:vr13 -+128:vr14 -+128:vr15 -+128:vr16 -+128:vr17 -+128:vr18 -+128:vr19 -+128:vr20 -+128:vr21 -+128:vr22 -+128:vr23 -+128:vr24 -+128:vr25 -+128:vr26 -+128:vr27 -+128:vr28 -+128:vr29 -+128:vr30 -+128:vr31 -+32:vscr -+32:vrsave ---- gdb/remote.c -+++ gdb/remote.c -@@ -4526,7 +4526,7 @@ process_stop_reply (struct stop_reply *s - for (ix = 0; - VEC_iterate(cached_reg_t, stop_reply->regcache, ix, reg); - ix++) -- regcache_raw_supply (get_thread_regcache (ptid), -+ regcache_raw_supply (get_thread_arch_regcache (ptid, target_gdbarch), - reg->num, reg->data); - VEC_free (cached_reg_t, stop_reply->regcache); - } -@@ -6785,7 +6785,7 @@ remote_insert_breakpoint (struct bp_targ - switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_Z0])) - { - case PACKET_ERROR: -- return -1; -+ return 1; - case PACKET_OK: - bp_tgt->placed_address = addr; - bp_tgt->placed_size = bpsize; -@@ -6972,7 +6972,7 @@ remote_insert_hw_breakpoint (struct bp_t - (target_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size); - - if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE) -- return -1; -+ return 1; - - rs = get_remote_state (); - p = rs->buf; -@@ -6992,7 +6992,7 @@ remote_insert_hw_breakpoint (struct bp_t - { - case PACKET_ERROR: - case PACKET_UNKNOWN: -- return -1; -+ return 1; - case PACKET_OK: - return 0; - } -@@ -7009,7 +7009,7 @@ remote_remove_hw_breakpoint (struct bp_t - char *p = rs->buf; - - if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE) -- return -1; -+ return 1; - - *(p++) = 'z'; - *(p++) = '1'; -@@ -7026,7 +7026,7 @@ remote_remove_hw_breakpoint (struct bp_t - { - case PACKET_ERROR: - case PACKET_UNKNOWN: -- return -1; -+ return 1; - case PACKET_OK: - return 0; - } ---- gdb/rs6000-tdep.c -+++ gdb/rs6000-tdep.c -@@ -3338,6 +3338,16 @@ rs6000_gdbarch_init (struct gdbarch_info - int num_pseudoregs = 0; - int cur_reg; - -+ /* INFO may refer to a binary that is not of the PowerPC architecture, -+ e.g. when debugging a stand-alone SPE executable on a Cell/B.E. system. -+ In this case, we must not attempt to infer properties of the (PowerPC -+ side) of the target system from properties of that executable. Trust -+ the target description instead. */ -+ if (info.abfd -+ && bfd_get_arch (info.abfd) != bfd_arch_powerpc -+ && bfd_get_arch (info.abfd) != bfd_arch_rs6000) -+ info.abfd = NULL; -+ - from_xcoff_exec = info.abfd && info.abfd->format == bfd_object && - bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour; - ---- gdb/sentinel-frame.c -+++ gdb/sentinel-frame.c -@@ -76,11 +76,23 @@ sentinel_frame_this_id (struct frame_inf - internal_error (__FILE__, __LINE__, _("sentinel_frame_this_id called")); - } - -+static struct gdbarch * -+sentinel_frame_prev_arch (struct frame_info *this_frame, -+ void **this_prologue_cache) -+{ -+ struct frame_unwind_cache *cache = *this_prologue_cache; -+ return get_regcache_arch (cache->regcache); -+} -+ - const struct frame_unwind sentinel_frame_unwinder = - { - SENTINEL_FRAME, - sentinel_frame_this_id, -- sentinel_frame_prev_register -+ sentinel_frame_prev_register, -+ NULL, -+ NULL, -+ NULL, -+ sentinel_frame_prev_arch, - }; - - const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder; ---- gdb/sol-thread.c -+++ gdb/sol-thread.c -@@ -1094,7 +1094,7 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwp - old_chain = save_inferior_ptid (); - - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - if (target_has_execution) - procfs_ops.to_fetch_registers (regcache, -1); -@@ -1119,7 +1119,7 @@ ps_lsetregs (gdb_ps_prochandle_t ph, lwp - old_chain = save_inferior_ptid (); - - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - supply_gregset (regcache, (const gdb_gregset_t *) gregset); - if (target_has_execution) -@@ -1230,7 +1230,7 @@ ps_lgetfpregs (gdb_ps_prochandle_t ph, l - old_chain = save_inferior_ptid (); - - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - if (target_has_execution) - procfs_ops.to_fetch_registers (regcache, -1); -@@ -1255,7 +1255,7 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, l - old_chain = save_inferior_ptid (); - - inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); -- regcache = get_thread_regcache (inferior_ptid); -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); - - supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset); - if (target_has_execution) ---- gdb/solib-spu.c -+++ gdb/solib-spu.c -@@ -0,0 +1,482 @@ -+/* Cell SPU GNU/Linux support -- shared library handling. -+ Copyright (C) 2008 Free Software Foundation, Inc. -+ -+ Contributed by Ulrich Weigand . -+ -+ 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. */ -+ -+#include "defs.h" -+#include "gdbcore.h" -+#include "gdb_string.h" -+#include "gdb_assert.h" -+#include "gdb_stat.h" -+#include "arch-utils.h" -+#include "bfd.h" -+#include "symtab.h" -+#include "solib.h" -+#include "solib-svr4.h" -+#include "solist.h" -+#include "inferior.h" -+#include "objfiles.h" -+#include "observer.h" -+ -+#include "spu-tdep.h" -+ -+/* Highest SPE id (file handle) the inferior may have. */ -+#define MAX_SPE_FD 1024 -+ -+/* Stand-alone SPE executable? */ -+#define spu_standalone_p() \ -+ (symfile_objfile && symfile_objfile->obfd \ -+ && bfd_get_arch (symfile_objfile->obfd) == bfd_arch_spu) -+ -+ -+/* Relocate main SPE executable. */ -+static void spu_relocate_main_executable (int spufs_fd) -+{ -+ struct objfile *objfile; -+ struct cleanup *old_chain; -+ struct section_offsets *new_offsets; -+ int i; -+ -+ for (objfile = symfile_objfile; -+ objfile; -+ objfile = objfile->separate_debug_objfile) -+ { -+ new_offsets = xcalloc (objfile->num_sections, -+ sizeof (struct section_offsets)); -+ old_chain = make_cleanup (xfree, new_offsets); -+ -+ for (i = 0; i < objfile->num_sections; i++) -+ new_offsets->offsets[i] = SPUADDR (spufs_fd, 0); -+ -+ objfile_relocate (objfile, new_offsets); -+ do_cleanups (old_chain); -+ } -+} -+ -+/* When running a stand-alone SPE executable, we need to skip one more -+ exec event on startup, to get past the binfmt_misc loader. */ -+static void -+spu_skip_standalone_loader (void) -+{ -+ if (target_has_execution) -+ { -+ struct cleanup *old_chain; -+ struct inferior *inferior = current_inferior (); -+ -+ /* Suppress MI messages that are unexpected at this point. */ -+ old_chain = make_cleanup_restore_integer (&suppress_resume_observer); -+ suppress_resume_observer = 1; -+ make_cleanup_restore_integer (&suppress_stop_observer); -+ suppress_stop_observer = 1; -+ -+ /* Only some kernels report an extra SIGTRAP with the binfmt_misc -+ loader; others do not. In addition, if we have attached to an -+ already running inferior instead of starting a new one, we will -+ not see the extra SIGTRAP -- and we cannot readily distinguish -+ the two cases, in particular with the extended-remote target. -+ -+ Thus we issue a single-step here. If no extra SIGTRAP was pending, -+ this will step past the first instruction of the stand-alone SPE -+ executable loader, but we don't care about that. */ -+ -+ inferior->stop_soon = STOP_QUIETLY; -+ resume (1, TARGET_SIGNAL_0); -+ wait_for_inferior (1); -+ inferior->stop_soon = NO_STOP_QUIETLY; -+ -+ do_cleanups (old_chain); -+ } -+} -+ -+/* Build a list of `struct so_list' objects describing the shared -+ objects currently loaded in the inferior. */ -+static struct so_list * -+spu_current_sos (void) -+{ -+ struct so_list *head; -+ struct so_list **link_ptr; -+ -+ char buf[MAX_SPE_FD * 4]; -+ int i, size; -+ -+ /* First, retrieve the SVR4 shared library list. Switch to the -+ PPE architecture while doing so. This should not be strictly -+ necessary, but it is right now. */ -+ struct cleanup *old_chain = save_current_gdbarch (); -+ current_gdbarch = target_gdbarch; -+ head = svr4_so_ops.current_sos (); -+ do_cleanups (old_chain); -+ -+ /* Append our libraries to the end of the list. */ -+ for (link_ptr = &head; *link_ptr; link_ptr = &(*link_ptr)->next) -+ ; -+ -+ /* Determine list of SPU ids. */ -+ size = target_read (¤t_target, TARGET_OBJECT_SPU, NULL, -+ buf, 0, sizeof buf); -+ -+ /* Do not add stand-alone SPE executable context as shared library, -+ but relocate main SPE executable objfile. */ -+ if (spu_standalone_p ()) -+ { -+ if (size == 4) -+ spu_relocate_main_executable (extract_unsigned_integer (buf, 4)); -+ -+ return head; -+ } -+ -+ /* As soon as any SPE context exists in the inferior, we have to -+ enable SPU multi-architecture target support. */ -+ if (size > 0) -+ spu_multiarch_enable (); -+ else -+ spu_multiarch_disable (); -+ -+ /* Create an so_list entry for each SPU id. */ -+ for (i = 0; i < size; i += 4) -+ { -+ int fd = extract_unsigned_integer (buf + i, 4); -+ struct so_list *new; -+ -+ unsigned long long addr; -+ char annex[32], id[100]; -+ int len; -+ -+ /* Read object ID. There's a race window where the inferior may have -+ already created the SPE context, but not installed the object-id -+ yet. Skip such entries; we'll be back for them later. */ -+ xsnprintf (annex, sizeof annex, "%d/object-id", fd); -+ len = target_read (¤t_target, TARGET_OBJECT_SPU, annex, -+ id, 0, sizeof id); -+ if (len <= 0 || len >= sizeof id) -+ continue; -+ id[len] = 0; -+ if (sscanf (id, "0x%llx", &addr) != 1 || !addr) -+ continue; -+ -+ /* Allocate so_list structure. */ -+ new = XZALLOC (struct so_list); -+ -+ /* Encode FD and object ID in path name. Choose the name so as not -+ to conflict with any (normal) SVR4 library path name. */ -+ xsnprintf (new->so_name, sizeof new->so_name, "@0x%llx <%d>", addr, fd); -+ strcpy (new->so_original_name, new->so_name); -+ -+ *link_ptr = new; -+ link_ptr = &new->next; -+ } -+ -+ return head; -+} -+ -+/* Free so_list information. */ -+static void -+spu_free_so (struct so_list *so) -+{ -+ if (so->so_original_name[0] != '@') -+ svr4_so_ops.free_so (so); -+} -+ -+/* Relocate section addresses. */ -+static void -+spu_relocate_section_addresses (struct so_list *so, -+ struct section_table *sec) -+{ -+ if (so->so_original_name[0] != '@') -+ svr4_so_ops.relocate_section_addresses (so, sec); -+ else -+ { -+ unsigned long long addr; -+ int fd; -+ -+ /* Set addr_low/high to just LS offset for display. */ -+ if (so->addr_low == 0 && so->addr_high == 0 -+ && strcmp (sec->the_bfd_section->name, ".text") == 0) -+ { -+ so->addr_low = sec->addr; -+ so->addr_high = sec->endaddr; -+ } -+ -+ /* Decode object ID. */ -+ if (sscanf (so->so_original_name, "@0x%llx <%d>", &addr, &fd) != 2) -+ internal_error (__FILE__, __LINE__, "bad object ID"); -+ -+ sec->addr = SPUADDR (fd, sec->addr); -+ sec->endaddr = SPUADDR (fd, sec->endaddr); -+ } -+} -+ -+ -+/* Inferior memory should contain an SPE executable image at location ADDR. -+ Allocate a BFD representing that executable. Return NULL on error. */ -+ -+static void * -+spu_bfd_iovec_open (bfd *nbfd, void *open_closure) -+{ -+ return open_closure; -+} -+ -+static int -+spu_bfd_iovec_close (bfd *nbfd, void *stream) -+{ -+ xfree (stream); -+ return 1; -+} -+ -+static file_ptr -+spu_bfd_iovec_pread (bfd *abfd, void *stream, void *buf, -+ file_ptr nbytes, file_ptr offset) -+{ -+ CORE_ADDR addr = *(CORE_ADDR *)stream; -+ int ret; -+ -+ /* Switch to the PPE architecture while reading target memory. -+ This should not be necessary, but it is right now. */ -+ struct cleanup *old_chain = save_current_gdbarch (); -+ current_gdbarch = target_gdbarch; -+ ret = target_read_memory (addr + offset, buf, nbytes); -+ do_cleanups (old_chain); -+ -+ if (ret != 0) -+ { -+ bfd_set_error (bfd_error_invalid_operation); -+ return -1; -+ } -+ -+ return nbytes; -+} -+ -+static int -+spu_bfd_iovec_stat (bfd *abfd, void *stream, struct stat *sb) -+{ -+ /* We don't have an easy way of finding the size of embedded spu -+ images. We could parse the in-memory ELF header and section -+ table to find the extent of the last section but that seems -+ pointless when the size is needed only for checks of other -+ parsed values in dbxread.c. */ -+ sb->st_size = INT_MAX; -+ return 0; -+} -+ -+static bfd * -+spu_bfd_open (char *name, CORE_ADDR addr) -+{ -+ bfd *nbfd; -+ -+ CORE_ADDR *open_closure = xmalloc (sizeof (CORE_ADDR)); -+ *open_closure = addr; -+ -+ nbfd = bfd_openr_iovec (xstrdup (name), "elf32-spu", -+ spu_bfd_iovec_open, open_closure, -+ spu_bfd_iovec_pread, spu_bfd_iovec_close, -+ spu_bfd_iovec_stat); -+ if (!nbfd) -+ return NULL; -+ -+ if (!bfd_check_format (nbfd, bfd_object)) -+ { -+ bfd_close (nbfd); -+ return NULL; -+ } -+ -+ return nbfd; -+} -+ -+/* Open shared library BFD. */ -+static bfd * -+spu_open_bfd (char *pathname) -+{ -+ char *original_name = strrchr (pathname, '@'); -+ char name[64]; -+ bfd *abfd; -+ asection *spu_name; -+ unsigned long long addr; -+ int fd; -+ -+ if (!original_name) -+ return NULL; -+ -+ /* Decode object ID. */ -+ if (sscanf (original_name, "@0x%llx <%d>", &addr, &fd) != 2) -+ internal_error (__FILE__, __LINE__, "bad object ID"); -+ -+ /* Open BFD representing SPE executable. */ -+ abfd = spu_bfd_open (original_name, (CORE_ADDR) addr); -+ if (!abfd) -+ error (_("Cannot read SPE executable at %s"), original_name); -+ -+ /* Retrieve SPU name note. */ -+ spu_name = bfd_get_section_by_name (abfd, ".note.spu_name"); -+ if (spu_name) -+ { -+ int sect_size = bfd_section_size (abfd, spu_name); -+ if (sect_size > 20) -+ { -+ char *buf = alloca (sect_size - 20 + strlen (original_name) + 1); -+ bfd_get_section_contents (abfd, spu_name, buf, 20, sect_size - 20); -+ buf[sect_size - 20] = '\0'; -+ -+ strcat (buf, original_name); -+ -+ xfree ((char *)abfd->filename); -+ abfd->filename = xstrdup (buf); -+ } -+ } -+ -+ return abfd; -+} -+ -+/* Lookup global symbol in a SPE executable. */ -+static struct symbol * -+spu_lookup_lib_symbol (const struct objfile *objfile, -+ const char *name, -+ const char *linkage_name, -+ const domain_enum domain) -+{ -+ if (bfd_get_arch (objfile->obfd) == bfd_arch_spu) -+ return lookup_global_symbol_from_objfile (objfile, name, linkage_name, -+ domain); -+ -+ if (svr4_so_ops.lookup_lib_global_symbol != NULL) -+ return svr4_so_ops.lookup_lib_global_symbol (objfile, name, linkage_name, -+ domain); -+ return NULL; -+} -+ -+/* Enable shared library breakpoint. */ -+static int -+spu_enable_break (struct objfile *objfile) -+{ -+ struct minimal_symbol *spe_event_sym = NULL; -+ -+ /* The libspe library will call __spe_context_update_event whenever any -+ SPE context is allocated or destroyed. */ -+ spe_event_sym = lookup_minimal_symbol ("__spe_context_update_event", -+ NULL, objfile); -+ -+ /* Place a solib_event breakpoint on the symbol. */ -+ if (spe_event_sym) -+ { -+ CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (spe_event_sym); -+ addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, addr, -+ ¤t_target); -+ create_solib_event_breakpoint (addr); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* Create inferior hook. */ -+static void -+spu_solib_create_inferior_hook (void) -+{ -+ /* Remove all previously installed solib breakpoints. Both the SVR4 -+ code and us will re-install all required breakpoints. */ -+ remove_solib_event_breakpoints (); -+ -+ /* Handle SPE stand-alone executables. */ -+ if (spu_standalone_p ()) -+ { -+ /* After an SPE stand-alone executable was loaded, we'll receive -+ an additional trap due to the binfmt_misc handler. Make sure -+ to skip that trap. */ -+ spu_skip_standalone_loader (); -+ -+ /* At this point, the target is executing, so GDB expects to be -+ able to read/write target memory. For the stand-alone case, -+ "target memory" is actually the local store of the stand-alone -+ SPE context -- but at this point this context has not yet been -+ allocated. This is a problem in particular for breakpoints that -+ may already have been established. -+ -+ We solve this by installing the multi-architecture handler -+ already at this point. This target will understand that -+ breakpoints falling the range of addresses covered by the -+ SPE local store need to be ignored. -+ -+ (Note that this needs to be done here, before the solib code gets -+ active -- otherwise we'd fail on the first breakpoint_re_set call -+ triggered when new shared libraries are found.) -+ -+ Once the actual stand-alone SPE context is installed, spu_current_sos -+ will detect this and relocate the main executable to its final (valid) -+ address range. Breakpoints will be automatically re-inserted at -+ that point. */ -+ spu_multiarch_enable (); -+ -+ /* A special case arises when re-starting an executable, because at -+ this point it still resides at the relocated address range that was -+ determined during its last execution. We need to undo the relocation -+ so that that multi-architecture target recognizes the stand-alone -+ initialization special case. */ -+ spu_relocate_main_executable (-1); -+ } -+ -+ /* Call SVR4 hook -- this will re-insert the SVR4 solib breakpoints. */ -+ svr4_so_ops.solib_create_inferior_hook (); -+ -+ /* If the inferior is statically linked against libspe, we need to install -+ our own solib breakpoint right now. Otherwise, it will be installed by -+ the solib_loaded observer below as soon as libspe is loaded. */ -+ spu_enable_break (NULL); -+} -+ -+/* Install SPE "shared library" handling. This is called by -tdep code -+ that wants to support SPU as a secondary architecture. */ -+void -+set_spu_solib_ops (struct gdbarch *gdbarch) -+{ -+ static struct target_so_ops spu_so_ops; -+ -+ /* Initialize this lazily, to avoid an initialization order -+ dependency on solib-svr4.c's _initialize routine. */ -+ if (spu_so_ops.current_sos == NULL) -+ { -+ spu_so_ops = svr4_so_ops; -+ spu_so_ops.solib_create_inferior_hook = spu_solib_create_inferior_hook; -+ spu_so_ops.relocate_section_addresses = spu_relocate_section_addresses; -+ spu_so_ops.free_so = spu_free_so; -+ spu_so_ops.current_sos = spu_current_sos; -+ spu_so_ops.open_bfd = spu_open_bfd; -+ spu_so_ops.lookup_lib_global_symbol = spu_lookup_lib_symbol; -+ } -+ -+ set_solib_ops (gdbarch, &spu_so_ops); -+} -+ -+/* Observer for the solib_loaded event. Used to install our breakpoint -+ if libspe is a shared library. */ -+static void -+spu_solib_loaded (struct so_list *so) -+{ -+ if (strstr (so->so_original_name, "/libspe") != NULL) -+ { -+ solib_read_symbols (so, so->from_tty); -+ spu_enable_break (so->objfile); -+ } -+} -+ -+void -+_initialize_spu_solib (void) -+{ -+ observer_attach_solib_loaded (spu_solib_loaded); -+} -+ ---- gdb/solib.c -+++ gdb/solib.c -@@ -345,15 +345,22 @@ static int - solib_map_sections (void *arg) - { - struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */ -+ struct target_so_ops *ops = solib_ops (target_gdbarch); - char *filename; - struct section_table *p; - struct cleanup *old_chain; -- bfd *abfd; -+ bfd *abfd = NULL; -+ -+ if (ops->open_bfd) -+ abfd = ops->open_bfd (so->so_name); - -- filename = tilde_expand (so->so_name); -- old_chain = make_cleanup (xfree, filename); -- abfd = solib_bfd_open (filename); -- do_cleanups (old_chain); -+ if (!abfd) -+ { -+ filename = tilde_expand (so->so_name); -+ old_chain = make_cleanup (xfree, filename); -+ abfd = solib_bfd_open (filename); -+ do_cleanups (old_chain); -+ } - - /* Leave bfd open, core_xfer_memory and "info files" need it. */ - so->abfd = abfd; -@@ -372,8 +379,6 @@ solib_map_sections (void *arg) - - for (p = so->sections; p < so->sections_end; p++) - { -- struct target_so_ops *ops = solib_ops (target_gdbarch); -- - /* Relocate the section binding addresses as recorded in the shared - object's file by the base address to which the object was actually - mapped. */ -@@ -454,7 +459,9 @@ static int - symbol_add_stub (void *arg) - { - struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */ -+ struct target_so_ops *ops = solib_ops (target_gdbarch); - struct section_addr_info *sap; -+ bfd *abfd = NULL; - - /* Have we already loaded this shared object? */ - ALL_OBJFILES (so->objfile) ---- gdb/solist.h -+++ gdb/solist.h -@@ -123,6 +123,10 @@ struct target_so_ops - Falls back to using strcmp on so_original_name field when set - to NULL. */ - int (*same) (struct so_list *gdb, struct so_list *inferior); -+ -+ /* Extra hook for opening a BFD for a solib. Can be used to -+ retrieve solibs from inferior memory instead of from files. */ -+ bfd *(*open_bfd) (char *pathname); - }; - - /* Free the memory associated with a (so_list *). */ ---- gdb/spu-multiarch.c -+++ gdb/spu-multiarch.c -@@ -0,0 +1,462 @@ -+/* Cell SPU GNU/Linux multi-architecture debugging support. -+ Copyright (C) 2008 Free Software Foundation, Inc. -+ -+ Contributed by Ulrich Weigand . -+ -+ 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. */ -+ -+#include "defs.h" -+#include "gdbcore.h" -+#include "gdbcmd.h" -+#include "gdb_string.h" -+#include "gdb_assert.h" -+#include "arch-utils.h" -+#include "observer.h" -+#include "inferior.h" -+#include "regcache.h" -+#include "symfile.h" -+#include "objfiles.h" -+#include "block.h" -+#include "exec.h" -+#include "target-descriptions.h" -+ -+#include "ppc-tdep.h" -+#include "ppc-linux-tdep.h" -+#include "spu-tdep.h" -+ -+/* This module's target vector. */ -+static struct target_ops spu_ops; -+ -+/* Stand-alone SPE executable? */ -+#define spu_standalone_p() \ -+ (symfile_objfile && symfile_objfile->obfd \ -+ && bfd_get_arch (symfile_objfile->obfd) == bfd_arch_spu) -+ -+/* PPU side system calls. */ -+#define INSTR_SC 0x44000002 -+#define NR_spu_run 0x0116 -+ -+/* If the PPU thread is currently stopped on a spu_run system call, -+ return to FD and ADDR the file handle and NPC parameter address -+ used with the system call. Return non-zero if successful. */ -+static int -+parse_spufs_run (ptid_t ptid, int *fd, CORE_ADDR *addr) -+{ -+ struct gdbarch_tdep *tdep; -+ struct regcache *regcache; -+ char buf[4]; -+ CORE_ADDR pc; -+ ULONGEST regval; -+ -+ /* If we're not on PPU, there's nothing to detect. */ -+ if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_powerpc) -+ return 0; -+ -+ /* Get PPU-side registers. */ -+ regcache = get_thread_arch_regcache (ptid, target_gdbarch); -+ tdep = gdbarch_tdep (target_gdbarch); -+ -+ /* Fetch instruction preceding current NIP. */ -+ if (target_read_memory (regcache_read_pc (regcache) - 4, buf, 4) != 0) -+ return 0; -+ /* It should be a "sc" instruction. */ -+ if (extract_unsigned_integer (buf, 4) != INSTR_SC) -+ return 0; -+ /* System call number should be NR_spu_run. */ -+ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum, ®val); -+ if (regval != NR_spu_run) -+ return 0; -+ -+ /* Register 3 contains fd, register 4 the NPC param pointer. */ -+ regcache_cooked_read_unsigned (regcache, PPC_ORIG_R3_REGNUM, ®val); -+ *fd = (int) regval; -+ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 4, ®val); -+ *addr = (CORE_ADDR) regval; -+ return 1; -+} -+ -+/* Find gdbarch for SPU context SPUFS_FD. */ -+static struct gdbarch * -+spu_gdbarch (int spufs_fd) -+{ -+ struct gdbarch_info info; -+ gdbarch_info_init (&info); -+ info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu); -+ info.byte_order = BFD_ENDIAN_BIG; -+ info.osabi = GDB_OSABI_LINUX; -+ info.tdep_info = (void *) &spufs_fd; -+ return gdbarch_find_by_info (info); -+} -+ -+/* Override the to_thread_architecture routine. */ -+static struct gdbarch * -+spu_thread_architecture (struct target_ops *ops, ptid_t ptid) -+{ -+ int spufs_fd; -+ CORE_ADDR spufs_addr; -+ -+ if (parse_spufs_run (ptid, &spufs_fd, &spufs_addr)) -+ return spu_gdbarch (spufs_fd); -+ -+ return target_gdbarch; -+} -+ -+/* Override the to_wait routine to detect current architecture. */ -+static ptid_t -+spu_wait (struct target_ops *ops, ptid_t ptid, -+ struct target_waitstatus *ourstatus) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (ops); -+ -+ /* Always switch to PPU while running the inferior. This allows -+ linux-thread-db.c code to work as expected. */ -+ current_gdbarch = target_gdbarch; -+ -+ /* Run it. */ -+ ptid = ops_beneath->to_wait (ops_beneath, ptid, ourstatus); -+ -+ /* Detect and switch to current architecture. */ -+ if (ourstatus->kind == TARGET_WAITKIND_STOPPED) -+ current_gdbarch = spu_thread_architecture (¤t_target, ptid); -+ -+ return ptid; -+} -+ -+ -+/* Override the to_region_ok_for_hw_watchpoint routine. */ -+static int -+spu_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops); -+ -+ while (ops_beneath && !ops_beneath->to_region_ok_for_hw_watchpoint) -+ ops_beneath = find_target_beneath (ops_beneath); -+ gdb_assert (ops_beneath); -+ -+ /* Ignore attempts to remove breakpoints in a stand-alone SPE -+ executable just after startup, before we know the FD. */ -+ if (spu_standalone_p () && addr < SPU_LS_SIZE) -+ return -1; -+ -+ /* We cannot watch SPU local store. */ -+ if (SPUADDR_SPU (addr) != -1) -+ return 0; -+ -+ if (ops_beneath) -+ return ops_beneath->to_region_ok_for_hw_watchpoint (addr, len); -+ -+ return 0; -+} -+ -+/* Override the to_insert_breakpoint routine. */ -+static int -+spu_insert_breakpoint (struct bp_target_info *bp) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops); -+ CORE_ADDR addr = bp->placed_address; -+ struct cleanup *old_chain; -+ int ret; -+ -+ while (ops_beneath && !ops_beneath->to_insert_breakpoint) -+ ops_beneath = find_target_beneath (ops_beneath); -+ gdb_assert (ops_beneath); -+ -+ /* Ignore attempts to insert breakpoints in a stand-alone SPE -+ executable just after startup, before we know the FD. */ -+ if (spu_standalone_p () && addr < SPU_LS_SIZE) -+ return -1; -+ -+ old_chain = save_current_gdbarch (); -+ if (SPUADDR_SPU (addr) != -1) -+ current_gdbarch = spu_gdbarch (SPUADDR_SPU (addr)); -+ else -+ current_gdbarch = target_gdbarch; -+ ret = ops_beneath->to_insert_breakpoint (bp); -+ do_cleanups (old_chain); -+ -+ /* Ignore failure to insert breakpoints in a stand-alone SPE -+ executable just before exit, when the FD is already gone. */ -+ if (spu_standalone_p () && ret > 0) -+ ret = -1; -+ -+ return ret; -+} -+ -+/* Override the to_remove_breakpoint routine. */ -+static int -+spu_remove_breakpoint (struct bp_target_info *bp) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops); -+ CORE_ADDR addr = bp->placed_address; -+ struct cleanup *old_chain; -+ int ret; -+ -+ while (ops_beneath && !ops_beneath->to_remove_breakpoint) -+ ops_beneath = find_target_beneath (ops_beneath); -+ gdb_assert (ops_beneath); -+ -+ /* Ignore attempts to remove breakpoints in a stand-alone SPE -+ executable just after startup, before we know the FD. */ -+ if (spu_standalone_p () && addr < SPU_LS_SIZE) -+ return -1; -+ -+ old_chain = save_current_gdbarch (); -+ if (SPUADDR_SPU (addr) != -1) -+ current_gdbarch = spu_gdbarch (SPUADDR_SPU (addr)); -+ else -+ current_gdbarch = target_gdbarch; -+ ret = ops_beneath->to_remove_breakpoint (bp); -+ do_cleanups (old_chain); -+ -+ /* Ignore failure to remove breakpoints in a stand-alone SPE -+ executable just before exit, when the FD is already gone. */ -+ if (spu_standalone_p () && ret > 0) -+ ret = -1; -+ -+ return ret; -+} -+ -+ -+/* Override the to_fetch_registers routine. */ -+static void -+spu_fetch_registers (struct regcache *regcache, int regno) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops); -+ int spufs_fd; -+ CORE_ADDR spufs_addr; -+ -+ /* This version applies only if we're currently in spu_run. */ -+ if (gdbarch_bfd_arch_info (get_regcache_arch (regcache))->arch -+ != bfd_arch_spu) -+ { -+ while (ops_beneath && !ops_beneath->to_fetch_registers) -+ ops_beneath = find_target_beneath (ops_beneath); -+ -+ gdb_assert (ops_beneath); -+ ops_beneath->to_fetch_registers (regcache, regno); -+ return; -+ } -+ -+ /* We must be stopped on a spu_run system call. */ -+ if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr)) -+ return; -+ -+ /* The ID register holds the spufs file handle. */ -+ if (regno == -1 || regno == SPU_ID_REGNUM) -+ { -+ char buf[4]; -+ store_unsigned_integer (buf, 4, spufs_fd); -+ regcache_raw_supply (regcache, SPU_ID_REGNUM, buf); -+ } -+ -+ /* The NPC register is found in PPC memory at SPUFS_ADDR. */ -+ if (regno == -1 || regno == SPU_PC_REGNUM) -+ { -+ struct cleanup *old_chain; -+ LONGEST ret; -+ char buf[4]; -+ -+ /* Switch to PPC arch while accessing target memory. */ -+ old_chain = save_current_gdbarch (); -+ current_gdbarch = target_gdbarch; -+ ret = target_read (ops_beneath, TARGET_OBJECT_MEMORY, NULL, -+ buf, spufs_addr, sizeof buf); -+ do_cleanups (old_chain); -+ -+ if (ret == sizeof buf) -+ regcache_raw_supply (regcache, SPU_PC_REGNUM, buf); -+ } -+ -+ /* The GPRs are found in the "regs" spufs file. */ -+ if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS)) -+ { -+ char buf[16 * SPU_NUM_GPRS], annex[32]; -+ int i; -+ -+ xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd); -+ if (target_read (ops_beneath, TARGET_OBJECT_SPU, annex, -+ buf, 0, sizeof buf) == sizeof buf) -+ for (i = 0; i < SPU_NUM_GPRS; i++) -+ regcache_raw_supply (regcache, i, buf + i*16); -+ } -+} -+ -+/* Override the to_store_registers routine. */ -+static void -+spu_store_registers (struct regcache *regcache, int regno) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops); -+ int spufs_fd; -+ CORE_ADDR spufs_addr; -+ -+ /* This version applies only if we're currently in spu_run. */ -+ if (gdbarch_bfd_arch_info (get_regcache_arch (regcache))->arch -+ != bfd_arch_spu) -+ { -+ while (ops_beneath && !ops_beneath->to_fetch_registers) -+ ops_beneath = find_target_beneath (ops_beneath); -+ -+ gdb_assert (ops_beneath); -+ ops_beneath->to_store_registers (regcache, regno); -+ return; -+ } -+ -+ /* We must be stopped on a spu_run system call. */ -+ if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr)) -+ return; -+ -+ /* The NPC register is found in PPC memory at SPUFS_ADDR. */ -+ if (regno == -1 || regno == SPU_PC_REGNUM) -+ { -+ struct cleanup *old_chain; -+ char buf[4]; -+ regcache_raw_collect (regcache, SPU_PC_REGNUM, buf); -+ -+ /* Switch to PPC arch while accessing target memory. */ -+ old_chain = save_current_gdbarch (); -+ current_gdbarch = target_gdbarch; -+ target_write (ops_beneath, TARGET_OBJECT_MEMORY, NULL, -+ buf, spufs_addr, sizeof buf); -+ do_cleanups (old_chain); -+ } -+ -+ /* The GPRs are found in the "regs" spufs file. */ -+ if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS)) -+ { -+ char buf[16 * SPU_NUM_GPRS], annex[32]; -+ int i; -+ -+ for (i = 0; i < SPU_NUM_GPRS; i++) -+ regcache_raw_collect (regcache, i, buf + i*16); -+ -+ xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd); -+ target_write (ops_beneath, TARGET_OBJECT_SPU, annex, -+ buf, 0, sizeof buf); -+ } -+} -+ -+/* Override the to_xfer_partial routine. */ -+static LONGEST -+spu_xfer_partial (struct target_ops *ops, enum target_object object, -+ const char *annex, gdb_byte *readbuf, -+ const gdb_byte *writebuf, ULONGEST offset, LONGEST len) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (ops); -+ -+ /* Use the "mem" spufs file to access SPU local store. */ -+ if (object == TARGET_OBJECT_MEMORY) -+ { -+ int fd = SPUADDR_SPU (offset); -+ CORE_ADDR addr = SPUADDR_ADDR (offset); -+ char mem_annex[32]; -+ -+ if (fd >= 0 && addr < SPU_LS_SIZE) -+ { -+ xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd); -+ return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU, -+ mem_annex, readbuf, writebuf, -+ addr, len); -+ } -+ } -+ -+ return ops_beneath->to_xfer_partial (ops_beneath, object, annex, -+ readbuf, writebuf, offset, len); -+} -+ -+/* Override the to_search_memory routine. */ -+static int -+spu_search_memory (struct target_ops* ops, -+ CORE_ADDR start_addr, ULONGEST search_space_len, -+ const gdb_byte *pattern, ULONGEST pattern_len, -+ CORE_ADDR *found_addrp) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (ops); -+ while (ops_beneath && !ops_beneath->to_search_memory) -+ ops_beneath = find_target_beneath (ops_beneath); -+ -+ /* For SPU local store, always fall back to the simple method. Likewise -+ if we do not have any target-specific special implementation. */ -+ if (!ops_beneath || SPUADDR_SPU (start_addr) >= 0) -+ return simple_search_memory (ops, -+ start_addr, search_space_len, -+ pattern, pattern_len, found_addrp); -+ -+ return ops_beneath->to_search_memory (ops_beneath, -+ start_addr, search_space_len, -+ pattern, pattern_len, found_addrp); -+} -+ -+ -+/* Push and pop the SPU multi-architecture support target. */ -+ -+void -+spu_multiarch_enable (void) -+{ -+ /* If GDB was configured without SPU architecture support, -+ we cannot install SPU multi-architecture support either. */ -+ if (spu_gdbarch (-1) == NULL) -+ return; -+ -+ push_target (&spu_ops); -+} -+ -+void -+spu_multiarch_disable (void) -+{ -+ unpush_target (&spu_ops); -+} -+ -+static void -+spu_mourn_inferior (struct target_ops *ops) -+{ -+ struct target_ops *ops_beneath = find_target_beneath (ops); -+ ops_beneath->to_mourn_inferior (ops_beneath); -+ spu_multiarch_disable (); -+} -+ -+ -+/* Initialize the SPU multi-architecture support target. */ -+ -+static void -+init_spu_ops (void) -+{ -+ spu_ops.to_shortname = "spu"; -+ spu_ops.to_longname = "SPU multi-architecture support."; -+ spu_ops.to_doc = "SPU multi-architecture support."; -+ spu_ops.to_mourn_inferior = spu_mourn_inferior; -+ spu_ops.to_fetch_registers = spu_fetch_registers; -+ spu_ops.to_store_registers = spu_store_registers; -+ spu_ops.to_xfer_partial = spu_xfer_partial; -+ spu_ops.to_search_memory = spu_search_memory; -+ spu_ops.to_insert_breakpoint = spu_insert_breakpoint; -+ spu_ops.to_remove_breakpoint = spu_remove_breakpoint; -+ spu_ops.to_region_ok_for_hw_watchpoint = spu_region_ok_for_hw_watchpoint; -+ spu_ops.to_wait = spu_wait; -+ spu_ops.to_thread_architecture = spu_thread_architecture; -+ spu_ops.to_stratum = arch_stratum; -+ spu_ops.to_magic = OPS_MAGIC; -+} -+ -+void -+_initialize_spu_multiarch (void) -+{ -+ /* Install ourselves on the target stack. */ -+ init_spu_ops (); -+ add_target (&spu_ops); -+} -+ ---- gdb/spu-tdep.c -+++ gdb/spu-tdep.c -@@ -40,14 +40,31 @@ - #include "regcache.h" - #include "reggroups.h" - #include "floatformat.h" -+#include "block.h" - #include "observer.h" -+#include "infcall.h" - - #include "spu-tdep.h" - - -+/* The list of available "set spu " and "show spu " commands. */ -+static struct cmd_list_element *setspucmdlist = NULL; -+static struct cmd_list_element *showspucmdlist = NULL; -+ -+/* Whether to stop for new SPE contexts. */ -+static int spu_stop_on_load_p = 0; -+/* Whether to automatically flush the SW-managed cache. */ -+static int spu_auto_flush_cache_p = 1; -+ -+ - /* The tdep structure. */ - struct gdbarch_tdep - { -+ /* The spufs ID identifying our address space. */ -+ int id; -+ /* The size of this address space. */ -+ CORE_ADDR lslr; -+ - /* SPU-specific vector type. */ - struct type *spu_builtin_type_vec128; - }; -@@ -324,33 +341,87 @@ spu_register_reggroup_p (struct gdbarch - return default_register_reggroup_p (gdbarch, regnum, group); - } - --/* Address conversion. */ -+ -+/* Address handling. */ - - static CORE_ADDR --spu_pointer_to_address (struct type *type, const gdb_byte *buf) -+spu_lslr (int id) - { -+ gdb_byte buf[16]; -+ char annex[32]; -+ -+ xsnprintf (annex, sizeof annex, "%d/lslr", id); -+ memset (buf, 0, sizeof buf); -+ target_read (¤t_target, TARGET_OBJECT_SPU, annex, -+ buf, 0, sizeof buf); -+ -+ return strtoulst (buf, NULL, 16); -+} -+ -+static int -+spu_address_class_type_flags (int byte_size, int dwarf2_addr_class) -+{ -+ if (dwarf2_addr_class == 1) -+ return TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1; -+ else -+ return 0; -+} -+ -+static const char * -+spu_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags) -+{ -+ if (type_flags & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1) -+ return "__ea"; -+ else -+ return NULL; -+} -+ -+static int -+spu_address_class_name_to_type_flags (struct gdbarch *gdbarch, -+ const char *name, int *type_flags_ptr) -+{ -+ if (strcmp (name, "__ea") == 0) -+ { -+ *type_flags_ptr = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1; -+ return 1; -+ } -+ else -+ return 0; -+} -+ -+static void -+spu_address_to_pointer (struct gdbarch *gdbarch, -+ struct type *type, gdb_byte *buf, CORE_ADDR addr) -+{ -+ store_unsigned_integer (buf, TYPE_LENGTH (type), SPUADDR_ADDR (addr)); -+} -+ -+static CORE_ADDR -+spu_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, const gdb_byte *buf) -+{ -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - ULONGEST addr = extract_unsigned_integer (buf, TYPE_LENGTH (type)); -- ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size. */ - -- if (target_has_registers && target_has_stack && target_has_memory) -- lslr = get_frame_register_unsigned (get_selected_frame (NULL), -- SPU_LSLR_REGNUM); -+ /* Do not convert __ea pointers. */ -+ if (TYPE_ADDRESS_CLASS_1 (type)) -+ return addr; - -- return addr & lslr; -+ return addr? SPUADDR (tdep->id, addr & tdep->lslr) : 0; - } - - static CORE_ADDR - spu_integer_to_address (struct gdbarch *gdbarch, - struct type *type, const gdb_byte *buf) - { -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - ULONGEST addr = unpack_long (type, buf); -- ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size. */ - -- if (target_has_registers && target_has_stack && target_has_memory) -- lslr = get_frame_register_unsigned (get_selected_frame (NULL), -- SPU_LSLR_REGNUM); -+ /* Do not convert __ea pointers. */ -+ if (TYPE_ADDRESS_CLASS_1 (type)) -+ return addr; - -- return addr & lslr; -+ return SPUADDR (tdep->id, addr & tdep->lslr); - } - - -@@ -840,8 +911,11 @@ static struct spu_unwind_cache * - spu_frame_unwind_cache (struct frame_info *this_frame, - void **this_prologue_cache) - { -+ struct gdbarch *gdbarch = get_frame_arch (this_frame); -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - struct spu_unwind_cache *info; - struct spu_prologue_data data; -+ CORE_ADDR id = tdep->id; - gdb_byte buf[16]; - - if (*this_prologue_cache) -@@ -874,6 +948,7 @@ spu_frame_unwind_cache (struct frame_inf - /* Determine CFA via unwound CFA_REG plus CFA_OFFSET. */ - get_frame_register (this_frame, data.cfa_reg, buf); - cfa = extract_unsigned_integer (buf, 4) + data.cfa_offset; -+ cfa = SPUADDR (id, cfa); - - /* Call-saved register slots. */ - for (i = 0; i < SPU_NUM_GPRS; i++) -@@ -896,7 +971,7 @@ spu_frame_unwind_cache (struct frame_inf - - /* Get the backchain. */ - reg = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM); -- status = safe_read_memory_integer (reg, 4, &backchain); -+ status = safe_read_memory_integer (SPUADDR (id, reg), 4, &backchain); - - /* A zero backchain terminates the frame chain. Also, sanity - check against the local store size limit. */ -@@ -904,11 +979,11 @@ spu_frame_unwind_cache (struct frame_inf - { - /* Assume the link register is saved into its slot. */ - if (backchain + 16 < SPU_LS_SIZE) -- info->saved_regs[SPU_LR_REGNUM].addr = backchain + 16; -+ info->saved_regs[SPU_LR_REGNUM].addr = SPUADDR (id, backchain + 16); - - /* Frame bases. */ -- info->frame_base = backchain; -- info->local_base = reg; -+ info->frame_base = SPUADDR (id, backchain); -+ info->local_base = SPUADDR (id, reg); - } - } - -@@ -917,7 +992,8 @@ spu_frame_unwind_cache (struct frame_inf - return info; - - /* The previous SP is equal to the CFA. */ -- trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, info->frame_base); -+ trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, -+ SPUADDR_ADDR (info->frame_base)); - - /* Read full contents of the unwound link register in order to - be able to determine the return address. */ -@@ -995,24 +1071,28 @@ static const struct frame_base spu_frame - static CORE_ADDR - spu_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) - { -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, SPU_PC_REGNUM); - /* Mask off interrupt enable bit. */ -- return pc & -4; -+ return SPUADDR (tdep->id, pc & -4); - } - - static CORE_ADDR - spu_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) - { -- return frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM); -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); -+ CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM); -+ return SPUADDR (tdep->id, sp); - } - - static CORE_ADDR - spu_read_pc (struct regcache *regcache) - { -+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache)); - ULONGEST pc; - regcache_cooked_read_unsigned (regcache, SPU_PC_REGNUM, &pc); - /* Mask off interrupt enable bit. */ -- return pc & -4; -+ return SPUADDR (tdep->id, pc & -4); - } - - static void -@@ -1022,9 +1102,111 @@ spu_write_pc (struct regcache *regcache, - ULONGEST old_pc; - regcache_cooked_read_unsigned (regcache, SPU_PC_REGNUM, &old_pc); - regcache_cooked_write_unsigned (regcache, SPU_PC_REGNUM, -- (pc & -4) | (old_pc & 3)); -+ (SPUADDR_ADDR (pc) & -4) | (old_pc & 3)); -+} -+ -+ -+/* Cell/B.E. cross-architecture unwinder support. */ -+ -+struct spu2ppu_cache -+{ -+ struct frame_id frame_id; -+ struct regcache *regcache; -+}; -+ -+static struct gdbarch * -+spu2ppu_prev_arch (struct frame_info *this_frame, void **this_cache) -+{ -+ struct spu2ppu_cache *cache = *this_cache; -+ return get_regcache_arch (cache->regcache); -+} -+ -+static void -+spu2ppu_this_id (struct frame_info *this_frame, -+ void **this_cache, struct frame_id *this_id) -+{ -+ struct spu2ppu_cache *cache = *this_cache; -+ *this_id = cache->frame_id; - } - -+static struct value * -+spu2ppu_prev_register (struct frame_info *this_frame, -+ void **this_cache, int regnum) -+{ -+ struct spu2ppu_cache *cache = *this_cache; -+ struct gdbarch *gdbarch = get_regcache_arch (cache->regcache); -+ gdb_byte *buf; -+ -+ buf = alloca (register_size (gdbarch, regnum)); -+ regcache_cooked_read (cache->regcache, regnum, buf); -+ return frame_unwind_got_bytes (this_frame, regnum, buf); -+} -+ -+static int -+spu2ppu_sniffer (const struct frame_unwind *self, -+ struct frame_info *this_frame, void **this_prologue_cache) -+{ -+ CORE_ADDR base, func, backchain; -+ gdb_byte buf[4]; -+ -+ if (gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_spu) -+ return 0; -+ -+ base = get_frame_sp (this_frame); -+ func = get_frame_pc (this_frame); -+ if (target_read_memory (base, buf, 4)) -+ return 0; -+ backchain = extract_unsigned_integer (buf, 4); -+ -+ if (!backchain) -+ { -+ struct frame_info *fi; -+ -+ struct spu2ppu_cache *cache -+ = FRAME_OBSTACK_CALLOC (1, struct spu2ppu_cache); -+ -+ cache->frame_id = frame_id_build (base + 16, func); -+ -+ for (fi = get_next_frame (this_frame); fi; fi = get_next_frame (fi)) -+ if (gdbarch_bfd_arch_info (get_frame_arch (fi))->arch != bfd_arch_spu) -+ break; -+ -+ if (fi) -+ { -+ cache->regcache = frame_save_as_regcache (fi); -+ *this_prologue_cache = cache; -+ return 1; -+ } -+ else -+ { -+ struct regcache *regcache; -+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch); -+ cache->regcache = regcache_dup (regcache); -+ *this_prologue_cache = cache; -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+static void -+spu2ppu_dealloc_cache (struct frame_info *self, void *this_cache) -+{ -+ struct spu2ppu_cache *cache = this_cache; -+ regcache_xfree (cache->regcache); -+} -+ -+static const struct frame_unwind spu2ppu_unwind = { -+ ARCH_FRAME, -+ spu2ppu_this_id, -+ spu2ppu_prev_register, -+ NULL, -+ spu2ppu_sniffer, -+ spu2ppu_dealloc_cache, -+ spu2ppu_prev_arch, -+}; -+ - - /* Function calling convention. */ - -@@ -1133,7 +1315,7 @@ spu_push_dummy_call (struct gdbarch *gdb - - /* Set the return address. */ - memset (buf, 0, sizeof buf); -- store_unsigned_integer (buf, 4, bp_addr); -+ store_unsigned_integer (buf, 4, SPUADDR_ADDR (bp_addr)); - regcache_cooked_write (regcache, SPU_LR_REGNUM, buf); - - /* If STRUCT_RETURN is true, then the struct return address (in -@@ -1142,7 +1324,7 @@ spu_push_dummy_call (struct gdbarch *gdb - if (struct_return) - { - memset (buf, 0, sizeof buf); -- store_unsigned_integer (buf, 4, struct_addr); -+ store_unsigned_integer (buf, 4, SPUADDR_ADDR (struct_addr)); - regcache_cooked_write (regcache, regnum++, buf); - } - -@@ -1220,9 +1402,10 @@ spu_push_dummy_call (struct gdbarch *gdb - static struct frame_id - spu_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) - { -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - CORE_ADDR pc = get_frame_register_unsigned (this_frame, SPU_PC_REGNUM); - CORE_ADDR sp = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM); -- return frame_id_build (sp, pc & -4); -+ return frame_id_build (SPUADDR (tdep->id, sp), SPUADDR (tdep->id, pc & -4)); - } - - /* Function return value access. */ -@@ -1302,18 +1485,18 @@ spu_software_single_step (struct frame_i - instruction is a PPE-assisted call, in which case it is at PC + 8. - Wrap around LS limit to be on the safe side. */ - if ((insn & 0xffffff00) == 0x00002100) -- next_pc = (pc + 8) & (SPU_LS_SIZE - 1); -+ next_pc = (SPUADDR_ADDR (pc) + 8) & (SPU_LS_SIZE - 1); - else -- next_pc = (pc + 4) & (SPU_LS_SIZE - 1); -+ next_pc = (SPUADDR_ADDR (pc) + 4) & (SPU_LS_SIZE - 1); - -- insert_single_step_breakpoint (next_pc); -+ insert_single_step_breakpoint (SPUADDR (SPUADDR_SPU (pc), next_pc)); - - if (is_branch (insn, &offset, ®)) - { - CORE_ADDR target = offset; - - if (reg == SPU_PC_REGNUM) -- target += pc; -+ target += SPUADDR_ADDR (pc); - else if (reg != -1) - { - get_frame_register_bytes (frame, reg, 0, 4, buf); -@@ -1322,12 +1505,35 @@ spu_software_single_step (struct frame_i - - target = target & (SPU_LS_SIZE - 1); - if (target != next_pc) -- insert_single_step_breakpoint (target); -+ insert_single_step_breakpoint (SPUADDR (SPUADDR_SPU (pc), target)); - } - - return 1; - } - -+ -+/* Disassembler. */ -+ -+static void -+spu_dis_asm_print_address (bfd_vma addr, struct disassemble_info *info) -+{ -+ int id = *(int *)info->application_data; -+ CORE_ADDR spu_addr = SPUADDR (id, addr); -+ print_address (spu_addr, info->stream); -+} -+ -+static int -+gdb_print_insn_spu (bfd_vma memaddr, disassemble_info * info) -+{ -+ /* The opcodes disassembler does 18-bit address arithmetic. Make sure the -+ SPU ID encoded in the high bits is added back when we call print_address. */ -+ int id = SPUADDR_SPU (memaddr); -+ info->application_data = &id; -+ info->print_address_func = spu_dis_asm_print_address; -+ return print_insn_spu (memaddr, info); -+} -+ -+ - /* Target overlays for the SPU overlay manager. - - See the documentation of simple_overlay_update for how the -@@ -1444,7 +1650,7 @@ static void - spu_overlay_update_osect (struct obj_section *osect) - { - struct spu_overlay_table *ovly_table; -- CORE_ADDR val; -+ CORE_ADDR id, val; - - ovly_table = spu_get_overlay_table (osect->objfile); - if (!ovly_table) -@@ -1454,7 +1660,8 @@ spu_overlay_update_osect (struct obj_sec - if (ovly_table->mapped_ptr == 0) - return; - -- val = read_memory_unsigned_integer (ovly_table->mapped_ptr, 4); -+ id = SPUADDR_SPU (obj_section_addr (osect)); -+ val = read_memory_unsigned_integer (SPUADDR (id, ovly_table->mapped_ptr), 4); - osect->ovly_mapped = (val == ovly_table->mapped_val); - } - -@@ -1516,6 +1723,131 @@ spu_overlay_new_objfile (struct objfile - } - - -+/* Insert temporary breakpoint on "main" function of newly loaded -+ SPE context OBJFILE. */ -+static void -+spu_catch_start (struct objfile *objfile) -+{ -+ struct minimal_symbol *minsym; -+ struct symtab *symtab; -+ CORE_ADDR pc; -+ char buf[32]; -+ -+ /* Do this only if requested by "set spu stop-on-load on". */ -+ if (!spu_stop_on_load_p) -+ return; -+ -+ /* Consider only SPU objfiles. */ -+ if (!objfile || bfd_get_arch (objfile->obfd) != bfd_arch_spu) -+ return; -+ -+ /* The main objfile is handled differently. */ -+ if (objfile == symfile_objfile) -+ return; -+ -+ /* There can be multiple symbols named "main". Search for the -+ "main" in *this* objfile. */ -+ minsym = lookup_minimal_symbol ("main", NULL, objfile); -+ if (!minsym) -+ return; -+ -+ /* If we have debugging information, try to use it -- this -+ will allow us to properly skip the prologue. */ -+ pc = SYMBOL_VALUE_ADDRESS (minsym); -+ symtab = find_pc_sect_symtab (pc, SYMBOL_OBJ_SECTION (minsym)); -+ if (symtab != NULL) -+ { -+ struct blockvector *bv = BLOCKVECTOR (symtab); -+ struct block *block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); -+ struct symbol *sym; -+ struct symtab_and_line sal; -+ -+ sym = lookup_block_symbol (block, "main", NULL, VAR_DOMAIN); -+ if (sym) -+ { -+ fixup_symbol_section (sym, objfile); -+ sal = find_function_start_sal (sym, 1); -+ pc = sal.pc; -+ } -+ } -+ -+ /* Use a numerical address for the tbreak command to avoid having -+ the breakpoint re-set incorrectly. */ -+ xsnprintf (buf, sizeof buf, "*%s", core_addr_to_string (pc)); -+ tbreak_command (buf, 0); -+} -+ -+/* Lookup OBJFILE corresponding to the current SPU context. */ -+static struct objfile * -+spu_objfile_from_context (void) -+{ -+ struct frame_info *frame = get_current_frame (); -+ struct gdbarch *gdbarch = get_frame_arch (frame); -+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); -+ struct objfile *obj; -+ -+ if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu) -+ return NULL; -+ -+ ALL_OBJFILES (obj) -+ { -+ if (obj->sections != obj->sections_end -+ && SPUADDR_SPU (obj_section_addr (obj->sections)) == tdep->id) -+ return obj; -+ } -+ -+ return NULL; -+} -+ -+/* Flush cache for ea pointer access if available and return 1. Return 0 if -+ inferior call was not executed. */ -+static void -+flush_ea_cache (void) -+{ -+ struct value *ea_flush_fn = NULL; -+ struct minimal_symbol *msymbol; -+ struct objfile *obj; -+ -+ obj = spu_objfile_from_context (); -+ if (obj == NULL) -+ return; -+ -+ /* Lookup inferior function __cache_flush. */ -+ msymbol = lookup_minimal_symbol ("__cache_flush", NULL, obj); -+ if (msymbol != NULL) -+ { -+ struct type *type; -+ CORE_ADDR addr; -+ -+ type = builtin_type_void; -+ type = lookup_function_type (type); -+ type = lookup_pointer_type (type); -+ addr = SYMBOL_VALUE_ADDRESS (msymbol); -+ ea_flush_fn = value_from_pointer (type, addr); -+ } -+ -+ if (ea_flush_fn) -+ call_function_by_hand (ea_flush_fn, 0, NULL); -+} -+ -+/* This handler is called when the inferior has stopped. If it is stopped in -+ SPU architecture then flush the ea cache if used. */ -+static void -+spu_attach_normal_stop (struct bpstats *bs, int unused) -+{ -+ if (!spu_auto_flush_cache_p) -+ return; -+ -+ if (!target_has_registers || !target_has_stack || !target_has_memory) -+ return; -+ -+ /* Temporarily reset the spu_auto_flush_cache_p to avoid recursively -+ re-entering this function when __cache_flush stops. */ -+ spu_auto_flush_cache_p = 0; -+ flush_ea_cache (); -+ spu_auto_flush_cache_p = 1; -+} -+ - /* "info spu" commands. */ - - static void -@@ -2065,6 +2397,37 @@ info_spu_command (char *args, int from_t - } - - -+/* Root of all "set spu "/"show spu " commands. */ -+ -+static void -+show_spu_command (char *args, int from_tty) -+{ -+ help_list (showspucmdlist, "show spu ", all_commands, gdb_stdout); -+} -+ -+static void -+set_spu_command (char *args, int from_tty) -+{ -+ help_list (setspucmdlist, "set spu ", all_commands, gdb_stdout); -+} -+ -+static void -+show_spu_stop_on_load (struct ui_file *file, int from_tty, -+ struct cmd_list_element *c, const char *value) -+{ -+ fprintf_filtered (file, _("Stopping for new SPE threads is %s.\n"), -+ value); -+} -+ -+static void -+show_spu_auto_flush_cache (struct ui_file *file, int from_tty, -+ struct cmd_list_element *c, const char *value) -+{ -+ fprintf_filtered (file, _("Automatic software-cache flush is %s.\n"), -+ value); -+} -+ -+ - /* Set up gdbarch struct. */ - - static struct gdbarch * -@@ -2072,22 +2435,30 @@ spu_gdbarch_init (struct gdbarch_info in - { - struct gdbarch *gdbarch; - struct gdbarch_tdep *tdep; -+ int id = -1; - -- /* Find a candidate among the list of pre-declared architectures. */ -- arches = gdbarch_list_lookup_by_info (arches, &info); -- if (arches != NULL) -- return arches->gdbarch; -+ /* Which spufs ID was requested as address space? */ -+ if (info.tdep_info) -+ id = *(int *)info.tdep_info; - -- /* Is is for us? */ -- if (info.bfd_arch_info->mach != bfd_mach_spu) -- return NULL; -+ /* Find a candidate among extant architectures. */ -+ for (arches = gdbarch_list_lookup_by_info (arches, &info); -+ arches != NULL; -+ arches = gdbarch_list_lookup_by_info (arches->next, &info)) -+ { -+ tdep = gdbarch_tdep (arches->gdbarch); -+ if (tdep && tdep->id == id) -+ return arches->gdbarch; -+ } - -- /* Yes, create a new architecture. */ -+ /* None found, so create a new architecture. */ - tdep = XCALLOC (1, struct gdbarch_tdep); -+ tdep->id = id; -+ tdep->lslr = id != -1? spu_lslr (id) : SPU_LS_SIZE - 1; - gdbarch = gdbarch_alloc (&info, tdep); - - /* Disassembler. */ -- set_gdbarch_print_insn (gdbarch, print_insn_spu); -+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_spu); - - /* Registers. */ - set_gdbarch_num_regs (gdbarch, SPU_NUM_REGS); -@@ -2118,9 +2489,16 @@ spu_gdbarch_init (struct gdbarch_info in - set_gdbarch_double_format (gdbarch, floatformats_ieee_double); - set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); - -- /* Address conversion. */ -+ /* Address handling. */ -+ set_gdbarch_address_to_pointer (gdbarch, spu_address_to_pointer); - set_gdbarch_pointer_to_address (gdbarch, spu_pointer_to_address); - set_gdbarch_integer_to_address (gdbarch, spu_integer_to_address); -+ set_gdbarch_address_class_type_flags (gdbarch, spu_address_class_type_flags); -+ set_gdbarch_address_class_type_flags_to_name -+ (gdbarch, spu_address_class_type_flags_to_name); -+ set_gdbarch_address_class_name_to_type_flags -+ (gdbarch, spu_address_class_name_to_type_flags); -+ - - /* Inferior function calls. */ - set_gdbarch_call_dummy_location (gdbarch, ON_STACK); -@@ -2142,6 +2520,9 @@ spu_gdbarch_init (struct gdbarch_info in - set_gdbarch_skip_prologue (gdbarch, spu_skip_prologue); - set_gdbarch_in_function_epilogue_p (gdbarch, spu_in_function_epilogue_p); - -+ /* Cell/B.E. cross-architecture unwinder support. */ -+ frame_unwind_prepend_unwinder (gdbarch, &spu2ppu_unwind); -+ - /* Breakpoints. */ - set_gdbarch_decr_pc_after_break (gdbarch, 4); - set_gdbarch_breakpoint_from_pc (gdbarch, spu_breakpoint_from_pc); -@@ -2163,6 +2544,50 @@ _initialize_spu_tdep (void) - observer_attach_new_objfile (spu_overlay_new_objfile); - spu_overlay_data = register_objfile_data (); - -+ /* Install spu stop-on-load handler. */ -+ observer_attach_new_objfile (spu_catch_start); -+ -+ /* Add ourselves to normal_stop event chain. */ -+ observer_attach_normal_stop (spu_attach_normal_stop); -+ -+ /* Add root prefix command for all "set spu"/"show spu" commands. */ -+ add_prefix_cmd ("spu", no_class, set_spu_command, -+ _("Various SPU specific commands."), -+ &setspucmdlist, "set spu ", 0, &setlist); -+ add_prefix_cmd ("spu", no_class, show_spu_command, -+ _("Various SPU specific commands."), -+ &showspucmdlist, "show spu ", 0, &showlist); -+ -+ /* Toggle whether or not to add a temporary breakpoint at the "main" -+ function of new SPE contexts. */ -+ add_setshow_boolean_cmd ("stop-on-load", class_support, -+ &spu_stop_on_load_p, _("\ -+Set whether to stop for new SPE threads."), -+ _("\ -+Show whether to stop for new SPE threads."), -+ _("\ -+Use \"on\" to give control to the user when a new SPE thread\n\ -+enters its \"main\" function.\n\ -+Use \"off\" to disable stopping for new SPE threads."), -+ NULL, -+ show_spu_stop_on_load, -+ &setspucmdlist, &showspucmdlist); -+ -+ /* Toggle whether or not to automatically flush the software-managed -+ cache whenever SPE execution stops. */ -+ add_setshow_boolean_cmd ("auto-flush-cache", class_support, -+ &spu_auto_flush_cache_p, _("\ -+Set whether to automatically flush the software-managed cache."), -+ _("\ -+Show whether to automatically flush the software-managed cache."), -+ _("\ -+Use \"on\" to automatically flush the software-managed cache\n\ -+whenever SPE execution stops.\n\ -+Use \"off\" to never automatically flush the software-managed cache."), -+ NULL, -+ show_spu_auto_flush_cache, -+ &setspucmdlist, &showspucmdlist); -+ - /* Add root prefix command for all "info spu" commands. */ - add_prefix_cmd ("spu", class_info, info_spu_command, - _("Various SPU specific commands."), ---- gdb/spu-tdep.h -+++ gdb/spu-tdep.h -@@ -50,4 +50,17 @@ enum spu_regnum - /* Local store. */ - #define SPU_LS_SIZE 0x40000 - -+/* Address conversions. */ -+#define SPUADDR(spu, addr) \ -+ ((spu) != -1? (ULONGEST)1 << 63 | (ULONGEST)(spu) << 32 | (addr) : (addr)) -+#define SPUADDR_SPU(addr) \ -+ (((addr) & (ULONGEST)1 << 63)? (ULONGEST)(addr) >> 32 & 0x7fffffff : -1) -+#define SPUADDR_ADDR(addr) \ -+ (((addr) & (ULONGEST)1 << 63)? (ULONGEST)(addr) & 0xffffffff : (addr)) -+ -+/* SPU multi-architecture support. */ -+extern void set_spu_solib_ops (struct gdbarch *gdbarch); -+extern void spu_multiarch_enable (void); -+extern void spu_multiarch_disable (void); -+ - #endif ---- gdb/stack.c -+++ gdb/stack.c -@@ -45,6 +45,7 @@ - #include "valprint.h" - #include "gdbthread.h" - #include "cp-support.h" -+#include "arch-utils.h" - - #include "gdb_assert.h" - #include -@@ -109,6 +110,8 @@ print_stack_frame (struct frame_info *fr - enum print_what print_what) - { - struct print_stack_frame_args args; -+ struct cleanup *old_chain = save_current_gdbarch (); -+ current_gdbarch = get_frame_arch (frame); - - args.frame = frame; - args.print_level = print_level; -@@ -118,6 +121,7 @@ print_stack_frame (struct frame_info *fr - args.print_args = 1; - - catch_errors (print_stack_frame_stub, &args, "", RETURN_MASK_ERROR); -+ do_cleanups (old_chain); - } - - struct print_args_args -@@ -223,6 +227,9 @@ print_frame_args (struct symbol *func, s - stb = ui_out_stream_new (uiout); - old_chain = make_cleanup_ui_out_stream_delete (stb); - -+ save_current_gdbarch (); -+ current_gdbarch = get_frame_arch (frame); -+ - if (func) - { - struct block *b = SYMBOL_BLOCK_VALUE (func); -@@ -474,9 +481,11 @@ print_frame_info (struct frame_info *fra - struct symtab_and_line sal; - int source_print; - int location_print; -+ struct cleanup *old_chain; - - if (get_frame_type (frame) == DUMMY_FRAME -- || get_frame_type (frame) == SIGTRAMP_FRAME) -+ || get_frame_type (frame) == SIGTRAMP_FRAME -+ || get_frame_type (frame) == ARCH_FRAME) - { - struct cleanup *uiout_cleanup - = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); -@@ -509,6 +518,10 @@ print_frame_info (struct frame_info *fra - annotate_signal_handler_caller (); - ui_out_field_string (uiout, "func", ""); - } -+ else if (get_frame_type (frame) == ARCH_FRAME) -+ { -+ ui_out_field_string (uiout, "func", ""); -+ } - ui_out_text (uiout, "\n"); - annotate_frame_end (); - -@@ -522,6 +535,10 @@ print_frame_info (struct frame_info *fra - the next frame is a SIGTRAMP_FRAME or a DUMMY_FRAME, then the - next frame was not entered as the result of a call, and we want - to get the line containing FRAME->pc. */ -+ -+ old_chain = save_current_gdbarch (); -+ current_gdbarch = get_frame_arch (frame); -+ - find_frame_sal (frame, &sal); - - location_print = (print_what == LOCATION -@@ -577,6 +594,7 @@ print_frame_info (struct frame_info *fra - annotate_frame_end (); - - gdb_flush (gdb_stdout); -+ do_cleanups (old_chain); - } - - static void -@@ -1435,6 +1453,7 @@ static void - print_frame_local_vars (struct frame_info *frame, int num_tabs, - struct ui_file *stream) - { -+ struct cleanup *old_chain; - struct block *block = get_frame_block (frame, 0); - int values_printed = 0; - -@@ -1444,6 +1463,9 @@ print_frame_local_vars (struct frame_inf - return; - } - -+ old_chain = save_current_gdbarch (); -+ current_gdbarch = get_frame_arch (frame); -+ - while (block) - { - if (print_block_frame_locals (block, frame, num_tabs, stream)) -@@ -1457,6 +1479,8 @@ print_frame_local_vars (struct frame_inf - - if (!values_printed) - fprintf_filtered (stream, _("No locals.\n")); -+ -+ do_cleanups (old_chain); - } - - /* Same, but print labels. */ ---- gdb/target-descriptions.c -+++ gdb/target-descriptions.c -@@ -104,6 +104,10 @@ typedef struct tdesc_feature - } *tdesc_feature_p; - DEF_VEC_P(tdesc_feature_p); - -+/* A compatible architecture from a target description. */ -+typedef const struct bfd_arch_info *arch_p; -+DEF_VEC_P(arch_p); -+ - /* A target description. */ - - struct target_desc -@@ -111,6 +115,9 @@ struct target_desc - /* The architecture reported by the target, if any. */ - const struct bfd_arch_info *arch; - -+ /* The list of compatible architectures reported by the target. */ -+ VEC(arch_p) *compatible; -+ - /* Any architecture-specific properties specified by the target. */ - VEC(property_s) *properties; - -@@ -290,6 +297,28 @@ tdesc_architecture (const struct target_ - { - return target_desc->arch; - } -+ -+/* Return non-zero if this target description is compatible -+ with the given BFD architecture. */ -+ -+int -+tdesc_compatible_p (const struct target_desc *target_desc, -+ const struct bfd_arch_info *arch) -+{ -+ const struct bfd_arch_info *compat; -+ int ix; -+ -+ for (ix = 0; VEC_iterate (arch_p, target_desc->compatible, ix, compat); -+ ix++) -+ { -+ if (compat == arch -+ || arch->compatible (arch, compat) -+ || compat->compatible (compat, arch)) -+ return 1; -+ } -+ -+ return 0; -+} - - - /* Return 1 if this target description includes any registers. */ -@@ -885,6 +914,8 @@ free_target_description (void *arg) - } - VEC_free (property_s, target_desc->properties); - -+ VEC_free (arch_p, target_desc->compatible); -+ - xfree (target_desc); - } - -@@ -895,6 +926,30 @@ make_cleanup_free_target_description (st - } - - void -+tdesc_add_compatible (struct target_desc *target_desc, -+ const struct bfd_arch_info *compatible) -+{ -+ const struct bfd_arch_info *compat; -+ int ix; -+ -+ /* If this instance of GDB is compiled without BFD support for the -+ compatible architecture, simply ignore it -- we would not be able -+ to handle it anyway. */ -+ if (compatible == NULL) -+ return; -+ -+ for (ix = 0; VEC_iterate (arch_p, target_desc->compatible, ix, compat); -+ ix++) -+ if (compat == compatible) -+ internal_error (__FILE__, __LINE__, -+ _("Attempted to add duplicate " -+ "compatible architecture \"%s\""), -+ compatible->printable_name); -+ -+ VEC_safe_push (arch_p, target_desc->compatible, compatible); -+} -+ -+void - set_tdesc_property (struct target_desc *target_desc, - const char *key, const char *value) - { -@@ -993,6 +1048,7 @@ static void - maint_print_c_tdesc_cmd (char *args, int from_tty) - { - const struct target_desc *tdesc; -+ const struct bfd_arch_info *compatible; - const char *filename, *inp; - char *function, *outp; - struct property *prop; -@@ -1049,6 +1105,16 @@ maint_print_c_tdesc_cmd (char *args, int - printf_unfiltered ("\n"); - } - -+ for (ix = 0; VEC_iterate (arch_p, tdesc->compatible, ix, compatible); -+ ix++) -+ { -+ printf_unfiltered -+ (" tdesc_add_compatible (result, bfd_scan_arch (\"%s\"));\n", -+ compatible->printable_name); -+ } -+ if (ix) -+ printf_unfiltered ("\n"); -+ - for (ix = 0; VEC_iterate (property_s, tdesc->properties, ix, prop); - ix++) - { ---- gdb/target-descriptions.h -+++ gdb/target-descriptions.h -@@ -123,6 +123,12 @@ int tdesc_numbered_register_choices (con - const struct bfd_arch_info *tdesc_architecture - (const struct target_desc *); - -+/* Return non-zero if this target description is compatible -+ with the given BFD architecture. */ -+ -+int tdesc_compatible_p (const struct target_desc *, -+ const struct bfd_arch_info *); -+ - /* Return the string value of a property named KEY, or NULL if the - property was not specified. */ - -@@ -169,6 +175,8 @@ void set_tdesc_architecture (struct targ - const struct bfd_arch_info *); - void set_tdesc_property (struct target_desc *, - const char *key, const char *value); -+void tdesc_add_compatible (struct target_desc *, -+ const struct bfd_arch_info *); - - struct tdesc_feature *tdesc_create_feature (struct target_desc *tdesc, - const char *name); ---- gdb/target.c -+++ gdb/target.c -@@ -91,6 +91,9 @@ static LONGEST target_xfer_partial (stru - void *readbuf, const void *writebuf, - ULONGEST offset, LONGEST len); - -+static struct gdbarch *default_thread_architecture (struct target_ops *ops, -+ ptid_t ptid); -+ - static void init_dummy_target (void); - - static struct target_ops debug_target; -@@ -480,6 +483,7 @@ update_current_target (void) - INHERIT (to_find_memory_regions, t); - INHERIT (to_make_corefile_notes, t); - /* Do not inherit to_get_thread_local_address. */ -+ INHERIT (to_thread_architecture, t); - INHERIT (to_can_execute_reverse, t); - /* Do not inherit to_read_description. */ - INHERIT (to_get_ada_task_ptid, t); -@@ -639,6 +643,8 @@ update_current_target (void) - de_fault (to_async_mask, - (int (*) (int)) - return_one); -+ de_fault (to_thread_architecture, -+ default_thread_architecture); - current_target.to_read_description = NULL; - de_fault (to_get_ada_task_ptid, - (ptid_t (*) (long, long)) -@@ -2134,7 +2140,8 @@ target_require_runnable (void) - /* Do not worry about thread_stratum targets that can not - create inferiors. Assume they will be pushed again if - necessary, and continue to the process_stratum. */ -- if (t->to_stratum == thread_stratum) -+ if (t->to_stratum == thread_stratum -+ || t->to_stratum == arch_stratum) - continue; - - error (_("\ -@@ -2294,6 +2301,12 @@ default_watchpoint_addr_within_range (st - return addr >= start && addr < start + length; - } - -+static struct gdbarch * -+default_thread_architecture (struct target_ops *ops, ptid_t ptid) -+{ -+ return target_gdbarch; -+} -+ - static int - return_zero (void) - { -@@ -3145,6 +3158,19 @@ debug_to_find_new_threads (void) - fputs_unfiltered ("target_find_new_threads ()\n", gdb_stdlog); - } - -+static struct gdbarch * -+debug_to_thread_architecture (struct target_ops *ops, ptid_t ptid) -+{ -+ struct gdbarch *retval; -+ -+ retval = debug_target.to_thread_architecture (ops, ptid); -+ -+ fprintf_unfiltered (gdb_stdlog, "target_thread_architecture (%s) = %p [%s]\n", -+ target_pid_to_str (ptid), retval, -+ gdbarch_bfd_arch_info (retval)->printable_name); -+ return retval; -+} -+ - static void - debug_to_stop (ptid_t ptid) - { -@@ -3224,6 +3250,7 @@ setup_target_debug (void) - current_target.to_stop = debug_to_stop; - current_target.to_rcmd = debug_to_rcmd; - current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file; -+ current_target.to_thread_architecture = debug_to_thread_architecture; - } - - ---- gdb/target.h -+++ gdb/target.h -@@ -62,7 +62,8 @@ enum strata - file_stratum, /* Executable files, etc */ - core_stratum, /* Core dump files */ - process_stratum, /* Executing processes */ -- thread_stratum /* Executing threads */ -+ thread_stratum, /* Executing threads */ -+ arch_stratum /* Architecture overrides */ - }; - - enum thread_control_capabilities -@@ -544,6 +545,9 @@ struct target_ops - simultaneously? */ - int (*to_supports_multi_process) (void); - -+ /* Determine current architecture of thread PTID. */ -+ struct gdbarch *(*to_thread_architecture) (struct target_ops *, ptid_t); -+ - int to_magic; - /* Need sub-structure for target machine related rather than comm related? - */ -@@ -1043,6 +1047,11 @@ extern char *normal_pid_to_str (ptid_t p - #define target_pid_to_exec_file(pid) \ - (current_target.to_pid_to_exec_file) (pid) - -+/* Determine current architecture of thread PTID. */ -+ -+#define target_thread_architecture(ptid) \ -+ (current_target.to_thread_architecture (¤t_target, ptid)) -+ - /* - * Iterator function for target memory regions. - * Calls a callback function once for each memory region 'mapped' ---- gdb/testsuite/gdb.base/dump.exp -+++ gdb/testsuite/gdb.base/dump.exp -@@ -42,6 +42,12 @@ if {[istarget "ia64*-*-*"] || [istarget - set is64bitonly "yes" - } - -+if {[istarget "spu*-*-*"]} then { -+ # The internal address format used for the combined Cell/B.E. -+ # debugger required 64-bit. -+ set is64bitonly "yes" -+} -+ - if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ${options}] != "" } { - untested dump.exp - return -1 ---- gdb/testsuite/gdb.xml/tdesc-regs.exp -+++ gdb/testsuite/gdb.xml/tdesc-regs.exp -@@ -39,6 +39,16 @@ switch -glob -- [istarget] { - set regdir "rs6000/" - set core-regs {power-core.xml} - } -+ "spu*-*-*" { -+ # This may be either the spu-linux-nat target, or the Cell/B.E. -+ # multi-architecture debugger in SPU standalone executable mode. -+ # We do not support XML register sets on SPU in either case. -+ # However, the multi-arch debugger will accept XML registers sets -+ # (on the PowerPC side), hence the test below would fail. -+ # Simply return unconditionally here. -+ unsupported "register tests" -+ return 0 -+ } - } - - # If no core registers were specified, assume this target does not ---- gdb/thread.c -+++ gdb/thread.c -@@ -824,6 +824,7 @@ switch_to_thread (ptid_t ptid) - inferior_ptid = ptid; - reinit_frame_cache (); - registers_changed (); -+ current_gdbarch = get_regcache_arch (get_current_regcache ()); - - /* We don't check for is_stopped, because we're called at times - while in the TARGET_RUNNING state, e.g., while handling an ---- gdb/utils.c -+++ gdb/utils.c -@@ -3119,7 +3119,6 @@ core_addr_to_string_nz (const CORE_ADDR - CORE_ADDR - string_to_core_addr (const char *my_string) - { -- int addr_bit = gdbarch_addr_bit (current_gdbarch); - CORE_ADDR addr = 0; - - if (my_string[0] == '0' && tolower (my_string[1]) == 'x') -@@ -3135,17 +3134,6 @@ string_to_core_addr (const char *my_stri - else - error (_("invalid hex \"%s\""), my_string); - } -- -- /* Not very modular, but if the executable format expects -- addresses to be sign-extended, then do so if the address was -- specified with only 32 significant bits. Really this should -- be determined by the target architecture, not by the object -- file. */ -- if (i - 2 == addr_bit / 4 -- && exec_bfd -- && bfd_get_sign_extend_vma (exec_bfd)) -- addr = (addr ^ ((CORE_ADDR) 1 << (addr_bit - 1))) -- - ((CORE_ADDR) 1 << (addr_bit - 1)); - } - else - { ---- gdb/varobj.c -+++ gdb/varobj.c -@@ -427,6 +427,8 @@ static struct frame_info * - find_frame_addr_in_frame_chain (CORE_ADDR frame_addr) - { - struct frame_info *frame = NULL; -+ CORE_ADDR frame_base; -+ int addr_bit; - - if (frame_addr == (CORE_ADDR) 0) - return NULL; -@@ -435,7 +437,16 @@ find_frame_addr_in_frame_chain (CORE_ADD - frame != NULL; - frame = get_prev_frame (frame)) - { -- if (get_frame_base_address (frame) == frame_addr) -+ /* The CORE_ADDR we get as argument was parsed from a string GDB -+ output as $fp. This output got truncated to gdbarch_addr_bit. -+ Truncate the frame base address in the same manner before -+ comparing it against our argument. */ -+ frame_base = get_frame_base_address (frame); -+ addr_bit = gdbarch_addr_bit (get_frame_arch (frame)); -+ if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT)) -+ frame_base &= ((CORE_ADDR) 1 << addr_bit) - 1; -+ -+ if (frame_base == frame_addr) - return frame; - } - ---- gdb/xml-tdesc.c -+++ gdb/xml-tdesc.c -@@ -106,6 +106,20 @@ tdesc_end_arch (struct gdb_xml_parser *p - set_tdesc_architecture (data->tdesc, arch); - } - -+/* Handle the end of a element and its value. */ -+ -+static void -+tdesc_end_compatible (struct gdb_xml_parser *parser, -+ const struct gdb_xml_element *element, -+ void *user_data, const char *body_text) -+{ -+ struct tdesc_parsing_data *data = user_data; -+ const struct bfd_arch_info *arch; -+ -+ arch = bfd_scan_arch (body_text); -+ tdesc_add_compatible (data->tdesc, arch); -+} -+ - /* Handle the start of a element. */ - - static void -@@ -345,6 +359,8 @@ static const struct gdb_xml_attribute ta - static const struct gdb_xml_element target_children[] = { - { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL, - NULL, tdesc_end_arch }, -+ { "compatible", NULL, NULL, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, -+ NULL, tdesc_end_compatible }, - { "feature", feature_attributes, feature_children, - GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, - tdesc_start_feature, NULL }, ---- gdb/xstormy16-tdep.c -+++ gdb/xstormy16-tdep.c -@@ -592,7 +592,8 @@ xstormy16_skip_trampoline_code (struct f - and vice versa. */ - - static CORE_ADDR --xstormy16_pointer_to_address (struct type *type, const gdb_byte *buf) -+xstormy16_pointer_to_address (struct gdbarch *gdbarch, -+ struct type *type, const gdb_byte *buf) - { - enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type)); - CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type)); -@@ -608,7 +609,8 @@ xstormy16_pointer_to_address (struct typ - } - - static void --xstormy16_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr) -+xstormy16_address_to_pointer (struct gdbarch *gdbarch, -+ struct type *type, gdb_byte *buf, CORE_ADDR addr) - { - enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type)); - diff --git a/expand-line-sal-maybe.diff b/expand-line-sal-maybe.diff deleted file mode 100644 index 194608f..0000000 --- a/expand-line-sal-maybe.diff +++ /dev/null @@ -1,26 +0,0 @@ -Index: gdb/breakpoint.c -=================================================================== -RCS file: /cvs/src/src/gdb/breakpoint.c,v -retrieving revision 1.325 -diff -u -a -p -u -p -a -r1.325 gdb/breakpoint.c ---- gdb/breakpoint.c 10 Jun 2008 09:29:15 -0000 1.325 -+++ gdb/breakpoint.c 22 Jun 2008 23:51:37 -0000 -@@ -5211,18 +5211,6 @@ expand_line_sal_maybe (struct symtab_and - return expanded; - } - -- if (original_pc) -- { -- found = 0; -- for (i = 0; i < expanded.nelts; ++i) -- if (expanded.sals[i].pc == original_pc) -- { -- found = 1; -- break; -- } -- gdb_assert (found); -- } -- - return expanded; - } - diff --git a/find-pc-sect-line.diff b/find-pc-sect-line.diff deleted file mode 100644 index f4a69b0..0000000 --- a/find-pc-sect-line.diff +++ /dev/null @@ -1,12 +0,0 @@ ---- gdb/symtab.c.~1.157.~ 2007-04-16 17:39:04.000000000 +0200 -+++ gdb/symtab.c 2007-04-18 14:10:52.000000000 +0200 -@@ -2252,6 +2252,9 @@ find_pc_sect_line (CORE_ADDR pc, struct - best_end = item->pc; - } - -+ if (notcurrent) -+ pc++; -+ - if (!best_symtab) - { - /* If we didn't find any line number info, just return zeros. diff --git a/find-separate-debug-file.diff b/find-separate-debug-file.diff deleted file mode 100644 index 3f2efb0..0000000 --- a/find-separate-debug-file.diff +++ /dev/null @@ -1,85 +0,0 @@ -Index: gdb/symfile.c -=================================================================== -RCS file: /cvs/src/src/gdb/symfile.c,v -retrieving revision 1.205 -diff -u -a -p -u -p -a -r1.205 gdb/symfile.c ---- gdb/symfile.c 5 Jun 2008 19:21:55 -0000 1.205 -+++ gdb/symfile.c 10 Jun 2008 09:56:34 -0000 -@@ -1414,12 +1414,13 @@ find_separate_debug_file (struct objfile - return NULL; - - dir = xstrdup (objfile->name); -+ canon_name = lrealpath (dir); - - /* Strip off the final filename part, leaving the directory name, - followed by a slash. Objfile names should always be absolute and - tilde-expanded, so there should always be a slash in there - somewhere. */ -- for (i = strlen(dir) - 1; i >= 0; i--) -+ for (i = strlen (dir) - 1; i >= 0; i--) - { - if (IS_DIR_SEPARATOR (dir[i])) - break; -@@ -1427,8 +1428,20 @@ find_separate_debug_file (struct objfile - gdb_assert (i >= 0 && IS_DIR_SEPARATOR (dir[i])); - dir[i+1] = '\0'; - -+ if (canon_name) -+ { -+ for (i = strlen (canon_name) - 1; i >= 0; i--) -+ { -+ if (IS_DIR_SEPARATOR (canon_name[i])) -+ break; -+ } -+ gdb_assert (i >= 0 && IS_DIR_SEPARATOR (canon_name[i])); -+ canon_name[i+1] = '\0'; -+ } -+ - debugfile = alloca (strlen (debug_file_directory) + 1 -- + strlen (dir) -+ + (canon_name != NULL && strlen (canon_name) > strlen (dir) -+ ? strlen (canon_name) : strlen (dir)) - + strlen (DEBUG_SUBDIRECTORY) - + strlen ("/") - + strlen (basename) -@@ -1440,6 +1453,8 @@ find_separate_debug_file (struct objfile - - if (separate_debug_file_exists (debugfile, crc32)) - { -+ if (canon_name) -+ xfree (canon_name); - xfree (basename); - xfree (dir); - return xstrdup (debugfile); -@@ -1453,6 +1468,8 @@ find_separate_debug_file (struct objfile - - if (separate_debug_file_exists (debugfile, crc32)) - { -+ if (canon_name) -+ xfree (canon_name); - xfree (basename); - xfree (dir); - return xstrdup (debugfile); -@@ -1461,11 +1478,13 @@ find_separate_debug_file (struct objfile - /* Then try in the global debugfile directory. */ - strcpy (debugfile, debug_file_directory); - strcat (debugfile, "/"); -- strcat (debugfile, dir); -+ strcat (debugfile, canon_name ? canon_name : dir); - strcat (debugfile, basename); - - if (separate_debug_file_exists (debugfile, crc32)) - { -+ if (canon_name) -+ xfree (canon_name); - xfree (basename); - xfree (dir); - return xstrdup (debugfile); -@@ -1473,7 +1492,6 @@ find_separate_debug_file (struct objfile - - /* If the file is in the sysroot, try using its base path in the - global debugfile directory. */ -- canon_name = lrealpath (dir); - if (canon_name - && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0 - && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)])) diff --git a/fix-gdb-backtrace.diff b/fix-gdb-backtrace.diff deleted file mode 100644 index 9eb2d2b..0000000 --- a/fix-gdb-backtrace.diff +++ /dev/null @@ -1,19 +0,0 @@ -Index: gdb/i386-tdep.c -=================================================================== ---- gdb/i386-tdep.c.orig -+++ gdb/i386-tdep.c -@@ -1023,11 +1023,13 @@ i386_frame_cache (struct frame_info *nex - /* This will be added back below. */ - cache->saved_regs[I386_EIP_REGNUM] -= cache->base; - } -- else -+ else if (cache->pc) - { - get_frame_register (this_frame, I386_ESP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset; - } -+ else -+ cache->saved_regs[I386_EBP_REGNUM] = 0; - } - - /* Now that we have the base address for the stack frame we can diff --git a/gdb-6.3-attach-see-vdso-test.patch b/gdb-6.3-attach-see-vdso-test.patch new file mode 100644 index 0000000..1490a34 --- /dev/null +++ b/gdb-6.3-attach-see-vdso-test.patch @@ -0,0 +1,110 @@ +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/attach-see-vdso.c 6 Jul 2007 14:14:44 -0000 +@@ -0,0 +1,25 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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. */ ++ ++#include ++ ++int main () ++{ ++ pause (); ++ return 1; ++} +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/attach-see-vdso.exp 6 Jul 2007 14:14:44 -0000 +@@ -0,0 +1,79 @@ ++# Copyright 2007 ++ ++# 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. ++ ++# This file was created by Jan Kratochvil . ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++# This test only works on Linux ++if { ![istarget "*-*-linux-gnu*"] } { ++ return 0 ++} ++ ++set testfile "attach-see-vdso" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++set escapedbinfile [string_to_regexp ${objdir}/${subdir}/${testfile}] ++ ++# The kernel VDSO is used for the syscalls returns only on i386 (not x86_64). ++# ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-m32}] != "" } { ++ gdb_suppress_entire_file "Testcase nonthraded compile failed, so all tests in this file will automatically fail." ++} ++ ++if [get_compiler_info ${binfile}] { ++ return -1 ++} ++ ++# Start the program running and then wait for a bit, to be sure ++# that it can be attached to. ++ ++set testpid [eval exec $binfile &] ++ ++# Avoid some race: ++sleep 2 ++ ++# Start with clean gdb ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++# Never call: gdb_load ${binfile} ++# as the former problem would not reproduce otherwise. ++ ++set test "attach" ++gdb_test_multiple "attach $testpid" "$test" { ++ -re "Attaching to process $testpid\r?\n.*$gdb_prompt $" { ++ pass "$test" ++ } ++} ++ ++gdb_test "bt" "#0 *0x\[0-9a-f\]* in \[^?\].*" "backtrace decodes VDSO" ++ ++# Exit and detach the process. ++ ++gdb_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}" diff --git a/gdb-6.3-bt-past-zero-20051201.patch b/gdb-6.3-bt-past-zero-20051201.patch new file mode 100644 index 0000000..545b34b --- /dev/null +++ b/gdb-6.3-bt-past-zero-20051201.patch @@ -0,0 +1,88 @@ +2005-12-01 Jeff Johnston + + * frame.c (backtrace_past_zero_pc): New static variable. + (get_prev_frame): Don't return NULL for zero pc value if + backtrace past-zero-frame option is turned on. + (_initialize_frame): Initialize new command to allow backtracing + past a zero pc value (set backtrace past-zero-pc). + +testsuite/gdb.base: +2005-12-01 Jeff Johnston + + * setshow.exp: Add testing of "set backtrace past-zero-pc" option. + +2007-10-15 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.7/gdb/testsuite/gdb.base/setshow.exp +=================================================================== +--- gdb-6.7.orig/gdb/testsuite/gdb.base/setshow.exp 2007-08-23 20:14:17.000000000 +0200 ++++ gdb-6.7/gdb/testsuite/gdb.base/setshow.exp 2007-10-15 21:34:52.000000000 +0200 +@@ -106,6 +106,16 @@ if { ![target_info exists use_gdb_stub] + delete_breakpoints + gdb_test "run" "Starting program:.*foo bar blup baz bubble.*" "passing args" + } ++#test show backtrace past-zero-pc ++gdb_test "show backtrace past-zero-pc" "Whether backtraces should continue past a zero pc value is off." "default show backtrace past-zero-pc (off)" ++#test set backtrace past-zero-pc on ++gdb_test "set backtrace past-zero-pc on" "" "set backtrace past-zero-pc on" ++#test show backtrace past-zero-pc ++gdb_test "show backtrace past-zero-pc" "Whether backtraces should continue past a zero pc value is on." "show backtrace past-zero-pc (on)" ++#test set backtrace past-zero-pc off ++gdb_test "set backtrace past-zero-pc off" "" "set backtrace past-zero-pc off" ++#test show backtrace past-zero-pc ++gdb_test "show backtrace past-zero-pc" "Whether backtraces should continue past a zero pc value is off." "show backtrace past-zero-pc (off)" + #test set check range on + gdb_test "set check range on" "" "set check range on" + #test show check range on +Index: gdb-6.7/gdb/frame.c +=================================================================== +--- gdb-6.7.orig/gdb/frame.c 2007-10-12 22:35:58.000000000 +0200 ++++ gdb-6.7/gdb/frame.c 2007-10-15 21:34:52.000000000 +0200 +@@ -133,6 +133,16 @@ Whether backtraces should continue past + value); + } + ++static int backtrace_past_zero_pc; ++static void ++show_backtrace_past_zero_pc (struct ui_file *file, int from_tty, ++ struct cmd_list_element *c, const char *value) ++{ ++ fprintf_filtered (file, _("\ ++Whether backtraces should continue past a zero pc value is %s.\n"), ++ value); ++} ++ + static int backtrace_past_entry; + static void + show_backtrace_past_entry (struct ui_file *file, int from_tty, +@@ -1483,9 +1493,7 @@ get_prev_frame (struct frame_info *this_ + } + + if (this_frame->level > 0 +-#if 0 +- && backtrace_past_zero_pc +-#endif ++ && !backtrace_past_zero_pc + && get_frame_type (this_frame) == NORMAL_FRAME + && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME + && get_frame_pc (this_frame) == 0) +@@ -1850,6 +1858,17 @@ the rest of the stack trace."), + &set_backtrace_cmdlist, + &show_backtrace_cmdlist); + ++ add_setshow_boolean_cmd ("past-zero-pc", class_obscure, ++ &backtrace_past_zero_pc, _("\ ++Set whether backtraces should continue past a zero pc value."), _("\ ++Show whether backtraces should continue past a zero pc value."), _("\ ++Normally GDB stops backtracing when it finds a zero pc.\n\ ++Set this variable if you need to see the rest of the stack trace."), ++ NULL, ++ show_backtrace_past_zero_pc, ++ &set_backtrace_cmdlist, ++ &show_backtrace_cmdlist); ++ + add_setshow_integer_cmd ("limit", class_obscure, + &backtrace_limit, _("\ + Set an upper bound on the number of backtrace levels."), _("\ diff --git a/gdb-6.3-bz140532-ppc-unwinding-test.patch b/gdb-6.3-bz140532-ppc-unwinding-test.patch new file mode 100644 index 0000000..0165916 --- /dev/null +++ b/gdb-6.3-bz140532-ppc-unwinding-test.patch @@ -0,0 +1,317 @@ +diff -u -ruNp gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm32.S gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm32.S +--- gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm32.S 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm32.S 2007-08-02 13:23:10.000000000 -0400 +@@ -0,0 +1,78 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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. */ ++ ++ .section ".text" ++ .align 2 ++ .globl func0 ++ .type func0, @function ++func0: ++ stwu 1,-16(1) ++ mflr 0 ++ stw 31,12(1) ++ stw 0,20(1) ++ mr 31,1 ++ bl abort ++ .size func0, .-func0 ++ .align 2 ++ .globl func1 ++ .type func1, @function ++func1: ++ stwu 1,-16(1) ++ mflr 0 ++/* 20 = BO = branch always ++ 31 = BI = CR bit (ignored) */ ++ bcl 20,31,.Lpie ++.Lpie: stw 31,12(1) ++ stw 0,20(1) ++ mr 31,1 ++ bl func0 ++ mr 0,3 ++ lis 9,var@ha ++ lwz 9,var@l(9) ++ add 0,0,9 ++ mr 3,0 ++ lwz 11,0(1) ++ lwz 0,4(11) ++ mtlr 0 ++ lwz 31,-4(11) ++ mr 1,11 ++ blr ++ .size func1, .-func1 ++ .section .note.GNU-stack,"",@progbits ++ .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-8)" ++ ++/* Original source file: ++ ++#include ++ ++extern volatile int var; ++ ++int func0 (void) __attribute__((__noinline__)); ++int func0 (void) ++{ ++ abort (); ++ return var; ++} ++ ++int func1 (void) __attribute__((__noinline__)); ++int func1 (void) ++{ ++ return func0 () + var; ++} ++ ++*/ +diff -u -ruNp gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm64.S gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm64.S +--- gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm64.S 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue-asm64.S 2007-08-02 14:28:56.000000000 -0400 +@@ -0,0 +1,98 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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. */ ++ ++ .section ".toc","aw" ++ .section ".text" ++ .align 2 ++ .globl func0 ++ .section ".opd","aw" ++ .align 3 ++func0: ++ .quad .L.func0,.TOC.@tocbase ++ .previous ++ .type func0, @function ++.L.func0: ++ mflr 0 ++ std 31,-8(1) ++ std 0,16(1) ++ stdu 1,-128(1) ++ mr 31,1 ++ bl abort ++ nop ++ .long 0 ++ .byte 0,0,0,1,128,1,0,1 ++ .size func0,.-.L.func0 ++ .section ".toc","aw" ++.LC1: ++ .tc var[TC],var ++ .section ".text" ++ .align 2 ++ .globl func1 ++ .section ".opd","aw" ++ .align 3 ++func1: ++ .quad .L.func1,.TOC.@tocbase ++ .previous ++ .type func1, @function ++.L.func1: ++ mflr 0 ++/* 20 = BO = branch always ++ 31 = BI = CR bit (ignored) */ ++ bcl 20,31,.Lpie ++.Lpie: std 31,-8(1) ++ std 0,16(1) ++ stdu 1,-128(1) ++ mr 31,1 ++ bl func0 ++ mr 11,3 ++ ld 9,.LC1@toc(2) ++ lwz 0,0(9) ++ add 0,11,0 ++ extsw 0,0 ++ mr 3,0 ++ ld 1,0(1) ++ ld 0,16(1) ++ mtlr 0 ++ ld 31,-8(1) ++ blr ++ .long 0 ++ .byte 0,0,0,1,128,1,0,1 ++ .size func1,.-.L.func1 ++ .section .note.GNU-stack,"",@progbits ++ .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-8)" ++ ++/* Original source file: ++ ++#include ++ ++extern volatile int var; ++ ++int func0 (void) __attribute__((__noinline__)); ++int func0 (void) ++{ ++ abort (); ++ return var; ++} ++ ++int func1 (void) __attribute__((__noinline__)); ++int func1 (void) ++{ ++ return func0 () + var; ++} ++ ++*/ +diff -u -ruNp gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.c gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.c +--- gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.c 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.c 2007-08-02 13:25:10.000000000 -0400 +@@ -0,0 +1,29 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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. */ ++ ++/* Force `-fpie' double jump bl->blrl. */ ++/* No longer used. */ ++volatile int var; ++ ++extern int func1 (void); ++ ++int main (void) ++{ ++ func1 (); ++ return 0; ++} +diff -u -ruNp gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.exp gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.exp +--- gdb-6.3-unpatched/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.exp 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.3/gdb/testsuite/gdb.arch/powerpc-bcl-prologue.exp 2007-08-02 14:21:29.000000000 -0400 +@@ -0,0 +1,79 @@ ++# Copyright 2006, 2007 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. ++ ++# Test unwinding fixes of the PPC platform, specifically on the coping with BCL ++# jump of the PIE code. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++if ![istarget "powerpc*-*-linux*"] then { ++ verbose "Skipping powerpc-linux prologue tests." ++ return ++} ++ ++set testfile "powerpc-bcl-prologue" ++set srcfile1 ${testfile}.c ++set flags "debug" ++if [istarget "powerpc-*"] then { ++ set srcfile2 ${testfile}-asm32.S ++ set flags "$flags additional_flags=-m32" ++} elseif [istarget "powerpc64-*"] then { ++ set srcfile2 ${testfile}-asm64.S ++ set flags "$flags additional_flags=-m64" ++} else { ++ fail "powerpc arch test" ++ return ++} ++set objfile2 ${objdir}/${subdir}/${testfile}-asm.o ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile1} ${srcdir}/${subdir}/${srcfile2}" ${binfile} executable $flags] != ""} { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# We should stop in abort(3). ++ ++gdb_run_cmd ++ ++gdb_test_multiple {} "continue to abort()" { ++ -re ".*Program received signal SIGABRT,.*$gdb_prompt $" { ++ pass "continue to abort()" ++ } ++} ++ ++# Check backtrace: ++# #3 0x0804835f in func0 () ++# #4 0x0804836a in func1 () ++# #5 0x0804838c in main () ++# (gdb) ++# `\\.?' prefixes are needed for ppc64 without `debug' (another bug). ++ ++set test "matching unwind" ++gdb_test_multiple "backtrace" $test { ++ -re "\r\n#\[0-9\]\[^\r\n\]* in \\.?func0 \\(\[^\r\n\]*\r\n#\[0-9\]\[^\r\n\]* in \\.?func1 \\(\[^\r\n\]*\r\n#\[0-9\]\[^\r\n\]* in \\.?main \\(\[^\r\n\]*\r\n$gdb_prompt $" { ++ pass $test ++ } ++} + +Fixup the testcase for ppc64 biarch GDB. + +--- ./gdb/testsuite/gdb.arch/powerpc-prologue.exp 2008-01-13 13:32:19.000000000 +0100 ++++ ./gdb/testsuite/gdb.arch/powerpc-prologue.exp 2008-01-02 00:04:10.000000000 +0100 +@@ -17,8 +17,9 @@ + # Test PowerPC prologue analyzer. + + # Do not run on AIX (where we won't be able to build the tests without +-# some surgery) or on PowerPC64 (ditto, dot symbols). +-if {[istarget *-*-aix*] || ![istarget "powerpc-*-*"]} then { ++# some surgery). PowerPC64 target would break due to dot symbols but we build ++# there PowerPC32 inferior. ++if {[istarget *-*-aix*] || ![istarget "powerpc*-*-*"]} then { + verbose "Skipping PowerPC prologue tests." + return + } diff --git a/gdb-6.3-bz202689-exec-from-pthread-test.patch b/gdb-6.3-bz202689-exec-from-pthread-test.patch new file mode 100644 index 0000000..3930abf --- /dev/null +++ b/gdb-6.3-bz202689-exec-from-pthread-test.patch @@ -0,0 +1,98 @@ +2007-01-17 Jan Kratochvil + + * gdb.threads/threaded-exec.exp, gdb.threads/threaded-exec.c: New files. + + +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threaded-exec.c 17 Jan 2007 23:10:22 -0000 +@@ -0,0 +1,46 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++static void * ++threader (void *arg) ++{ ++ return NULL; ++} ++ ++int ++main (void) ++{ ++ pthread_t t1; ++ int i; ++ ++ i = pthread_create (&t1, NULL, threader, (void *) NULL); ++ assert (i == 0); ++ i = pthread_join (t1, NULL); ++ assert (i == 0); ++ ++ execl ("/bin/true", "/bin/true", NULL); ++ abort (); ++} +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threaded-exec.exp 17 Jan 2007 23:10:22 -0000 +@@ -0,0 +1,41 @@ ++# threaded-exec.exp -- Check reset of the tracked threads on exec*(2) ++# Copyright (C) 2007 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 ++ ++set testfile threaded-exec ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable []] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++ ++gdb_load ${binfile} ++ ++gdb_run_cmd ++ ++gdb_test_multiple {} "Program exited" { ++ -re "\r\nProgram exited normally.\r\n$gdb_prompt $" { ++ pass "Program exited" ++ } ++} diff --git a/gdb-6.3-bz231832-obstack-2gb.patch b/gdb-6.3-bz231832-obstack-2gb.patch new file mode 100644 index 0000000..c63124a --- /dev/null +++ b/gdb-6.3-bz231832-obstack-2gb.patch @@ -0,0 +1,201 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=231832 + + +Index: gdb-6.8/gdb/symmisc.c +=================================================================== +--- gdb-6.8.orig/gdb/symmisc.c 2008-03-17 16:06:24.000000000 +0100 ++++ gdb-6.8/gdb/symmisc.c 2008-07-14 10:27:50.000000000 +0200 +@@ -230,8 +230,8 @@ print_objfile_statistics (void) + if (OBJSTAT (objfile, sz_strtab) > 0) + printf_filtered (_(" Space used by a.out string tables: %d\n"), + OBJSTAT (objfile, sz_strtab)); +- printf_filtered (_(" Total memory used for objfile obstack: %d\n"), +- obstack_memory_used (&objfile->objfile_obstack)); ++ printf_filtered (_(" Total memory used for objfile obstack: %ld\n"), ++ (long) obstack_memory_used (&objfile->objfile_obstack)); + printf_filtered (_(" Total memory used for psymbol cache: %d\n"), + bcache_memory_used (objfile->psymbol_cache)); + printf_filtered (_(" Total memory used for macro cache: %d\n"), +Index: gdb-6.8/include/obstack.h +=================================================================== +--- gdb-6.8.orig/include/obstack.h 2005-05-10 12:21:08.000000000 +0200 ++++ gdb-6.8/include/obstack.h 2008-07-14 10:27:50.000000000 +0200 +@@ -188,31 +188,31 @@ struct obstack /* control current objec + + /* Declare the external functions we use; they are in obstack.c. */ + +-extern void _obstack_newchunk (struct obstack *, int); ++extern void _obstack_newchunk (struct obstack *, PTR_INT_TYPE); + extern void _obstack_free (struct obstack *, void *); +-extern int _obstack_begin (struct obstack *, int, int, ++extern int _obstack_begin (struct obstack *, PTR_INT_TYPE, int, + void *(*) (long), void (*) (void *)); +-extern int _obstack_begin_1 (struct obstack *, int, int, ++extern int _obstack_begin_1 (struct obstack *, PTR_INT_TYPE, int, + void *(*) (void *, long), + void (*) (void *, void *), void *); +-extern int _obstack_memory_used (struct obstack *); ++extern PTR_INT_TYPE _obstack_memory_used (struct obstack *); + + /* Do the function-declarations after the structs + but before defining the macros. */ + + void obstack_init (struct obstack *obstack); + +-void * obstack_alloc (struct obstack *obstack, int size); ++void * obstack_alloc (struct obstack *obstack, PTR_INT_TYPE size); + +-void * obstack_copy (struct obstack *obstack, void *address, int size); +-void * obstack_copy0 (struct obstack *obstack, void *address, int size); ++void * obstack_copy (struct obstack *obstack, void *address, PTR_INT_TYPE size); ++void * obstack_copy0 (struct obstack *obstack, void *address, PTR_INT_TYPE size); + + void obstack_free (struct obstack *obstack, void *block); + +-void obstack_blank (struct obstack *obstack, int size); ++void obstack_blank (struct obstack *obstack, PTR_INT_TYPE size); + +-void obstack_grow (struct obstack *obstack, void *data, int size); +-void obstack_grow0 (struct obstack *obstack, void *data, int size); ++void obstack_grow (struct obstack *obstack, void *data, PTR_INT_TYPE size); ++void obstack_grow0 (struct obstack *obstack, void *data, PTR_INT_TYPE size); + + void obstack_1grow (struct obstack *obstack, int data_char); + void obstack_ptr_grow (struct obstack *obstack, void *data); +@@ -220,20 +220,20 @@ void obstack_int_grow (struct obstack *o + + void * obstack_finish (struct obstack *obstack); + +-int obstack_object_size (struct obstack *obstack); ++PTR_INT_TYPE obstack_object_size (struct obstack *obstack); + +-int obstack_room (struct obstack *obstack); +-void obstack_make_room (struct obstack *obstack, int size); ++PTR_INT_TYPE obstack_room (struct obstack *obstack); ++void obstack_make_room (struct obstack *obstack, PTR_INT_TYPE size); + void obstack_1grow_fast (struct obstack *obstack, int data_char); + void obstack_ptr_grow_fast (struct obstack *obstack, void *data); + void obstack_int_grow_fast (struct obstack *obstack, int data); +-void obstack_blank_fast (struct obstack *obstack, int size); ++void obstack_blank_fast (struct obstack *obstack, PTR_INT_TYPE size); + + void * obstack_base (struct obstack *obstack); + void * obstack_next_free (struct obstack *obstack); + int obstack_alignment_mask (struct obstack *obstack); +-int obstack_chunk_size (struct obstack *obstack); +-int obstack_memory_used (struct obstack *obstack); ++size_t obstack_chunk_size (struct obstack *obstack); ++size_t obstack_memory_used (struct obstack *obstack); + + /* Error handler called when `obstack_chunk_alloc' failed to allocate + more memory. This can be set to a user defined function. The +@@ -318,7 +318,7 @@ extern int obstack_exit_failure; + # define obstack_make_room(OBSTACK,length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ +- int __len = (length); \ ++ PTR_INT_TYPE __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + (void) 0; }) +@@ -331,7 +331,7 @@ __extension__ \ + # define obstack_grow(OBSTACK,where,length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ +- int __len = (length); \ ++ PTR_INT_TYPE __len = (length); \ + if (__o->next_free + __len > __o->chunk_limit) \ + _obstack_newchunk (__o, __len); \ + _obstack_memcpy (__o->next_free, (where), __len); \ +@@ -341,7 +341,7 @@ __extension__ \ + # define obstack_grow0(OBSTACK,where,length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ +- int __len = (length); \ ++ PTR_INT_TYPE __len = (length); \ + if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, __len + 1); \ + _obstack_memcpy (__o->next_free, (where), __len); \ +@@ -392,7 +392,7 @@ __extension__ \ + # define obstack_blank(OBSTACK,length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ +- int __len = (length); \ ++ PTR_INT_TYPE __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + obstack_blank_fast (__o, __len); \ +@@ -532,7 +532,7 @@ __extension__ \ + # define obstack_free(h,obj) \ + ( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ +- ? (int) ((h)->next_free = (h)->object_base \ ++ ? (PTR_INT_TYPE) ((h)->next_free = (h)->object_base \ + = (h)->temp + (char *) (h)->chunk) \ + : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) + +Index: gdb-6.8/libiberty/obstack.c +=================================================================== +--- gdb-6.8.orig/libiberty/obstack.c 2005-05-10 17:33:33.000000000 +0200 ++++ gdb-6.8/libiberty/obstack.c 2008-07-14 10:27:50.000000000 +0200 +@@ -44,9 +44,11 @@ + #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 + #include + #if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION ++#if 0 /* 64-bit obstack is not compatible with any glibc implementation. */ + #define ELIDE_CODE + #endif + #endif ++#endif + + + #ifndef ELIDE_CODE +@@ -139,7 +141,7 @@ struct obstack *_obstack; + free up some memory, then call this again. */ + + int +-_obstack_begin (struct obstack *h, int size, int alignment, ++_obstack_begin (struct obstack *h, PTR_INT_TYPE size, int alignment, + POINTER (*chunkfun) (long), void (*freefun) (void *)) + { + register struct _obstack_chunk *chunk; /* points to new chunk */ +@@ -183,7 +185,7 @@ _obstack_begin (struct obstack *h, int s + } + + int +-_obstack_begin_1 (struct obstack *h, int size, int alignment, ++_obstack_begin_1 (struct obstack *h, PTR_INT_TYPE size, int alignment, + POINTER (*chunkfun) (POINTER, long), + void (*freefun) (POINTER, POINTER), POINTER arg) + { +@@ -235,7 +237,7 @@ _obstack_begin_1 (struct obstack *h, int + to the beginning of the new one. */ + + void +-_obstack_newchunk (struct obstack *h, int length) ++_obstack_newchunk (struct obstack *h, PTR_INT_TYPE length) + { + register struct _obstack_chunk *old_chunk = h->chunk; + register struct _obstack_chunk *new_chunk; +@@ -388,11 +390,11 @@ obstack_free (struct obstack *h, POINTER + abort (); + } + +-int ++PTR_INT_TYPE + _obstack_memory_used (struct obstack *h) + { + register struct _obstack_chunk* lp; +- register int nbytes = 0; ++ register PTR_INT_TYPE nbytes = 0; + + for (lp = h->chunk; lp != 0; lp = lp->prev) + { +@@ -421,6 +423,7 @@ print_and_abort (void) + } + + #if 0 ++/* These functions are now broken for 64-bit obstack! */ + /* These are now turned off because the applications do not use it + and it uses bcopy via obstack_grow, which causes trouble on sysV. */ + diff --git a/gdb-6.3-dtorfix-20050121.patch b/gdb-6.3-dtorfix-20050121.patch new file mode 100644 index 0000000..b4e3e54 --- /dev/null +++ b/gdb-6.3-dtorfix-20050121.patch @@ -0,0 +1,52 @@ +2005-01-21 Jeff Johnston + + * linespec.c (collect_methods): Don't do special processing for + destructors as this will be handled in find_methods. + (find_methods): Fix ctor check to also check for dtor. + +2007-10-14 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.7/gdb/linespec.c +=================================================================== +--- gdb-6.7.orig/gdb/linespec.c 2007-10-13 05:26:33.000000000 +0200 ++++ gdb-6.7/gdb/linespec.c 2007-10-14 23:31:03.000000000 +0200 +@@ -398,12 +398,14 @@ add_matching_methods (int method_counter + + /* Check for special case of looking for member that + doesn't have a mangled name provided. This will happen +- when we have in-charge and not-in-charge constructors. ++ when we have in-charge and not-in-charge ctors/dtors. + Since we don't have a mangled name to work with, if we +- look for the symbol, we can only find the class itself. ++ look for the symbol, we can at best find the class itself. + We can find the information we need in the minimal symbol + table which has the full member name information we need. */ +- if (strlen (phys_name) <= strlen (class_name)) ++ if (strlen (phys_name) <= strlen (class_name) ++ || (strlen (phys_name) == strlen (class_name) + 1 ++ && phys_name[0] == '~')) + return add_minsym_members (class_name, phys_name, msym_arr); + + /* Destructor is handled by caller, don't add it to +@@ -1731,6 +1733,11 @@ collect_methods (char *copy, struct type + { + int i1 = 0; /* Counter for the symbol array. */ + ++#if 0 ++ /* Ignore this special method for getting destructors because ++ find_methods is more robust and can handle multiple ++ destructors which is the case when gcc generates a not-in-charge ++ vs an in-charge destructor. */ + if (destructor_name_p (copy, t)) + { + /* Destructors are a special case. */ +@@ -1749,6 +1756,7 @@ collect_methods (char *copy, struct type + } + } + else ++#endif + i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr, msym_arr); + + return i1; diff --git a/gdb-6.3-focus-cmd-prev-test.patch b/gdb-6.3-focus-cmd-prev-test.patch new file mode 100644 index 0000000..48ae3c5 --- /dev/null +++ b/gdb-6.3-focus-cmd-prev-test.patch @@ -0,0 +1,28 @@ +--- /dev/null 2008-03-23 13:41:46.072650180 +0100 ++++ gdb-6.3/gdb/testsuite/gdb.base/focus-cmd-prev.exp 2008-03-23 23:46:45.000000000 +0100 +@@ -0,0 +1,25 @@ ++# Copyright 2008 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++gdb_exit ++gdb_start ++ ++gdb_test "focus cmd" ++gdb_test "focus prev" diff --git a/gdb-6.3-framepczero-20040927.patch b/gdb-6.3-framepczero-20040927.patch new file mode 100644 index 0000000..3c9ed05 --- /dev/null +++ b/gdb-6.3-framepczero-20040927.patch @@ -0,0 +1,28 @@ +2004-09-27 Andrew Cagney + + * frame.c (get_prev_frame): Stop backtrace when a zero PC and + successive normal frames. + +Index: gdb-6.8.50.20081128/gdb/frame.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/frame.c 2008-12-04 01:34:37.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/frame.c 2008-12-04 01:35:47.000000000 +0100 +@@ -1566,6 +1566,18 @@ get_prev_frame (struct frame_info *this_ + return NULL; + } + ++ if (this_frame->level > 0 ++#if 0 ++ && backtrace_past_zero_pc ++#endif ++ && get_frame_type (this_frame) == NORMAL_FRAME ++ && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME ++ && get_frame_pc (this_frame) == 0) ++ { ++ frame_debug_got_null_frame (this_frame, "zero PC"); ++ return NULL; ++ } ++ + return get_prev_frame_1 (this_frame); + } + diff --git a/gdb-6.3-gcore-thread-20050204.patch b/gdb-6.3-gcore-thread-20050204.patch new file mode 100644 index 0000000..1afb832 --- /dev/null +++ b/gdb-6.3-gcore-thread-20050204.patch @@ -0,0 +1,25 @@ +2005-02-07 Jeff Johnston + + * linux-nat.c (linux_nat_xfer_memory): Don't use + linux_proc_xfer_memory for ia64. + +Index: gdb-6.8.50.20081209/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/linux-nat.c 2008-12-10 01:22:23.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/linux-nat.c 2008-12-10 01:25:26.000000000 +0100 +@@ -4123,10 +4123,15 @@ linux_xfer_partial (struct target_ops *o + return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf, + offset, len); + ++#ifndef NATIVE_XFER_UNWIND_TABLE ++ /* FIXME: For ia64, we cannot currently use linux_proc_xfer_memory ++ for accessing thread storage. Revert when Bugzilla 147436 ++ is fixed. */ + xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf, + offset, len); + if (xfer != 0) + return xfer; ++#endif + + return super_xfer_partial (ops, object, annex, readbuf, writebuf, + offset, len); diff --git a/gstack.patch b/gdb-6.3-gstack-20050411.patch similarity index 56% rename from gstack.patch rename to gdb-6.3-gstack-20050411.patch index 2422459..8715abb 100644 --- a/gstack.patch +++ b/gdb-6.3-gstack-20050411.patch @@ -2,20 +2,22 @@ * Makefile.in (uninstall-gstack, install-gstack): New rules, add to install and uninstall. - * gstack.sh: New file. + * gstack.sh, gstack.1: New files. ---- gdb/Makefile.in 2004-11-23 13:31:03.000000000 -0500 -+++ gdb/Makefile.in 2004-11-23 15:06:34.623389592 -0500 -@@ -970,7 +970,7 @@ - # time it takes for make to check that all is up to date. - # install-only is intended to address that need. - install: all install-only --install-only: $(CONFIG_INSTALL) -+install-only: install-gstack $(CONFIG_INSTALL) +Index: gdb-6.8.50.20090226/gdb/Makefile.in +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/Makefile.in 2009-02-26 22:09:59.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/Makefile.in 2009-02-26 22:10:22.000000000 +0100 +@@ -973,7 +973,7 @@ install: all install-only + + # The "install-only" target also installs the syscalls' XML files in + # the system. +-install-only: $(CONFIG_INSTALL) xml-syscall-install ++install-only: install-gstack $(CONFIG_INSTALL) xml-syscall-install transformed_name=`t='$(program_transform_name)'; \ echo gdb | sed -e "$$t"` ; \ if test "x$$transformed_name" = x; then \ -@@ -1002,9 +1002,22 @@ +@@ -1005,9 +1005,26 @@ install-tui: $(DESTDIR)$(man1dir) ; \ $(INSTALL_DATA) $(srcdir)/gdb.1 \ $(DESTDIR)$(man1dir)/$$transformed_name.1 @@ -24,14 +26,18 @@ +install-gstack: + transformed_name=`t='$(program_transform_name)'; \ + echo $(GSTACK) | sed -e "$$t"` ; \ -+ if test "x$$transformed_name" = x; then \ -+ transformed_name=$(GSTACK) ; \ -+ else \ -+ true ; \ -+ fi ; \ -+ $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) ; \ -+ $(INSTALL_PROGRAM) $(srcdir)/$(GSTACK).sh \ -+ $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) ; \ ++ if test "x$$transformed_name" = x; then \ ++ transformed_name=$(GSTACK) ; \ ++ else \ ++ true ; \ ++ fi ; \ ++ $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) ; \ ++ $(INSTALL_PROGRAM) $(srcdir)/$(GSTACK).sh \ ++ $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) ; \ ++ : $(SHELL) $(srcdir)/../mkinstalldirs \ ++ $(DESTDIR)$(man1dir) ; \ ++ : $(INSTALL_DATA) $(srcdir)/gstack.1 \ ++ $(DESTDIR)$(man1dir)/$$transformed_name.1 -uninstall: force $(CONFIG_UNINSTALL) @@ -39,7 +45,7 @@ transformed_name=`t='$(program_transform_name)'; \ echo gdb | sed -e $$t` ; \ if test "x$$transformed_name" = x; then \ -@@ -1026,6 +1043,16 @@ +@@ -1029,6 +1046,17 @@ uninstall-tui: fi ; \ rm -f $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) \ $(DESTDIR)$(man1dir)/$$transformed_name.1 @@ -47,17 +53,20 @@ +uninstall-gstack: + transformed_name=`t='$(program_transform_name)'; \ + echo $(GSTACK) | sed -e $$t` ; \ -+ if test "x$$transformed_name" = x; then \ -+ transformed_name=$(GSTACK) ; \ -+ else \ -+ true ; \ -+ fi ; \ -+ rm -f $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) ++ if test "x$$transformed_name" = x; then \ ++ transformed_name=$(GSTACK) ; \ ++ else \ ++ true ; \ ++ fi ; \ ++ rm -f $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) \ ++ $(DESTDIR)$(man1dir)/$$transformed_name.1 - # We do this by grepping through sources. If that turns out to be too slow, - # maybe we could just require every .o file to have an initialization routine ---- /dev/null 2005-04-09 23:51:05.027867440 -0400 -+++ gdb/gstack.sh 2005-04-08 18:00:49.000000000 -0400 + # The C++ name parser can be built standalone for testing. + test-cp-name-parser.o: cp-name-parser.c +Index: gdb-6.8.50.20090226/gdb/gstack.sh +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090226/gdb/gstack.sh 2009-02-26 22:10:05.000000000 +0100 @@ -0,0 +1,45 @@ +#!/bin/sh + diff --git a/gdb-6.3-gstack-without-path-20060414.patch b/gdb-6.3-gstack-without-path-20060414.patch new file mode 100644 index 0000000..b39300f --- /dev/null +++ b/gdb-6.3-gstack-without-path-20060414.patch @@ -0,0 +1,34 @@ +Index: gdb-6.3/gdb/gstack.sh +=================================================================== +--- gdb-6.3.orig/gdb/gstack.sh 2006-02-14 17:21:05.000000000 -0200 ++++ gdb-6.3/gdb/gstack.sh 2006-04-14 03:17:12.000000000 -0300 +@@ -17,17 +17,17 @@ fi + backtrace="bt" + if test -d /proc/$1/task ; then + # Newer kernel; has a task/ directory. +- if test `ls /proc/$1/task | wc -l` -gt 1 2>/dev/null ; then ++ if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then + backtrace="thread apply all bt" + fi + elif test -f /proc/$1/maps ; then + # Older kernel; go by it loading libpthread. +- if grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then ++ if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then + backtrace="thread apply all bt" + fi + fi + +-GDB=${GDB:-gdb} ++GDB=${GDB:-/usr/bin/gdb} + + if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then + readnever=--readnever +@@ -39,7 +39,7 @@ fi + $GDB --quiet $readnever -nx /proc/$1/exe $1 <&1 | + $backtrace + EOF +-sed -n \ ++/bin/sed -n \ + -e 's/^(gdb) //' \ + -e '/^#/p' \ + -e '/^Thread/p' diff --git a/gdb-6.3-ia64-gcore-page0-20050421.patch b/gdb-6.3-ia64-gcore-page0-20050421.patch new file mode 100644 index 0000000..0998ede --- /dev/null +++ b/gdb-6.3-ia64-gcore-page0-20050421.patch @@ -0,0 +1,20 @@ +Index: gdb-6.8.50.20081128/gdb/gcore.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/gcore.c 2008-09-11 16:27:34.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/gcore.c 2008-12-01 16:39:04.000000000 +0100 +@@ -475,8 +475,14 @@ gcore_copy_callback (bfd *obfd, asection + if (size > total_size) + size = total_size; + ++ /* Warn if read error occurs except if we were trying to read the ++ first page for ia64. The first page is marked readable, but it cannot ++ be read. */ + if (target_read_memory (bfd_section_vma (obfd, osec) + offset, +- memhunk, size) != 0) ++ memhunk, size) != 0 ++ && (strcmp (gdbarch_bfd_arch_info (current_gdbarch)->arch_name, ++ "ia64") ++ || bfd_section_vma (obfd, osec) != 0)) + { + warning (_("Memory read failed for corefile section, %s bytes at 0x%s."), + plongest (size), paddr (bfd_section_vma (obfd, osec))); diff --git a/gdb-6.3-ia64-gcore-speedup-20050714.patch b/gdb-6.3-ia64-gcore-speedup-20050714.patch new file mode 100644 index 0000000..cf60efc --- /dev/null +++ b/gdb-6.3-ia64-gcore-speedup-20050714.patch @@ -0,0 +1,126 @@ +2005-07-14 Jeff Johnsotn + + * linux-nat.c (linux_nat_xfer_memory): Incorporate Fujitsu + work-around to use /proc/mem for storage, but to fall-back + to PTRACE for ia64 rse register areas. + * ia64-linux-nat.c (ia64_rse_slot_num): New static function. + (ia64_rse_skip_regs): Ditto. + (ia64_linux_check_stack_region): New function. + +Index: gdb-6.8.50.20090226/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/linux-nat.c 2009-02-27 07:51:44.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/linux-nat.c 2009-02-28 07:19:05.000000000 +0100 +@@ -4386,15 +4386,38 @@ linux_xfer_partial (struct target_ops *o + return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf, + offset, len); + +-#ifndef NATIVE_XFER_UNWIND_TABLE +- /* FIXME: For ia64, we cannot currently use linux_proc_xfer_memory +- for accessing thread storage. Revert when Bugzilla 147436 +- is fixed. */ + xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf, + offset, len); + if (xfer != 0) +- return xfer; ++ { ++#ifdef NATIVE_XFER_UNWIND_TABLE ++ struct mem_region range; ++ range.lo = memaddr; ++ range.hi = memaddr + len; ++ ++ /* FIXME: For ia64, we cannot currently use ++ linux_proc_xfer_partial for accessing rse register storage. ++ Revert when Bugzilla 147436 is fixed. */ ++#ifdef NATIVE_XFER_UNWIND_TABLE ++ extern int ia64_linux_check_stack_region (struct lwp_info *lwp, ++ void *range); ++#endif ++ if (iterate_over_lwps (ia64_linux_check_stack_region, &range) != NULL) ++ { /* This region contains ia64 rse registers, we have to re-read. */ ++ int xxfer; ++ ++ /* Re-read register stack area. */ ++ xxfer = super_xfer_partial (ops, object, annex, ++ readbuf + (range.lo - memaddr), ++ writebuf + (range.lo - memaddr), ++ offset + (range.lo - memaddr), ++ range.hi - range.lo); ++ if (xxfer == 0) ++ xfer = 0; ++ } + #endif ++ return xfer; ++ } + + return super_xfer_partial (ops, object, annex, readbuf, writebuf, + offset, len); +Index: gdb-6.8.50.20090226/gdb/ia64-linux-nat.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/ia64-linux-nat.c 2009-02-23 01:03:49.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/ia64-linux-nat.c 2009-02-28 07:18:10.000000000 +0100 +@@ -809,6 +809,64 @@ ia64_linux_xfer_partial (struct target_o + + void _initialize_ia64_linux_nat (void); + ++/* ++ * Note: taken from ia64_tdep.c ++ * ++ */ ++ ++static __inline__ unsigned long ++ia64_rse_slot_num (unsigned long addr) ++{ ++ return (addr >> 3) & 0x3f; ++} ++ ++/* Skip over a designated number of registers in the backing ++ store, remembering every 64th position is for NAT. */ ++static __inline__ unsigned long ++ia64_rse_skip_regs (unsigned long addr, long num_regs) ++{ ++ long delta = ia64_rse_slot_num(addr) + num_regs; ++ ++ if (num_regs < 0) ++ delta -= 0x3e; ++ return addr + ((num_regs + delta/0x3f) << 3); ++} ++ ++/* ++ * Check mem_region is stack or not. If stack, /proc//mem cannot return ++ * expected value. ++ */ ++int ia64_linux_check_stack_region(struct lwp_info *ti, struct mem_region *range) ++{ ++ CORE_ADDR addr; ++ int error; ++ unsigned long bsp, cfm, bspstore; ++ long sof; ++ pid_t pid = ptid_get_lwp(ti->ptid); ++ bsp = ptrace(PTRACE_PEEKUSER, pid, PT_AR_BSP ,NULL); ++ if (bsp == (unsigned long)-1) { ++ return 1; ++ } ++ /* stack is allocated by one-segment, not separated into several segments. ++ So, we only have to check whether bsp is in *range* or not. */ ++ if((range->lo <= bsp) && (bsp <= range->hi)) { ++ bspstore = ptrace(PTRACE_PEEKUSER, pid, PT_AR_BSPSTORE, NULL); ++ cfm = ptrace(PTRACE_PEEKUSER, pid, PT_CFM, NULL); ++ sof = cfm & 0x3f; ++ bsp = ia64_rse_skip_regs(bsp, -sof); ++ range->lo = bspstore; ++ range->hi = bsp; ++ /* we have to check the size of dirty register stack area */ ++ /* ++ fprintf_unfiltered(gdb_stdlog, "<%d> <%p> <%lx> <%p> <%p>\n", ++ pid, bsp, sof, range->lo, range->hi); ++ */ ++ return 1; ++ } ++ ++ return 0; ++} ++ + void + _initialize_ia64_linux_nat (void) + { diff --git a/gdb-6.3-ia64-info-frame-fix-20050725.patch b/gdb-6.3-ia64-info-frame-fix-20050725.patch new file mode 100644 index 0000000..d764af2 --- /dev/null +++ b/gdb-6.3-ia64-info-frame-fix-20050725.patch @@ -0,0 +1,110 @@ +2005-07-25 Jeff Johnstno + + * libunwind-frame.c (libunwind_frame_prev_register): Check valuep + is not NULL before copying cursor address into it. + +testsuite: +2005-07-25 Jeff Johnstno + + * gdb.arch/ia64-sigtramp.exp: New test. + * gdb.arch/ia64-sigtramp.c: Ditto. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. (Only the testcase has remained.) + +--- gdb-6.3/gdb/testsuite/gdb.arch/ia64-sigtramp.c.fix 2005-07-25 16:42:46.000000000 -0400 ++++ gdb-6.3/gdb/testsuite/gdb.arch/ia64-sigtramp.c 2005-07-25 16:42:08.000000000 -0400 +@@ -0,0 +1,23 @@ ++#include ++#include ++ ++int *l; ++ ++void x (int sig) ++{ ++ printf ("in signal handler for signal %d\n", sig); ++} ++ ++int main() ++{ ++ int k; ++ ++ signal (SIGSEGV, &x); ++ ++ k = *l; ++ ++ printf ("k is %d\n", k); ++ ++ return 0; ++} ++ +--- gdb-6.3/gdb/testsuite/gdb.arch/ia64-sigtramp.exp.fix 2005-07-25 16:42:50.000000000 -0400 ++++ gdb-6.3/gdb/testsuite/gdb.arch/ia64-sigtramp.exp 2005-07-25 16:42:01.000000000 -0400 +@@ -0,0 +1,66 @@ ++# Copyright 2005 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 Jeff Johnston (jjohnstn@redhat.com) ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++# ++# test running programs ++# ++set prms_id 0 ++set bug_id 0 ++ ++if ![istarget "ia64-*-*"] then { ++ return ++} ++ ++set testfile "ia64-sigtramp" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } { ++ 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 ![runto_main] then { ++ fail "Can't run to main" ++ return 0 ++} ++ ++gdb_test "handle SIGSEGV" "SIGSEGV.*Yes.*Yes.*Yes.*Segmentation fault" ++gdb_test "next" "" "first next" ++gdb_test "next" "Program received signal SIGSEGV.*" "getting SIGSEGV" ++gdb_breakpoint "x" ++gdb_test "continue" "Breakpoint.*x.*" "continue to x" ++ ++gdb_test "f 1" ".*signal handler called.*" "frame 1" ++gdb_test "info frame" "Stack level 1.*p63 at .*" "info sigtramp frame" ++ diff --git a/gdb-6.3-ia64-sigill-20051115.patch b/gdb-6.3-ia64-sigill-20051115.patch new file mode 100644 index 0000000..695bb83 --- /dev/null +++ b/gdb-6.3-ia64-sigill-20051115.patch @@ -0,0 +1,116 @@ +2005-11-15 Jeff Johnston + + * linux-thread-db.c (thread_db_wait): Don't bother continuing if + the wait result indicates the program terminated with a signal. + * linux-nat.c (linux_nat_wait): For SIGILL and SIGTRAP, don't + throw away the event if the user has specified nostop noprint. + +gdb/testsuite: + +2005-11-15 Jeff Johnston + + * gdb.arch/ia64-sigill.c: New test. + * gdb.arch/ia64-sigill.exp: Ditto. + +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.arch/ia64-sigill.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.arch/ia64-sigill.exp 2008-12-02 21:10:57.000000000 +0100 +@@ -0,0 +1,59 @@ ++# Copyright 2005 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 Jeff Johnston (jjohnstn@redhat.com) ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++# ++# test running programs ++# ++set prms_id 0 ++set bug_id 0 ++ ++if ![istarget "ia64-*-*"] then { ++ return ++} ++ ++set testfile "ia64-sigill" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++# Deliberately compile with pthreads, even though test is single-threaded. ++# We want to force gdb thread code to be exercised. ++if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } { ++ 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} ++ ++# We set up SIGILL nostop, noprint, pass and then run the program. ++# We expect to just see a normal run. ++gdb_test "handle SIGILL nostop noprint" "SIGILL.*No.*No.*Yes.*" "handle sigill" ++gdb_test "run" "Starting program.*ia64-sigill.*\[New thread.*\].*hello world.*Program exited normally." "run to exit" ++ +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.arch/ia64-sigill.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.arch/ia64-sigill.c 2008-12-02 21:10:57.000000000 +0100 +@@ -0,0 +1,8 @@ ++#include ++ ++int main() ++{ ++ printf ("hello world\n"); ++ return 0; ++} ++ +Index: gdb-6.8.50.20081128/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/linux-nat.c 2008-12-02 19:04:38.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/linux-nat.c 2008-12-02 21:11:11.000000000 +0100 +@@ -2974,7 +2974,8 @@ retry: + threads can be a bit time-consuming so if we want decent + performance with heavily multi-threaded programs, especially when + they're using a high frequency timer, we'd better avoid it if we +- can. */ ++ can. For possible trap signals like SIGTRAP and SIGILL, don't ++ avoid reporting. */ + + if (WIFSTOPPED (status)) + { +@@ -2992,7 +2993,9 @@ retry: + && inf->stop_soon == NO_STOP_QUIETLY + && signal_stop_state (signo) == 0 + && signal_print_state (signo) == 0 +- && signal_pass_state (signo) == 1) ++ && signal_pass_state (signo) == 1 ++ && signo != TARGET_SIGNAL_ILL ++ && signo != TARGET_SIGNAL_TRAP) + { + /* FIMXE: kettenis/2001-06-06: Should we resume all threads + here? It is not clear we should. GDB may not expect diff --git a/gdb-6.3-ia64-sigtramp-fp-20050926.patch b/gdb-6.3-ia64-sigtramp-fp-20050926.patch new file mode 100644 index 0000000..dd60976 --- /dev/null +++ b/gdb-6.3-ia64-sigtramp-fp-20050926.patch @@ -0,0 +1,163 @@ +2005-09-27 Jeff Johnston + + * libunwind-frame.c (libunwind_frame_cache): Save the current + stack pointer in the cache. + (libunwind_sigtramp_frame_this_id): New function. + (libunwind_sigtramp_frame_unwind): New unwinder. + (libunwind_sigtramp_frame_sniffer): Return + libunwind_sigtramp_frame_unwind address. + * libunwind-frame.h (libunwind_sigtramp_frame_this_id): New + prototype. + * ia64-tdep.c (ia64_libunwind_sigtramp_frame_this_id): Calculate + the base address using the current stack pointer plus a fixed + offset. + +2007-10-14 Jan Kratochvil + + Port to GDB-6.7. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +2008-04-16 Yi Zhan + + Fix a compilation error on a typo. + +Index: gdb-6.8.50.20081128/gdb/libunwind-frame.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/libunwind-frame.c 2008-05-06 20:37:46.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/libunwind-frame.c 2008-12-02 19:46:26.000000000 +0100 +@@ -61,6 +61,7 @@ static unw_word_t (*unw_find_dyn_list_p) + struct libunwind_frame_cache + { + CORE_ADDR base; ++ CORE_ADDR sp; + CORE_ADDR func_addr; + unw_cursor_t cursor; + unw_addr_space_t as; +@@ -133,6 +134,7 @@ libunwind_frame_cache (struct frame_info + unw_accessors_t *acc; + unw_addr_space_t as; + unw_word_t fp; ++ unw_word_t sp; + unw_regnum_t uw_sp_regnum; + struct libunwind_frame_cache *cache; + struct libunwind_descr *descr; +@@ -174,14 +176,30 @@ libunwind_frame_cache (struct frame_info + : __LITTLE_ENDIAN); + + unw_init_remote_p (&cache->cursor, as, this_frame); ++ ++ /* For the base address, we have a small problem. The majority ++ of the time, we can get the stack pointer of the previous ++ frame to use as a frame pointer. In the case where we have ++ a signal trampoline, the stack may change due to a sigaltstack ++ being set up. In that case, the normal mechanism will give us ++ an address in the regular stack which is not at the end of the ++ sigaltstack as we want. To handle this, we record the stack ++ address so the caller may calculate a more correct base address ++ to use. */ ++ uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch)); ++ ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &sp); ++ if (ret < 0) ++ { ++ unw_destroy_addr_space_p (as); ++ error (_("Can't get libunwind sp register.")); ++ } ++ + if (unw_step_p (&cache->cursor) < 0) + { + unw_destroy_addr_space_p (as); + return NULL; + } + +- /* To get base address, get sp from previous frame. */ +- uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch)); + ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp); + if (ret < 0) + { +@@ -189,6 +207,7 @@ libunwind_frame_cache (struct frame_info + error (_("Can't get libunwind sp register.")); + } + ++ cache->sp = (CORE_ADDR)sp; + cache->base = (CORE_ADDR)fp; + cache->as = as; + +@@ -376,6 +395,31 @@ libunwind_search_unwind_table (void *as, + di, pi, need_unwind_info, args); + } + ++void ++libunwind_sigtramp_frame_this_id (struct frame_info *this_frame, ++ void **this_cache, ++ struct frame_id *this_id) ++{ ++ struct libunwind_frame_cache *cache = ++ libunwind_frame_cache (this_frame, this_cache); ++ ++ /* Unlike a regular frame, we can't use the normal frame pointer ++ mechanism because a sigaltstack may have been used. Instead, ++ we return the current stack pointer for the caller to use ++ to calculate the base address. */ ++ if (cache != NULL) ++ (*this_id) = frame_id_build (cache->sp, cache->func_addr); ++ else ++ (*this_id) = null_frame_id; ++} ++ ++static const struct frame_unwind libunwind_sigtramp_frame_unwind = ++{ ++ SIGTRAMP_FRAME, ++ libunwind_sigtramp_frame_this_id, ++ libunwind_frame_prev_register ++}; ++ + /* Verify if we are in a sigtramp frame and we can use libunwind to unwind. */ + int + libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self, +Index: gdb-6.8.50.20081128/gdb/libunwind-frame.h +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/libunwind-frame.h 2008-05-06 20:37:46.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/libunwind-frame.h 2008-12-02 19:38:55.000000000 +0100 +@@ -52,6 +52,9 @@ void libunwind_frame_set_descr (struct g + + void libunwind_frame_this_id (struct frame_info *this_frame, void **this_cache, + struct frame_id *this_id); ++void libunwind_sigtramp_frame_this_id (struct frame_info *this_frame, ++ void **this_cache, ++ struct frame_id *this_id); + struct value *libunwind_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum); + void libunwind_frame_dealloc_cache (struct frame_info *self, void *cache); +Index: gdb-6.8.50.20081128/gdb/ia64-tdep.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/ia64-tdep.c 2008-12-02 19:04:32.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/ia64-tdep.c 2008-12-02 21:09:46.000000000 +0100 +@@ -2964,7 +2964,7 @@ ia64_libunwind_sigtramp_frame_this_id (s + struct frame_id id; + CORE_ADDR prev_ip; + +- libunwind_frame_this_id (this_frame, this_cache, &id); ++ libunwind_sigtramp_frame_this_id (this_frame, this_cache, &id); + if (frame_id_eq (id, null_frame_id)) + { + (*this_id) = null_frame_id; +@@ -2976,8 +2976,14 @@ ia64_libunwind_sigtramp_frame_this_id (s + get_frame_register (this_frame, IA64_BSP_REGNUM, buf); + bsp = extract_unsigned_integer (buf, 8); + +- /* For a sigtramp frame, we don't make the check for previous ip being 0. */ +- (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp); ++ /* For a sigtramp frame, we don't make the check for previous ip being 0. ++ We also must calculate the frame pointer because libunwind will give ++ us back the current stack pointer instead of the frame pointer since ++ it cannot figure this out when in a sigaltstack. We make a basic ++ assumption of 16 (default size) + 8 bytes for sigcontext address. ++ FIXME: if libunwind were to export the frame pointer address, we ++ could eliminate the assumption and get the actual value. */ ++ (*this_id) = frame_id_build_special (id.stack_addr + 24, id.code_addr, bsp); + + if (gdbarch_debug >= 1) + fprintf_unfiltered (gdb_stdlog, diff --git a/gdb-6.3-ia64-sigtramp-frame-20050708.patch b/gdb-6.3-ia64-sigtramp-frame-20050708.patch new file mode 100644 index 0000000..243b80c --- /dev/null +++ b/gdb-6.3-ia64-sigtramp-frame-20050708.patch @@ -0,0 +1,158 @@ +2005-07-08 Jeff Johnston + + * ia64-tdep.c (ia64_sigtramp_frame_prev_register): Build + pseudo-registers the same as ia64_pseudo_register_read. + +2008-04-16 Yi Zhan + + * ia64-tdep.c (ia64_sigtramp_frame_prev_register): Fix an + ISO C compliance compilation error. + +2008-02-12 Jan Kratochvil + + Port to gdb-6.8.50.20081128, follow the upstream change: + http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ia64-tdep.c.diff?cvsroot=src&r1=1.176&r2=1.177 + +Index: gdb-6.8.50.20081128/gdb/ia64-tdep.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/ia64-tdep.c 2008-11-26 06:27:48.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/ia64-tdep.c 2008-12-02 19:04:32.000000000 +0100 +@@ -2107,6 +2107,94 @@ ia64_sigtramp_frame_prev_register (struc + return frame_unwind_got_constant (this_frame, regnum, pc); + } + ++ /* Red Hat patch begin. */ ++ else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT31_REGNUM) ++ { ++ /* NAT pseudo registers 0-31: get them from UNAT. ++ * "copied" from ia64_pseudo_register_read() */ ++ ULONGEST unatN_val; ++ ULONGEST unat; ++ read_memory (cache->saved_regs[IA64_UNAT_REGNUM], (char *) &unat, ++ register_size (current_gdbarch, IA64_UNAT_REGNUM)); ++ unatN_val = (unat & (1LL << (regnum - IA64_NAT0_REGNUM))) != 0; ++ return frame_unwind_got_constant (this_frame, regnum, unatN_val); ++ } ++ else if (IA64_NAT32_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM) ++ { ++ /* NAT pseudo registers 32-127. ++ * "copied" from ia64_pseudo_register_read() ++ * FIXME: Not currently tested -- cannot get the frame to include ++ * NAT32-NAT127. */ ++ ULONGEST bsp; ++ ULONGEST cfm; ++ ULONGEST natN_val = 0; ++ CORE_ADDR gr_addr = 0, nat_addr = 0; ++ ++ read_memory (cache->saved_regs[IA64_BSP_REGNUM], (char *) &bsp, ++ register_size (current_gdbarch, IA64_BSP_REGNUM)); ++ read_memory (cache->saved_regs[IA64_CFM_REGNUM], (char *) &cfm, ++ register_size (current_gdbarch, IA64_CFM_REGNUM)); ++ ++ /* The bsp points at the end of the register frame so we ++ subtract the size of frame from it to get start of register frame. */ ++ bsp = rse_address_add (bsp, -(cfm & 0x7f)); ++ ++ if ((cfm & 0x7f) > regnum - V32_REGNUM) ++ gr_addr = rse_address_add (bsp, (regnum - V32_REGNUM)); ++ ++ if (gr_addr != 0) ++ { ++ /* Compute address of nat collection bits */ ++ CORE_ADDR nat_collection; ++ int nat_bit; ++ nat_addr = gr_addr | 0x1f8; ++ /* If our nat collection address is bigger than bsp, we have to get ++ the nat collection from rnat. Otherwise, we fetch the nat ++ collection from the computed address. FIXME: Do not know if ++ RNAT can be not stored in the frame--being extra cautious. */ ++ if (nat_addr >= bsp) ++ { ++ nat_addr = cache->saved_regs[IA64_RNAT_REGNUM]; ++ if (nat_addr != 0) ++ read_memory (nat_addr, (char *) &nat_collection, ++ register_size (current_gdbarch, IA64_RNAT_REGNUM)); ++ } ++ else ++ nat_collection = read_memory_integer (nat_addr, 8); ++ if (nat_addr != 0) ++ { ++ nat_bit = (gr_addr >> 3) & 0x3f; ++ natN_val = (nat_collection >> nat_bit) & 1; ++ return frame_unwind_got_constant (this_frame, regnum, natN_val); ++ } ++ } ++ warning (_("ia64_sigtramp_frame_prev_register: unhandled register %d"), ++ regnum); ++ } ++ else if (regnum == VBOF_REGNUM) ++ { ++ /* BOF pseudo register. ++ * "copied" from ia64_pseudo_register_read() ++ * ++ * A virtual register frame start is provided for user convenience. ++ * It can be calculated as the bsp - sof (sizeof frame). */ ++ ULONGEST bsp; ++ ULONGEST cfm; ++ ULONGEST bof; ++ ++ read_memory (cache->saved_regs[IA64_BSP_REGNUM], (char *) &bsp, ++ register_size (current_gdbarch, IA64_BSP_REGNUM)); ++ read_memory (cache->saved_regs[IA64_CFM_REGNUM], (char *) &cfm, ++ register_size (current_gdbarch, IA64_CFM_REGNUM)); ++ ++ /* The bsp points at the end of the register frame so we ++ subtract the size of frame from it to get beginning of frame. */ ++ bof = rse_address_add (bsp, -(cfm & 0x7f)); ++ ++ return frame_unwind_got_constant (this_frame, regnum, bof); ++ } ++ /* Red Hat patch end. */ ++ + else if ((regnum >= IA64_GR32_REGNUM && regnum <= IA64_GR127_REGNUM) + || (regnum >= V32_REGNUM && regnum <= V127_REGNUM)) + { +@@ -2121,7 +2209,42 @@ ia64_sigtramp_frame_prev_register (struc + return frame_unwind_got_constant (this_frame, regnum, 0); + } + +- else /* All other registers not listed above. */ ++ /* Red Hat patch begin. */ ++ else if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM) ++ { ++ /* VP 0-63. ++ * "copied" from ia64_pseudo_register_read() ++ * ++ * FIXME: Not currently tested--cannot get the frame to include PR. */ ++ CORE_ADDR pr_addr = 0; ++ ++ pr_addr = cache->saved_regs[IA64_PR_REGNUM]; ++ if (pr_addr != 0) ++ { ++ ULONGEST pr; ++ ULONGEST cfm; ++ ULONGEST prN_val; ++ read_memory (pr_addr, (char *) &pr, ++ register_size (current_gdbarch, IA64_PR_REGNUM)); ++ read_memory (cache->saved_regs[IA64_CFM_REGNUM], (char *) &cfm, ++ register_size (current_gdbarch, IA64_CFM_REGNUM)); ++ ++ /* Get the register rename base for this frame and adjust the ++ * register name to take rotation into account. */ ++ if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM) ++ { ++ int rrb_pr = (cfm >> 32) & 0x3f; ++ regnum = VP16_REGNUM + ((regnum - VP16_REGNUM) + rrb_pr) % 48; ++ } ++ prN_val = (pr & (1LL << (regnum - VP0_REGNUM))) != 0; ++ return frame_unwind_got_constant (this_frame, regnum, prN_val); ++ } ++ warning (_("ia64_sigtramp_frame_prev_register: unhandled register %d"), ++ regnum); ++ } ++ /* Red Hat patch end. */ ++ ++ /* All other registers not listed above. */ + { + CORE_ADDR addr = cache->saved_regs[regnum]; + diff --git a/gdb-6.3-inferior-notification-20050721.patch b/gdb-6.3-inferior-notification-20050721.patch new file mode 100644 index 0000000..67579bf --- /dev/null +++ b/gdb-6.3-inferior-notification-20050721.patch @@ -0,0 +1,322 @@ +2005-07-21 Jeff Johnston + + * gdb.base/attach-32.exp: New test for attaching in 32-bit + mode on 64-bit systems. + * gdb.base/attach-32.c: Ditto. + * gdb.base/attach-32b.c: Ditto. + +2007-12-26 Jan Kratochvil + + * gdb.base/attach-32.exp: Fix forgotten $GDBFLAGS as set. + +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.c 2008-12-07 10:06:03.000000000 +0100 +@@ -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 ++ ++int should_exit = 0; ++ ++int main () ++{ ++ int local_i = 0; ++ ++ while (! should_exit) ++ { ++ local_i++; ++ } ++ return 0; ++} +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.exp 2008-12-07 10:08:52.000000000 +0100 +@@ -0,0 +1,252 @@ ++# Copyright 2005 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. ++# ++# This test was based on attach.exp and modified for 32/64 bit Linux systems. */ ++ ++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 "x86_64*-*linux*"] ++ && ![istarget "powerpc64*-*linux*"]} { ++ return 0 ++} ++ ++# are we on a target board ++if [is_remote target] then { ++ return 0 ++} ++ ++set testfile "attach-32" ++set srcfile ${testfile}.c ++set srcfile2 ${testfile}b.c ++set binfile ${objdir}/${subdir}/${testfile} ++set binfile2 ${objdir}/${subdir}/${testfile}b ++set escapedbinfile [string_to_regexp ${objdir}/${subdir}/${testfile}] ++ ++#execute_anywhere "rm -f ${binfile} ${binfile2}" ++remote_exec build "rm -f ${binfile} ${binfile2}" ++# For debugging this test ++# ++#log_user 1 ++ ++# build the first test case ++# ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "additional_flags=-m32"]] != "" } { ++ 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 [list debug "additional_flags=-m32"]] != "" } { ++ 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 ++ global testpid ++ ++ # Verify that we can "see" the variable "should_exit" in the ++ # program, and that it is zero. ++ ++ gdb_test "print should_exit" " = 0" "after attach-32, print should_exit" ++ ++ # Verify that we can modify the variable "should_exit" in the ++ # program. ++ ++ gdb_test "set should_exit=1" "" "after attach-32, set should_exit" ++ ++ # Verify that the modification really happened. ++ ++ send_gdb "tbreak 19\n" ++ gdb_expect { ++ -re "reakpoint .*at.*$srcfile, line 19.*$gdb_prompt $" { ++ pass "after attach-32, set tbreak postloop" ++ } ++ -re "$gdb_prompt $" { ++ fail "after attach-32, set tbreak postloop" ++ } ++ timeout { ++ fail "(timeout) after attach-32, set tbreak postloop" ++ } ++ } ++ send_gdb "continue\n" ++ gdb_expect { ++ -re "main.*at.*$srcfile:19.*$gdb_prompt $" { ++ pass "after attach-32, reach tbreak postloop" ++ } ++ -re "$gdb_prompt $" { ++ fail "after attach-32, reach tbreak postloop" ++ } ++ timeout { ++ fail "(timeout) after attach-32, reach tbreak postloop" ++ } ++ } ++ ++ # Allow the test process to exit, to cleanup after ourselves. ++ ++ gdb_test "continue" "Program exited normally." "after attach-32, 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 ++ if { [istarget "*-*-cygwin*"] } { ++ # testpid is the Cygwin PID, GDB uses the Windows PID, which might be ++ # different due to the way fork/exec works. ++ set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ] ++ } ++ ++ # 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.) ++ ++ gdb_test "dir ${objdir}/${subdir}" "Source directories searched: .*" \ ++ "set source path" ++ ++ gdb_test "cd /tmp" "Working directory /tmp." \ ++ "cd away from process working directory" ++ ++ # Explicitly flush out any knowledge of the previous attachment. ++ ++ set test "before attach-32-3, flush symbols" ++ gdb_test_multiple "symbol" "$test" { ++ -re "Discard symbol table from.*y or n. $" { ++ gdb_test "y" "No symbol file now." \ ++ "$test" ++ } ++ -re "No symbol file now.*$gdb_prompt $" { ++ pass "$test" ++ } ++ } ++ ++ gdb_test "exec" "No executable file now." \ ++ "before attach-32-3, flush exec" ++ ++ gdb_test "attach $testpid" \ ++ "Attaching to process $testpid.*Reading symbols from $escapedbinfile.*main.*at .*" \ ++ "attach-32 when process' a.out not in cwd" ++ ++ set test "after attach-32-3, exit" ++ gdb_test_multiple "kill" "$test" { ++ -re "Kill the program being debugged.*y or n. $" { ++ gdb_test "y" "" "$test" ++ } ++ } ++ ++ # Another "don't leave a process around" ++ remote_exec build "kill -9 ${testpid}" ++} ++ ++proc do_call_attach_tests {} { ++ global gdb_prompt ++ global binfile2 ++ global testpid ++ ++ # See if other registers are problems ++ ++ set test "info other register" ++ gdb_test_multiple "i r r3" "$test" { ++ -re "warning: reading register.*$gdb_prompt $" { ++ fail "$test" ++ } ++ -re "r3.*$gdb_prompt $" { ++ pass "$test" ++ } ++ } ++ ++ # 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 ++set testpid [eval exec $binfile &] ++exec sleep 3 ++if { [istarget "*-*-cygwin*"] } { ++ # testpid is the Cygwin PID, GDB uses the Windows PID, which might be ++ # different due to the way fork/exec works. ++ set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ] ++} ++ ++set GDBFLAGS_orig $GDBFLAGS ++set GDBFLAGS "--pid=$testpid" ++gdb_start ++set GDBFLAGS $GDBFLAGS_orig ++ ++gdb_reinitialize_dir $srcdir/$subdir ++ ++# 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 ++set testpid [eval exec $binfile2 &] ++exec sleep 3 ++if { [istarget "*-*-cygwin*"] } { ++ # testpid is the Cygwin PID, GDB uses the Windows PID, which might be ++ # different due to the way fork/exec works. ++ set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ] ++} ++ ++set GDBFLAGS_orig $GDBFLAGS ++set GDBFLAGS "--pid=$testpid" ++gdb_start ++set GDBFLAGS $GDBFLAGS_orig ++ ++gdb_reinitialize_dir $srcdir/$subdir ++do_call_attach_tests ++ ++return 0 +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32b.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32b.c 2008-12-07 10:06:03.000000000 +0100 +@@ -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 ++#include ++#include ++ ++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); ++} diff --git a/gdb-6.3-inheritance-20050324.patch b/gdb-6.3-inheritance-20050324.patch new file mode 100644 index 0000000..ba2b540 --- /dev/null +++ b/gdb-6.3-inheritance-20050324.patch @@ -0,0 +1,26 @@ +2005-03-24 Jeff Johnston + + * valops.c (check_field_in): Use check_typedef for base classes + to avoid problems with opaque type references. + +Index: gdb-6.8.50.20081128/gdb/valops.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/valops.c 2008-12-08 10:56:11.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/valops.c 2008-12-08 10:59:14.000000000 +0100 +@@ -2484,8 +2484,14 @@ check_field (struct type *type, const ch + } + + for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) +- if (check_field (TYPE_BASECLASS (type, i), name)) +- return 1; ++ { ++ /* Check the base classes. Make sure we have the real type for ++ each base class as opposed to an opaque declaration. */ ++ struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); ++ ++ if (check_field (baseclass, name)) ++ return 1; ++ } + + return 0; + } diff --git a/gdb-6.3-inheritancetest-20050726.patch b/gdb-6.3-inheritancetest-20050726.patch new file mode 100644 index 0000000..0abf47e --- /dev/null +++ b/gdb-6.3-inheritancetest-20050726.patch @@ -0,0 +1,153 @@ +2005-07-26 Jeff Johnston + + * gdb.cp/b146835.exp: New testcase. + * gdb.cp/b146835.cc: Ditto. + * gdb.cp/b146835b.cc: Ditto. + * gdb.cp/b146835.h: Ditto. + +--- gdb-6.3/gdb/testsuite/gdb.cp/b146835b.cc.fix3 2005-07-26 16:47:12.000000000 -0400 ++++ gdb-6.3/gdb/testsuite/gdb.cp/b146835b.cc 2005-07-26 16:53:31.000000000 -0400 +@@ -0,0 +1,11 @@ ++#include "b146835.h" ++ ++C::C() { d = 0; x = 3; } ++ ++int C::z (char *s) { return 0; } ++ ++C::~C() {} ++ ++void A::funcD (class E *e, class D *d) {} ++void A::funcE (E *e, D *d) {} ++void A::funcF (unsigned long x, D *d) {} +--- gdb-6.3/gdb/testsuite/gdb.cp/b146835.cc.fix3 2005-07-26 16:47:20.000000000 -0400 ++++ gdb-6.3/gdb/testsuite/gdb.cp/b146835.cc 2005-07-26 16:46:50.000000000 -0400 +@@ -0,0 +1,32 @@ ++#include "b146835.h" ++#include ++ ++class F : public C { ++ ++protected: ++ ++ virtual void funcA (unsigned long a, B *b); ++ virtual void funcB (E *e); ++ virtual void funcC (unsigned long x, bool y); ++ ++ char *s1, *s2; ++ bool b1; ++ int k; ++ ++public: ++ void foo() { ++ std::cout << "foo" << std::endl; ++ } ++}; ++ ++ ++void F::funcA (unsigned long a, B *b) {} ++void F::funcB (E *e) {} ++void F::funcC (unsigned long x, bool y) {} ++ ++int main() ++{ ++ F f; ++ f.foo(); ++} ++ +--- gdb-6.3/gdb/testsuite/gdb.cp/b146835.exp.fix3 2005-07-26 16:47:26.000000000 -0400 ++++ gdb-6.3/gdb/testsuite/gdb.cp/b146835.exp 2005-07-26 16:46:50.000000000 -0400 +@@ -0,0 +1,55 @@ ++# This testcase is part of GDB, the GNU debugger. ++ ++# Copyright 2005 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. ++ ++# Check that GDB can properly print an inherited member variable ++# (Bugzilla 146835) ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile "b146835" ++set srcfile ${testfile}.cc ++set srcfile2 ${testfile}b.cc ++set binfile ${objdir}/${subdir}/${testfile} ++if {[gdb_compile "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile2}" "${binfile}" executable {debug c++}] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# ++# Run to `main' where we begin our tests. ++# ++ ++if ![runto_main] then { ++ gdb_suppress_tests ++} ++ ++gdb_test "break 'F::foo()'" "" ++gdb_continue_to_breakpoint "First line foo" ++ ++# Verify that we can access the inherited member d ++gdb_test "p d" ".*(struct D \*.).*0x0" "Verify inherited member d accessible" ++ +--- gdb-6.3/gdb/testsuite/gdb.cp/b146835.h.fix3 2005-07-26 16:47:36.000000000 -0400 ++++ gdb-6.3/gdb/testsuite/gdb.cp/b146835.h 2005-07-26 16:53:18.000000000 -0400 +@@ -0,0 +1,36 @@ ++ ++class A { ++ ++protected: ++ ++ virtual void funcA (unsigned long a, class B *b) = 0; ++ virtual void funcB (class E *e) = 0; ++ virtual void funcC (unsigned long x, bool y) = 0; ++ ++ void funcD (class E *e, class D* d); ++ virtual void funcE (E *e, D *d); ++ virtual void funcF (unsigned long x, D *d); ++}; ++ ++ ++class C : public A { ++ ++protected: ++ ++ int x; ++ class K *k; ++ class H *h; ++ ++ D *d; ++ ++ class W *w; ++ class N *n; ++ class L *l; ++ unsigned long *r; ++ ++public: ++ ++ C(); ++ int z (char *s); ++ virtual ~C(); ++}; diff --git a/gdb-6.3-large-core-20051206.patch b/gdb-6.3-large-core-20051206.patch new file mode 100644 index 0000000..f81ccf0 --- /dev/null +++ b/gdb-6.3-large-core-20051206.patch @@ -0,0 +1,316 @@ +2005-12-14 Jeff Johnston + + * symfile-mem.c (read_memory): New static read callback function. + (symfile_add_from_memory): Pass read_memory to bfd instead of + target_read_memory. + * target.c (target_xfer_memory): Add support for LONGEST len and + change all callers. + (deprecated_debug_xfer_memory, target_read_memory): Ditto. + (target_write_memory, do_xfer_memory): Ditto. + (target_xfer_memory_partial, target_read_memory_partial): Ditto. + (target_write_memory_partial): Ditto. + * infptrace.c (child_xfer_memory): Ditto. + * linux-nat.c (linux_nat_xfer_memory): Ditto. + (linux_nat_proc_xfer_memory): Ditto. + * dcache.c (dcache_xfer_memory): Ditto. + * exec.c (xfer_memory): Ditto. + * remote.c (remote_xfer_memory): Ditto. + * remote-sim.c (gdbsim_xfer_interior_memory): Ditto. + * target.h: Change prototypes for functions changed above. + * linux-nat.h: Ditto. + * remote.h: Ditto. + * dcache.h: Ditto. + +2007-10-15 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.8.50.20090226/gdb/symfile-mem.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/symfile-mem.c 2009-02-21 17:14:49.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/symfile-mem.c 2009-02-28 07:22:09.000000000 +0100 +@@ -56,6 +56,14 @@ + #include "elf/common.h" + + ++/* Local callback routine to pass to bfd to read from target memory, ++ using a len constrained to INT_MAX. */ ++static int ++read_target_memory (bfd_vma addr, bfd_byte *buf, int len) ++{ ++ return target_read_memory (addr, buf, (LONGEST)len); ++} ++ + /* Read inferior memory at ADDR to find the header of a loaded object file + and read its in-core symbols out of inferior memory. TEMPL is a bfd + representing the target's format. NAME is the name to use for this +@@ -76,7 +84,7 @@ symbol_file_add_from_memory (struct bfd + error (_("add-symbol-file-from-memory not supported for this target")); + + nbfd = bfd_elf_bfd_from_remote_memory (templ, addr, &loadbase, +- target_read_memory); ++ read_target_memory); + if (nbfd == NULL) + error (_("Failed to read a valid object file image from memory.")); + +Index: gdb-6.8.50.20090226/gdb/target.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/target.c 2009-02-27 00:04:32.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/target.c 2009-02-28 07:22:09.000000000 +0100 +@@ -57,7 +57,7 @@ static int nosymbol (char *, CORE_ADDR * + + static void tcomplain (void) ATTR_NORETURN; + +-static int nomemory (CORE_ADDR, char *, int, int, struct target_ops *); ++static LONGEST nomemory (CORE_ADDR, char *, int, int, struct target_ops *); + + static int return_zero (void); + +@@ -286,7 +286,7 @@ target_create_inferior (char *exec_file, + } + + +-static int ++static LONGEST + nomemory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct target_ops *t) + { +@@ -507,7 +507,7 @@ update_current_target (void) + (void (*) (struct regcache *)) + noprocess); + de_fault (deprecated_xfer_memory, +- (int (*) (CORE_ADDR, gdb_byte *, int, int, struct mem_attrib *, struct target_ops *)) ++ (LONGEST (*) (CORE_ADDR, gdb_byte *, LONGEST, int, struct mem_attrib *, struct target_ops *)) + nomemory); + de_fault (to_files_info, + (void (*) (struct target_ops *)) +@@ -1237,7 +1237,7 @@ target_xfer_partial (struct target_ops * + it makes no progress, and then return how much was transferred). */ + + int +-target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len) ++target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, LONGEST len) + { + if (target_read (¤t_target, TARGET_OBJECT_MEMORY, NULL, + myaddr, memaddr, len) == len) +@@ -1247,7 +1247,7 @@ target_read_memory (CORE_ADDR memaddr, g + } + + int +-target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len) ++target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, LONGEST len) + { + if (target_write (¤t_target, TARGET_OBJECT_MEMORY, NULL, + myaddr, memaddr, len) == len) +@@ -2777,8 +2777,8 @@ debug_to_prepare_to_store (struct regcac + fprintf_unfiltered (gdb_stdlog, "target_prepare_to_store ()\n"); + } + +-static int +-deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, int len, ++static LONGEST ++deprecated_debug_xfer_memory (CORE_ADDR memaddr, bfd_byte *myaddr, LONGEST len, + int write, struct mem_attrib *attrib, + struct target_ops *target) + { +@@ -2788,8 +2788,8 @@ deprecated_debug_xfer_memory (CORE_ADDR + attrib, target); + + fprintf_unfiltered (gdb_stdlog, +- "target_xfer_memory (%s, xxx, %d, %s, xxx) = %d", +- paddress (memaddr), len, write ? "write" : "read", ++ "target_xfer_memory (%s, xxx, %ld, %s, xxx) = %d", ++ paddress (memaddr), (long) len, write ? "write" : "read", + retval); + + if (retval > 0) +Index: gdb-6.8.50.20090226/gdb/target.h +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/target.h 2009-02-27 00:04:32.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/target.h 2009-02-28 07:22:09.000000000 +0100 +@@ -376,10 +376,10 @@ struct target_ops + NOTE: cagney/2004-10-01: This has been entirely superseeded by + to_xfer_partial and inferior inheritance. */ + +- int (*deprecated_xfer_memory) (CORE_ADDR memaddr, gdb_byte *myaddr, +- int len, int write, +- struct mem_attrib *attrib, +- struct target_ops *target); ++ LONGEST (*deprecated_xfer_memory) (CORE_ADDR memaddr, gdb_byte *myaddr, ++ LONGEST len, int write, ++ struct mem_attrib *attrib, ++ struct target_ops *target); + + void (*to_files_info) (struct target_ops *); + int (*to_insert_breakpoint) (struct bp_target_info *); +@@ -679,13 +679,14 @@ extern DCACHE *target_dcache; + + extern int target_read_string (CORE_ADDR, char **, int, int *); + +-extern int target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len); ++extern int target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ++ LONGEST len); + + extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, +- int len); ++ LONGEST len); + +-extern int xfer_memory (CORE_ADDR, gdb_byte *, int, int, +- struct mem_attrib *, struct target_ops *); ++extern LONGEST xfer_memory (CORE_ADDR, gdb_byte *, LONGEST, int, ++ struct mem_attrib *, struct target_ops *); + + /* Fetches the target's memory map. If one is found it is sorted + and returned, after some consistency checking. Otherwise, NULL +Index: gdb-6.8.50.20090226/gdb/dcache.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/dcache.c 2009-01-03 06:57:51.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/dcache.c 2009-02-28 07:22:09.000000000 +0100 +@@ -524,9 +524,9 @@ dcache_free (DCACHE *dcache) + + This routine is indended to be called by remote_xfer_ functions. */ + +-int ++LONGEST + dcache_xfer_memory (DCACHE *dcache, CORE_ADDR memaddr, gdb_byte *myaddr, +- int len, int should_write) ++ LONGEST len, int should_write) + { + int i; + int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr); +Index: gdb-6.8.50.20090226/gdb/dcache.h +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/dcache.h 2009-01-03 06:57:51.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/dcache.h 2009-02-28 07:22:09.000000000 +0100 +@@ -35,7 +35,7 @@ void dcache_free (DCACHE *); + + /* Simple to call from _xfer_memory */ + +-int dcache_xfer_memory (DCACHE *cache, CORE_ADDR mem, gdb_byte *my, +- int len, int should_write); ++LONGEST dcache_xfer_memory (DCACHE *cache, CORE_ADDR mem, gdb_byte *my, ++ LONGEST len, int should_write); + + #endif /* DCACHE_H */ +Index: gdb-6.8.50.20090226/gdb/exec.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/exec.c 2009-02-22 20:35:47.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/exec.c 2009-02-28 07:22:09.000000000 +0100 +@@ -464,8 +464,8 @@ map_vmap (bfd *abfd, bfd *arch) + The same routine is used to handle both core and exec files; + we just tail-call it with more arguments to select between them. */ + +-int +-xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write, ++LONGEST ++xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, LONGEST len, int write, + struct mem_attrib *attrib, struct target_ops *target) + { + int res; +Index: gdb-6.8.50.20090226/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/linux-nat.c 2009-02-28 07:22:02.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/linux-nat.c 2009-02-28 07:22:32.000000000 +0100 +@@ -4407,7 +4407,7 @@ linux_xfer_partial (struct target_ops *o + #endif + if (iterate_over_lwps (ia64_linux_check_stack_region, &range) != NULL) + { /* This region contains ia64 rse registers, we have to re-read. */ +- int xxfer; ++ LONGEST xxfer; + + /* Re-read register stack area. */ + xxfer = super_xfer_partial (ops, object, annex, +Index: gdb-6.8.50.20090226/gdb/remote.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/remote.c 2009-02-25 03:14:22.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/remote.c 2009-02-28 07:22:09.000000000 +0100 +@@ -25,6 +25,7 @@ + #include "gdb_string.h" + #include + #include ++#include + #include "inferior.h" + #include "bfd.h" + #include "symfile.h" +@@ -5683,12 +5684,19 @@ handle_notification (char *buf, size_t l + if SHOULD_WRITE is nonzero. Returns length of data written or + read; 0 for error. TARGET is unused. */ + +-static int +-remote_xfer_memory (CORE_ADDR mem_addr, gdb_byte *buffer, int mem_len, ++static LONGEST ++remote_xfer_memory (CORE_ADDR mem_addr, gdb_byte *buffer, LONGEST mem_len, + int should_write, struct mem_attrib *attrib, + struct target_ops *target) + { + int res; ++ int len; ++ ++ /* This routine is not set up to handle > INT_MAX bytes. */ ++ if (mem_len >= (LONGEST)INT_MAX) ++ return 0; ++ ++ len = (int)mem_len; + + set_general_thread (inferior_ptid); + +@@ -5697,7 +5705,7 @@ remote_xfer_memory (CORE_ADDR mem_addr, + else + res = remote_read_bytes (mem_addr, buffer, mem_len); + +- return res; ++ return (LONGEST)res; + } + + /* Sends a packet with content determined by the printf format string +Index: gdb-6.8.50.20090226/gdb/remote-sim.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/remote-sim.c 2009-02-23 19:31:23.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/remote-sim.c 2009-02-28 07:22:09.000000000 +0100 +@@ -754,11 +754,14 @@ gdbsim_prepare_to_store (struct regcache + + Returns the number of bytes transferred. */ + +-static int +-gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, ++static LONGEST ++gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, gdb_byte *myaddr, LONGEST len, + int write, struct mem_attrib *attrib, + struct target_ops *target) + { ++ /* Convert to len type that sim_read and sim_write can handle. */ ++ int xfer_len = (int)len; ++ + /* If no program is running yet, then ignore the simulator for + memory. Pass the request down to the next target, hopefully + an exec file. */ +@@ -774,22 +777,22 @@ gdbsim_xfer_inferior_memory (CORE_ADDR m + printf_filtered ("gdbsim_xfer_inferior_memory: myaddr 0x"); + gdb_print_host_address (myaddr, gdb_stdout); + printf_filtered (", memaddr 0x%s, len %d, write %d\n", +- paddr_nz (memaddr), len, write); ++ paddr_nz (memaddr), xfer_len, write); + if (remote_debug && write) +- dump_mem (myaddr, len); ++ dump_mem (myaddr, xfer_len); + } + + if (write) + { +- len = sim_write (gdbsim_desc, memaddr, myaddr, len); ++ xfer_len = sim_write (gdbsim_desc, memaddr, myaddr, xfer_len); + } + else + { +- len = sim_read (gdbsim_desc, memaddr, myaddr, len); +- if (remote_debug && len > 0) +- dump_mem (myaddr, len); ++ xfer_len = sim_read (gdbsim_desc, memaddr, myaddr, xfer_len); ++ if (remote_debug && xfer_len > 0) ++ dump_mem (myaddr, xfer_len); + } +- return len; ++ return (LONGEST)xfer_len; + } + + static void diff --git a/gdb-6.3-linespec-20041213.patch b/gdb-6.3-linespec-20041213.patch new file mode 100644 index 0000000..acc08cb --- /dev/null +++ b/gdb-6.3-linespec-20041213.patch @@ -0,0 +1,464 @@ +[base] + +2007-09-21 Jan Kratochvil + + * linespec.c (add_minsym_members): Support also the `$allocate' and + `$delete' variants. + +2007-10-05 Jan Kratochvil + + * linespec.c (add_minsym_members): Support also the `$allocate' and + `$delete' variants. + (decode_variable): Renamed to ... + (decode_variable_1) ... here, its parameter NOT_FOUND_PTR and its + exception throwing was moved to ... + (decode_variable_not_found): ... a new function here. + (decode_variable): New function. + +2007-10-31 Jan Kratochvil + + Port to GDB-6.7. + +[ Remove decode_variable* for GDB-6.8+ as no longer needed. ] + +Index: gdb-6.8.50.20081128/gdb/linespec.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/linespec.c 2008-09-05 13:37:17.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/linespec.c 2008-12-04 01:43:36.000000000 +0100 +@@ -39,6 +39,7 @@ + #include "interps.h" + #include "mi/mi-cmds.h" + #include "target.h" ++#include "gdb_assert.h" + + /* We share this one with symtab.c, but it is not exported widely. */ + +@@ -78,7 +79,8 @@ static struct symtabs_and_lines find_met + + static int collect_methods (char *copy, struct type *t, + struct symbol *sym_class, +- struct symbol **sym_arr); ++ struct symbol **sym_arr, ++ struct minimal_symbol **msym_arr); + + static NORETURN void cplusplus_error (const char *name, + const char *fmt, ...) +@@ -87,11 +89,13 @@ static NORETURN void cplusplus_error (co + static int total_number_of_methods (struct type *type); + + static int find_methods (struct type *, char *, +- enum language, struct symbol **); ++ enum language, struct symbol **, ++ struct minimal_symbol **); + + static int add_matching_methods (int method_counter, struct type *t, + enum language language, +- struct symbol **sym_arr); ++ struct symbol **sym_arr, ++ struct minimal_symbol **msym_arr); + + static int add_constructors (int method_counter, struct type *t, + enum language language, +@@ -107,6 +111,9 @@ static int is_objc_method_format (const + static struct symtabs_and_lines decode_line_2 (struct symbol *[], + int, int, char ***); + ++static struct symtabs_and_lines decode_line_3 (struct minimal_symbol *[], ++ int, int, char ***); ++ + static struct symtab *symtab_from_filename (char **argptr, + char *p, int is_quote_enclosed, + int *not_found_ptr); +@@ -196,13 +203,18 @@ total_number_of_methods (struct type *ty + /* Recursive helper function for decode_line_1. + Look for methods named NAME in type T. + Return number of matches. +- Put matches in SYM_ARR, which should have been allocated with ++ Put symbol matches in SYM_ARR, which should have been allocated with + a size of total_number_of_methods (T) * sizeof (struct symbol *). ++ In a special case where we are looking for constructors, we may ++ have to return minimal symbols in the array: MSYM_ARR. This occurs ++ when the compiler does not generate mangled names for the constructor's ++ debug info because there are multiple versions of the constructor ++ (in-charge vs not-in-charge). + Note that this function is g++ specific. */ + + static int + find_methods (struct type *t, char *name, enum language language, +- struct symbol **sym_arr) ++ struct symbol **sym_arr, struct minimal_symbol **msym_arr) + { + int i1 = 0; + int ibase; +@@ -244,7 +256,7 @@ find_methods (struct type *t, char *name + if (strcmp_iw (name, method_name) == 0) + /* Find all the overloaded methods with that name. */ + i1 += add_matching_methods (method_counter, t, language, +- sym_arr + i1); ++ sym_arr + i1, msym_arr); + else if (strncmp (class_name, name, name_len) == 0 + && (class_name[name_len] == '\0' + || class_name[name_len] == '<')) +@@ -267,21 +279,100 @@ find_methods (struct type *t, char *name + if (i1 == 0) + for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++) + i1 += find_methods (TYPE_BASECLASS (t, ibase), name, +- language, sym_arr + i1); ++ language, sym_arr + i1, msym_arr); + + return i1; + } + ++static int ++add_minsym_members (const char *class_name, ++ const char *member_name, ++ struct minimal_symbol **msym_arr) ++{ ++ char *completion_name; ++ char **list; ++ int i; ++ int comp_len; ++ int counter = 0; ++ ++ /* To find the member, we first cheat and use symbol completion. ++ This will give us a list of all the member names including ++ the function signature. */ ++ completion_name = xmalloc (strlen (class_name) + ++ strlen (member_name) + 9); ++ completion_name[0] = '\''; ++ strcpy (completion_name+1, class_name); ++ /* FIXME: make this the language class separator. */ ++ strcat (completion_name, "::"); ++ strcat (completion_name, member_name); ++ strcat (completion_name, "("); ++ list = make_symbol_completion_list (completion_name, ++ completion_name+1); ++ ++ /* Now that we have the list, we generate an array of their ++ corresponding minimal symbols. */ ++ counter = 0; ++ while (list && list[counter] != NULL) ++ { ++ msym_arr[counter] = lookup_minimal_symbol (list[counter], NULL, NULL); ++ ++counter; ++ } ++ ++ xfree (list); ++ ++ /* In the case of constructors, there may be in-charge vs not-in-charge ++ constructors. Check for names with $base which indicates not-in-charge ++ constructors. */ ++ comp_len = strlen (completion_name); ++ strcpy (completion_name + comp_len - 1, "$base("); ++ list = make_symbol_completion_list (completion_name, ++ completion_name+1); ++ ++ /* Again we have a list. Add their minimal symbols to the array. */ ++ i = 0; ++ while (list && list[i] != NULL) ++ { ++ msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL); ++ ++counter; ++ } ++ xfree (list); ++ ++ /* Target also the allocating/deleting variants. */ ++ if (member_name[0] == '~') ++ strcpy (completion_name + comp_len - 1, "$delete("); ++ else ++ strcpy (completion_name + comp_len - 1, "$allocate("); ++ list = make_symbol_completion_list (completion_name, ++ completion_name+1); ++ ++ /* Again we have a list. Add their minimal symbols to the array. */ ++ i = 0; ++ while (list && list[i] != NULL) ++ { ++ msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL); ++ ++counter; ++ } ++ xfree (list); ++ ++ xfree (completion_name); ++ ++ return counter; ++} ++ + /* Add the symbols associated to methods of the class whose type is T + and whose name matches the method indexed by METHOD_COUNTER in the + array SYM_ARR. Return the number of methods added. */ + + static int + add_matching_methods (int method_counter, struct type *t, +- enum language language, struct symbol **sym_arr) ++ enum language language, struct symbol **sym_arr, ++ struct minimal_symbol **msym_arr) + { + int field_counter; + int i1 = 0; ++ int cons_index = 0; ++ char *class_name = type_name_no_tag (t); ++ char **list = NULL; + + for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1; + field_counter >= 0; +@@ -306,6 +397,16 @@ add_matching_methods (int method_counter + else + phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter); + ++ /* Check for special case of looking for member that ++ doesn't have a mangled name provided. This will happen ++ when we have in-charge and not-in-charge constructors. ++ Since we don't have a mangled name to work with, if we ++ look for the symbol, we can only find the class itself. ++ We can find the information we need in the minimal symbol ++ table which has the full member name information we need. */ ++ if (strlen (phys_name) <= strlen (class_name)) ++ return add_minsym_members (class_name, phys_name, msym_arr); ++ + /* Destructor is handled by caller, don't add it to + the list. */ + if (is_destructor_name (phys_name) != 0) +@@ -330,6 +431,9 @@ add_matching_methods (int method_counter + } + } + ++ if (list) ++ xfree (list); ++ + return i1; + } + +@@ -630,6 +734,146 @@ See set/show multiple-symbol.")); + discard_cleanups (old_chain); + return return_values; + } ++ ++/* Given a list of NELTS minimal symbols in MSYM_ARR, return a list of lines to ++ operate on (ask user if necessary). ++ If CANONICAL is non-NULL return a corresponding array of mangled names ++ as canonical line specs there. */ ++ ++static struct symtabs_and_lines ++decode_line_3 (struct minimal_symbol *msym_arr[], ++ int nelts, int funfirstline, ++ char ***canonical) ++{ ++ struct symtabs_and_lines values, return_values; ++ char *args, *arg1; ++ int i; ++ char *prompt; ++ char *symname; ++ struct cleanup *old_chain; ++ char **canonical_arr = (char **) NULL; ++ ++ values.sals = (struct symtab_and_line *) ++ alloca (nelts * sizeof (struct symtab_and_line)); ++ return_values.sals = (struct symtab_and_line *) ++ xmalloc (nelts * sizeof (struct symtab_and_line)); ++ old_chain = make_cleanup (xfree, return_values.sals); ++ ++ if (canonical) ++ { ++ canonical_arr = (char **) xmalloc (nelts * sizeof (char *)); ++ make_cleanup (xfree, canonical_arr); ++ memset (canonical_arr, 0, nelts * sizeof (char *)); ++ *canonical = canonical_arr; ++ } ++ ++ i = 0; ++ printf_unfiltered ("[0] cancel\n[1] all\n"); ++ while (i < nelts) ++ { ++ init_sal (&return_values.sals[i]); /* Initialize to zeroes. */ ++ init_sal (&values.sals[i]); ++ if (msym_arr[i]) ++ { ++ struct symtabs_and_lines msal = minsym_found (funfirstline, ++ msym_arr[i]); ++ memcpy (&values.sals[i], &msal.sals[0], ++ sizeof (struct symtab_and_line)); ++ if (values.sals[i].symtab) ++ printf_unfiltered ("[%d] %s at %s:%d\n", ++ (i + 2), ++ SYMBOL_PRINT_NAME (msym_arr[i]), ++ values.sals[i].symtab->filename, ++ values.sals[i].line); ++ else ++ printf_unfiltered ("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n", ++ (i + 2), ++ SYMBOL_PRINT_NAME (msym_arr[i]), ++ values.sals[i].line); ++ ++ } ++ else ++ printf_unfiltered ("?HERE\n"); ++ i++; ++ } ++ ++ prompt = getenv ("PS2"); ++ if (prompt == NULL) ++ { ++ prompt = "> "; ++ } ++ args = command_line_input (prompt, 0, "overload-choice"); ++ ++ if (args == 0 || *args == 0) ++ error_no_arg ("one or more choice numbers"); ++ ++ i = 0; ++ while (*args) ++ { ++ int num; ++ ++ arg1 = args; ++ while (*arg1 >= '0' && *arg1 <= '9') ++ arg1++; ++ if (*arg1 && *arg1 != ' ' && *arg1 != '\t') ++ error ("Arguments must be choice numbers."); ++ ++ num = atoi (args); ++ ++ if (num == 0) ++ error ("canceled"); ++ else if (num == 1) ++ { ++ if (canonical_arr) ++ { ++ for (i = 0; i < nelts; i++) ++ { ++ if (canonical_arr[i] == NULL) ++ { ++ symname = SYMBOL_LINKAGE_NAME (msym_arr[i]); ++ canonical_arr[i] = savestring (symname, strlen (symname)); ++ } ++ } ++ } ++ memcpy (return_values.sals, values.sals, ++ (nelts * sizeof (struct symtab_and_line))); ++ return_values.nelts = nelts; ++ discard_cleanups (old_chain); ++ return return_values; ++ } ++ ++ if (num >= nelts + 2) ++ { ++ printf_unfiltered ("No choice number %d.\n", num); ++ } ++ else ++ { ++ num -= 2; ++ if (values.sals[num].pc) ++ { ++ if (canonical_arr) ++ { ++ symname = SYMBOL_LINKAGE_NAME (msym_arr[num]); ++ make_cleanup (xfree, symname); ++ canonical_arr[i] = savestring (symname, strlen (symname)); ++ } ++ return_values.sals[i++] = values.sals[num]; ++ values.sals[num].pc = 0; ++ } ++ else ++ { ++ printf_unfiltered ("duplicate request for %d ignored.\n", num); ++ } ++ } ++ ++ args = arg1; ++ while (*args == ' ' || *args == '\t') ++ args++; ++ } ++ return_values.nelts = i; ++ discard_cleanups (old_chain); ++ return return_values; ++} + + /* The parser of linespec itself. */ + +@@ -1438,35 +1682,47 @@ find_method (int funfirstline, char ***c + struct symbol **sym_arr = alloca (total_number_of_methods (t) + * sizeof (struct symbol *)); + ++ struct minimal_symbol **msym_arr = alloca (total_number_of_methods (t) ++ * sizeof (struct minimal_symbol *)); ++ ++ msym_arr[0] = NULL; ++ + /* Find all methods with a matching name, and put them in + sym_arr. */ + +- i1 = collect_methods (copy, t, sym_class, sym_arr); ++ i1 = collect_methods (copy, t, sym_class, sym_arr, msym_arr); + + if (i1 == 1) + { + /* There is exactly one field with that name. */ +- sym = sym_arr[0]; +- +- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) +- { +- values.sals = (struct symtab_and_line *) +- xmalloc (sizeof (struct symtab_and_line)); +- values.nelts = 1; +- values.sals[0] = find_function_start_sal (sym, +- funfirstline); +- } ++ if (msym_arr[0] != NULL) ++ return minsym_found (funfirstline, msym_arr[0]); + else + { +- values.sals = NULL; +- values.nelts = 0; ++ sym = sym_arr[0]; ++ ++ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ++ { ++ values.sals = (struct symtab_and_line *) ++ xmalloc (sizeof (struct symtab_and_line)); ++ values.nelts = 1; ++ values.sals[0] = find_function_start_sal (sym, ++ funfirstline); ++ } ++ else ++ { ++ values.sals = NULL; ++ values.nelts = 0; ++ } ++ return values; + } +- return values; + } + if (i1 > 0) + { + /* There is more than one field with that name + (overloaded). Ask the user which one to use. */ ++ if (msym_arr[0] != NULL) ++ return decode_line_3 (msym_arr, i1, funfirstline, canonical); + return decode_line_2 (sym_arr, i1, funfirstline, canonical); + } + else +@@ -1493,11 +1748,12 @@ find_method (int funfirstline, char ***c + } + + /* Find all methods named COPY in the class whose type is T, and put +- them in SYM_ARR. Return the number of methods found. */ ++ them in SYM_ARR or MSYM_ARR. Return the number of methods found. */ + + static int + collect_methods (char *copy, struct type *t, +- struct symbol *sym_class, struct symbol **sym_arr) ++ struct symbol *sym_class, struct symbol **sym_arr, ++ struct minimal_symbol **msym_arr) + { + int i1 = 0; /* Counter for the symbol array. */ + +@@ -1518,7 +1774,7 @@ collect_methods (char *copy, struct type + } + } + else +- i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr); ++ i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr, msym_arr); + + return i1; + } diff --git a/gdb-6.3-mapping-zero-inode-test.patch b/gdb-6.3-mapping-zero-inode-test.patch new file mode 100644 index 0000000..4537985 --- /dev/null +++ b/gdb-6.3-mapping-zero-inode-test.patch @@ -0,0 +1,221 @@ +--- /dev/null 2008-05-02 23:36:22.370004160 +0200 ++++ gdb-6.8/gdb/testsuite/gdb.base/gcore-shmid0.exp 2008-05-03 22:36:56.000000000 +0200 +@@ -0,0 +1,120 @@ ++# Copyright 2007 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 ++ ++# Test GDB's handling of gcore for mapping with a name but zero inode. ++ ++set testfile "gcore-shmid0" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested gcore.exp ++ return -1 ++} ++ ++# Start with a fresh gdb. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Does this gdb support gcore? ++send_gdb "help gcore\n" ++gdb_expect { ++ -re "Undefined command: .gcore.*$gdb_prompt $" { ++ # gcore command not supported -- nothing to test here. ++ unsupported "gdb does not support gcore on this target" ++ return -1; ++ } ++ -re "Save a core file .*$gdb_prompt $" { ++ pass "help gcore" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "help gcore" ++ } ++ timeout { ++ fail "help gcore (timeout)" ++ } ++} ++ ++if { ! [ runto_main ] } then { ++ untested gcore-shmid0.exp ++ return -1 ++} ++ ++gdb_breakpoint "initialized" ++gdb_breakpoint "unresolved" ++ ++set test "Continue to initialized." ++gdb_test_multiple "continue" $test { ++ -re "Breakpoint .*, initialized .* at .*\r\n$gdb_prompt $" { ++ pass $test ++ } ++ -re "Breakpoint .*, unresolved .* at .*\r\n$gdb_prompt $" { ++ unsupported $test ++ return -1 ++ } ++} ++ ++set escapedfilename [string_to_regexp ${objdir}/${subdir}/gcore-shmid0.test] ++ ++set test "save a corefile" ++gdb_test_multiple "gcore ${objdir}/${subdir}/gcore-shmid0.test" $test { ++ -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" { ++ pass $test ++ } ++ -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" { ++ unsupported $test ++ } ++ eof { ++ fail $test ++ } ++} ++ ++# Be sure to remove the handle first. ++# But it would get removed even on a kill by GDB as the handle is already ++# deleted, just it is still attached. ++gdb_continue_to_end "finish" ++ ++set test "core-file command" ++gdb_test_multiple "core-file $objdir/$subdir/gcore-shmid0.test" $test { ++ -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 .*\r\n\#0 .*\\\(\\\).*\r\n$gdb_prompt $" { ++ # The filename does not fit there anyway so do not check it. ++ pass $test ++ } ++ -re ".*registers from core file: File in wrong format.* $" { ++ fail "core-file command (could not read registers from core file)" ++ } ++} ++ ++set test "backtrace" ++gdb_test_multiple "bt" $test { ++ -re "#0 *initialized \\\(\\\) at .*#1 .* main \\\(.*$gdb_prompt $" { ++ pass $test ++ } ++ -re "#0 *initialized \\\(\\\) at .*Cannot access memory at address .*$gdb_prompt $" { ++ fail $test ++ } ++} +--- /dev/null 2008-05-02 23:36:22.370004160 +0200 ++++ gdb-6.8/gdb/testsuite/gdb.base/gcore-shmid0.c 2008-05-03 22:39:10.000000000 +0200 +@@ -0,0 +1,95 @@ ++/* Copyright 2007 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. */ ++ ++/* ++ * Test GDB's handling of gcore for mapping with a name but zero inode. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* We need a backtrace through the stack. */ ++ ++static void ++initialized (void) ++{ ++} ++ ++static void ++unresolved (void) ++{ ++} ++ ++int ++main (void) ++{ ++ int sid; ++ unsigned int *addr = (void *) -1L; ++ int try; ++ ++ /* The generated SID will cycle with an increment of 32768, try until it ++ * wraps to 0. */ ++ ++ for (try = 0; addr == (void *) -1L; try++) ++ { ++ /* At least kernel-2.6.25-8.fc9.x86_64 just never returns the value 0 by ++ shmget(2). */ ++ if (try > 0x10000) ++ { ++ printf ("Problem no longer reproducible on this kernel (try %d)\n", ++ try); ++ unresolved (); ++ exit (1); ++ } ++ ++ sid = shmget ((key_t) rand (), 0x1000, IPC_CREAT | IPC_EXCL | 0777); ++ if (sid == -1) ++ { ++ printf ("shmget (%d, 0x1000, IPC_CREAT): errno %d\n", 0, errno); ++ exit (1); ++ } ++ ++ /* Use SID only if it is 0, retry it otherwise. */ ++ ++ if (sid == 0) ++ { ++ addr = shmat (sid, NULL, SHM_RND); ++ if (addr == (void *) -1L) ++ { ++ printf ("shmat (%d, NULL, SHM_RND): errno %d\n", sid, ++ errno); ++ exit (1); ++ } ++ } ++ if (shmctl (sid, IPC_RMID, NULL) != 0) ++ { ++ printf ("shmctl (%d, IPC_RMID, NULL): errno %d\n", sid, errno); ++ exit (1); ++ } ++ } ++ ++ initialized (); ++ ++ return 0; ++} diff --git a/gdb-6.3-nonthreaded-wp-20050117.patch b/gdb-6.3-nonthreaded-wp-20050117.patch new file mode 100644 index 0000000..83a5df7 --- /dev/null +++ b/gdb-6.3-nonthreaded-wp-20050117.patch @@ -0,0 +1,119 @@ +[base] + +2007-10-13 Jan Kratochvil + + * linux-nat.c (iterate_over_lwps): Fixed missing LWP initialization for + current INFERIOR_PTID. + +2007-10-13 Jan Kratochvil + + * gdb.base/follow-child.exp, gdb.base/follow-child.c: New files. + +2007-10-16 Jan Kratochvil + + Port to GDB-6.7. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +2008-08-25 Jan Kratochvil + + Remove the fix as causing an assertion failure for + gdb.base/checkpoint.exp and it is no longer needed for + gdb.base/follow-child.exp . + +Index: gdb-6.8cvs20080219/gdb/testsuite/gdb.base/follow-child.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8cvs20080219/gdb/testsuite/gdb.base/follow-child.c 2008-02-22 08:14:04.000000000 +0100 +@@ -0,0 +1,29 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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 */ ++ ++#include ++ ++int main() ++{ ++ fork (); ++ sleep (60); ++ return 0; ++} +Index: gdb-6.8cvs20080219/gdb/testsuite/gdb.base/follow-child.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8cvs20080219/gdb/testsuite/gdb.base/follow-child.exp 2008-02-22 08:14:17.000000000 +0100 +@@ -0,0 +1,55 @@ ++# Copyright 2007 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile follow-child ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# For C programs, "start" should stop in main(). ++ ++gdb_test "set follow-fork-mode child" "" ++set test "started" ++# GDB_RUN_CMD already checks for `Starting program:'. ++gdb_run_cmd ++sleep 5 ++send_gdb "\003" ++set test "break" ++gdb_test_multiple "" $test { ++ -re "Program received signal SIGINT.*$gdb_prompt $" { ++ pass $test ++ } ++ -re "\\\[New process \[0-9\]+\\\]" { ++ fail $test ++ } ++} diff --git a/gdb-6.3-pie-20050110.patch b/gdb-6.3-pie-20050110.patch new file mode 100644 index 0000000..0e95f61 --- /dev/null +++ b/gdb-6.3-pie-20050110.patch @@ -0,0 +1,1441 @@ +2007-11-02 Jan Kratochvil + + Port to GDB-6.7.1. + +2007-11-02 Jan Kratochvil + + Port to post-GDB-6.7.1 multi-PC breakpoints. + +2007-11-09 Jan Kratochvil + + * solib-svr4.c (svr4_current_sos): Fix segfault on NULL EXEC_BFD. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +2008-02-27 Jan Kratochvil + + Port to gdb-6.7.50.20080227. + +2008-06-01 Jan Kratochvil + + Fix crash on a watchpoint update on an inferior stop. + +2008-09-01 Jan Kratochvil + + Fix scan_dyntag() for binaries provided by valgrind (BZ 460319). + +Index: gdb-6.8.50.20090302/gdb/amd64-tdep.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/amd64-tdep.c 2009-03-07 00:30:09.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/amd64-tdep.c 2009-03-07 00:30:12.000000000 +0100 +@@ -36,6 +36,7 @@ + #include "regcache.h" + #include "regset.h" + #include "symfile.h" ++#include "exceptions.h" + + #include "gdb_assert.h" + +@@ -1586,16 +1587,28 @@ amd64_analyze_stack_align (CORE_ADDR pc, + 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; ++ } + + pc = amd64_analyze_stack_align (pc, current_pc, cache); + +@@ -1610,18 +1623,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; + } + +Index: gdb-6.8.50.20090302/gdb/auxv.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/auxv.c 2009-03-07 00:30:06.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/auxv.c 2009-03-07 00:30:12.000000000 +0100 +@@ -81,7 +81,7 @@ procfs_xfer_auxv (struct target_ops *ops + Return 1 if an entry was read into *TYPEP and *VALP. */ + static int + default_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 = gdbarch_ptr_bit (target_gdbarch) + / TARGET_CHAR_BIT; +@@ -108,7 +108,7 @@ default_auxv_parse (struct target_ops *o + 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) + { + struct target_ops *t; + for (t = ops; t != NULL; t = t->beneath) +@@ -123,9 +123,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; +@@ -135,10 +136,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; +@@ -161,7 +162,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); +@@ -171,13 +173,13 @@ 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) + { + 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 +@@ -232,7 +234,7 @@ fprint_target_auxv (struct ui_file *file + } + + fprintf_filtered (file, "%-4s %-20s %-30s ", +- plongest (type), name, description); ++ plongest (at_type), name, description); + switch (flavor) + { + case dec: +@@ -254,7 +256,7 @@ fprint_target_auxv (struct ui_file *file + break; + } + ++ents; +- if (type == AT_NULL) ++ if (at_type == AT_NULL) + break; + } + +Index: gdb-6.8.50.20090302/gdb/auxv.h +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/auxv.h 2009-01-03 06:57:50.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/auxv.h 2009-03-07 00:30:12.000000000 +0100 +@@ -36,14 +36,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-6.8.50.20090302/gdb/breakpoint.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/breakpoint.c 2009-03-07 00:30:10.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/breakpoint.c 2009-03-07 00:30:12.000000000 +0100 +@@ -3920,7 +3920,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)" +@@ -5008,6 +5009,61 @@ create_catchpoint (int tempflag, char *c + return b; + } + ++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, + struct breakpoint_ops *ops) +Index: gdb-6.8.50.20090302/gdb/breakpoint.h +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/breakpoint.h 2009-03-07 00:30:06.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/breakpoint.h 2009-03-07 00:30:12.000000000 +0100 +@@ -127,6 +127,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 +@@ -847,6 +848,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-6.8.50.20090302/gdb/dwarf2read.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/dwarf2read.c 2009-03-07 00:30:10.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/dwarf2read.c 2009-03-07 00:30:12.000000000 +0100 +@@ -1413,7 +1413,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-6.8.50.20090302/gdb/elfread.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/elfread.c 2009-03-07 00:30:06.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/elfread.c 2009-03-07 00:30:12.000000000 +0100 +@@ -680,7 +680,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-6.8.50.20090302/gdb/infrun.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/infrun.c 2009-03-07 00:30:10.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/infrun.c 2009-03-07 00:30:12.000000000 +0100 +@@ -3354,6 +3354,11 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( + #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-6.8.50.20090302/gdb/objfiles.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/objfiles.c 2009-03-07 00:30:06.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/objfiles.c 2009-03-07 00:30:12.000000000 +0100 +@@ -51,6 +51,9 @@ + #include "arch-utils.h" + #include "exec.h" + ++#include "auxv.h" ++#include "elf/common.h" ++ + /* Prototypes for local functions */ + + static void objfile_alloc_data (struct objfile *objfile); +@@ -271,7 +274,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 (¤t_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. +@@ -443,6 +458,9 @@ free_objfile (struct objfile *objfile) + if (objfile == rt_common_objfile) + rt_common_objfile = NULL; + ++ if (objfile == symfile_objfile) ++ symfile_objfile = NULL; ++ + /* Before the symbol table code was redone to make it easier to + selectively load and remove information particular to a specific + linkage unit, gdb used to do these things whenever the monolithic +Index: gdb-6.8.50.20090302/gdb/solib-svr4.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/solib-svr4.c 2009-03-07 00:30:09.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/solib-svr4.c 2009-03-07 00:30:12.000000000 +0100 +@@ -45,6 +45,7 @@ + #include "exec.h" + #include "auxv.h" + #include "exceptions.h" ++#include "command.h" + + static struct link_map_offsets *svr4_fetch_link_map_offsets (void); + static int svr4_have_link_map_offsets (void); +@@ -287,7 +288,9 @@ static CORE_ADDR main_lm_addr; + + /* Local function prototypes */ + ++#if 0 + static int match_main (char *); ++#endif + + static CORE_ADDR bfd_lookup_symbol (bfd *, char *); + +@@ -521,10 +524,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 reloc_addr = 0; + 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; +@@ -532,19 +537,81 @@ 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) ++ { ++ CORE_ADDR entry_addr; ++ ++ /* Find the address of the entry point of the program from the ++ auxv vector. */ ++ ret = target_auxv_search (¤t_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); ++ } ++ reloc_addr = entry_addr - bfd_get_start_address (exec_bfd); ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "elf_locate_base: expected relocation offset 0x%s for %s\n", ++ paddr_nz (reloc_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) +@@ -565,26 +632,105 @@ scan_dyntag (int dyntag, bfd *abfd, CORE + dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag); + dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr); + } +- if (dyn_tag == DT_NULL) ++ ++ /* Verify RELOC_ADDR makes sense - it does not have to for valgrind which ++ supplies us a specially crafted executable in /proc/PID/fd/X while ++ /proc/PID/auxv corresponds to a different executable (.../memcheck). */ ++ if (reloc_addr) ++ { ++ gdb_byte tag_buf[8]; ++ CORE_ADDR tag_addr; ++ ++ tag_addr = dyn_addr + (buf - bufstart) + reloc_addr; ++ if (target_read_memory (tag_addr, tag_buf, arch_size / 8) == 0) ++ { ++ if (memcmp (tag_buf, buf, arch_size / 8) != 0) ++ { ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "elf_locate_base: tag at offset 0x%lx does not match," ++ " dropping relocation offset %s\n", ++ (unsigned long) (buf - bufstart), paddr_nz (reloc_addr)); ++ reloc_addr = 0; ++ } ++ } ++ else ++ { ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "elf_locate_base: tag at offset 0x%lx is not readable," ++ " dropping relocation offset %s\n", ++ (unsigned long) (buf - bufstart), paddr_nz (reloc_addr)); ++ reloc_addr = 0; ++ } ++ } ++ ++ if (dyn_tag == DT_NULL) + return 0; +- if (dyn_tag == dyntag) +- { +- /* If requested, try to read the runtime value of this .dynamic +- entry. */ +- if (ptr) +- { +- struct type *ptr_type; +- gdb_byte ptr_buf[8]; +- CORE_ADDR ptr_addr; +- +- ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; +- ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8; +- if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0) +- dyn_ptr = extract_typed_address (ptr_buf, ptr_type); +- *ptr = dyn_ptr; +- } +- return 1; +- } ++ if (dyn_tag == dyntag) ++ { ++ /* If requested, try to read the runtime value of this .dynamic ++ entry. */ ++ if (ptr) ++ { ++ gdb_byte ptr_buf[8]; ++ CORE_ADDR ptr_addr; ++ int got; ++ ++ 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 += reloc_addr; ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "elf_locate_base: relocated ptr addr 0x%s" ++ " (relocation offset %s) for %s\n", ++ paddr_nz (ptr_addr), paddr_nz (reloc_addr), ++ exec_bfd->filename); ++ } ++ got = target_read_memory (ptr_addr, ptr_buf, arch_size / 8); ++ if (got != 0 && reloc_addr) ++ { ++ ptr_addr -= reloc_addr; ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "elf_locate_base: unrelocated back to ptr addr 0x%s" ++ " as the memory was unreable for %s\n", ++ paddr_nz (ptr_addr), exec_bfd->filename); ++ got = target_read_memory (ptr_addr, ptr_buf, arch_size / 8); ++ } ++ ++ if (got == 0) ++ { ++ struct type *ptr_type; ++ ++ ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; ++ dyn_ptr = extract_typed_address (ptr_buf, ptr_type); ++ 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; ++ } + } + + return 0; +@@ -774,6 +920,10 @@ solib_svr4_r_map (void) + struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; + ++ 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, ptr_type); + } + +@@ -945,6 +1095,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 : ""; ++ ++ 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; +@@ -953,10 +1108,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) +@@ -973,26 +1137,104 @@ 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) ++ if (exec_bfd != NULL && IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0) + { +- main_lm_addr = new->lm_info->lm_addr; +- free_so (new); +- } ++ /* 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. */ ++ main_lm_addr = new->lm_info->lm_addr; ++ 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*/, ¤t_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) +@@ -1000,47 +1242,60 @@ svr4_current_sos (void) + safe_strerror (errcode)); + else + { +- struct build_id *build_id; ++ 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 ++ { ++ struct build_id *build_id; + +- strncpy (new->so_original_name, buffer, SO_NAME_MAX_PATH_SIZE - 1); +- new->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; +- /* May get overwritten below. */ +- strcpy (new->so_name, new->so_original_name); ++ strncpy (new->so_original_name, buffer, SO_NAME_MAX_PATH_SIZE - 1); ++ new->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; ++ /* May get overwritten below. */ ++ strcpy (new->so_name, new->so_original_name); + +- build_id = build_id_addr_get (LM_DYNAMIC_FROM_LINK_MAP (new)); +- if (build_id != NULL) +- { +- char *name, *build_id_filename; ++ build_id = build_id_addr_get (LM_DYNAMIC_FROM_LINK_MAP (new)); ++ if (build_id != NULL) ++ { ++ char *name, *build_id_filename; ++ ++ /* Missing the build-id matching separate debug info file ++ would be handled while SO_NAME gets loaded. */ ++ name = build_id_to_filename (build_id, &build_id_filename, 0); ++ if (name != NULL) ++ { ++ strncpy (new->so_name, name, SO_NAME_MAX_PATH_SIZE - 1); ++ new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; ++ xfree (name); ++ } ++ else ++ debug_print_missing (new->so_name, build_id_filename); ++ ++ xfree (build_id_filename); ++ xfree (build_id); ++ } + +- /* Missing the build-id matching separate debug info file +- would be handled while SO_NAME gets loaded. */ +- name = build_id_to_filename (build_id, &build_id_filename, 0); +- if (name != NULL) ++ if (debug_solib) + { +- strncpy (new->so_name, name, SO_NAME_MAX_PATH_SIZE - 1); +- new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; +- xfree (name); ++ 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)); + } +- else +- debug_print_missing (new->so_name, build_id_filename); + +- xfree (build_id_filename); +- xfree (build_id); ++ new->next = 0; ++ *link_ptr = new; ++ link_ptr = &new->next; + } + } +- 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; +- } ++ xfree (buffer); + } + + /* On Solaris, the dynamic linker is not in the normal list of +@@ -1056,6 +1311,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; + } + +@@ -1087,7 +1345,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) + { +@@ -1101,6 +1359,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. */ +@@ -1251,15 +1510,29 @@ enable_break (void) + /* Find the program interpreter; if not found, warn the user and drop + into the old breakpoint at symbol code. */ + interp_name = find_program_interpreter (); ++ ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "enable_break: search for .interp in %s\n", ++ exec_bfd->filename); + if (interp_name) + { + CORE_ADDR load_addr = 0; ++ CORE_ADDR load_addr_mask = -1L; + int load_addr_found = 0; + int loader_found_in_list = 0; + struct so_list *so; + bfd *tmp_bfd = NULL; + struct target_ops *tmp_bfd_target; + volatile struct gdb_exception ex; ++ int arch_size; ++ ++ /* For 32bit inferiors with 64bit GDB we may get LOAD_ADDR at 0xff...... ++ and thus overflowing its addition to the address while CORE_ADDR is ++ 64bit producing 0x1........ address invalid across GDB. */ ++ arch_size = bfd_get_arch_size (exec_bfd); ++ if (arch_size > 0 && arch_size < sizeof (1UL) * 8) ++ load_addr_mask = (1UL << arch_size) - 1; + + sym_addr = 0; + +@@ -1276,6 +1549,9 @@ enable_break (void) + { + tmp_bfd = solib_bfd_open (interp_name); + } ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "enable_break: opening %s\n", interp_name); + if (tmp_bfd == NULL) + goto bkpt_at_symbol; + +@@ -1329,16 +1605,16 @@ enable_break (void) + interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); + if (interp_sect) + { +- interp_text_sect_low = +- bfd_section_vma (tmp_bfd, interp_sect) + load_addr; ++ interp_text_sect_low = (bfd_section_vma (tmp_bfd, interp_sect) ++ + load_addr) & load_addr_mask; + interp_text_sect_high = + interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect); + } + interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt"); + if (interp_sect) + { +- interp_plt_sect_low = +- bfd_section_vma (tmp_bfd, interp_sect) + load_addr; ++ interp_plt_sect_low = (bfd_section_vma (tmp_bfd, interp_sect) ++ + load_addr) & load_addr_mask; + interp_plt_sect_high = + interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect); + } +@@ -1373,7 +1649,11 @@ enable_break (void) + + if (sym_addr != 0) + { +- create_solib_event_breakpoint (load_addr + sym_addr); ++ create_solib_event_breakpoint ((load_addr + sym_addr) ++ & load_addr_mask); ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "enable_break: solib bp set\n"); + xfree (interp_name); + return 1; + } +@@ -1639,6 +1919,8 @@ svr4_solib_create_inferior_hook (void) + while (tp->stop_signal != TARGET_SIGNAL_TRAP); + inf->stop_soon = NO_STOP_QUIETLY; + #endif /* defined(_SCO_DS) */ ++ ++ disable_breakpoints_at_startup (1); + } + + static void +@@ -1820,6 +2102,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; +@@ -1859,4 +2210,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-6.8.50.20090302/gdb/solib.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/solib.c 2009-02-21 17:14:49.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/solib.c 2009-03-07 00:30:12.000000000 +0100 +@@ -81,6 +81,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; +@@ -104,6 +106,8 @@ The search path for loading non-absolute + value); + } + ++void add_to_target_sections (int, struct target_ops *, struct so_list *); ++ + /* + + GLOBAL FUNCTION +@@ -426,10 +430,23 @@ free_so (struct so_list *so) + + if (so->abfd) + { +- bfd_filename = bfd_get_filename (so->abfd); +- if (! bfd_close (so->abfd)) +- warning (_("cannot close \"%s\": %s"), +- bfd_filename, bfd_errmsg (bfd_get_error ())); ++ struct objfile *objfile; ++ ++ ALL_OBJFILES (objfile) ++ if (objfile->obfd == so->abfd) ++ { ++ gdb_assert (objfile->flags & OBJF_KEEPBFD); ++ objfile->flags &= ~OBJF_KEEPBFD; ++ break; ++ } ++ ++ if (!objfile) ++ { ++ bfd_filename = bfd_get_filename (so->abfd); ++ if (! bfd_close (so->abfd)) ++ warning (_("cannot close \"%s\": %s"), ++ bfd_filename, bfd_errmsg (bfd_get_error ())); ++ } + } + + if (bfd_filename) +@@ -460,15 +477,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_from_bfd (so->abfd, so->from_tty, +- sap, 0, OBJF_SHARED | OBJF_KEEPBFD); ++ if (so->main) ++ { ++ if (debug_solib) ++ fprintf_unfiltered (gdb_stdlog, ++ "symbol_add_stub: adding symbols for main\n"); ++ so->objfile = symbol_file_add_from_bfd (so->abfd, /*so->from_tty*/ 0, ++ sap, 1, OBJF_KEEPBFD); ++ so->main_relocated = 1; ++ } ++ else ++ so->objfile = symbol_file_add_from_bfd (so->abfd, so->from_tty, ++ sap, 0, OBJF_SHARED | OBJF_KEEPBFD); ++ + free_section_addr_info (sap); + + return (1); +@@ -600,6 +642,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; + } +@@ -654,28 +700,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. */ +@@ -771,6 +796,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])); ++ } ++ } ++} + + /* + +@@ -1089,4 +1149,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-6.8.50.20090302/gdb/solist.h +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/solist.h 2009-02-04 09:42:11.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/solist.h 2009-03-07 00:30:12.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; +@@ -149,4 +151,10 @@ struct symbol *solib_global_lookup (cons + const char *linkage_name, + const domain_enum domain); + ++/* 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 *); ++ ++/* Controls the printing of debugging output. */ ++extern int debug_solib; ++ + #endif +Index: gdb-6.8.50.20090302/gdb/symfile-mem.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/symfile-mem.c 2009-03-07 00:30:08.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/symfile-mem.c 2009-03-07 00:30:12.000000000 +0100 +@@ -116,7 +116,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-6.8.50.20090302/gdb/symfile.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/symfile.c 2009-03-07 00:30:09.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/symfile.c 2009-03-07 00:31:24.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" +@@ -787,7 +788,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. */ +@@ -815,7 +816,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; +@@ -917,17 +918,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); +@@ -980,7 +985,7 @@ symbol_file_add_with_addrs_or_offsets (b + /* Give user a chance to burp if we'd be + interactively wiping out any existing symbols. */ + +- if (mainline ++ if (mainline == 1 + && from_tty + && (have_full_symbols () || have_partial_symbols ()) + && !query (_("Load new symbol table from \"%s\"? "), name)) +@@ -1175,6 +1180,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 +@@ -3275,6 +3284,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. */ +Index: gdb-6.8.50.20090302/gdb/target.h +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/target.h 2009-03-07 00:30:09.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/target.h 2009-03-07 00:30:12.000000000 +0100 +@@ -542,7 +542,7 @@ struct target_ops + Return -1 if there is insufficient buffer for a whole entry. + Return 1 if an entry was read into *TYPEP and *VALP. */ + int (*to_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); + + /* Search SEARCH_SPACE_LEN bytes beginning at START_ADDR for the + sequence of bytes in PATTERN with length PATTERN_LEN. diff --git a/gdb-6.3-ppc64displaysymbol-20041124.patch b/gdb-6.3-ppc64displaysymbol-20041124.patch new file mode 100644 index 0000000..7c5e54e --- /dev/null +++ b/gdb-6.3-ppc64displaysymbol-20041124.patch @@ -0,0 +1,24 @@ +2004-11-24 Andrew Cagney + + * printcmd.c (build_address_symbolic): Find a section for the + address. + +Index: gdb-6.8.50.20081128/gdb/printcmd.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/printcmd.c 2008-12-04 01:36:05.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/printcmd.c 2008-12-04 01:37:18.000000000 +0100 +@@ -616,6 +616,14 @@ build_address_symbolic (CORE_ADDR addr, + addr = overlay_mapped_address (addr, section); + } + } ++ /* To ensure that the symbol returned belongs to the correct setion ++ (and that the last [random] symbol from the previous section ++ isn't returned) try to find the section containing PC. First try ++ the overlay code (which by default returns NULL); and second try ++ the normal section code (which almost always succeeds). */ ++ section = find_pc_overlay (addr); ++ if (section == NULL) ++ section = find_pc_section (addr); + + /* First try to find the address in the symbol table, then + in the minsyms. Take the closest one. */ diff --git a/gdb-6.3-ppc64syscall-20040622.patch b/gdb-6.3-ppc64syscall-20040622.patch new file mode 100644 index 0000000..fda58ae --- /dev/null +++ b/gdb-6.3-ppc64syscall-20040622.patch @@ -0,0 +1,110 @@ +2004-06-22 Andrew Cagney + + * rs6000-tdep.c (struct rs6000_framedata): Add field "func_start". + (skip_prologue): Delete local variable "orig_pc", use + "func_start". Add local variable "num_skip_linux_syscall_insn", + use to skip over first half of a GNU/Linux syscall and update + "func_start". + +Index: gdb-6.8/gdb/rs6000-tdep.c +=================================================================== +--- gdb-6.8.orig/gdb/rs6000-tdep.c 2008-02-20 15:34:43.000000000 +0100 ++++ gdb-6.8/gdb/rs6000-tdep.c 2008-07-14 10:25:29.000000000 +0200 +@@ -124,6 +124,7 @@ static const char *powerpc_vector_abi_st + + struct rs6000_framedata + { ++ CORE_ADDR func_start; /* True function start. */ + int offset; /* total size of frame --- the distance + by which we decrement sp to allocate + the frame */ +@@ -1262,7 +1263,6 @@ static CORE_ADDR + skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, + struct rs6000_framedata *fdata) + { +- CORE_ADDR orig_pc = pc; + CORE_ADDR last_prologue_pc = pc; + CORE_ADDR li_found_pc = 0; + gdb_byte buf[4]; +@@ -1280,11 +1280,13 @@ skip_prologue (struct gdbarch *gdbarch, + int minimal_toc_loaded = 0; + int prev_insn_was_prologue_insn = 1; + int num_skip_non_prologue_insns = 0; ++ int num_skip_ppc64_gnu_linux_syscall_insn = 0; + int r0_contains_arg = 0; + const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + memset (fdata, 0, sizeof (struct rs6000_framedata)); ++ fdata->func_start = pc; + fdata->saved_gpr = -1; + fdata->saved_fpr = -1; + fdata->saved_vr = -1; +@@ -1313,6 +1315,55 @@ skip_prologue (struct gdbarch *gdbarch, + break; + op = extract_unsigned_integer (buf, 4); + ++ /* A PPC64 GNU/Linux system call function is split into two ++ sub-functions: a non-threaded fast-path (__NAME_nocancel) ++ which does not use a frame; and a threaded slow-path ++ (Lpseudo_cancel) that does create a frame. Ref: ++ nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h ++ ++ *INDENT-OFF* ++ NAME: ++ SINGLE_THREAD_P ++ bne- .Lpseudo_cancel ++ __NAME_nocancel: ++ li r0,162 ++ sc ++ bnslr+ ++ b 0x7fe014ef64 <.__syscall_error> ++ Lpseudo_cancel: ++ stdu r1,-128(r1) ++ ... ++ *INDENT-ON* ++ ++ Unfortunatly, because the latter case uses a local label (not ++ in the symbol table) a PC in "Lpseudo_cancel" appears to be ++ in "__NAME_nocancel". The following code recognizes this, ++ adjusting FUNC_START to point to where "Lpseudo_cancel" ++ should be, and parsing the prologue sequence as if ++ "Lpseudo_cancel" was the entry point. */ ++ ++ if (((op & 0xffff0000) == 0x38000000 /* li r0,N */ ++ && pc == fdata->func_start + 0 ++ && num_skip_ppc64_gnu_linux_syscall_insn == 0) ++ || (op == 0x44000002 /* sc */ ++ && pc == fdata->func_start + 4 ++ && num_skip_ppc64_gnu_linux_syscall_insn == 1) ++ || (op == 0x4ca30020 /* bnslr+ */ ++ && pc == fdata->func_start + 8 ++ && num_skip_ppc64_gnu_linux_syscall_insn == 2)) ++ { ++ num_skip_ppc64_gnu_linux_syscall_insn++; ++ continue; ++ } ++ else if ((op & 0xfc000003) == 0x48000000 /* b __syscall_error */ ++ && pc == fdata->func_start + 12 ++ && num_skip_ppc64_gnu_linux_syscall_insn == 3) ++ { ++ num_skip_ppc64_gnu_linux_syscall_insn = -1; ++ fdata->func_start = pc; ++ continue; ++ } ++ + if ((op & 0xfc1fffff) == 0x7c0802a6) + { /* mflr Rx */ + /* Since shared library / PIC code, which needs to get its +@@ -1486,9 +1537,9 @@ skip_prologue (struct gdbarch *gdbarch, + we have no line table information or the line info tells + us that the subroutine call is not part of the line + associated with the prologue. */ +- if ((pc - orig_pc) > 8) ++ if ((pc - fdata->func_start) > 8) + { +- struct symtab_and_line prologue_sal = find_pc_line (orig_pc, 0); ++ struct symtab_and_line prologue_sal = find_pc_line (fdata->func_start, 0); + struct symtab_and_line this_sal = find_pc_line (pc, 0); + + if ((prologue_sal.line == 0) || (prologue_sal.line != this_sal.line)) diff --git a/gdb-6.3-ppcdotsolib-20041022.patch b/gdb-6.3-ppcdotsolib-20041022.patch new file mode 100644 index 0000000..5c580fa --- /dev/null +++ b/gdb-6.3-ppcdotsolib-20041022.patch @@ -0,0 +1,31 @@ +2004-10-22 Andrew Cagney + + * solib-svr4.c (enable_break): Convert a symbol descriptor into + the corresponding function entry point. + (solib_break_names): Delete "._dl_debug_state", no longer needed. + +2007-10-12 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.7/gdb/solib-svr4.c +=================================================================== +--- gdb-6.7.orig/gdb/solib-svr4.c 2007-10-09 20:03:30.000000000 +0200 ++++ gdb-6.7/gdb/solib-svr4.c 2007-10-12 22:34:03.000000000 +0200 +@@ -1089,7 +1089,15 @@ enable_break (void) + { + sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep); + if (sym_addr != 0) +- break; ++ { ++ /* The symbol might be a descriptor, convert to into the ++ corresponding code address. */ ++ sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch, ++ sym_addr, ++ tmp_bfd_target); ++ if (sym_addr != 0) ++ break; ++ } + } + + if (sym_addr != 0) diff --git a/gdb-6.3-readnever-20050907.patch b/gdb-6.3-readnever-20050907.patch new file mode 100644 index 0000000..e0dbecd --- /dev/null +++ b/gdb-6.3-readnever-20050907.patch @@ -0,0 +1,96 @@ +2004-11-18 Andrew Cagney + + * dwarf2read.c: Include "top.c". + (dwarf2_has_info): Check for readnever_symbol_files. + * symfile.c (readnever_symbol_files): Define. + * top.h (readnever_symbol_files): Declare. + * main.c (captured_main): Add --readnever option. + (print_gdb_help): Ditto. + +2004-11-18 Andrew Cagney + + * gdb.texinfo (File Options): Document --readnever. + +Index: gdb-6.8.50.20090228/gdb/doc/gdb.texinfo +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/doc/gdb.texinfo 2009-03-02 01:01:15.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/doc/gdb.texinfo 2009-03-02 01:01:23.000000000 +0100 +@@ -988,6 +988,12 @@ Read each symbol file's entire symbol ta + the default, which is to read it incrementally as it is needed. + This makes startup slower, but makes future operations faster. + ++@item --readnever ++@cindex @code{--readnever} ++Do not read each symbol file's symbolic debug information. This makes ++startup faster but at the expense of not being able to perform ++symbolic debugging. ++ + @end table + + @node Mode Options +Index: gdb-6.8.50.20090228/gdb/main.c +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/main.c 2009-03-02 01:01:17.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/main.c 2009-03-02 01:01:23.000000000 +0100 +@@ -427,6 +427,7 @@ captured_main (void *data) + {"xdb", no_argument, &xdb_commands, 1}, + {"dbx", no_argument, &dbx_commands, 1}, + {"readnow", no_argument, &readnow_symbol_files, 1}, ++ {"readnever", no_argument, &readnever_symbol_files, 1}, + {"r", no_argument, &readnow_symbol_files, 1}, + {"quiet", no_argument, &quiet, 1}, + {"q", no_argument, &quiet, 1}, +@@ -1070,6 +1071,7 @@ Options:\n\n\ + fputs_unfiltered (_("\ + --quiet Do not print version number on startup.\n\ + --readnow Fully read symbol files on first access.\n\ ++ --readnever Do not read symbol files.\n\ + "), stream); + fputs_unfiltered (_("\ + --se=FILE Use FILE as symbol file and executable file.\n\ +Index: gdb-6.8.50.20090228/gdb/symfile.c +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/symfile.c 2009-03-02 01:01:17.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/symfile.c 2009-03-02 01:01:23.000000000 +0100 +@@ -77,6 +77,7 @@ static void clear_symtab_users_cleanup ( + + /* Global variables owned by this file */ + int readnow_symbol_files; /* Read full symbols immediately */ ++int readnever_symbol_files; /* Never read full symbols. */ + + /* External variables and functions referenced. */ + +Index: gdb-6.8.50.20090228/gdb/dwarf2read.c +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/dwarf2read.c 2009-03-02 01:01:15.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/dwarf2read.c 2009-03-02 01:01:36.000000000 +0100 +@@ -49,6 +49,7 @@ + #include "f-lang.h" + #include "c-lang.h" + #include "typeprint.h" ++#include "top.h" + + #include + #include "gdb_string.h" +@@ -1161,7 +1162,8 @@ dwarf2_has_info (struct objfile *objfile + dwarf_aranges_section = 0; + + bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, &update_sizes); +- return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL); ++ return !readnever_symbol_files ++ && dwarf_info_section != NULL && dwarf_abbrev_section != NULL; + } + + /* When loading sections, we can either look for ".", or for +Index: gdb-6.8.50.20090228/gdb/top.h +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/top.h 2009-01-03 06:57:53.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/top.h 2009-03-02 01:01:23.000000000 +0100 +@@ -59,6 +59,7 @@ extern void set_prompt (char *); + + /* From random places. */ + extern int readnow_symbol_files; ++extern int readnever_symbol_files; + + /* Perform _initialize initialization */ + extern void gdb_init (char *); diff --git a/gdb-6.3-removebp-20041130.patch b/gdb-6.3-removebp-20041130.patch new file mode 100644 index 0000000..4000e62 --- /dev/null +++ b/gdb-6.3-removebp-20041130.patch @@ -0,0 +1,29 @@ +2004-11-30 Jeff Johnston + + * breakpoint.c (remove_breakpoints): Continue removing breakpoints + even if an error occurs. Remove a failure code for the last failure + only. + +--- gdb+dejagnu-20040607/gdb/breakpoint.c.fix2 Tue Nov 30 18:01:33 2004 ++++ gdb+dejagnu-20040607/gdb/breakpoint.c Tue Nov 30 18:06:01 2004 +@@ -1297,6 +1297,7 @@ remove_breakpoints (void) + { + struct bp_location *b; + int val; ++ int return_val = 0; + + ALL_BP_LOCATIONS (b) + { +@@ -1304,10 +1305,10 @@ remove_breakpoints (void) + { + val = remove_breakpoint (b, mark_uninserted); + if (val != 0) +- return val; ++ return_val = val; + } + } +- return 0; ++ return return_val; + } + + int diff --git a/gdb-6.3-rh-dummykfail-20041202.patch b/gdb-6.3-rh-dummykfail-20041202.patch new file mode 100644 index 0000000..708baee --- /dev/null +++ b/gdb-6.3-rh-dummykfail-20041202.patch @@ -0,0 +1,22 @@ +2003-07-11 Elena Zannoni + + * lib/gdb.exp (setup_kfail, kfail): Redefine procedures. + +--- ./gdb/testsuite/lib/gdb.exp.1 2004-11-24 15:59:46.131394720 -0500 ++++ ./gdb/testsuite/lib/gdb.exp 2004-11-24 16:01:06.304206600 -0500 +@@ -63,6 +63,15 @@ + + ### Only procedures should come after this point. + ++if {![llength [info procs kfail]]} { ++ proc setup_kfail { args } { ++ #setup_xfail args ++ } ++ proc kfail { bugid message } { ++ fail $message ++ } ++} ++ + # + # gdb_version -- extract and print the version number of GDB + # diff --git a/gdb-6.3-rh-testlibunwind-20041202.patch b/gdb-6.3-rh-testlibunwind-20041202.patch new file mode 100644 index 0000000..2abfd68 --- /dev/null +++ b/gdb-6.3-rh-testlibunwind-20041202.patch @@ -0,0 +1,76 @@ +2003-11-17 Elena Zannoni + + From Jeff Johnston + * gdb.arch/ia64-libunwind.exp: New file. + * gdb.arch/ia64-libunwind.c: New file. + +--- /dev/null Thu Apr 11 10:25:15 2002 ++++ gdb+dejagnu-20040223/gdb/testsuite/gdb.arch/ia64-libunwind.exp Mon Nov 17 15:57:04 2003 +@@ -0,0 +1,55 @@ ++# Copyright 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 ++ ++# This file was written by Jeff Johnston (jjohnstn@redhat.com) ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++# ++# test running programs ++# ++set prms_id 0 ++set bug_id 0 ++ ++if ![istarget "ia64-*-*"] then { ++ return ++} ++ ++set testfile "ia64-libunwind" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } { ++ 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} ++send_gdb "set debug arch 1\n" ++send_gdb "break main\n" ++gdb_test "run" ".*acquire_unwind_info.*" ++ +--- /dev/null Thu Apr 11 10:25:15 2002 ++++ gdb+dejagnu-20040223/gdb/testsuite/gdb.arch/ia64-libunwind.c Mon Nov 17 15:58:27 2003 +@@ -0,0 +1,9 @@ ++#include ++ ++int main() ++{ ++ printf ("hello world\n"); ++ ++ return 0; ++} ++ diff --git a/gdb-6.3-rh-testlibunwind1fix-20041202.patch b/gdb-6.3-rh-testlibunwind1fix-20041202.patch new file mode 100644 index 0000000..8a4f6ab --- /dev/null +++ b/gdb-6.3-rh-testlibunwind1fix-20041202.patch @@ -0,0 +1,14 @@ +2004-08-03 Jeff Johnston + + * gdb.arch/ia64-libunwind.exp: Fix test string to match + current code base. + +--- gdb+dejagnu-20040607/gdb/testsuite/gdb.arch/ia64-libunwind.exp.fix Tue Aug 3 18:29:22 2004 ++++ gdb+dejagnu-20040607/gdb/testsuite/gdb.arch/ia64-libunwind.exp Tue Aug 3 18:41:01 2004 +@@ -51,5 +51,5 @@ gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + send_gdb "set debug arch 1\n" + send_gdb "break main\n" +-gdb_test "run" ".*acquire_unwind_info.*" ++gdb_test "run" ".*ia64_find_proc_info_x.*" + diff --git a/gdb-6.3-rh-testversion-20041202.patch b/gdb-6.3-rh-testversion-20041202.patch new file mode 100644 index 0000000..0205f0f --- /dev/null +++ b/gdb-6.3-rh-testversion-20041202.patch @@ -0,0 +1,19 @@ +2003-02-24 Elena Zannoni + + * gdb.gdb/selftest.exp: Add matching on specific Red Hat only version + string. + +Index: gdb-6.8/gdb/testsuite/gdb.gdb/selftest.exp +=================================================================== +--- gdb-6.8.orig/gdb/testsuite/gdb.gdb/selftest.exp 2008-01-26 14:56:37.000000000 +0100 ++++ gdb-6.8/gdb/testsuite/gdb.gdb/selftest.exp 2008-07-14 10:23:50.000000000 +0200 +@@ -354,6 +354,9 @@ proc test_with_self { executable } { + -re ".\[0-9\]+ = +.+ +0x.*\[0-9.\]+.*$gdb_prompt $" { + pass "printed version with cast" + } ++ -re ".\[0-9\]+ = .Fedora \[\\(\\)0-9.a-z\\-\]+.*$gdb_prompt $" { ++ pass "printed version Fedora only" ++ } + -re ".*$gdb_prompt $" { fail "printed version" } + timeout { fail "(timeout) printed version" } + } diff --git a/gdb-6.3-security-errata-20050610.patch b/gdb-6.3-security-errata-20050610.patch new file mode 100644 index 0000000..61589bb --- /dev/null +++ b/gdb-6.3-security-errata-20050610.patch @@ -0,0 +1,211 @@ +http://sourceware.org/ml/gdb-patches/2005-05/threads.html#00637 +Proposed upstream but never committed upstream. + +2005-06-09 Jeff Johnston + + * gdb.base/gdbinit.exp: New testcase. + * gdb.base/gdbinit.sample: Sample .gdbinit for gdbinit.exp. + +2005-06-08 Daniel Jacobowitz + Jeff Johnston + + * Makefile.in (cli-cmds.o): Update. + * configure.in: Add check for getuid. + * configure: Regenerated. + * config.in: Ditto. + * main.c (captured_main): Pass -1 to source_command when loading + gdbinit files. + * cli/cli-cmds.c: Include "gdb_stat.h" and . + (source_command): Update documentation. Check permissions if + FROM_TTY is -1. + +Index: gdb-6.8.50.20090226/gdb/cli/cli-cmds.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/cli/cli-cmds.c 2009-02-27 00:04:32.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/cli/cli-cmds.c 2009-02-28 07:17:49.000000000 +0100 +@@ -36,6 +36,7 @@ + #include "objfiles.h" + #include "source.h" + #include "disasm.h" ++#include "gdb_stat.h" + + #include "ui-out.h" + +@@ -466,7 +467,7 @@ source_script (char *file, int from_tty) + + if (fd == -1) + { +- if (from_tty) ++ if (from_tty > 0) + perror_with_name (file); + else + { +@@ -475,6 +476,29 @@ source_script (char *file, int from_tty) + } + } + ++#ifdef HAVE_GETUID ++ if (from_tty == -1) ++ { ++ struct stat statbuf; ++ ++ if (fstat (fd, &statbuf) < 0) ++ { ++ close (fd); ++ /* Do not do_cleanups (old_cleanups) as FILE is allocated there. ++ perror_with_name calls error which should call the cleanups. */ ++ perror_with_name (file); ++ } ++ if (statbuf.st_uid != getuid () || (statbuf.st_mode & S_IWOTH)) ++ { ++ /* FILE gets freed by do_cleanups (old_cleanups). */ ++ warning (_("not using untrusted file \"%s\""), file); ++ close (fd); ++ do_cleanups (old_cleanups); ++ return; ++ } ++ } ++#endif ++ + is_python = source_python; + if (strlen (file) > 3 && !strcmp (&file[strlen (file) - 3], ".py")) + is_python = 1; +@@ -486,6 +510,7 @@ source_script (char *file, int from_tty) + else + script_from_file (stream, file); + ++ /* FILE gets freed by do_cleanups (old_cleanups). */ + do_cleanups (old_cleanups); + } + +Index: gdb-6.8.50.20090226/gdb/testsuite/gdb.base/gdbinit.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090226/gdb/testsuite/gdb.base/gdbinit.exp 2009-02-28 07:15:57.000000000 +0100 +@@ -0,0 +1,98 @@ ++# Copyright 2005 ++# 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 Jeff Johnston . ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++# are we on a target board ++if [is_remote target] { ++ return ++} ++ ++ ++global verbose ++global GDB ++global GDBFLAGS ++global gdb_prompt ++global timeout ++global gdb_spawn_id; ++ ++gdb_stop_suppressing_tests; ++ ++verbose "Spawning $GDB -nw" ++ ++if [info exists gdb_spawn_id] { ++ return 0; ++} ++ ++if ![is_remote host] { ++ if { [which $GDB] == 0 } then { ++ perror "$GDB does not exist." ++ exit 1 ++ } ++} ++ ++set env(HOME) [pwd] ++remote_exec build "rm .gdbinit" ++remote_exec build "cp ${srcdir}/${subdir}/gdbinit.sample .gdbinit" ++remote_exec build "chmod 646 .gdbinit" ++ ++set res [remote_spawn host "$GDB -nw [host_info gdb_opts]"]; ++if { $res < 0 || $res == "" } { ++ perror "Spawning $GDB failed." ++ return 1; ++} ++gdb_expect 360 { ++ -re "warning: not using untrusted file.*\.gdbinit.*\[\r\n\]$gdb_prompt $" { ++ pass "untrusted .gdbinit caught." ++ } ++ -re "$gdb_prompt $" { ++ fail "untrusted .gdbinit caught." ++ } ++ timeout { ++ fail "(timeout) untrusted .gdbinit caught." ++ } ++} ++ ++remote_exec build "chmod 644 .gdbinit" ++set res [remote_spawn host "$GDB -nw [host_info gdb_opts]"]; ++if { $res < 0 || $res == "" } { ++ perror "Spawning $GDB failed." ++ return 1; ++} ++gdb_expect 360 { ++ -re "warning: not using untrusted file.*\.gdbinit.*\[\r\n\]$gdb_prompt $" { ++ fail "trusted .gdbinit allowed." ++ } ++ -re "in gdbinit.*$gdb_prompt $" { ++ pass "trusted .gdbinit allowed." ++ } ++ timeout { ++ fail "(timeout) trusted .gdbinit allowed." ++ } ++} ++ ++remote_exec build "rm .gdbinit" +Index: gdb-6.8.50.20090226/gdb/testsuite/gdb.base/gdbinit.sample +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090226/gdb/testsuite/gdb.base/gdbinit.sample 2009-02-28 07:15:57.000000000 +0100 +@@ -0,0 +1 @@ ++echo "\nin gdbinit" +Index: gdb-6.8.50.20090226/gdb/main.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/main.c 2009-02-27 00:04:32.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/main.c 2009-02-28 07:15:57.000000000 +0100 +@@ -855,7 +855,7 @@ Excess command line arguments ignored. ( + debugging or what directory you are in. */ + + if (home_gdbinit && !inhibit_gdbinit) +- catch_command_errors (source_script, home_gdbinit, 0, RETURN_MASK_ALL); ++ catch_command_errors (source_script, home_gdbinit, -1, RETURN_MASK_ALL); + + /* Now perform all the actions indicated by the arguments. */ + if (cdarg != NULL) +@@ -924,7 +924,7 @@ Can't attach to process and specify a co + /* Read the .gdbinit file in the current directory, *if* it isn't + the same as the $HOME/.gdbinit file (it should exist, also). */ + if (local_gdbinit && !inhibit_gdbinit) +- catch_command_errors (source_script, local_gdbinit, 0, RETURN_MASK_ALL); ++ catch_command_errors (source_script, local_gdbinit, -1, RETURN_MASK_ALL); + + for (i = 0; i < ncmd; i++) + { diff --git a/gdb-6.3-sepcrc-20050402.patch b/gdb-6.3-sepcrc-20050402.patch new file mode 100644 index 0000000..2fe3b90 --- /dev/null +++ b/gdb-6.3-sepcrc-20050402.patch @@ -0,0 +1,82 @@ +2005-04-02 Andrew Cagney + + * symfile.c (separate_debug_file_exists): When the CRCs mismatch + print a warning. + (find_separate_debug_file): Pass in the objfile's name. + +Index: gdb-6.8.50.20081128/gdb/symfile.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/symfile.c 2008-10-03 18:36:10.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/symfile.c 2008-12-01 16:34:36.000000000 +0100 +@@ -1296,7 +1296,8 @@ get_debug_link_info (struct objfile *obj + } + + static int +-separate_debug_file_exists (const char *name, unsigned long crc) ++separate_debug_file_exists (const char *name, unsigned long crc, ++ const char *parent_name) + { + unsigned long file_crc = 0; + bfd *abfd; +@@ -1316,7 +1317,15 @@ separate_debug_file_exists (const char * + + bfd_close (abfd); + +- return crc == file_crc; ++ if (crc != file_crc) ++ { ++ warning (_("the debug information found in \"%s\"" ++ " does not match \"%s\" (CRC mismatch).\n"), ++ name, parent_name); ++ return 0; ++ } ++ ++ return 1; + } + + char *debug_file_directory = NULL; +@@ -1368,6 +1377,8 @@ find_separate_debug_file (struct objfile + basename = get_debug_link_info (objfile, &crc32); + + if (basename == NULL) ++ /* There's no separate debug info, hence there's no way we could ++ load it => no warning. */ + return NULL; + + dir = xstrdup (objfile->name); +@@ -1395,7 +1406,7 @@ find_separate_debug_file (struct objfile + strcpy (debugfile, dir); + strcat (debugfile, basename); + +- if (separate_debug_file_exists (debugfile, crc32)) ++ if (separate_debug_file_exists (debugfile, crc32, objfile->name)) + { + xfree (basename); + xfree (dir); +@@ -1408,7 +1419,7 @@ find_separate_debug_file (struct objfile + strcat (debugfile, "/"); + strcat (debugfile, basename); + +- if (separate_debug_file_exists (debugfile, crc32)) ++ if (separate_debug_file_exists (debugfile, crc32, objfile->name)) + { + xfree (basename); + xfree (dir); +@@ -1421,7 +1432,7 @@ find_separate_debug_file (struct objfile + strcat (debugfile, dir); + strcat (debugfile, basename); + +- if (separate_debug_file_exists (debugfile, crc32)) ++ if (separate_debug_file_exists (debugfile, crc32, objfile->name)) + { + xfree (basename); + xfree (dir); +@@ -1440,7 +1451,7 @@ find_separate_debug_file (struct objfile + strcat (debugfile, "/"); + strcat (debugfile, basename); + +- if (separate_debug_file_exists (debugfile, crc32)) ++ if (separate_debug_file_exists (debugfile, crc32, objfile->name)) + { + xfree (canon_name); + xfree (basename); diff --git a/gdb-6.3-step-thread-exit-20050211-test.patch b/gdb-6.3-step-thread-exit-20050211-test.patch new file mode 100644 index 0000000..4d6aef9 --- /dev/null +++ b/gdb-6.3-step-thread-exit-20050211-test.patch @@ -0,0 +1,195 @@ +2005-02-11 Jeff Johnston + + * testsuite/gdb.threads/step-thread-exit.c: New testcase. + * testsuite/gdb.threads/step-thread-exit.exp: Ditto. + +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/step-thread-exit.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/step-thread-exit.c 2008-12-08 22:21:26.000000000 +0100 +@@ -0,0 +1,50 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2005 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. */ ++ ++#include ++#include ++#include ++#include ++ ++void *thread_function (void *ptr) ++{ ++ int *x = (int *)ptr; ++ printf("In thread_function, *x is %d\n", *x); ++} /* thread_function_end */ ++ ++volatile int repeat = 0; ++ ++main() ++{ ++ int ret; ++ pthread_t th; ++ int i = 3; ++ ++ ret = pthread_create (&th, NULL, thread_function, &i); ++ do ++ { ++ repeat = 0; ++ sleep (3); /* sleep */ ++ } ++ while (repeat); ++ pthread_join (th, NULL); ++ return 0; ++} ++ ++ +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/step-thread-exit.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/step-thread-exit.exp 2008-12-08 22:22:14.000000000 +0100 +@@ -0,0 +1,130 @@ ++# This testcase is part of GDB, the GNU debugger. ++ ++# Copyright 2005 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. ++ ++# Check that GDB can step over a thread exit. ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile "step-thread-exit" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Reset the debug file directory so we can't debug within the C library ++gdb_test "set debug-file-directory ." "" "" ++ ++# ++# Run to `main' where we begin our tests. ++# ++ ++if ![runto_main] then { ++ gdb_suppress_tests ++} ++ ++# FIXME: Currently the main thread will escape/exit before our thread finishes ++# without this setting. ++gdb_test "set scheduler-locking step" ++gdb_test "show scheduler-locking" "Mode for locking scheduler during execution is \"step\"." "check scheduler-locking first" ++ ++set sleep_line [expr [gdb_get_line_number "sleep"]] ++set end_line [expr [gdb_get_line_number "thread_function_end"]] ++ ++gdb_breakpoint "$end_line" ++gdb_test "continue" "Break.*thread_function.*" "continue to thread_function 1" ++ ++# Keep nexting until we cause the thread to exit. We expect the main ++# thread to be stopped and a message printed to tell us we have stepped ++# over the thread exit. ++set test "step over thread exit 1" ++gdb_test_multiple "next" "$test" { ++ -re "\}.*$gdb_prompt $" { ++ send_gdb "next\n" ++ exp_continue ++ } ++ -re "\[Thread .* exited\].*Program received signal SIGSTOP.*$gdb_prompt $" { ++ pass "$test" ++ } ++ -re "start_thread.*$gdb_prompt $" { ++ send_gdb "next\n" ++ exp_continue ++ } ++} ++ ++# Without this fixup we could end up in: ++# #0 0x00110416 in __kernel_vsyscall () ++# #1 0x0011de26 in __lll_unlock_wake_private () from /lib/libpthread.so.0 ++# #2 0x001179f4 in _L_unlock_3164 () from /lib/libpthread.so.0 ++# #3 0x00116f01 in pthread_create@@GLIBC_2.1 () from /lib/libpthread.so.0 ++# #4 0x08048531 in main () at ../.././gdb/testsuite/gdb.threads/step-thread-exit.c:39 ++gdb_breakpoint "$sleep_line" ++gdb_test "set repeat=1" "" "Get to the sleep function prepare 1" ++gdb_test "continue" "Break.*$sleep_line.*" "Get to the sleep function 1" ++ ++gdb_test "bt" "main.*$sleep_line.*" "backtrace after step 1" ++ ++runto_main ++gdb_test "show scheduler-locking" "Mode for locking scheduler during execution is \"step\"." "check scheduler-locking second" ++ ++gdb_breakpoint "$sleep_line" ++gdb_breakpoint "$end_line" ++set test "continue to thread_function 2" ++gdb_test_multiple "continue" "$test" { ++ -re "Break.*thread_function.*$gdb_prompt $" { ++ pass $test ++ } ++ -re "Break.*$sleep_line.*$gdb_prompt $" { ++ gdb_test "set repeat=1" "" "" ++ send_gdb "continue\n" ++ exp_continue ++ } ++} ++ ++# Keep nexting until we cause the thread to exit. In this case, we ++# expect the breakpoint in the main thread to have already triggered ++# and so we should stop there with a message that we stepped over ++# the thread exit. ++set test "step over thread exit 2" ++gdb_test_multiple "next" "$test" { ++ -re "\}.*$gdb_prompt $" { ++ send_gdb "next\n" ++ exp_continue ++ } ++ -re "\[Thread .* exited\].*Break.*$sleep_line.*$gdb_prompt $" { ++ pass "$test (breakpoint hit)" ++ } ++ -re "\[Thread .* exited\].*$gdb_prompt $" { ++ pass "$test (breakpoint not hit)" ++ } ++ -re "start_thread.*$gdb_prompt $" { ++ send_gdb "next\n" ++ exp_continue ++ } ++} ++ diff --git a/gdb-6.3-terminal-fix-20050214.patch b/gdb-6.3-terminal-fix-20050214.patch new file mode 100644 index 0000000..ea5b098 --- /dev/null +++ b/gdb-6.3-terminal-fix-20050214.patch @@ -0,0 +1,28 @@ +2005-02-14 Jeff Johnston + + * top.c (gdb_readline_wrapper): Ensure terminal is gdb's before calling + readline. + +2007-10-14 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.7/gdb/top.c +=================================================================== +--- gdb-6.7.orig/gdb/top.c 2007-09-02 23:13:56.000000000 +0200 ++++ gdb-6.7/gdb/top.c 2007-10-14 23:38:27.000000000 +0200 +@@ -795,6 +795,14 @@ gdb_readline_wrapper (char *prompt) + + back_to = make_cleanup (gdb_readline_wrapper_cleanup, cleanup); + ++ /* Before calling readline, ensure we have the terminal. If we don't ++ have the terminal and call readline, we risk the possibility of ++ gdb being thrown into the background. This problem occurs when ++ we attach to a background process on the same terminal the background ++ process was started from and then perform some action which requires ++ a page break prompt. */ ++ terminal_ours (); ++ + /* Display our prompt and prevent double prompt display. */ + display_gdb_prompt (prompt); + rl_already_prompted = 1; diff --git a/gdb-6.3-test-dtorfix-20050121.patch b/gdb-6.3-test-dtorfix-20050121.patch new file mode 100644 index 0000000..cccf89b --- /dev/null +++ b/gdb-6.3-test-dtorfix-20050121.patch @@ -0,0 +1,263 @@ +Index: gdb/testsuite/ChangeLog +2005-01-21 Jeff Johnston + + * gdb.cp/constructortest.exp: New test. + * gdb.cp/constructortest.cc: Ditto. + * gdb.cp/templates.exp: Change break of dtor to be fully quoted. + +2007-09-22 Jan Kratochvil + + * gdb.cp/constructortest.exp, gdb.cp/constructortest.cc: Test also the + `$delete' destructor variant. + +2007-09-25 Jan Kratochvil + + * gdb.cp/constructortest.exp: Delete the FIXME workaround of restarting + the whole GDB. + +2007-10-05 Jan Kratochvil + + * gdb.cp/constructortest.exp: Test BREAKPOINT_RE_SET for multiple PCs + by PIE. + * gdb.cp/constructortest.exp: Handle the change of settings breakpoints + always at all the ctor/dtor variants. + +[ Removed the `gdb.cp/templates.exp' patch. ] +[ Updated the patch for "(X location") of GDB-6.8+. ] + +--- gdb-6.3/gdb/testsuite/gdb.cp/constructortest.cc.fix Fri Jan 21 17:06:56 2005 ++++ gdb-6.3/gdb/testsuite/gdb.cp/constructortest.cc Fri Jan 21 17:05:18 2005 +@@ -0,0 +1,99 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2005 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. */ ++ ++class A ++{ ++ public: ++ A(); ++ ~A(); ++ int k; ++ private: ++ int x; ++}; ++ ++class B: public A ++{ ++ public: ++ B(); ++ private: ++ int y; ++}; ++ ++/* C and D are for the $delete destructor. */ ++ ++class C ++{ ++ public: ++ C(); ++ virtual ~C(); ++ private: ++ int x; ++}; ++ ++class D: public C ++{ ++ public: ++ D(); ++ private: ++ int y; ++}; ++ ++int main(int argc, char *argv[]) ++{ ++ A* a = new A; ++ B* b = new B; ++ D* d = new D; ++ delete a; ++ delete b; ++ delete d; ++ return 0; ++} ++ ++A::A() /* Constructor A */ ++{ ++ x = 1; /* First line A */ ++ k = 4; /* Second line A */ ++} ++ ++A::~A() /* Destructor A */ ++{ ++ x = 3; /* First line ~A */ ++ k = 6; /* Second line ~A */ ++} ++ ++B::B() ++{ ++ y = 2; /* First line B */ ++ k = 5; ++} ++ ++C::C() /* Constructor C */ ++{ ++ x = 1; /* First line C */ ++} ++ ++C::~C() /* Destructor C */ ++{ ++ x = 3; /* First line ~C */ ++} ++ ++D::D() ++{ ++ y = 2; /* First line D */ ++} +--- gdb-6.3/gdb/testsuite/gdb.cp/constructortest.exp.fix Fri Jan 21 17:07:02 2005 ++++ gdb-6.3/gdb/testsuite/gdb.cp/constructortest.exp Fri Jan 21 17:05:29 2005 +@@ -0,0 +1,131 @@ ++# This testcase is part of GDB, the GNU debugger. ++ ++# Copyright 2005, 2007 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. ++ ++# Check that GDB can break at multiple forms of constructors. ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile "constructortest" ++set srcfile ${testfile}.cc ++set binfile ${objdir}/${subdir}/${testfile} ++# PIE is required for testing proper BREAKPOINT_RE_SET of the multiple-PC ++# breakpoints. ++if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++ "additional_flags=-fpie -pie"}] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# ++# Run to `main' where we begin our tests. ++# ++ ++if ![runto_main] then { ++ gdb_suppress_tests ++} ++ ++# Break on the various forms of the A::A constructor ++gdb_test "break A\:\:A" "Breakpoint 2 at .* \\(2 locations\\)" "breaking on A::A" ++ ++# Verify that we break for the A constructor two times ++# Once for new A and once for new B ++gdb_continue_to_breakpoint "First line A" ++gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in in-charge A::A" ++gdb_continue_to_breakpoint "First line A" ++gdb_test "bt" "#0.*A.*#1.*B.*#2.*main.*" "Verify in not-in-charge A::A" ++ ++# Now do the same for destructors ++gdb_test "break 'A::~A()'" "" ++ ++# Verify that we break for the A destructor two times ++# Once for delete a and once for delete b ++gdb_continue_to_breakpoint "First line ~A" ++gdb_test "bt" "#0.*~A.*#1.*main.*" "Verify in in-charge A::~A" ++gdb_continue_to_breakpoint "First line ~A" ++gdb_test "bt" "#0.*~A.*#1.*~B.*#2.*main.*" "Verify in not-in-charge A::~A" ++ ++ ++# Verify that we can break by line number in a constructor and find ++# both occurrences ++runto_main ++gdb_test "break 'A::A()'" "" "break in constructor A 2" ++gdb_continue_to_breakpoint "First line A" ++set second_line [gdb_get_line_number "Second line A"] ++gdb_test "break $second_line" "Breakpoint .*, line $second_line. \\(2 locations\\)" "break by line in constructor" ++gdb_continue_to_breakpoint "Second line A" ++gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in in-charge A::A second line" ++gdb_continue_to_breakpoint "Second line A" ++gdb_test "bt" "#0.*A.*#1.*B.*#2.*main.*" "Verify in not-in-charge A::A second line" ++ ++# Verify that we can break by line number in a destructor and find ++# both occurrences ++gdb_test "break 'A::~A()'" "" "break in constructor ~A 2" ++gdb_continue_to_breakpoint "First line ~A" ++set second_line_dtor [gdb_get_line_number "Second line ~A"] ++gdb_test "break $second_line_dtor" "Breakpoint .*, line $second_line_dtor. \\(2 locations\\)" "break by line in destructor" ++gdb_continue_to_breakpoint "Second line ~A" ++gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in in-charge A::~A second line" ++# FIXME: Analyse this case better. ++gdb_continue_to_breakpoint "Second line ~A" ++gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in A::~A second line #2" ++gdb_continue_to_breakpoint "Second line ~A" ++gdb_test "bt" "#0.*A.*#1.*B.*#2.*main.*" "Verify in not-in-charge A::~A second line" ++ ++ ++# Test now the $delete destructors. ++ ++gdb_load ${binfile} ++runto_main ++ ++# Break on the various forms of the C::~C destructor ++gdb_test "break C\:\:~C" "Breakpoint .* \\(3 locations\\)" "breaking on C::~C" ++gdb_continue_to_breakpoint "First line ~C" ++ ++# Verify that we can break by line number in a destructor and find ++# the $delete occurence ++ ++gdb_load ${binfile} ++delete_breakpoints ++ ++set first_line_dtor [gdb_get_line_number "First line ~C"] ++gdb_test "break $first_line_dtor" "Breakpoint .*, line $first_line_dtor. \\(3 locations\\)" "break by line in destructor" ++ ++# Run to `main' where we begin our tests. ++# Set the breakpoints first to test PIE multiple-PC BREAKPOINT_RE_SET. ++# RUNTO_MAIN or RUNTO MAIN are not usable here as it runs DELETE_BREAKPOINTS. ++ ++if ![gdb_breakpoint main] { ++ gdb_suppress_tests ++} ++gdb_run_cmd ++set test "running to main" ++gdb_test_multiple "" $test { ++ -re "Breakpoint \[0-9\]*, main .*$gdb_prompt $" { ++ pass $test ++ } ++} ++ ++gdb_continue_to_breakpoint "First line ~C" diff --git a/gdb-6.3-test-movedir-20050125.patch b/gdb-6.3-test-movedir-20050125.patch new file mode 100644 index 0000000..4b40756 --- /dev/null +++ b/gdb-6.3-test-movedir-20050125.patch @@ -0,0 +1,105 @@ +2005-01-25 Elena Zannoni + + * gdb.base/move-dir.exp: New test. + * gdb.base/move-dir.c: Ditto. + * gdb.base/move-dir.h: Ditto. + +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/move-dir.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/move-dir.c 2008-12-07 23:57:41.000000000 +0100 +@@ -0,0 +1,10 @@ ++#include ++#include ++#include "move-dir.h" ++ ++int main() { ++ const char* hw = "hello world."; ++ printf ("%s\n", hw);; ++ other(); ++} ++ +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/move-dir.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/move-dir.exp 2008-12-07 10:13:01.000000000 +0100 +@@ -0,0 +1,67 @@ ++# Copyright 2005 ++# 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 ++ ++set testfile "move-dir" ++set srcfile ${testfile}.c ++set incfile ${testfile}.h ++set binfile ${objdir}/${subdir}/${testfile} ++ ++set testdir "${objdir}/${subdir}/incdir" ++ ++remote_exec build "mkdir $testdir" ++remote_exec build "cp ${srcdir}/${subdir}/${srcfile} ${objdir}/${subdir}" ++remote_exec build "cp ${srcdir}/${subdir}/${incfile} ${testdir}" ++ ++set additional_flags "additional_flags=-I${subdir}/incdir" ++ ++if { [gdb_compile "${objdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $additional_flags]] != "" } { ++ 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; ++} ++ ++ ++set oldtimeout $timeout ++set timeout [expr "$timeout + 60"] ++ ++# Start with a fresh gdb. ++ ++gdb_exit ++gdb_start ++gdb_test "cd ../.." "" "" ++gdb_load ${binfile} ++gdb_test "list main" ".*hw.*other.*" "found main" ++gdb_test "list other" ".*ostring.*" "found include file" ++ ++ ++set timeout $oldtimeout ++return 0 +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/move-dir.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/move-dir.h 2008-12-07 10:13:01.000000000 +0100 +@@ -0,0 +1,7 @@ ++#include ++ ++void other() { ++ const char* ostring = "other"; ++ printf ("%s\n", ostring);; ++} ++ diff --git a/gdb-6.3-test-pie-20050107.patch b/gdb-6.3-test-pie-20050107.patch new file mode 100644 index 0000000..d6d6b46 --- /dev/null +++ b/gdb-6.3-test-pie-20050107.patch @@ -0,0 +1,2121 @@ +Index: gdb-6.8.50.20081128/gdb/testsuite/configure.ac +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/testsuite/configure.ac 2008-12-09 17:02:39.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/testsuite/configure.ac 2008-12-09 17:02:55.000000000 +0100 +@@ -116,6 +116,6 @@ AC_OUTPUT([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.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.pie/Makefile \ + gdb.python/Makefile \ + gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile]) +Index: gdb-6.8.50.20081128/gdb/testsuite/configure +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/testsuite/configure 2008-12-09 17:02:39.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/testsuite/configure 2008-12-09 17:02:55.000000000 +0100 +@@ -3131,7 +3131,7 @@ done + + + +- 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.python/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.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.pie/Makefile gdb.python/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 +@@ -3698,6 +3698,7 @@ do + "gdb.objc/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.objc/Makefile" ;; + "gdb.opt/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.opt/Makefile" ;; + "gdb.pascal/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.pascal/Makefile" ;; ++ "gdb.pie/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.pie/Makefile" ;; + "gdb.python/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.python/Makefile" ;; + "gdb.threads/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.threads/Makefile" ;; + "gdb.trace/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.trace/Makefile" ;; +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/attach.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/attach.c 2008-12-09 17:02:55.000000000 +0100 +@@ -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 ++ ++int should_exit = 0; ++ ++int main () ++{ ++ int local_i = 0; ++ ++ while (! should_exit) ++ { ++ local_i++; ++ } ++ return 0; ++} +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/attach2.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/attach2.c 2008-12-09 17:02:55.000000000 +0100 +@@ -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 ++#include ++#include ++ ++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.50.20081128/gdb/testsuite/gdb.pie/break.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/break.c 2008-12-09 17:02:55.000000000 +0100 +@@ -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 ++ ++/* 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 ++# include ++#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 \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.50.20081128/gdb/testsuite/gdb.pie/break1.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/break1.c 2008-12-09 17:02:55.000000000 +0100 +@@ -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.50.20081128/gdb/testsuite/gdb.pie/coremaker.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/coremaker.c 2008-12-09 17:02:55.000000000 +0100 +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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; ++} ++ +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/attach.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/attach.exp 2008-12-09 17:02:55.000000000 +0100 +@@ -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 "reakpoint .*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.50.20081128/gdb/testsuite/gdb.pie/break.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/break.exp 2008-12-09 17:24:34.000000000 +0100 +@@ -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" "reakpoint.*at.* file .*$srcfile, line.*" "Temporary breakpoint function" ++ ++# ++# test break at function in file ++# ++ ++gdb_test "tbreak $srcfile:factorial" "reakpoint.*at.* file .*$srcfile, line.*" \ ++ "Temporary breakpoint function in file" ++ ++# ++# test break at line number ++# ++send_gdb "tbreak $bp_location1\n" ++gdb_expect { ++ -re "reakpoint.*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" "reakpoint.*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 "reakpoint.*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" "reakpoint.*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.50.20081128/gdb/testsuite/gdb.pie/corefile.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/corefile.exp 2008-12-09 17:02:55.000000000 +0100 +@@ -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.50.20081128/gdb/testsuite/gdb.pie/Makefile.in +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.pie/Makefile.in 2008-12-09 17:02:55.000000000 +0100 +@@ -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.* diff --git a/gdb-6.3-test-self-20050110.patch b/gdb-6.3-test-self-20050110.patch new file mode 100644 index 0000000..7dccbe6 --- /dev/null +++ b/gdb-6.3-test-self-20050110.patch @@ -0,0 +1,101 @@ +2004-02-23 Elena Zannoni + + * gdb.gdb/selftest.exp: Make sure that the debug directory is + set up properly. + * gdb.gdb/complaints.exp: Ditto. + * gdb.gdb/xfullpath.exp: Ditto. + * gdb.gdb/observer.exp: Ditto. + +Index: gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/complaints.exp +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/testsuite/gdb.gdb/complaints.exp 2009-01-03 06:58:04.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/complaints.exp 2009-02-26 22:10:48.000000000 +0100 +@@ -302,13 +302,13 @@ proc find_gdb { arg } { + set GDB_FULLPATH [find_gdb $GDB] + + # Remove any old copy lying around. +-remote_file host delete x$tool ++#remote_file host delete x$tool + + gdb_start + +-set file [remote_download host $GDB_FULLPATH x$tool] ++#set file [remote_download host $GDB_FULLPATH x$tool] + +-set setup_result [setup_test $file ] ++set setup_result [setup_test $GDB_FULLPATH ] + if {$setup_result <0} then { + return -1 + } +@@ -319,4 +319,4 @@ test_short_complaints + test_empty_complaints + + gdb_exit; +-catch "remote_file host delete $file"; ++#catch "remote_file host delete $file"; +Index: gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/observer.exp +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/testsuite/gdb.gdb/observer.exp 2009-02-17 20:52:27.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/observer.exp 2009-02-26 22:11:40.000000000 +0100 +@@ -258,13 +258,13 @@ proc find_gdb { arg } { + set GDB_FULLPATH [find_gdb $GDB] + + # Remove any old copy lying around. +-remote_file host delete x$tool ++#remote_file host delete x$tool + + gdb_start +-set file [remote_download host $GDB_FULLPATH x$tool] +-set result [test_observer $file]; ++#set file [remote_download host $GDB_FULLPATH x$tool] ++set result [test_observer $GDB_FULLPATH]; + gdb_exit; +-catch "remote_file host delete $file"; ++#catch "remote_file host delete $file"; + + if {$result <0} then { + warning "Couldn't test self" +Index: gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/selftest.exp +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/testsuite/gdb.gdb/selftest.exp 2009-02-26 22:09:59.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/selftest.exp 2009-02-26 22:10:48.000000000 +0100 +@@ -551,13 +551,13 @@ proc find_gdb { arg } { + set GDB_FULLPATH [find_gdb $GDB] + + # Remove any old copy lying around. +-remote_file host delete x$tool ++#remote_file host delete x$tool + + gdb_start +-set file [remote_download host $GDB_FULLPATH x$tool] +-set result [test_with_self $file]; ++#set file [remote_download host $GDB_FULLPATH x$tool] ++set result [test_with_self $GDB_FULLPATH]; + gdb_exit; +-catch "remote_file host delete $file"; ++#catch "remote_file host delete $file"; + + if {$result <0} then { + warning "Couldn't test self" +Index: gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/xfullpath.exp +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/testsuite/gdb.gdb/xfullpath.exp 2009-01-03 06:58:04.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/testsuite/gdb.gdb/xfullpath.exp 2009-02-26 22:10:48.000000000 +0100 +@@ -179,13 +179,13 @@ proc find_gdb { arg } { + set GDB_FULLPATH [find_gdb $GDB] + + # Remove any old copy lying around. +-remote_file host delete x$tool ++#remote_file host delete x$tool + + gdb_start +-set file [remote_download host $GDB_FULLPATH x$tool] +-set result [test_with_self $file]; ++#set file [remote_download host $GDB_FULLPATH x$tool] ++set result [test_with_self $GDB_FULLPATH]; + gdb_exit; +-catch "remote_file host delete $file"; ++#catch "remote_file host delete $file"; + + if {$result <0} then { + warning "Couldn't test self" diff --git a/gdb-6.3-test-sepcrc-20050402.patch b/gdb-6.3-test-sepcrc-20050402.patch new file mode 100644 index 0000000..cff7c11 --- /dev/null +++ b/gdb-6.3-test-sepcrc-20050402.patch @@ -0,0 +1,55 @@ +Index: gdb-6.8/gdb/testsuite/gdb.base/sepdebug.exp +=================================================================== +--- gdb-6.8.orig/gdb/testsuite/gdb.base/sepdebug.exp 2008-02-26 09:14:11.000000000 +0100 ++++ gdb-6.8/gdb/testsuite/gdb.base/sepdebug.exp 2008-07-14 10:26:19.000000000 +0200 +@@ -981,3 +981,40 @@ if ![string compare $build_id_debug_file + # Spare debug files may confuse testsuite runs in the future. + remote_exec build "rm -f ${objdir}/${subdir}/${build_id_debug_filename}" + } ++ ++ ++# Compile up a second, different, object file. Copy its debug info ++# over the top of the new debug info. Note that somewhere in the ++# above the "set debug-file-directory" variable is set to ++# ${objdir}/${subdir} so need to move things there. ++ ++set existing_binfile $binfile ++set testfile "sepdebug2" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++set corrupt_debug_file [separate_debug_filename $binfile] ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } { ++ return -1 ++} ++if [gdb_gnu_strip_debug $binfile] { ++ # check that you have a recent version of strip and objcopy installed ++ unsupported "cannot produce separate debug info files" ++ return -1 ++} ++remote_exec build "cp $corrupt_debug_file ${existing_binfile}.debug" ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set test "A corrupt debug file gets a warning" ++gdb_test_multiple "file $existing_binfile" "$test" { ++ -re "warning:.*mismatch.*" { ++ pass "$test" ++ } ++ -re ".y or n. " { ++ send_gdb "y\n" ++ exp_continue ++ } ++} +Index: gdb-6.8/gdb/testsuite/gdb.base/sepdebug2.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8/gdb/testsuite/gdb.base/sepdebug2.c 2008-07-14 10:26:19.000000000 +0200 +@@ -0,0 +1,5 @@ ++int ++main (int argc, char *argv[], char *envp[]) ++{ ++ return 0; ++} diff --git a/gdb-6.3-threaded-watchpoints2-20050225.patch b/gdb-6.3-threaded-watchpoints2-20050225.patch new file mode 100644 index 0000000..44f1e9c --- /dev/null +++ b/gdb-6.3-threaded-watchpoints2-20050225.patch @@ -0,0 +1,250 @@ +2005-02-28 Jeff Johnston + + * config/i386/nm-linux.h: Change dr register routines to + accept a ptid_t first argument. Change all calling macros + to default the inferior_ptid for the first argument. + (i386_linux_insert_watchpoint): New prototype. + (i386_linux_remove_watchpoint, i386_linux_insert_hw_breakpoint): Ditto. + (i386_linux_remove_hw_breakpoint): Ditto. + (target_insert_watchpoint, target_remove_watchpoint): Undef and + override. + (target_insert_hw_breakpoint, target_remove_hw_breakpoint): Ditto. + * config/i386/nm-linux64.h: Ditto except add amd64 versions of + the watchpoint/hw-breakpoint insert/remove routines. + * i386-nat.c: Include "inferior.h" to define inferior_ptid. + * i386-linux-nat.c: Change all dr get/set routines to accept + ptid_t as first argument and to use this argument to determine + the tid for PTRACE. + (i386_linux_set_debug_regs_for_thread): New function. + (i386_linux_sync_debug_registers_callback): Ditto. + (i386_linux_sync_debug_registers_across_threads): Ditto. + (i386_linux_insert_watchpoint, i386_linux_remove_watchpoint): Ditto. + (i386_linux_hw_breakpoint, i386_linux_remove_hw_breakpoint): Ditto. + (i386_linux_new_thread): Ditto. + (_initialize_i386_linux_nat): Ditto. + * amd64-linux-nat.c: Change all dr get/set routines to accept + ptid_t as first argument and to use this argument to determine + the tid for PTRACE. + (amd64_linux_set_debug_regs_for_thread): New function. + (amd64_linux_sync_debug_registers_callback): Ditto. + (amd64_linux_sync_debug_registers_across_threads): Ditto. + (amd64_linux_insert_watchpoint, amd64_linux_remove_watchpoint): Ditto. + (amd64_linux_hw_breakpoint, amd64_linux_remove_hw_breakpoint): Ditto. + (amd64_linux_new_thread): Ditto. + (_initialize_amd64_linux_nat): Register linux new thread observer. + * testsuite/gdb.threads/watchthreads2.c: New test case. + * testsuite/gdb.threads/watchthreads2.exp: Ditto. + +[ With recent upstream GDB (6.8) reduced only to the testcase. ] + +FIXME: The testcase does not expects multiple watchpoints hits per one stop. + +Index: gdb-6.5/gdb/testsuite/gdb.threads/watchthreads2.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.5/gdb/testsuite/gdb.threads/watchthreads2.c 2006-07-12 01:54:29.000000000 -0300 +@@ -0,0 +1,66 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2002, 2003, 2004, 2005 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. ++ ++ This file is copied from schedlock.c. */ ++ ++#include ++#include ++#include ++#include ++ ++void *thread_function(void *arg); /* Pointer to function executed by each thread */ ++ ++#define NUM 5 ++ ++unsigned int args[NUM+1]; ++ ++int main() { ++ int res; ++ pthread_t threads[NUM]; ++ void *thread_result; ++ long i; ++ ++ for (i = 0; i < NUM; i++) ++ { ++ args[i] = 1; /* Init value. */ ++ res = pthread_create(&threads[i], ++ NULL, ++ thread_function, ++ (void *) i); ++ } ++ ++ args[i] = 1; ++ thread_function ((void *) i); ++ ++ exit(EXIT_SUCCESS); ++} ++ ++void *thread_function(void *arg) { ++ int my_number = (long) arg; ++ int *myp = (int *) &args[my_number]; ++ ++ /* Don't run forever. Run just short of it :) */ ++ while (*myp > 0) ++ { ++ (*myp) ++; usleep (1); /* Loop increment. */ ++ } ++ ++ pthread_exit(NULL); ++} ++ +Index: gdb-6.5/gdb/testsuite/gdb.threads/watchthreads2.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.5/gdb/testsuite/gdb.threads/watchthreads2.exp 2006-07-12 01:54:29.000000000 -0300 +@@ -0,0 +1,133 @@ ++# This testcase is part of GDB, the GNU debugger. ++ ++# Copyright 2005 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. ++ ++# Check that GDB can support multiple watchpoints across threads. ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++# This test verifies that a watchpoint is detected in the proper thread ++# so the test is only meaningful on a system with hardware watchpoints. ++if [target_info exists gdb,no_hardware_watchpoints] { ++ return 0; ++} ++ ++set testfile "watchthreads2" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_test "set can-use-hw-watchpoints 1" "" "" ++ ++# ++# Run to `main' where we begin our tests. ++# ++ ++if ![runto_main] then { ++ gdb_suppress_tests ++} ++ ++set args_2 0 ++set args_3 0 ++ ++gdb_breakpoint "thread_function" ++gdb_continue_to_breakpoint "thread_function" ++gdb_test "disable 2" "" ++ ++gdb_test_multiple "p args\[2\]" "get initial args2" { ++ -re "\\\$\[0-9\]* = (.*)$gdb_prompt $" { ++ set init_args_2 $expect_out(1,string) ++ pass "get initial args2" ++ } ++} ++ ++gdb_test_multiple "p args\[3\]" "get initial args3" { ++ -re "\\\$\[0-9\]* = (.*)$gdb_prompt $" { ++ set init_args_3 $expect_out(1,string) ++ pass "get initial args3" ++ } ++} ++ ++set args_2 $init_args_2 ++set args_3 $init_args_3 ++ ++# Watch values that will be modified by distinct threads. ++gdb_test "watch args\[2\]" "Hardware watchpoint 3: args\\\[2\\\]" ++gdb_test "watch args\[3\]" "Hardware watchpoint 4: args\\\[3\\\]" ++ ++set init_line [expr [gdb_get_line_number "Init value"]+1] ++set inc_line [gdb_get_line_number "Loop increment"] ++ ++# Loop and continue to allow both watchpoints to be triggered. ++for {set i 0} {$i < 30} {incr i} { ++ set test_flag 0 ++ gdb_test_multiple "continue" "threaded watch loop" { ++ -re "Hardware watchpoint 3: args\\\[2\\\].*Old value = 0.*New value = 1.*main \\\(\\\) at .*watchthreads2.c:$init_line.*$gdb_prompt $" ++ { set args_2 1; set test_flag 1 } ++ -re "Hardware watchpoint 4: args\\\[3\\\].*Old value = 0.*New value = 1.*main \\\(\\\) at .*watchthreads2.c:$init_line.*$gdb_prompt $" ++ { set args_3 1; set test_flag 1 } ++ -re "Hardware watchpoint 3: args\\\[2\\\].*Old value = $args_2.*New value = [expr $args_2+1].*in thread_function \\\(arg=0x2\\\) at .*watchthreads2.c:$inc_line.*$gdb_prompt $" ++ { set args_2 [expr $args_2+1]; set test_flag 1 } ++ -re "Hardware watchpoint 4: args\\\[3\\\].*Old value = $args_3.*New value = [expr $args_3+1].*in thread_function \\\(arg=0x3\\\) at .*watchthreads2.c:$inc_line.*$gdb_prompt $" ++ { set args_3 [expr $args_3+1]; set test_flag 1 } ++ } ++ # If we fail above, don't bother continuing loop ++ if { $test_flag == 0 } { ++ set i 30; ++ } ++} ++ ++# Print success message if loop succeeded. ++if { $test_flag == 1 } { ++ pass "threaded watch loop" ++} ++ ++# Verify that we hit first watchpoint in child thread. ++set message "watchpoint on args\[2\] hit in thread" ++if { $args_2 > 1 } { ++ pass $message ++} else { ++ fail $message ++} ++ ++# Verify that we hit second watchpoint in child thread. ++set message "watchpoint on args\[3\] hit in thread" ++if { $args_3 > 1 } { ++ pass $message ++} else { ++ fail $message ++} ++ ++# Verify that all watchpoint hits are accounted for. ++set message "combination of threaded watchpoints = 30 + initial values" ++if { [expr $args_2+$args_3] == [expr [expr 30+$init_args_2]+$init_args_3] } { ++ pass $message ++} else { ++ fail $message ++} diff --git a/gdb-6.3-watchpoint-cond-gone-test.patch b/gdb-6.3-watchpoint-cond-gone-test.patch new file mode 100644 index 0000000..f2334ad --- /dev/null +++ b/gdb-6.3-watchpoint-cond-gone-test.patch @@ -0,0 +1,128 @@ +--- /dev/null 2008-04-03 00:39:30.714021604 +0200 ++++ gdb-6.3/gdb/testsuite/gdb.base/watchpoint-cond-gone-stripped.c 2008-04-05 20:26:29.000000000 +0200 +@@ -0,0 +1,23 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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. */ ++ ++void ++jumper (void (*jumpto) (void)) ++{ ++ (*jumpto) (); ++} +--- /dev/null 2008-04-03 00:39:30.714021604 +0200 ++++ gdb-6.3/gdb/testsuite/gdb.base/watchpoint-cond-gone.c 2008-04-05 20:26:48.000000000 +0200 +@@ -0,0 +1,37 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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. */ ++ ++extern void jumper (void (*jumpto) (void)); ++ ++void ++func () ++{ ++ int a, b, c; ++ ++ a = b = c = 5; ++ a = b = c = 10; /* watchpoint-here */ ++ c = a + b; ++} ++ ++int ++main () ++{ ++ jumper (func); ++ ++ return 0; ++} +--- /dev/null 2008-04-03 00:39:30.714021604 +0200 ++++ gdb-6.3/gdb/testsuite/gdb.base/watchpoint-cond-gone.exp 2008-04-05 20:33:19.000000000 +0200 +@@ -0,0 +1,59 @@ ++# Copyright 2008 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile "watchpoint-cond-gone" ++set srcfile ${testfile}.c ++set srcfilestripped ${testfile}-stripped.c ++set objfilestripped ${objdir}/${subdir}/${testfile}-stripped.o ++set binfile ${objdir}/${subdir}/${testfile} ++ ++# We need to generate a function without DWARF to crash older GDB. ++# Stepping into a dynamic function trampoline or stepping out of MAIN may work ++# but it is not a reliable FAIL case. ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfilestripped}" "${objfilestripped}" object {}] != "" } { ++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${objfilestripped}" "${binfile}" executable {debug}] != "" } { ++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Problem does not occur otherwise. ++gdb_test "set can-use-hw-watchpoints 0" ++ ++runto_main ++gdb_breakpoint [gdb_get_line_number "watchpoint-here"] ++gdb_continue_to_breakpoint "Place to set the watchpoint" ++ ++# The condition `c == 30' is the tested culprit. ++gdb_test "watch c if c == 30" "" "Place the watchpoint" ++ ++# No functionality, just to check the state. ++gdb_test "backtrace" ++ ++gdb_test "finish" \ ++ "Watchpoint .* deleted because the program has left the block in.*which its expression is valid..*in (jumper|func).*" \ ++ "Catch the no longer valid watchpoint" diff --git a/gdb-6.5-BEA-testsuite.patch b/gdb-6.5-BEA-testsuite.patch new file mode 100644 index 0000000..d30e0fe --- /dev/null +++ b/gdb-6.5-BEA-testsuite.patch @@ -0,0 +1,938 @@ +Index: ./gdb/testsuite/gdb.threads/threadcrash.c +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.c +diff -N gdb/testsuite/gdb.threads/threadcrash.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.c 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,301 @@ ++/* ++ * The point of this program is to crash in a multi-threaded app. ++ * There are seven threads, doing the following things: ++ * * Spinning ++ * * Spinning inside a signal handler ++ * * Spinning inside a signal handler executing on the altstack ++ * * In a syscall ++ * * In a syscall inside a signal handler ++ * * In a syscall inside a signal handler executing on the altstack ++ * * Finally, the main thread crashes in main, with no frills. ++ * ++ * These are the things threads in JRockit tend to be doing. If gdb ++ * can handle those things, both in core files and during live ++ * debugging, that will help (at least) JRockit development. ++ * ++ * Let the program create a core file, then load the core file into ++ * gdb. Inside gdb, you should be able to do something like this: ++ * ++ * (gdb) t a a bt ++ * ++ * Thread 7 (process 4352): ++ * #0 0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6 ++ * #1 0x001ba5ff in sleep () from /lib/tls/libc.so.6 ++ * #2 0x080488a2 in makeSyscall (ignored=0x0) at threadcrash.c:118 ++ * #3 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #4 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 6 (process 4353): ++ * #0 0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6 ++ * #1 0x001ba5ff in sleep () from /lib/tls/libc.so.6 ++ * #2 0x0804898f in syscallingSighandler (signo=10, info=0xb6be76f0, context=0xb6be7770) ++ * at threadcrash.c:168 ++ * #3 ++ * #4 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #5 0x08048a51 in makeSyscallFromSighandler (ignored=0x0) at threadcrash.c:204 ++ * #6 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #7 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 5 (process 4354): ++ * #0 0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6 ++ * #1 0x001ba5ff in sleep () from /lib/tls/libc.so.6 ++ * #2 0x08048936 in syscallingAltSighandler (signo=3, info=0x959cd70, context=0x959cdf0) ++ * at threadcrash.c:144 ++ * #3 ++ * #4 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #5 0x080489e2 in makeSyscallFromAltSighandler (ignored=0x0) at threadcrash.c:190 ++ * #6 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #7 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 4 (process 4355): ++ * #0 spin (ignored=0x0) at threadcrash.c:242 ++ * #1 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #2 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 3 (process 4356): ++ * #0 spinningSighandler (signo=12, info=0xb4de46f0, context=0xb4de4770) at threadcrash.c:180 ++ * #1 ++ * #2 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #3 0x08048b2f in spinFromSighandler (ignored=0x0) at threadcrash.c:232 ++ * #4 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #5 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 2 (process 4357): ++ * #0 spinningAltSighandler (signo=14, info=0x959ee50, context=0x959eed0) at threadcrash.c:156 ++ * #1 ++ * #2 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #3 0x08048ac0 in spinFromAltSighandler (ignored=0x0) at threadcrash.c:218 ++ * #4 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #5 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 1 (process 4351): ++ * #0 0x08048cf3 in main (argc=1, argv=0xbfff9d74) at threadcrash.c:273 ++ * (gdb) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SIGSYSCALL_ALT SIGQUIT ++#define SIGSYSCALL SIGUSR1 ++#define SIGSPIN_ALT SIGALRM ++#define SIGSPIN SIGUSR2 ++ ++typedef void (*sigaction_t)(int, siginfo_t *, void *); ++ ++static void installHandler(int signo, sigaction_t handler, int onAltstack) { ++ struct sigaction action; ++ sigset_t sigset; ++ int result; ++ stack_t altstack; ++ stack_t oldaltstack; ++ ++ memset(&action, 0, sizeof(action)); ++ memset(&altstack, 0, sizeof(altstack)); ++ memset(&oldaltstack, 0, sizeof(oldaltstack)); ++ ++ if (onAltstack) { ++ altstack.ss_sp = malloc(SIGSTKSZ); ++ assert(altstack.ss_sp != NULL); ++ altstack.ss_size = SIGSTKSZ; ++ altstack.ss_flags = 0; ++ result = sigaltstack(&altstack, &oldaltstack); ++ assert(result == 0); ++ assert(oldaltstack.ss_flags == SS_DISABLE); ++ } ++ ++ sigemptyset(&sigset); ++ ++ action.sa_handler = NULL; ++ action.sa_sigaction = handler; ++ action.sa_mask = sigset; ++ action.sa_flags = SA_SIGINFO; ++ if (onAltstack) { ++ action.sa_flags |= SA_ONSTACK; ++ } ++ ++ result = sigaction(signo, &action, NULL); ++ assert(result == 0); ++} ++ ++static void installNormalHandler(int signo, sigaction_t handler) { ++ installHandler(signo, handler, 0); ++} ++ ++static void installAlthandler(int signo, sigaction_t handler) { ++ installHandler(signo, handler, 1); ++} ++ ++static void *makeSyscall(void *ignored) { ++ (void)ignored; ++ ++ sleep(42); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++/* Return true if we're currently executing on the altstack */ ++static int onAltstack(void) { ++ stack_t stack; ++ int result; ++ ++ result = sigaltstack(NULL, &stack); ++ assert(result == 0); ++ ++ return stack.ss_flags & SS_ONSTACK; ++} ++ ++static void syscallingAltSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (!onAltstack()) { ++ printf("%s() not running on altstack!\n", __FUNCTION__); ++ } ++ ++ sleep(42); ++} ++ ++static void spinningAltSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (!onAltstack()) { ++ printf("%s() not running on altstack!\n", __FUNCTION__); ++ } ++ ++ while (1); ++} ++ ++static void syscallingSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (onAltstack()) { ++ printf("%s() running on altstack!\n", __FUNCTION__); ++ } ++ ++ sleep(42); ++} ++ ++static void spinningSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (onAltstack()) { ++ printf("%s() running on altstack!\n", __FUNCTION__); ++ } ++ ++ while (1); ++} ++ ++static void *makeSyscallFromAltSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installAlthandler(SIGSYSCALL_ALT, syscallingAltSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSYSCALL_ALT); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *makeSyscallFromSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installNormalHandler(SIGSYSCALL, syscallingSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSYSCALL); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *spinFromAltSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installAlthandler(SIGSPIN_ALT, spinningAltSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSPIN_ALT); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *spinFromSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installNormalHandler(SIGSPIN, spinningSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSPIN); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *spin(void *ignored) { ++ (void)ignored; ++ ++ while (1); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++int main(int argc, char *argv[]) { ++ int result; ++ pthread_t thread; ++ volatile int bad; ++ ++ result = pthread_create(&thread, NULL, makeSyscall, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, makeSyscallFromSighandler, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, makeSyscallFromAltSighandler, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, spin, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, spinFromSighandler, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, spinFromAltSighandler, NULL); ++ assert(result == 0); ++ ++ // Give threads some time to get going ++ sleep(3); ++ ++ // Crash ++ bad = *(int*)7; ++ ++ /* Workaround: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29628 ++ Simulate use to ensure `DW_AT_location' for them: ++ readelf -a --debug threadcrash|grep -A5 -w argc ++ --> DW_AT_location : 2 byte block: 71 0 (DW_OP_breg1: 0) ++ This case verified on: gcc-4.1.1-30.i386 ++ Keep it late to ensure persistency in the registers. */ ++ bad = (int) argc; ++ bad = (unsigned long) argv; ++ ++ return 0; ++} +Index: ./gdb/testsuite/gdb.threads/threadcrash.exp +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.exp +diff -N gdb/testsuite/gdb.threads/threadcrash.exp +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.exp 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,37 @@ ++# threadcrash.exp - The point of this program is to crash in a multi-threaded app. ++ ++ ++set testfile threadcrash ++set srcfile ${testfile}.c ++set shellfile ${srcdir}/${subdir}/${testfile}.sh ++set binfile ${objdir}/${subdir}/${testfile} ++ ++set GDB_abs ${GDB} ++if [regexp "^\[^/\]" ${GDB_abs}] { ++ set GDB_abs $env(PWD)/${GDB_abs} ++} ++ ++if [istarget "*-*-linux"] then { ++ set target_cflags "-D_MIT_POSIX_THREADS" ++} else { ++ set target_cflags "" ++} ++ ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ return -1 ++} ++ ++# ${shellfile} argument must not contain any directories. ++set fd [open "|bash ${shellfile} ${binfile} $GDB -nw $GDBFLAGS" r] ++while { [gets $fd line] >= 0 } { ++ if [regexp " PASS: (.*)$" $line trash message] { ++ pass $message ++ } elseif [regexp " FAIL: (.*)$" $line trash message] { ++ fail $message ++ } ++} ++catch { ++ close $fd ++} ++ ++return 0 +Index: ./gdb/testsuite/gdb.threads/threadcrash.sh +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.sh +diff -N gdb/testsuite/gdb.threads/threadcrash.sh +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.sh 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,324 @@ ++#! /bin/bash ++ ++# NOTE: threadcrash.c *must* be built with debugging symbols ++# ++# The point of this shell script is to crash treadcrash.c, load the ++# resulting core file into gdb and verify that gdb can extract enough ++# information from the core file. ++# ++# The return code from this script is the number of failed tests. ++ ++LOG=gdbresult.log ++ ++if [ $# = 0 ] ; then ++ echo >&2 Syntax: $0 \ [\ \] ++ exit 1 ++fi ++RUNME="$1" ++shift ++GDB="${*:-gdb}" ++ ++ ++pf_prefix="" ++function pf_prefix() { ++ pf_prefix="$*" ++} ++ ++set_test="" ++function set_test() { ++ if [ -n "$set_test" ] ; then ++ echo >&2 "DEJAGNU-BASH ERROR: set_test already set" ++ exit 1 ++ fi ++ set_test="$*" ++ if [ -n "$pf_prefix" ] ; then ++ set_test="$pf_prefix: $set_test" ++ fi ++} ++ ++# INTERNAL ++function record_test { ++ if [ -z "$set_test" ] ; then ++ echo >&2 "DEJAGNU-BASH ERROR: set_test not set" ++ exit 1 ++ fi ++ # Provide the leading whitespace delimiter: ++ echo " $1: $set_test" ++ set_test="" ++} ++ ++function pass() { ++ record_test PASS ++} ++function fail() { ++ record_test FAIL ++} ++ ++ ++# Verify that the gdb output doesn't contain $1. ++function mustNotHave() { ++ local BADWORD=$1 ++ set_test gdb output contains "$BADWORD" ++ if grep -q "$BADWORD" $LOG ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that the gdb output contains exactly $1 $2s. ++function mustHaveCorrectAmount() { ++ local WANTEDNUMBER=$1 ++ local GOODWORD=$2 ++ local ACTUALNUMBER=$(grep "$GOODWORD" $LOG | wc -l) ++ set_test gdb output contained $ACTUALNUMBER \""$GOODWORD"\", not $WANTEDNUMBER as expected ++ if [ $ACTUALNUMBER != $WANTEDNUMBER ] ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that the gdb output contains seven threads ++function mustHaveSevenThreads() { ++ NTHREADS=$(egrep "^Thread [1-7] \(" $LOG | wc -l) ++ set_test gdb output contains $NTHREADS threads, not 7 as expected ++ if [ $NTHREADS != 7 ] ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that the gdb output has all parameters on consecutive lines ++function mustHaveSequence() { ++ SEQUENCE="$*" ++ NPARTS=$# ++ grep "$1" -A$((NPARTS - 1)) $LOG > matches.log ++ ++ while [ $# -gt 1 ] ; do ++ shift ++ ((NPARTS--)) ++ grep "$1" -A$((NPARTS - 1)) matches.log > temp.log ++ mv temp.log matches.log ++ done ++ LASTPART=$1 ++ ++ set_test gdb output does not contain the sequence: $SEQUENCE ++ if ! grep -q "$LASTPART" matches.log ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that $LOG contains all information we want ++function verifyLog() { ++ local FAILURES=0 ++ ++ mustNotHave '??' || ((FAILURES++)) ++ mustHaveCorrectAmount 12 threadcrash.c: || ((FAILURES++)) ++ ++ mustHaveSevenThreads || ((FAILURES++)) ++ mustHaveSequence sleep "makeSyscall (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "spin (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "main (argc=1, argv=" || ((FAILURES++)) ++ ++ return $FAILURES ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromCore() { ++ # Make sure we get a core file ++ set_test Make sure we get a core file ++ if ! ulimit -c unlimited ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Run the crasher ++ ./$(basename "$RUNME") ++ EXITCODE=$? ++ ++ # Verify that we actually crashed ++ set_test $RUNME should have been killed by a signal, got non-signal exit code $EXITCODE ++ if [ $EXITCODE -lt 128 ] ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Verify that we got a core file ++ set_test $RUNME did not create a core file ++ if [ ! -r core* ] ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ set_test gdb exited with error code ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE ++ fail ++ fi ++ pass ++} ++ ++# Put result of debugging a gcore file in $LOG ++function getLogFromGcore() { ++ # Create the core file ++ rm -f core* ++ cat > gdbscript.gdb < /dev/null ++ EXITCODE=$? ++ ++ set_test gdb exited with error code when creating gcore file ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE when creating gcore file ++ fail ++ fi ++ pass ++ ++ # Verify that we got a core file from gcore ++ set_test gdb gcore did not create a core file ++ if [ ! -r core* ] ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Run gdb on the gcore file ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ set_test gdb exited with error code when examining gcore file ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE when examining gcore file ++ fail ++ fi ++ pass ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromLiveProcess() { ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ set_test gdb exited with error code ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE ++ fail ++ fi ++ pass ++} ++ ++####### Main program follows ##################### ++ ++# Make sure we don't clobber anybody else's (core) file(s) ++WORKDIR=/tmp/$PPID ++mkdir -p $WORKDIR ++cp "$RUNME" $WORKDIR ++cd $WORKDIR ++ ++# Count problems ++FAILURES=0 ++ ++echo === Testing gdb vs core file... ++pf_prefix core file ++getLogFromCore ++verifyLog ++((FAILURES+=$?)) ++pf_prefix ++echo === Core file tests done. ++ ++echo ++ ++echo === Testing gdb vs gcore file... ++pf_prefix gcore file ++getLogFromGcore ++verifyLog ++((FAILURES+=$?)) ++pf_prefix ++echo === Gcore file tests done. ++ ++echo ++ ++echo === Testing gdb vs live process... ++pf_prefix live process ++getLogFromLiveProcess ++verifyLog ++((FAILURES+=$?)) ++pf_prefix ++echo === Live process tests done. ++ ++# Executive summary ++echo ++if [ $FAILURES == 0 ] ; then ++ echo All tests passed! ++else ++ echo $FAILURES tests failed! ++ echo ++ echo Make sure the threadcrash binary contains debugging information \(build with \"gcc -g\"\). ++fi ++ ++# Clean up ++cd / ++rm -rf $WORKDIR ++ ++exit $FAILURES +Index: ./gdb/testsuite/gdb.threads/threadcrash.sh-orig +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.sh-orig +diff -N gdb/testsuite/gdb.threads/threadcrash.sh-orig +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.sh-orig 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,248 @@ ++#! /bin/bash ++ ++# NOTE: threadcrash.c *must* be built with debugging symbols ++# ++# The point of this shell script is to crash treadcrash.c, load the ++# resulting core file into gdb and verify that gdb can extract enough ++# information from the core file. ++# ++# The return code from this script is the number of failed tests. ++ ++LOG=gdbresult.log ++ ++if [ $# != 1 ] ; then ++ echo > /dev/stderr Syntax: $0 \ ++ exit 1 ++fi ++RUNME="$1" ++ ++# Verify that the gdb output doesn't contain $1. ++function mustNotHave() { ++ local BADWORD=$1 ++ if grep -q "$BADWORD" $LOG ; then ++ echo >> /dev/stderr WARNING: gdb output contains "$BADWORD" ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that the gdb output contains exactly $1 $2s. ++function mustHaveCorrectAmount() { ++ local WANTEDNUMBER=$1 ++ local GOODWORD=$2 ++ local ACTUALNUMBER=$(grep "$GOODWORD" $LOG | wc -l) ++ if [ $ACTUALNUMBER != $WANTEDNUMBER ] ; then ++ echo >> /dev/stderr WARNING: gdb output contained $ACTUALNUMBER \""$GOODWORD"\", not $WANTEDNUMBER as expected ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that the gdb output contains seven threads ++function mustHaveSevenThreads() { ++ NTHREADS=$(egrep "^Thread [1-7] \(" $LOG | wc -l) ++ if [ $NTHREADS != 7 ] ; then ++ echo >> /dev/stderr WARNING: gdb output contains $NTHREADS threads, not 7 as expected ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that the gdb output has all parameters on consecutive lines ++function mustHaveSequence() { ++ SEQUENCE="$*" ++ NPARTS=$# ++ grep "$1" -A$((NPARTS - 1)) $LOG > matches.log ++ ++ while [ $# -gt 1 ] ; do ++ shift ++ ((NPARTS--)) ++ grep "$1" -A$((NPARTS - 1)) matches.log > temp.log ++ mv temp.log matches.log ++ done ++ LASTPART=$1 ++ ++ if ! grep -q "$LASTPART" matches.log ; then ++ echo >> /dev/stderr WARNING: gdb output does not contain the sequence: $SEQUENCE ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that $LOG contains all information we want ++function verifyLog() { ++ local FAILURES=0 ++ ++ mustNotHave '??' || ((FAILURES++)) ++ mustHaveCorrectAmount 12 threadcrash.c: || ((FAILURES++)) ++ ++ mustHaveSevenThreads || ((FAILURES++)) ++ mustHaveSequence sleep "makeSyscall (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "spin (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "main (argc=1, argv=" || ((FAILURES++)) ++ ++ return $FAILURES ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromCore() { ++ # Make sure we get a core file ++ ulimit -c unlimited || exit 1 ++ ++ # Run the crasher ++ ./$(basename "$RUNME") ++ EXITCODE=$? ++ ++ # Verify that we actually crashed ++ if [ $EXITCODE -lt 128 ] ; then ++ echo >> /dev/stderr ERROR: $RUNME should have been killed by a signal, got non-signal exit code $EXITCODE ++ exit 1 ++ fi ++ ++ # Verify that we got a core file ++ if [ ! -r core* ] ; then ++ echo >> /dev/stderr ERROR: $RUNME did not create a core file ++ exit 1 ++ fi ++ ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE ++ fi ++} ++ ++# Put result of debugging a gcore file in $LOG ++function getLogFromGcore() { ++ # Create the core file ++ rm -f core* ++ cat > gdbscript.gdb < /dev/null ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE when creating gcore file ++ fi ++ ++ # Verify that we got a core file from gcore ++ if [ ! -r core* ] ; then ++ echo >> /dev/stderr ERROR: gdb gcore did not create a core file ++ exit 1 ++ fi ++ ++ # Run gdb on the gcore file ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE when examining gcore file ++ fi ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromLiveProcess() { ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE ++ fi ++} ++ ++####### Main program follows ##################### ++ ++# Make sure we don't clobber anybody else's (core) file(s) ++WORKDIR=/tmp/$PPID ++mkdir -p $WORKDIR ++cp "$RUNME" $WORKDIR ++cd $WORKDIR ++ ++# Count problems ++FAILURES=0 ++ ++echo === Testing gdb vs core file... ++getLogFromCore ++verifyLog ++((FAILURES+=$?)) ++echo === Core file tests done. ++ ++echo ++ ++echo === Testing gdb vs gcore file... ++getLogFromGcore ++verifyLog ++((FAILURES+=$?)) ++echo === Gcore file tests done. ++ ++echo ++ ++echo === Testing gdb vs live process... ++getLogFromLiveProcess ++verifyLog ++((FAILURES+=$?)) ++echo === Live process tests done. ++ ++# Executive summary ++echo ++if [ $FAILURES == 0 ] ; then ++ echo All tests passed! ++else ++ echo $FAILURES tests failed! ++ echo ++ echo Make sure the threadcrash binary contains debugging information \(build with \"gcc -g\"\). ++fi ++ ++# Clean up ++cd / ++rm -rf $WORKDIR ++ ++exit $FAILURES diff --git a/gdb-6.5-bz109921-DW_AT_decl_file-test.patch b/gdb-6.5-bz109921-DW_AT_decl_file-test.patch new file mode 100644 index 0000000..ddef622 --- /dev/null +++ b/gdb-6.5-bz109921-DW_AT_decl_file-test.patch @@ -0,0 +1,120 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=109921 + +It is duplicite to its upstream variant: +http://sourceware.org/ml/gdb-cvs/2007-01/msg00157.html +http://sourceware.org/ml/gdb-patches/2007-01/msg00434.html +2007-01-21 Jan Kratochvil + Daniel Jacobowitz + + * gdb.base/included.c, gdb.base/included.exp, + gdb.base/included.h: New files. + +------------------------------------------------------------------------------ + +2007-01-09 Jan Kratochvil + + * gdb.dwarf2/dw2-included.exp, gdb.dwarf2/dw2-included.c, + gdb.dwarf2/dw2-included.h: New files. + +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.dwarf2/dw2-included.c 2 Jan 2007 00:20:27 -0000 +@@ -0,0 +1,26 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2006 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. */ ++ ++#include "dw2-included.h" ++ ++int ++main() ++{ ++ return 0; ++} +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.dwarf2/dw2-included.exp 2 Jan 2007 00:20:27 -0000 +@@ -0,0 +1,47 @@ ++# Copyright 2006 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. ++ ++# Minimal DWARF-2 unit test ++ ++# This test can only be run on targets which support DWARF-2. ++# For now pick a sampling of likely targets. ++if {![istarget *-*-linux*] ++ && ![istarget *-*-gnu*] ++ && ![istarget *-*-elf*] ++ && ![istarget *-*-openbsd*] ++ && ![istarget arm-*-eabi*] ++ && ![istarget powerpc-*-eabi*]} { ++ return 0 ++} ++ ++set testfile "dw2-included" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_test "set listsize 1" "" ++gdb_test "list integer" "int integer;\r" ++gdb_test "ptype integer" "type = int\r" ++# Path varies depending on the build location. ++gdb_test "info variables integer" "\r\nFile \[^\r\n\]*/gdb.dwarf2/dw2-included.h:\r\nint integer;\r" +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.dwarf2/dw2-included.h 2 Jan 2007 00:20:27 -0000 +@@ -0,0 +1,20 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2006 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. */ ++ ++int integer; diff --git a/gdb-6.5-bz181390-memory-address-width.patch b/gdb-6.5-bz181390-memory-address-width.patch new file mode 100644 index 0000000..192a8bc --- /dev/null +++ b/gdb-6.5-bz181390-memory-address-width.patch @@ -0,0 +1,197 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=181390 + +2006-09-28 Jan Kratochvil + + * gdb/utils.c (paddress): Disable cutting of the printed addresses + to the target's address bit size; user wants to see everything. + * gdb/value.c (value_as_address1): Original `value_as_address'. + (value_as_address): New `value_as_address' wrapper - cut memory address + to the target's address bit size, bugreport by John Reiser. + +2008-03-02 Jan Kratochvil + + Port to GDB-6.8pre. + New testcase `gdb.arch/amd64-i386-address.exp'. + +Index: gdb-6.7.50.20080227/gdb/utils.c +=================================================================== +--- gdb-6.7.50.20080227.orig/gdb/utils.c 2008-03-02 14:28:44.000000000 +0100 ++++ gdb-6.7.50.20080227/gdb/utils.c 2008-03-02 14:35:09.000000000 +0100 +@@ -2540,6 +2540,14 @@ paddr_nz (CORE_ADDR addr) + const char * + paddress (CORE_ADDR addr) + { ++ /* Do not cut the address as the user should see all the information ++ available. Otherwise 64-bit gdb debugging 32-bit inferior would ++ report for `x/x 0xffffffffffffce70' error ++ `Cannot access memory at 0xffffce70' while the error occured just ++ because of the higher order bits 0xffffffff00000000 there. ++ This specific error no longer occurs as the address is now cut ++ during execution by `value_as_address'. */ ++#if 0 + /* Truncate address to the size of a target address, avoiding shifts + larger or equal than the width of a CORE_ADDR. The local + variable ADDR_BIT stops the compiler reporting a shift overflow +@@ -2553,6 +2561,8 @@ paddress (CORE_ADDR addr) + + if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT)) + addr &= ((CORE_ADDR) 1 << addr_bit) - 1; ++#endif ++ + return hex_string (addr); + } + +Index: gdb-6.7.50.20080227/gdb/value.c +=================================================================== +--- gdb-6.7.50.20080227.orig/gdb/value.c 2008-01-18 18:07:40.000000000 +0100 ++++ gdb-6.7.50.20080227/gdb/value.c 2008-03-02 14:36:38.000000000 +0100 +@@ -983,11 +983,9 @@ value_as_double (struct value *val) + return foo; + } + +-/* Extract a value as a C pointer. Does not deallocate the value. +- Note that val's type may not actually be a pointer; value_as_long +- handles all the cases. */ +-CORE_ADDR +-value_as_address (struct value *val) ++/* See `value_as_address' below - core of value to C pointer extraction. */ ++static CORE_ADDR ++value_as_address1 (struct value *val) + { + /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure + whether we want this to be true eventually. */ +@@ -1087,6 +1085,34 @@ value_as_address (struct value *val) + return unpack_long (value_type (val), value_contents (val)); + #endif + } ++ ++/* Extract a value as a C pointer. Does not deallocate the value. ++ Note that val's type may not actually be a pointer; value_as_long ++ handles all the cases. */ ++CORE_ADDR ++value_as_address (struct value *val) ++{ ++ CORE_ADDR addr; ++ int addr_bit; ++ ++ addr = value_as_address1 (val); ++ ++ /* Truncate address to the size of a target address, avoiding shifts ++ larger or equal than the width of a CORE_ADDR. The local ++ variable ADDR_BIT stops the compiler reporting a shift overflow ++ when it won't occur. */ ++ /* NOTE: This assumes that the significant address information is ++ kept in the least significant bits of ADDR - the upper bits were ++ either zero or sign extended. Should ADDRESS_TO_POINTER() or ++ some ADDRESS_TO_PRINTABLE() be used to do the conversion? */ ++ ++ addr_bit = gdbarch_addr_bit (current_gdbarch); ++ ++ if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT)) ++ addr &= ((CORE_ADDR) 1 << addr_bit) - 1; ++ ++ return addr; ++} + + /* Unpack raw data (copied from debugee, target byte order) at VALADDR + as a long, or as a double, assuming the raw data is described +--- /dev/null 2008-03-01 10:30:54.797374318 +0100 ++++ gdb-6.7.50.20080227/gdb/testsuite/gdb.arch/amd64-i386-address.S 2008-03-02 12:47:06.000000000 +0100 +@@ -0,0 +1,32 @@ ++/* Copyright 2008 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 3 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, see . ++ ++ Please email any bugs, comments, and/or additions to this file to: ++ bug-gdb@gnu.org ++ ++ This file is part of the gdb testsuite. ++ ++ Test UNsigned extension of the 32-bit inferior address on a 64-bit host. ++ This file is based on the work by John Reiser. ++ This file was created by Jan Kratochvil . ++ https://bugzilla.redhat.com/show_bug.cgi?id=181390 */ ++ ++_start: .globl _start ++ nop ++ int3 ++ movl %esp,%ebx ++ int3 # examining memory from $ebx fails, from $esp succeeds ++ nop ++ nop +--- /dev/null 2008-03-01 10:30:54.797374318 +0100 ++++ gdb-6.7.50.20080227/gdb/testsuite/gdb.arch/amd64-i386-address.exp 2008-03-02 12:57:11.000000000 +0100 +@@ -0,0 +1,62 @@ ++# Copyright 2008 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 3 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, see . ++ ++# Please email any bugs, comments, and/or additions to this file to: ++# bug-gdb@gnu.org ++ ++# This file is part of the gdb testsuite. ++ ++# Test UNsigned extension of the 32-bit inferior address on a 64-bit host. ++# This file is based on the work by John Reiser. ++# This file was created by Jan Kratochvil . ++# https://bugzilla.redhat.com/show_bug.cgi?id=181390 ++ ++if {![istarget "x86_64-*-*"]} then { ++ verbose "Skipping amd64->i386 adress test." ++ return ++} ++ ++set testfile "amd64-i386-address" ++set srcfile ${testfile}.S ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "additional_flags=-m32 -nostdlib"]] != "" } { ++ untested amd64-i386-address.exp ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_run_cmd ++ ++set test "trap stop" ++gdb_test_multiple "" $test { ++ -re "Program received signal SIGTRAP,.*_start .*$gdb_prompt $" { ++ pass $test ++ } ++} ++ ++gdb_test "stepi" ".*_start .*int3.*" ++ ++gdb_test "x/x \$esp" "0x\[0-9a-f\]*:\t0x0*1" ++ ++# Failure case would be: ++# 0xff8d7f00: Cannot access memory at address 0xff8d7f00 ++gdb_test "x/x \$ebx" "0x\[0-9a-f\]*:\t0x0*1" diff --git a/gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch b/gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch new file mode 100644 index 0000000..1ca5610 --- /dev/null +++ b/gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch @@ -0,0 +1,261 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=185337 + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +currently for trivial nonthreaded helloworld with no debug info up to -ggdb2 you +will get: + (gdb) p errno + [some error] + +* with -ggdb2 and less "errno" in fact does not exist anywhere as it was + compiled to "(*__errno_location ())" and the macro definition is not present. + Unfortunately gdb will find the TLS symbol and it will try to access it but + as the program has been compiled without -lpthread the TLS base register + (%gs on i386) is not setup and it will result in: + Cannot access memory at address 0x8 + +Attached suggestion patch how to deal with the most common "errno" symbol +for the most common under-ggdb3 compiled programs. + + + +2007-11-03 Jan Kratochvil + + * ./gdb/dwarf2read.c (read_partial_die, dwarf2_linkage_name): Prefer + DW_AT_MIPS_linkage_name over DW_AT_name now only for non-C. + +glibc-debuginfo-2.7-2.x86_64: /usr/lib/debug/lib64/libc.so.6.debug: + <81a2> DW_AT_name : (indirect string, offset: 0x280e): __errno_location + <81a8> DW_AT_MIPS_linkage_name: (indirect string, offset: 0x2808): *__GI___errno_location + +Index: gdb-6.8.50.20090228/gdb/gdbtypes.c +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/gdbtypes.c 2009-03-02 01:01:15.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/gdbtypes.c 2009-03-02 01:01:53.000000000 +0100 +@@ -3633,6 +3633,8 @@ gdbtypes_post_init (struct gdbarch *gdba + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, + 0, "int", OBJFILE_INTERNAL); ++ builtin_type->builtin_int_ptr = ++ make_pointer_type (builtin_type->builtin_int, NULL); + builtin_type->builtin_unsigned_int = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, +@@ -3742,6 +3744,12 @@ gdbtypes_post_init (struct gdbarch *gdba + "", OBJFILE_INTERNAL); + TYPE_TARGET_TYPE (builtin_type->nodebug_text_symbol) = + builtin_type->builtin_int; ++ builtin_type->nodebug_text_symbol_errno_location = ++ init_type (TYPE_CODE_FUNC, 1, 0, ++ "", ++ OBJFILE_INTERNAL); ++ TYPE_TARGET_TYPE (builtin_type->nodebug_text_symbol_errno_location) = ++ builtin_type->builtin_int_ptr; + builtin_type->nodebug_data_symbol = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, +Index: gdb-6.8.50.20090228/gdb/gdbtypes.h +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/gdbtypes.h 2009-03-02 01:01:15.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/gdbtypes.h 2009-03-02 01:01:53.000000000 +0100 +@@ -1053,6 +1053,7 @@ struct builtin_type + + /* Types used for symbols with no debug information. */ + struct type *nodebug_text_symbol; ++ struct type *nodebug_text_symbol_errno_location; + struct type *nodebug_data_symbol; + struct type *nodebug_unknown_symbol; + struct type *nodebug_tls_symbol; +@@ -1065,6 +1066,7 @@ struct builtin_type + struct type *builtin_char; + struct type *builtin_short; + struct type *builtin_int; ++ struct type *builtin_int_ptr; + struct type *builtin_long; + struct type *builtin_signed_char; + struct type *builtin_unsigned_char; +Index: gdb-6.8.50.20090228/gdb/parse.c +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/parse.c 2009-03-02 01:01:15.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/parse.c 2009-03-02 01:01:53.000000000 +0100 +@@ -508,7 +508,12 @@ write_exp_msymbol (struct minimal_symbol + case mst_text: + case mst_file_text: + case mst_solib_trampoline: +- write_exp_elt_type (builtin_type (gdbarch)->nodebug_text_symbol); ++ if (builtin_type (gdbarch)->nodebug_text_symbol_errno_location != NULL ++ && strcmp (SYMBOL_LINKAGE_NAME (msymbol), "__errno_location") == 0) ++ write_exp_elt_type (builtin_type (gdbarch) ++ ->nodebug_text_symbol_errno_location); ++ else ++ write_exp_elt_type (builtin_type (gdbarch)->nodebug_text_symbol); + break; + + case mst_data: +Index: gdb-6.8.50.20090228/gdb/target.c +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/target.c 2009-03-02 01:01:44.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/target.c 2009-03-02 01:01:53.000000000 +0100 +@@ -827,6 +827,25 @@ pop_all_targets (int quitting) + pop_all_targets_above (dummy_stratum, quitting); + } + ++static int ++resolve_errno (void *arg) ++{ ++ CORE_ADDR *arg_addr = arg; ++ struct expression *expr; ++ struct cleanup *old_chain = 0; ++ struct value *val; ++ ++ expr = parse_expression ("__errno_location()"); ++ old_chain = make_cleanup (free_current_contents, &expr); ++ val = evaluate_expression (expr); ++ *arg_addr = value_as_address (val); ++ release_value (val); ++ value_free (val); ++ do_cleanups (old_chain); ++ ++ return 1; ++} ++ + /* Using the objfile specified in OBJFILE, find the address for the + current thread's thread-local storage with offset OFFSET. */ + CORE_ADDR +@@ -917,7 +936,28 @@ target_translate_tls_address (struct obj + /* It wouldn't be wrong here to try a gdbarch method, too; finding + TLS is an ABI-specific thing. But we don't do that yet. */ + else +- error (_("Cannot find thread-local variables on this target")); ++ { ++ struct minimal_symbol *msymbol; ++ ++ msymbol = lookup_minimal_symbol ("errno", NULL, NULL); ++ if (msymbol != NULL ++ && SYMBOL_VALUE_ADDRESS (msymbol) == offset ++ && (SYMBOL_OBJ_SECTION (msymbol)->objfile == objfile ++ || (objfile->separate_debug_objfile != NULL ++ && SYMBOL_OBJ_SECTION (msymbol)->objfile ++ == objfile->separate_debug_objfile) ++ || (objfile->separate_debug_objfile_backlink != NULL ++ && SYMBOL_OBJ_SECTION (msymbol)->objfile ++ == objfile->separate_debug_objfile_backlink))) ++ { ++ if (!catch_errors (resolve_errno, (void *) &addr, "", ++ RETURN_MASK_ALL)) ++ error (_("TLS symbol `errno' not resolved for non-TLS program." ++ " You should compile the program with `gcc -pthread'.")); ++ } ++ else ++ error (_("Cannot find thread-local variables on this target")); ++ } + + return addr; + } +Index: gdb-6.8.50.20090228/gdb/testsuite/gdb.dwarf2/dw2-errno.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090228/gdb/testsuite/gdb.dwarf2/dw2-errno.c 2009-03-02 01:01:53.000000000 +0100 +@@ -0,0 +1,28 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2005, 2007 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 3 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, see . ++ ++ Please email any bugs, comments, and/or additions to this file to: ++ bug-gdb@prep.ai.mit.edu */ ++ ++#include ++ ++int main() ++{ ++ errno = 42; ++ ++ return 0; /* breakpoint */ ++} +Index: gdb-6.8.50.20090228/gdb/testsuite/gdb.dwarf2/dw2-errno.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090228/gdb/testsuite/gdb.dwarf2/dw2-errno.exp 2009-03-02 01:01:53.000000000 +0100 +@@ -0,0 +1,67 @@ ++# Copyright 2007 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 3 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, see . ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile dw2-errno ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++proc prep {} { ++ global srcdir subdir binfile ++ gdb_exit ++ gdb_start ++ gdb_reinitialize_dir $srcdir/$subdir ++ gdb_load ${binfile} ++ ++ runto_main ++ ++ gdb_breakpoint [gdb_get_line_number "breakpoint"] ++ gdb_continue_to_breakpoint "breakpoint" ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++prep ++gdb_test "print errno" ".* = 42" "errno with macros=N threads=N" ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++prep ++gdb_test "print errno" ".* = 42" "errno with macros=Y threads=N" ++ ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } { ++ return -1 ++} ++prep ++gdb_test "print errno" ".* = 42" "errno with macros=N threads=Y" ++ ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } { ++ return -1 ++} ++prep ++gdb_test "print errno" ".* = 42" "errno with macros=Y threads=Y" ++ ++# TODO: Test the error on resolving ERRNO with only libc loaded. ++# Just how to find the current libc filename? diff --git a/gdb-6.5-bz190810-gdbserver-arch-advice.patch b/gdb-6.5-bz190810-gdbserver-arch-advice.patch new file mode 100644 index 0000000..1428471 --- /dev/null +++ b/gdb-6.5-bz190810-gdbserver-arch-advice.patch @@ -0,0 +1,29 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=190810 + + +2006-09-26 Jan Kratochvil + + * remote.c (remote_wait): Suggestion on crash due to nonmatching target. + (remote_async_wait): Likewise. + + +Index: gdb-6.8.50.20081128/gdb/remote.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/remote.c 2008-12-09 16:59:51.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/remote.c 2008-12-09 17:00:04.000000000 +0100 +@@ -4329,8 +4329,13 @@ Packet: '%s'\n"), + VEC_safe_push (cached_reg_t, event->regcache, &cached_reg); + } + +- if (*p != ';') +- error (_("Remote register badly formatted: %s\nhere: %s"), ++ /* It may also occur on amd64 which defaults to 32-bit i386 ++ target. gdbserver(1) is not aware of the `set architecture' ++ name itself as it is not using libbfd. */ ++ if (*p != ';') ++ error (_("Remote register badly formatted: %s\nhere: %s" ++ "\nTry to load the executable by `file' first," ++ "\nyou may also check `set/show architecture'."), + buf, p); + ++p; + } diff --git a/gdb-6.5-bz203661-emit-relocs.patch b/gdb-6.5-bz203661-emit-relocs.patch new file mode 100644 index 0000000..89bf498 --- /dev/null +++ b/gdb-6.5-bz203661-emit-relocs.patch @@ -0,0 +1,17 @@ +Index: gdb-6.5/gdb/symfile.c +=================================================================== +--- gdb-6.5.orig/gdb/symfile.c 2006-08-24 02:56:02.000000000 -0300 ++++ gdb-6.5/gdb/symfile.c 2006-08-24 02:56:36.000000000 -0300 +@@ -3739,6 +3739,12 @@ symfile_dummy_outputs (bfd *abfd, asecti + bfd_byte * + symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf) + { ++ /* Executable files have all the relocations already resolved. ++ * Handle files linked with --emit-relocs. ++ * http://sources.redhat.com/ml/gdb/2006-08/msg00137.html */ ++ if ((abfd->flags & EXEC_P) != 0) ++ return NULL; ++ + /* We're only interested in debugging sections with relocation + information. */ + if ((sectp->flags & SEC_RELOC) == 0) diff --git a/gdb-6.5-bz216711-clone-is-outermost.patch b/gdb-6.5-bz216711-clone-is-outermost.patch new file mode 100644 index 0000000..30835f6 --- /dev/null +++ b/gdb-6.5-bz216711-clone-is-outermost.patch @@ -0,0 +1,278 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=216711 + +FIXME: This workaround should be dropped and +glibc/sysdeps/unix/sysv/linux/x86_64/clone.S should get CFI for the child +instead. + +2006-12-17 Jan Kratochvil + + * gdb/amd64-linux-tdep.c (linux_clone_code): New variable. + (LINUX_CLONE_LEN): New definition. + (amd64_linux_clone_running, amd64_linux_outermost_frame): New function. + (amd64_linux_init_abi): Initialize `outermost_frame_p'. + * gdb/i386-tdep.c (i386_gdbarch_init): Likewise. + * gdb/i386-tdep.h (gdbarch_tdep): Add `outermost_frame_p' member. + * gdb/amd64-tdep.c (amd64_frame_this_id): Call `outermost_frame_p'. + +2006-12-17 Jan Kratochvil + + * gdb.threads/bt-clone-stop.exp, gdb.threads/bt-clone-stop.c: + New file. + +2007-10-16 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.8.50.20081128/gdb/amd64-linux-tdep.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/amd64-linux-tdep.c 2008-12-08 10:56:17.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/amd64-linux-tdep.c 2008-12-08 21:11:08.000000000 +0100 +@@ -234,6 +234,80 @@ amd64_linux_register_reggroup_p (struct + + /* Set the program counter for process PTID to PC. */ + ++/* Detect the outermost frame; during unwind of ++ #5 0x000000305cec68c3 in clone () from /lib64/tls/libc.so.6 ++ avoid the additional bogus frame ++ #6 0x0000000000000000 in ?? ++ We compare if the `linux_clone_code' block is _before_ unwound PC. */ ++ ++static const unsigned char linux_clone_code[] = ++{ ++/* libc/sysdeps/unix/sysv/linux/x86_64/clone.S */ ++/* #ifdef RESET_PID */ ++/* ... */ ++/* mov $SYS_ify(getpid), %eax */ ++/* 0xb8, 0x27, 0x00, 0x00, 0x00 */ ++/* OR */ ++/* mov $SYS_ify(getpid), %rax */ ++/* 0x48, 0xc7, 0xc0, 0x27, 0x00, 0x00, 0x00 */ ++/* so just: */ ++ 0x27, 0x00, 0x00, 0x00, ++/* syscall */ ++ 0x0f, 0x05, ++/* movl %eax, %fs:PID */ ++ 0x64, 0x89, 0x04, 0x25, 0x94, 0x00, 0x00, 0x00, ++/* movl %eax, %fs:TID */ ++ 0x64, 0x89, 0x04, 0x25, 0x90, 0x00, 0x00, 0x00, ++/* #endif */ ++/* |* Set up arguments for the function call. *| */ ++/* popq %rax |* Function to call. *| */ ++ 0x58, ++/* popq %rdi |* Argument. *| */ ++ 0x5f, ++/* call *%rax$ */ ++ 0xff, 0xd0 ++}; ++ ++#define LINUX_CLONE_LEN (sizeof linux_clone_code) ++ ++static int ++amd64_linux_clone_running (struct frame_info *this_frame) ++{ ++ CORE_ADDR pc = get_frame_pc (this_frame); ++ unsigned char buf[LINUX_CLONE_LEN]; ++ ++ if (!safe_frame_unwind_memory (this_frame, pc - LINUX_CLONE_LEN, buf, ++ LINUX_CLONE_LEN)) ++ return 0; ++ ++ if (memcmp (buf, linux_clone_code, LINUX_CLONE_LEN) != 0) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++amd64_linux_outermost_frame (struct frame_info *this_frame) ++{ ++ CORE_ADDR pc = get_frame_pc (this_frame); ++ char *name; ++ ++ find_pc_partial_function (pc, &name, NULL, NULL); ++ ++ /* If we have NAME, we can optimize the search. ++ `clone' NAME still needs to have the code checked as its name may be ++ present in the user code. ++ `__clone' NAME should not be present in the user code but in the initial ++ parts of the `__clone' implementation the unwind still makes sense. ++ More detailed unwinding decision would be too much sensitive to possible ++ subtle changes in specific glibc revisions. */ ++ if (name == NULL || strcmp (name, "clone") == 0 ++ || strcmp ("__clone", name) == 0) ++ return (amd64_linux_clone_running (this_frame) != 0); ++ ++ return 0; ++} ++ + static void + amd64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) + { +@@ -272,6 +346,8 @@ amd64_linux_init_abi (struct gdbarch_inf + tdep->sc_reg_offset = amd64_linux_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset); + ++ tdep->outermost_frame_p = amd64_linux_outermost_frame; ++ + /* GNU/Linux uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); +Index: gdb-6.8.50.20081128/gdb/amd64-tdep.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/amd64-tdep.c 2008-12-08 10:56:17.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/amd64-tdep.c 2008-12-08 21:05:12.000000000 +0100 +@@ -1044,11 +1044,16 @@ amd64_frame_this_id (struct frame_info * + { + struct amd64_frame_cache *cache = + amd64_frame_cache (this_frame, this_cache); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame)); + + /* This marks the outermost frame. */ + if (cache->base == 0) + return; + ++ /* Detect OS dependent outermost frames; such as `clone'. */ ++ if (tdep->outermost_frame_p && tdep->outermost_frame_p (this_frame)) ++ return; ++ + (*this_id) = frame_id_build (cache->base + 16, cache->pc); + } + +Index: gdb-6.8.50.20081128/gdb/i386-tdep.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/i386-tdep.c 2008-12-08 10:56:17.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/i386-tdep.c 2008-12-08 11:00:43.000000000 +0100 +@@ -2698,6 +2698,9 @@ i386_gdbarch_init (struct gdbarch_info i + tdep->sc_pc_offset = -1; + tdep->sc_sp_offset = -1; + ++ /* Unwinding stops on i386 automatically. */ ++ tdep->outermost_frame_p = NULL; ++ + /* The format used for `long double' on almost all i386 targets is + the i387 extended floating-point format. In fact, of all targets + in the GCC 2.95 tree, only OSF/1 does it different, and insists +Index: gdb-6.8.50.20081128/gdb/i386-tdep.h +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/i386-tdep.h 2008-12-08 10:56:17.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/i386-tdep.h 2008-12-08 21:07:47.000000000 +0100 +@@ -106,6 +106,9 @@ struct gdbarch_tdep + /* ISA-specific data types. */ + struct type *i386_mmx_type; + struct type *i386_sse_type; ++ ++ /* Detect OS dependent outermost frames; such as `clone'. */ ++ int (*outermost_frame_p) (struct frame_info *this_frame); + }; + + /* Floating-point registers. */ +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/bt-clone-stop.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/bt-clone-stop.c 2008-12-08 11:00:43.000000000 +0100 +@@ -0,0 +1,39 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2006 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., 51 Franklin Street, Fifth Floor, Boston, ++ MA 02110-1301, USA. */ ++ ++ ++#include ++#include ++#include ++ ++ ++void *threader (void *arg) ++{ ++ assert (0); ++ return NULL; ++} ++ ++int main (void) ++{ ++ pthread_t t1; ++ ++ pthread_create (&t1, NULL, threader, (void *) NULL); ++ for (;;) ++ pause(); ++} +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/bt-clone-stop.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/bt-clone-stop.exp 2008-12-08 11:00:43.000000000 +0100 +@@ -0,0 +1,61 @@ ++# Copyright 2006 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. ++ ++# Backtraced `clone' must not have `PC == 0' as its previous frame. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile bt-clone-stop ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# threader: threader.c:8: threader: Assertion `0' failed. ++# Program received signal SIGABRT, Aborted. ++ ++gdb_test "run" \ ++ "Program received signal SIGABRT.*" \ ++ "run" ++ ++# Former gdb unwind (the first function is `clone'): ++# #5 0x0000003421ecd62d in ?? () from /lib64/libc.so.6 ++# #6 0x0000000000000000 in ?? () ++# (gdb) ++# Tested `amd64_linux_outermost_frame' functionality should omit the line `#6'. ++# ++# Two `-re' cases below must be in this order (1st is a subset of the 2nd one). ++# Unhandled case below should not happen and it is fortunately handled by ++# `amd64_linux_outermost_frame' as FAIL (and result `0x0 entry output invalid'). ++gdb_test_multiple "bt" "0x0 entry output invalid" { ++ -re "in threader \\(.*\n#\[0-9\]* *0x0* in .*$gdb_prompt $" { ++ fail "0x0 entry found" ++ } ++ -re "in threader \\(.*$gdb_prompt $" { ++ pass "0x0 entry not found" ++ } ++} diff --git a/gdb-6.5-bz218379-ppc-solib-trampoline-fix.patch b/gdb-6.5-bz218379-ppc-solib-trampoline-fix.patch new file mode 100644 index 0000000..59b2157 --- /dev/null +++ b/gdb-6.5-bz218379-ppc-solib-trampoline-fix.patch @@ -0,0 +1,19 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=218379 + + +Index: gdb-6.8.50.20081128/gdb/minsyms.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/minsyms.c 2008-10-01 18:56:52.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/minsyms.c 2008-12-02 23:24:27.000000000 +0100 +@@ -544,6 +544,11 @@ lookup_minimal_symbol_by_pc_section_1 (C + don't fill the bfd_section member, so don't + throw away symbols on those platforms. */ + && SYMBOL_OBJ_SECTION (&msymbol[hi]) != NULL ++ /* Don't ignore symbols for solib trampolines. ++ Limit its sideeffects - only for non-0 sized trampolines. ++ Red Hat Bug 200533 with its regression Bug 218379. */ ++ && (MSYMBOL_TYPE (&msymbol[hi]) != mst_solib_trampoline ++ || MSYMBOL_SIZE (&msymbol[hi])) + && (!matching_obj_sections + (SYMBOL_OBJ_SECTION (&msymbol[hi]), section))) + { diff --git a/gdb-6.5-bz218379-ppc-solib-trampoline-test.patch b/gdb-6.5-bz218379-ppc-solib-trampoline-test.patch new file mode 100644 index 0000000..f04e90f --- /dev/null +++ b/gdb-6.5-bz218379-ppc-solib-trampoline-test.patch @@ -0,0 +1,91 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=218379 + + +--- /dev/null 2006-12-17 14:18:21.881669220 -0500 ++++ gdb-6.5/gdb/testsuite/gdb.base/step-over-trampoline.exp 2006-12-17 16:52:51.000000000 -0500 +@@ -0,0 +1,54 @@ ++# Copyright 2006 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile step-over-trampoline ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# For C programs, "start" should stop in main(). ++ ++gdb_test "start" \ ++ "main \\(\\) at .*$srcfile.*" \ ++ "start" ++ ++# main () at hello2.c:5 ++# 5 puts("hello world\n"); ++# (gdb) next ++# 0x100007e0 in call___do_global_ctors_aux () ++ ++gdb_test_multiple "next" "invalid `next' output" { ++ -re "\nhello world.*return 0;.*" { ++ pass "stepped over" ++ } ++ -re " in call___do_global_ctors_aux \\(\\).*" { ++ fail "stepped into trampoline" ++ } ++} +--- /dev/null 2006-12-17 14:18:21.881669220 -0500 ++++ gdb-6.5/gdb/testsuite/gdb.base/step-over-trampoline.c 2006-12-17 16:18:12.000000000 -0500 +@@ -0,0 +1,28 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2006 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 */ ++ ++#include ++ ++int main (void) ++{ ++ puts ("hello world"); ++ return 0; ++} diff --git a/gdb-6.5-bz218379-solib-trampoline-lookup-lock-fix.patch b/gdb-6.5-bz218379-solib-trampoline-lookup-lock-fix.patch new file mode 100644 index 0000000..bdfdc07 --- /dev/null +++ b/gdb-6.5-bz218379-solib-trampoline-lookup-lock-fix.patch @@ -0,0 +1,21 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=218379 + + +Index: gdb-6.8/gdb/symtab.c +=================================================================== +--- gdb-6.8.orig/gdb/symtab.c 2008-02-05 23:17:40.000000000 +0100 ++++ gdb-6.8/gdb/symtab.c 2008-07-14 10:27:32.000000000 +0200 +@@ -2132,6 +2132,13 @@ find_pc_sect_line (CORE_ADDR pc, struct + /* See above comment about why warning is commented out */ + /* warning ("In stub for %s; unable to find real function/line info", SYMBOL_LINKAGE_NAME (msymbol)) */ ; + /* fall through */ ++ /* `msymbol' trampoline may be located before its .text symbol ++ but this text symbol may be the address we were looking for. ++ Avoid `find_pc_sect_line'<->`find_pc_line' infinite loop. ++ Red Hat Bug 218379. */ ++ else if (SYMBOL_VALUE (mfunsym) == pc) ++ warning ("In stub for %s (0x%s); interlocked, please submit the binary to http://bugzilla.redhat.com", SYMBOL_LINKAGE_NAME (msymbol), paddr (pc)); ++ /* fall through */ + else + return find_pc_line (SYMBOL_VALUE_ADDRESS (mfunsym), 0); + } diff --git a/gdb-6.5-bz243845-stale-testing-zombie-test.patch b/gdb-6.5-bz243845-stale-testing-zombie-test.patch new file mode 100644 index 0000000..5b77b0f --- /dev/null +++ b/gdb-6.5-bz243845-stale-testing-zombie-test.patch @@ -0,0 +1,86 @@ +diff -u -ruNp gdb-6.3-unpatched/gdb/testsuite/gdb.base/tracefork-zombie.exp gdb-6.3/gdb/testsuite/gdb.base/tracefork-zombie.exp +--- gdb-6.3-unpatched/gdb/testsuite/gdb.base/tracefork-zombie.exp 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.3/gdb/testsuite/gdb.base/tracefork-zombie.exp 2007-07-31 13:04:12.000000000 -0400 +@@ -0,0 +1,82 @@ ++# Copyright 2007 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. */ ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++# are we on a target board ++if [is_remote target] then { ++ return 0 ++} ++ ++# Start the program running and then wait for a bit, to be sure ++# that it can be attached to. ++ ++gdb_exit ++gdb_start ++gdb_load sleep ++ ++set gdb_pid [exp_pid -i [board_info host fileid]] ++set test "identified the child GDB" ++if {$gdb_pid != "" && $gdb_pid > 0} { ++ pass $test ++ verbose -log "Child GDB PID $gdb_pid" ++} else { ++ fail $test ++} ++ ++set testpid [eval exec sleep 10 &] ++exec sleep 2 ++ ++set test "attach" ++gdb_test_multiple "attach $testpid" "$test" { ++ -re "Attaching to program.*`?.*'?, process $testpid..*$gdb_prompt $" { ++ pass "$test" ++ } ++ -re "Attaching to program.*`?.*\.exe'?, process $testpid.*\[Switching to thread $testpid\..*\].*$gdb_prompt $" { ++ # Response expected on Cygwin ++ pass "$test" ++ } ++} ++ ++# Some time to let GDB spawn its testing child. ++exec sleep 2 ++ ++set found none ++foreach procpid [glob -directory /proc -type d {[0-9]*}] { ++ if {[catch {open $procpid/status} statusfi]} { ++ continue ++ } ++ set status [read $statusfi] ++ close $statusfi ++ if {1 ++ && [regexp -line {^Name:\tgdb$} $status] ++ && [regexp -line {^PPid:\t1$} $status] ++ && [regexp -line "^TracerPid:\t$gdb_pid$" $status]} { ++ set found $procpid ++ verbose -log "Found linux_test_for_tracefork zombie PID $procpid" ++ } ++} ++set test "linux_test_for_tracefork leaves no zombie" ++if {$found eq {none}} { ++ pass $test ++} else { ++ fail $test ++} diff --git a/gdb-6.5-dwarf-stack-overflow.patch b/gdb-6.5-dwarf-stack-overflow.patch new file mode 100644 index 0000000..cd2e023 --- /dev/null +++ b/gdb-6.5-dwarf-stack-overflow.patch @@ -0,0 +1,52 @@ +for gdb/ChangeLog: +2006-08-22 Will Drewry + Tavis Ormandy + + * dwarf2read.c (decode_locdesc): Enforce location description stack + boundaries. + * dwarfread.c (locval): Likewise. + +2007-10-15 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.7/gdb/dwarf2read.c +=================================================================== +--- gdb-6.7.orig/gdb/dwarf2read.c 2007-10-15 00:08:30.000000000 +0200 ++++ gdb-6.7/gdb/dwarf2read.c 2007-10-15 21:42:43.000000000 +0200 +@@ -9070,8 +9070,7 @@ dwarf2_fundamental_type (struct objfile + callers will only want a very basic result and this can become a + complaint. + +- Note that stack[0] is unused except as a default error return. +- Note that stack overflow is not yet handled. */ ++ Note that stack[0] is unused except as a default error return. */ + + static CORE_ADDR + decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) +@@ -9088,7 +9087,7 @@ decode_locdesc (struct dwarf_block *blk, + + i = 0; + stacki = 0; +- stack[stacki] = 0; ++ stack[++stacki] = 0; + + while (i < size) + { +@@ -9270,6 +9269,16 @@ decode_locdesc (struct dwarf_block *blk, + dwarf_stack_op_name (op)); + return (stack[stacki]); + } ++ /* Enforce maximum stack depth of size-1 to avoid ++stacki writing ++ outside of the allocated space. Also enforce minimum > 0. ++ -- wad@google.com 14 Aug 2006 */ ++ if (stacki >= sizeof (stack) / sizeof (*stack) - 1) ++ internal_error (__FILE__, __LINE__, ++ _("location description stack too deep: %d"), ++ stacki); ++ if (stacki <= 0) ++ internal_error (__FILE__, __LINE__, ++ _("location description stack too shallow")); + } + return (stack[stacki]); + } diff --git a/gdb-6.5-gcore-buffer-limit-test.patch b/gdb-6.5-gcore-buffer-limit-test.patch new file mode 100644 index 0000000..299279c --- /dev/null +++ b/gdb-6.5-gcore-buffer-limit-test.patch @@ -0,0 +1,146 @@ +diff -u -X /home/jkratoch/.diffi.list -ruNp gdb-6.5/gdb/testsuite/gdb.base/gcore-excessive-memory.c gdb-6.5-unknown/gdb/testsuite/gdb.base/gcore-excessive-memory.c +--- gdb-6.5/gdb/testsuite/gdb.base/gcore-excessive-memory.c 1970-01-01 01:00:00.000000000 +0100 ++++ gdb-6.5-unknown/gdb/testsuite/gdb.base/gcore-excessive-memory.c 2008-01-08 11:25:45.000000000 +0100 +@@ -0,0 +1,37 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 */ ++ ++#include ++#include ++ ++#define MEGS 64 ++ ++int main() ++{ ++ void *mem; ++ ++ mem = malloc (MEGS * 1024ULL * 1024ULL); ++ ++ for (;;) ++ sleep (1); ++ ++ return 0; ++} +diff -u -X /home/jkratoch/.diffi.list -ruNp gdb-6.5/gdb/testsuite/gdb.base/gcore-excessive-memory.exp gdb-6.5-unknown/gdb/testsuite/gdb.base/gcore-excessive-memory.exp +--- gdb-6.5/gdb/testsuite/gdb.base/gcore-excessive-memory.exp 1970-01-01 01:00:00.000000000 +0100 ++++ gdb-6.5-unknown/gdb/testsuite/gdb.base/gcore-excessive-memory.exp 2008-01-08 11:47:32.000000000 +0100 +@@ -0,0 +1,101 @@ ++# Copyright 2008 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile gcore-excessive-memory ++set srcfile ${testfile}.c ++set shfile ${objdir}/${subdir}/${testfile}-gdb.sh ++set corefile ${objdir}/${subdir}/${testfile}.core ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++set f [open "|getconf PAGESIZE" "r"] ++gets $f pagesize ++close $f ++ ++set pid_of_bin [eval exec $binfile &] ++sleep 2 ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set pid_of_gdb [exp_pid -i [board_info host fileid]] ++ ++gdb_test "attach $pid_of_bin" "Attaching to .*" "attach" ++gdb_test "up 99" "in main .*" "verify we can get to main" ++ ++proc memory_v_pages_get {} { ++ global pid_of_gdb pagesize ++ set fd [open "/proc/$pid_of_gdb/statm"] ++ gets $fd line ++ close $fd ++ # number of pages of virtual memory ++ scan $line "%d" drs ++ return $drs ++} ++ ++set pages_found [memory_v_pages_get] ++ ++# It must be definitely less than `MEGS' of `gcore-excessive-memory.c'. ++set mb_gcore_reserve 4 ++verbose -log "pages_found = $pages_found, mb_gcore_reserve = $mb_gcore_reserve" ++set kb_found [expr $pages_found * $pagesize / 1024] ++set kb_permit [expr $kb_found + 1 * 1024 + $mb_gcore_reserve * 1024] ++verbose -log "kb_found = $kb_found, kb_permit = $kb_permit" ++ ++# Create the ulimit wrapper. ++set f [open $shfile "w"] ++puts $f "#! /bin/sh" ++puts $f "ulimit -v $kb_permit" ++puts $f "exec $GDB \"\$@\"" ++close $f ++remote_exec host "chmod +x $shfile" ++ ++gdb_exit ++set GDBold $GDB ++set GDB "$shfile" ++gdb_start ++set GDB $GDBold ++ ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set pid_of_gdb [exp_pid -i [board_info host fileid]] ++ ++gdb_test "attach $pid_of_bin" "Attaching to .*" "attach" ++gdb_test "up 99" "in main .*" "verify we can get to main" ++ ++verbose -log "kb_found before gcore = [expr [memory_v_pages_get] * $pagesize / 1024]" ++ ++gdb_test "gcore $corefile" "Saved corefile \[^\n\r\]*" "Save the core file" ++ ++verbose -log "kb_found after gcore = [expr [memory_v_pages_get] * $pagesize / 1024]" ++ ++# Cleanup. ++exec kill -9 $pid_of_bin diff --git a/gdb-6.5-gcore-i386-on-amd64.patch b/gdb-6.5-gcore-i386-on-amd64.patch new file mode 100644 index 0000000..a08acc2 --- /dev/null +++ b/gdb-6.5-gcore-i386-on-amd64.patch @@ -0,0 +1,847 @@ +2006-10-01 Jan Kratochvil + Fujitsu + + * amd64-linux-nat.c: Support new linux_elfcore_write_prpsinfo, + linux_elfcore_write_prstatus, linux_elfcore_write_prfpreg. + (i386_linux_gregset32_reg_offset): New mapping for i386 on amd64. + * gcore.c (gcore_create_callback): Comment vdso Linux kernel bug. + * configure.ac: Check for , . + * configure, config.in: Regenerated. + * gdb_user32.h, gdb_procfs32.h: Define 32-bit core files even for + 64-bit gdb, provide fallbacks for and . + * linux-nat.c: Virtualize `elfcore_*' by (*`linux_elfcore_*'). + (linux_nat_do_thread_registers): Likewise. + (linux_nat_make_corefile_notes): Likewise. + * linux-nat.h: Likewise. + * Makefile.in: Dependencies updated. + +2007-10-16 Jan Kratochvil + + Port to GDB-6.7. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +Index: gdb-6.8.50.20081214/gdb/amd64-linux-nat.c +=================================================================== +--- gdb-6.8.50.20081214.orig/gdb/amd64-linux-nat.c 2008-12-14 21:17:01.000000000 +0100 ++++ gdb-6.8.50.20081214/gdb/amd64-linux-nat.c 2008-12-14 21:24:19.000000000 +0100 +@@ -50,6 +50,9 @@ + #include "amd64-tdep.h" + #include "i386-linux-tdep.h" + #include "amd64-nat.h" ++#include "i387-tdep.h" ++#include "elf-bfd.h" ++#include "gdb_procfs32.h" + + /* Mapping between the general-purpose registers in GNU/Linux x86-64 + `struct user' format and GDB's register cache layout. */ +@@ -84,6 +87,35 @@ static int amd64_linux_gregset64_reg_off + GNU/Linux i386 registers are all 32-bit, but since we're + little-endian we get away with that. */ + ++/* This info is not reusable from "i386-linux-nat.c" as gdb itself runs in ++ 64-bit mode and so ptrace(2) has 64-bit structure layout. ++ Just the corefile being generated has 32-bit layout so we need to do ++ a conversion specific to the i386-on-amd64 compatibility mode. */ ++static int i386_linux_gregset32_reg_offset[] = ++{ ++ 6 * 4, /* %eax */ ++ 1 * 4, /* %ecx */ ++ 2 * 4, /* %edx */ ++ 0 * 4, /* %ebx */ ++ 15 * 4, /* %esp */ ++ 5 * 4, /* %ebp */ ++ 3 * 4, /* %esi */ ++ 4 * 4, /* %edi */ ++ 12 * 4, /* %eip */ ++ 14 * 4, /* %eflags */ ++ 13 * 4, /* %cs */ ++ 16 * 4, /* %ss */ ++ 7 * 4, /* %ds */ ++ 8 * 4, /* %es */ ++ 9 * 4, /* %fs */ ++ 10 * 4, /* %gs */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ -1, ++ 11 * 4 /* "orig_eax" */ ++}; ++ + /* From on GNU/Linux i386. */ + static int amd64_linux_gregset32_reg_offset[] = + { +@@ -102,6 +134,96 @@ static int amd64_linux_gregset32_reg_off + }; + + ++/* This functions make ELF32 32-bit elfcore note sections ++ on amd64 environment. */ ++ ++static char * ++amd64_linux_elfcore_write_prpsinfo (bfd *abfd, char *buf, int *bufsiz, ++ const char *fname, const char *psargs) ++{ ++ if (gdbarch_ptr_bit(current_gdbarch) == 32) ++ { ++ int note_type; ++ char *note_name = "CORE"; ++ struct elf_prpsinfo32 data; ++ note_type = NT_PRPSINFO; ++ ++ memset (&data, 0, sizeof (data)); ++ strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); ++ strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); ++ return elfcore_write_note (abfd, buf, bufsiz, ++ note_name, note_type, &data, sizeof (data)); ++ } ++ else ++ return elfcore_write_prpsinfo (abfd, buf, bufsiz, fname, psargs); ++} ++ ++static void ++amd64_linux_set_registers (const gdb_byte *gregs, gdb_byte *buf) ++{ ++ int i; ++ /* Copy the i386 registers in the amd64 layout into i386 layout. */ ++ for (i = 0; i < I386_NUM_GREGS; i++) ++ memcpy(buf + i386_linux_gregset32_reg_offset[i], ++ gregs + amd64_linux_gregset32_reg_offset[i], 4); ++ for (i = I386_CS_REGNUM; i <= I386_GS_REGNUM; i++) ++ memcpy(buf + i386_linux_gregset32_reg_offset[i], ++ gregs + amd64_linux_gregset32_reg_offset[i], 4); ++} ++ ++static char * ++amd64_linux_elfcore_write_prstatus (bfd *abfd, char *buf, int *bufsiz, ++ long pid, int cursig, const void *gregs) ++{ ++ if (gdbarch_ptr_bit(current_gdbarch) == 32) ++ { ++ char *note_name = "CORE"; ++ struct elf_prstatus32 prstat; ++ memset (&prstat, 0, sizeof (prstat)); ++ prstat.pr_pid = pid; ++ prstat.pr_cursig = cursig; ++ amd64_linux_set_registers (gregs, (gdb_byte *) &prstat.pr_reg); ++ return elfcore_write_note (abfd, buf, bufsiz, note_name, ++ NT_PRSTATUS, &prstat, sizeof (prstat)); ++ } ++ else ++ return elfcore_write_prstatus (abfd, buf, bufsiz, pid, cursig, gregs); ++} ++ ++static char * ++amd64_elfcore_write_prxfpreg32 (bfd *abfd, char *buf, int *bufsiz, ++ struct regcache *regcache) ++{ ++ char *note_name = "LINUX"; ++ elf_fpxregset32_t fpxregs32; ++ ++ i387_collect_fxsave (regcache, -1, &fpxregs32); ++ return elfcore_write_note(abfd, buf, bufsiz, ++ note_name, NT_PRXFPREG, &fpxregs32, ++ sizeof(fpxregs32)); ++} ++ ++static char * ++amd64_linux_elfcore_write_prfpreg (bfd *abfd, char *buf, ++ int *bufsiz, const void *fpregs, int size, ++ struct regcache *regcache) ++{ ++ if (gdbarch_ptr_bit(current_gdbarch) == 32) ++ { ++ char *note_name = "CORE"; ++ elf_fpregset32_t fpregs32; ++ ++ i387_collect_fsave (regcache, -1, &fpregs32); ++ buf = elfcore_write_note(abfd, buf, bufsiz, note_name, ++ NT_FPREGSET, &fpregs32, sizeof(fpregs32)); ++ ++ return amd64_elfcore_write_prxfpreg32 (abfd, buf, bufsiz, regcache); ++ } ++ else ++ return elfcore_write_prfpreg (abfd, buf, bufsiz, fpregs, size); ++} ++ ++ + /* Transfering the general-purpose registers between GDB, inferiors + and core files. */ + +@@ -431,6 +553,11 @@ _initialize_amd64_linux_nat (void) + t->to_fetch_registers = amd64_linux_fetch_inferior_registers; + t->to_store_registers = amd64_linux_store_inferior_registers; + ++ /* This functions make elfcore note sections. */ ++ linux_elfcore_write_prpsinfo = amd64_linux_elfcore_write_prpsinfo; ++ linux_elfcore_write_prstatus = amd64_linux_elfcore_write_prstatus; ++ linux_elfcore_write_prfpreg = amd64_linux_elfcore_write_prfpreg; ++ + /* Register the target. */ + linux_nat_add_target (t); + linux_nat_set_new_thread (t, amd64_linux_new_thread); +Index: gdb-6.8.50.20081214/gdb/config.in +=================================================================== +--- gdb-6.8.50.20081214.orig/gdb/config.in 2008-12-14 21:17:01.000000000 +0100 ++++ gdb-6.8.50.20081214/gdb/config.in 2008-12-14 21:34:50.000000000 +0100 +@@ -136,6 +136,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_ELF_HP_H + ++/* Define if struct elf_prstatus32 is available. */ ++#undef HAVE_ELF_PRSTATUS32 ++ + /* Define to 1 if your system has the etext variable. */ + #undef HAVE_ETEXT + +@@ -465,6 +468,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_POLL_H + ++/* Define to 1 if you have the header file. */ ++#undef HAVE_SYS_PROCFS32_H ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_PROCFS_H + +@@ -492,6 +498,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_TYPES_H + ++/* Define to 1 if you have the header file. */ ++#undef HAVE_SYS_USER32_H ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_USER_H + +Index: gdb-6.8.50.20081214/gdb/configure +=================================================================== +--- gdb-6.8.50.20081214.orig/gdb/configure 2008-12-14 21:17:01.000000000 +0100 ++++ gdb-6.8.50.20081214/gdb/configure 2008-12-14 21:33:30.000000000 +0100 +@@ -12026,6 +12026,268 @@ _ACEOF + + fi + ++ ++ ++for ac_header in sys/user32.h sys/procfs32.h ++do ++as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` ++if eval "test \"\${$as_ac_Header+set}\" = set"; then ++ echo "$as_me:$LINENO: checking for $ac_header" >&5 ++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 ++if eval "test \"\${$as_ac_Header+set}\" = set"; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++fi ++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 ++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 ++else ++ # Is the header compilable? ++echo "$as_me:$LINENO: checking $ac_header usability" >&5 ++echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 ++cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++$ac_includes_default ++#include <$ac_header> ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ac_header_compiler=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ac_header_compiler=no ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 ++echo "${ECHO_T}$ac_header_compiler" >&6 ++ ++# Is the header present? ++echo "$as_me:$LINENO: checking $ac_header presence" >&5 ++echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 ++cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include <$ac_header> ++_ACEOF ++if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 ++ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } >/dev/null; then ++ if test -s conftest.err; then ++ ac_cpp_err=$ac_c_preproc_warn_flag ++ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag ++ else ++ ac_cpp_err= ++ fi ++else ++ ac_cpp_err=yes ++fi ++if test -z "$ac_cpp_err"; then ++ ac_header_preproc=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ac_header_preproc=no ++fi ++rm -f conftest.err conftest.$ac_ext ++echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 ++echo "${ECHO_T}$ac_header_preproc" >&6 ++ ++# So? What about this header? ++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in ++ yes:no: ) ++ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 ++echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} ++ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 ++echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ++ ac_header_preproc=yes ++ ;; ++ no:yes:* ) ++ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 ++echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} ++ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 ++echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} ++ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 ++echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} ++ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 ++echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} ++ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 ++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ++ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 ++echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ++ ( ++ cat <<\_ASBOX ++## ------------------------------------------ ## ++## Report this to the AC_PACKAGE_NAME lists. ## ++## ------------------------------------------ ## ++_ASBOX ++ ) | ++ sed "s/^/$as_me: WARNING: /" >&2 ++ ;; ++esac ++echo "$as_me:$LINENO: checking for $ac_header" >&5 ++echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 ++if eval "test \"\${$as_ac_Header+set}\" = set"; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ eval "$as_ac_Header=\$ac_header_preproc" ++fi ++echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 ++echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 ++ ++fi ++if test `eval echo '${'$as_ac_Header'}'` = yes; then ++ cat >>confdefs.h <<_ACEOF ++#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 ++_ACEOF ++ ++fi ++ ++done ++ ++echo "$as_me:$LINENO: checking for struct elf_prstatus32.pr_reg" >&5 ++echo $ECHO_N "checking for struct elf_prstatus32.pr_reg... $ECHO_C" >&6 ++if test "${ac_cv_member_struct_elf_prstatus32_pr_reg+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++ ++int ++main () ++{ ++static struct elf_prstatus32 ac_aggr; ++if (ac_aggr.pr_reg) ++return 0; ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ac_cv_member_struct_elf_prstatus32_pr_reg=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++ ++int ++main () ++{ ++static struct elf_prstatus32 ac_aggr; ++if (sizeof ac_aggr.pr_reg) ++return 0; ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ac_cv_member_struct_elf_prstatus32_pr_reg=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ac_cv_member_struct_elf_prstatus32_pr_reg=no ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++echo "$as_me:$LINENO: result: $ac_cv_member_struct_elf_prstatus32_pr_reg" >&5 ++echo "${ECHO_T}$ac_cv_member_struct_elf_prstatus32_pr_reg" >&6 ++if test $ac_cv_member_struct_elf_prstatus32_pr_reg = yes; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_ELF_PRSTATUS32 1 ++_ACEOF ++ ++fi ++ + # elf_hp.h is for HP/UX 64-bit shared library support. + # FIXME: kettenis/20030102: In most cases we include these (ctype.h, time.h) + # unconditionally, so what's the point in checking these? +Index: gdb-6.8.50.20081214/gdb/configure.ac +=================================================================== +--- gdb-6.8.50.20081214.orig/gdb/configure.ac 2008-12-14 21:17:01.000000000 +0100 ++++ gdb-6.8.50.20081214/gdb/configure.ac 2008-12-14 21:32:35.000000000 +0100 +@@ -686,6 +686,11 @@ AC_SUBST(PYTHON_CFLAGS) + AC_HEADER_DIRENT + AC_HEADER_STAT + AC_HEADER_STDC ++AC_CHECK_HEADERS([sys/user32.h sys/procfs32.h]) ++AC_CHECK_MEMBER([struct elf_prstatus32.pr_reg], ++ [AC_DEFINE(HAVE_ELF_PRSTATUS32, 1, ++ [Define if struct elf_prstatus32 is available. ])], ++ [], [#include ]) + # elf_hp.h is for HP/UX 64-bit shared library support. + # FIXME: kettenis/20030102: In most cases we include these (ctype.h, time.h) + # unconditionally, so what's the point in checking these? +Index: gdb-6.8.50.20081214/gdb/gcore.c +=================================================================== +--- gdb-6.8.50.20081214.orig/gdb/gcore.c 2008-12-14 21:17:01.000000000 +0100 ++++ gdb-6.8.50.20081214/gdb/gcore.c 2008-12-14 21:17:10.000000000 +0100 +@@ -320,6 +320,11 @@ gcore_create_callback (CORE_ADDR vaddr, + asection *osec; + flagword flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_LOAD; + ++ /* Some Linux kernel versions around 2.6.17 have for i386 inferiors running ++ in compatibility mode on amd64 kernel their VSYSCALL page (at 0xffffe000) ++ protected as RWX==000 by default and gdb fails to read the library header ++ upon loading the core. This is a Linux kernel bug being fixed. */ ++ + /* If the memory segment has no permissions set, ignore it, otherwise + when we later try to access it for read/write, we'll get an error + or jam the kernel. */ +Index: gdb-6.8.50.20081214/gdb/gdb_procfs32.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081214/gdb/gdb_procfs32.h 2008-12-14 21:32:56.000000000 +0100 +@@ -0,0 +1,128 @@ ++#ifdef HAVE_SYS_PROCFS32_H ++#include ++#elif !defined HAVE_ELF_PRSTATUS32 ++ ++/* Copyright (C) 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#ifndef _SYS_PROCFS32_H ++#define _SYS_PROCFS32_H 1 ++ ++/* This is somewhat modelled after the file of the same name on SVR4 ++ systems. It provides a definition of the core file format for ELF ++ used on Linux. It doesn't have anything to do with the /proc file ++ system, even though Linux has one. ++ ++ Anyway, the whole purpose of this file is for GDB and GDB only. ++ Don't read too much into it. Don't use it for anything other than ++ GDB unless you know what you are doing. */ ++ ++#include ++#include ++#include ++#include "gdb_user32.h" ++ ++/* We define here only the symbols differing from their 64-bit variant. */ ++#include ++ ++__BEGIN_DECLS ++ ++/* Type for a general-purpose register. */ ++typedef unsigned int elf_greg32_t; ++ ++/* And the whole bunch of them. We could have used `struct ++ user_regs_struct' directly in the typedef, but tradition says that ++ the register set is an array, which does have some peculiar ++ semantics, so leave it that way. */ ++#define ELF_NGREG32 (sizeof (struct user_regs32_struct) / sizeof(elf_greg32_t)) ++typedef elf_greg32_t elf_gregset32_t[ELF_NGREG32]; ++ ++/* Register set for the floating-point registers. */ ++typedef struct user_fpregs32_struct elf_fpregset32_t; ++ ++/* Register set for the extended floating-point registers. Includes ++ the Pentium III SSE registers in addition to the classic ++ floating-point stuff. */ ++typedef struct user_fpxregs32_struct elf_fpxregset32_t; ++ ++ ++/* Definitions to generate Intel SVR4-like core files. These mostly ++ have the same names as the SVR4 types with "elf_" tacked on the ++ front to prevent clashes with Linux definitions, and the typedef ++ forms have been avoided. This is mostly like the SVR4 structure, ++ but more Linuxy, with things that Linux does not support and which ++ GDB doesn't really use excluded. */ ++ ++struct prstatus32_timeval ++ { ++ int tv_sec; ++ int tv_usec; ++ }; ++ ++struct elf_prstatus32 ++ { ++ struct elf_siginfo pr_info; /* Info associated with signal. */ ++ short int pr_cursig; /* Current signal. */ ++ unsigned int pr_sigpend; /* Set of pending signals. */ ++ unsigned int pr_sighold; /* Set of held signals. */ ++ __pid_t pr_pid; ++ __pid_t pr_ppid; ++ __pid_t pr_pgrp; ++ __pid_t pr_sid; ++ struct prstatus32_timeval pr_utime; /* User time. */ ++ struct prstatus32_timeval pr_stime; /* System time. */ ++ struct prstatus32_timeval pr_cutime; /* Cumulative user time. */ ++ struct prstatus32_timeval pr_cstime; /* Cumulative system time. */ ++ elf_gregset32_t pr_reg; /* GP registers. */ ++ int pr_fpvalid; /* True if math copro being used. */ ++ }; ++ ++ ++struct elf_prpsinfo32 ++ { ++ char pr_state; /* Numeric process state. */ ++ char pr_sname; /* Char for pr_state. */ ++ char pr_zomb; /* Zombie. */ ++ char pr_nice; /* Nice val. */ ++ unsigned int pr_flag; /* Flags. */ ++ unsigned short int pr_uid; ++ unsigned short int pr_gid; ++ int pr_pid, pr_ppid, pr_pgrp, pr_sid; ++ /* Lots missing */ ++ char pr_fname[16]; /* Filename of executable. */ ++ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ ++ }; ++ ++ ++/* The rest of this file provides the types for emulation of the ++ Solaris interfaces that should be implemented by ++ users of libthread_db. */ ++ ++/* Register sets. Linux has different names. */ ++typedef elf_gregset_t prgregset32_t; ++typedef elf_fpregset_t prfpregset32_t; ++ ++/* Process status and info. In the end we do provide typedefs for them. */ ++typedef struct elf_prstatus32 prstatus32_t; ++typedef struct elf_prpsinfo32 prpsinfo32_t; ++ ++__END_DECLS ++ ++#endif /* _SYS_PROCFS32_H */ ++ ++#endif /* HAVE_SYS_PROCFS32_H */ +Index: gdb-6.8.50.20081214/gdb/gdb_user32.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081214/gdb/gdb_user32.h 2008-12-14 21:17:10.000000000 +0100 +@@ -0,0 +1,108 @@ ++#ifdef HAVE_SYS_USER32_H ++#include ++#else ++ ++#ifdef HAVE_STDINT_H ++#include ++typedef int32_t gdb_int32_t; ++typedef uint32_t gdb_uint32_t; ++#else ++typedef signed int gdb_uint32_t; ++typedef unsigned int gdb_uint32_t; ++#endif ++ ++/* Copyright (C) 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#ifndef _SYS_USER32_H ++#define _SYS_USER32_H 1 ++ ++/* These are the 32-bit x86 structures. */ ++ ++struct user_fpregs32_struct ++{ ++ int32_t cwd; ++ int32_t swd; ++ int32_t twd; ++ int32_t fip; ++ int32_t fcs; ++ int32_t foo; ++ int32_t fos; ++ int32_t st_space [20]; ++}; ++ ++struct user_fpxregs32_struct ++{ ++ unsigned short int cwd; ++ unsigned short int swd; ++ unsigned short int twd; ++ unsigned short int fop; ++ int32_t fip; ++ int32_t fcs; ++ int32_t foo; ++ int32_t fos; ++ int32_t mxcsr; ++ int32_t reserved; ++ int32_t st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ ++ int32_t xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ ++ int32_t padding[56]; ++}; ++ ++struct user_regs32_struct ++{ ++ int32_t ebx; ++ int32_t ecx; ++ int32_t edx; ++ int32_t esi; ++ int32_t edi; ++ int32_t ebp; ++ int32_t eax; ++ int32_t xds; ++ int32_t xes; ++ int32_t xfs; ++ int32_t xgs; ++ int32_t orig_eax; ++ int32_t eip; ++ int32_t xcs; ++ int32_t eflags; ++ int32_t esp; ++ int32_t xss; ++}; ++ ++struct user32 ++{ ++ struct user_regs32_struct regs; ++ int u_fpvalid; ++ struct user_fpregs32_struct i387; ++ uint32_t u_tsize; ++ uint32_t u_dsize; ++ uint32_t u_ssize; ++ uint32_t start_code; ++ uint32_t start_stack; ++ int32_t signal; ++ int reserved; ++ struct user_regs32_struct* u_ar0; ++ struct user_fpregs32_struct* u_fpstate; ++ uint32_t magic; ++ char u_comm [32]; ++ int u_debugreg [8]; ++}; ++ ++#endif /* _SYS_USER32_H */ ++ ++#endif /* HAVE_SYS_USER32_H */ +Index: gdb-6.8.50.20081214/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20081214.orig/gdb/linux-nat.c 2008-12-14 21:17:01.000000000 +0100 ++++ gdb-6.8.50.20081214/gdb/linux-nat.c 2008-12-14 21:24:20.000000000 +0100 +@@ -213,6 +213,21 @@ static LONGEST (*super_xfer_partial) (st + const gdb_byte *, + ULONGEST, LONGEST); + ++/* This functions make elfcore note sections. ++ They may get overriden by code adjusting data for multi-target builds. */ ++char *(*linux_elfcore_write_prpsinfo) ++ (bfd *, char *, int *, const char *, const char *) = elfcore_write_prpsinfo; ++char *(*linux_elfcore_write_prstatus) ++ (bfd *, char *, int *, long, int, const void *) = elfcore_write_prstatus; ++static char * ++linux_elfcore_write_prfpreg_bfd (bfd *abfd, char *buf, int *bufsiz, ++ const void *fpregs, int size, struct regcache *regcache) ++{ ++ return elfcore_write_prfpreg (abfd, buf, bufsiz, fpregs, size); ++} ++char *(*linux_elfcore_write_prfpreg) (bfd *, char *, int *, const void *, int, ++ struct regcache *) = linux_elfcore_write_prfpreg_bfd; ++ + static int debug_linux_nat; + static void + show_debug_linux_nat (struct ui_file *file, int from_tty, +@@ -3473,7 +3488,7 @@ linux_nat_do_thread_registers (bfd *obfd + else + fill_gregset (regcache, &gregs, -1); + +- note_data = (char *) elfcore_write_prstatus (obfd, ++ note_data = (char *) linux_elfcore_write_prstatus (obfd, + note_data, + note_size, + lwp, +@@ -3523,10 +3538,10 @@ linux_nat_do_thread_registers (bfd *obfd + else + fill_fpregset (regcache, &fpregs, -1); + +- note_data = (char *) elfcore_write_prfpreg (obfd, ++ note_data = (char *) linux_elfcore_write_prfpreg (obfd, + note_data, + note_size, +- &fpregs, sizeof (fpregs)); ++ &fpregs, sizeof (fpregs), regcache); + } + + return note_data; +@@ -3595,9 +3610,9 @@ linux_nat_make_corefile_notes (bfd *obfd + psargs_end - string_end); + } + } +- note_data = (char *) elfcore_write_prpsinfo (obfd, +- note_data, +- note_size, fname, psargs); ++ note_data = (char *) linux_elfcore_write_prpsinfo (obfd, note_data, ++ note_size, fname, ++ psargs); + } + + /* Dump information for threads. */ +Index: gdb-6.8.50.20081214/gdb/linux-nat.h +=================================================================== +--- gdb-6.8.50.20081214.orig/gdb/linux-nat.h 2008-12-14 21:17:01.000000000 +0100 ++++ gdb-6.8.50.20081214/gdb/linux-nat.h 2008-12-14 21:24:11.000000000 +0100 +@@ -134,3 +134,12 @@ void linux_nat_switch_fork (ptid_t new_p + + /* Return the saved siginfo associated with PTID. */ + struct siginfo *linux_nat_get_siginfo (ptid_t ptid); ++ ++/* These functions make elfcore note sections. ++ They may get overriden by code adjusting data for multi-target builds. */ ++extern char *(*linux_elfcore_write_prpsinfo) ++ (bfd *, char *, int *, const char *, const char *); ++extern char *(*linux_elfcore_write_prstatus) ++ (bfd *, char *, int *, long, int, const void *); ++extern char *(*linux_elfcore_write_prfpreg) ++ (bfd *, char *, int *, const void *, int, struct regcache *); diff --git a/gdb-6.5-ia64-libunwind-leak-test.patch b/gdb-6.5-ia64-libunwind-leak-test.patch new file mode 100644 index 0000000..31905bd --- /dev/null +++ b/gdb-6.5-ia64-libunwind-leak-test.patch @@ -0,0 +1,127 @@ +diff -u -rup gdb-6.3-orig/gdb/testsuite/gdb.base/unwind-leak.c gdb-6.3/gdb/testsuite/gdb.base/unwind-leak.c +--- gdb-6.3-orig/gdb/testsuite/gdb.base/unwind-leak.c 2007-12-19 15:12:55.000000000 -0500 ++++ gdb-6.3/gdb/testsuite/gdb.base/unwind-leak.c 2007-12-19 13:55:22.000000000 -0500 +@@ -0,0 +1,29 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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 */ ++ ++#include ++ ++int main() ++{ ++ for (;;) ++ alarm (0); ++ return 0; ++} +diff -u -rup gdb-6.3-orig/gdb/testsuite/gdb.base/unwind-leak.exp gdb-6.3/gdb/testsuite/gdb.base/unwind-leak.exp +--- gdb-6.3-orig/gdb/testsuite/gdb.base/unwind-leak.exp 2007-12-19 15:12:53.000000000 -0500 ++++ gdb-6.3/gdb/testsuite/gdb.base/unwind-leak.exp 2007-12-19 15:11:35.000000000 -0500 +@@ -0,0 +1,90 @@ ++# Copyright 2007 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile unwind-leak ++set srcfile ${testfile}.c ++set shfile ${objdir}/${subdir}/${testfile}-gdb.sh ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set pid [exp_pid -i [board_info host fileid]] ++ ++# For C programs, "start" should stop in main(). ++ ++gdb_test "start" \ ++ "main \\(\\) at .*$srcfile.*" \ ++ "start" ++ ++set loc [gdb_get_line_number "alarm"] ++gdb_breakpoint $loc ++ ++proc memory_get {} { ++ global pid ++ set fd [open "/proc/$pid/statm"] ++ gets $fd line ++ close $fd ++ # number of pages of data/stack ++ scan $line "%*d%*d%*d%*d%*d%d" drs ++ return $drs ++} ++ ++set cycles 100 ++# For 100 cycles it was 1308: from = 363 KB, to = 1671 KB ++set permit_kb 100 ++verbose -log "cycles = $cycles, permit_kb = $permit_kb" ++ ++set fail 0 ++set test "breakpoint stop/continue cycles" ++for {set i $cycles} {$i > 0} {set i [expr {$i - 1}]} { ++ gdb_test_multiple "continue" $test { ++ -re "Breakpoint 2, main .*alarm .*.*${gdb_prompt} $" { ++ } ++ -re "Segmentation fault" { ++ fail $test ++ set i 0 ++ set fail 1 ++ } ++ } ++ if ![info exists from] { ++ set from [memory_get] ++ } ++} ++set to [memory_get] ++if {!$fail} { ++ verbose -log "from = $from KB, to = $to KB" ++ if {$from > 0 && $to > 10 && $to < $from + $permit_kb} { ++ pass $test ++ } else { ++ fail $test ++ } ++} diff --git a/gdb-6.5-last-address-space-byte-test.patch b/gdb-6.5-last-address-space-byte-test.patch new file mode 100644 index 0000000..22b4429 --- /dev/null +++ b/gdb-6.5-last-address-space-byte-test.patch @@ -0,0 +1,56 @@ +Index: ./gdb/testsuite/gdb.base/largecore-last-address-lock.exp +=================================================================== +RCS file: ./gdb/testsuite/gdb.base/largecore-last-address-lock.exp +diff -N ./gdb/testsuite/gdb.base/largecore-last-address-lock.exp +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/largecore-last-address-lock.exp 15 Nov 2006 21:43:24 -0000 +@@ -0,0 +1,49 @@ ++# Copyright 2006 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++ ++# i386 (32-bit) only: gdb with Red Hat largecore patch did lock up: ++# https://enterprise.redhat.com/issue-tracker/?module=issues&action=view&tid=103263 ++# https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=210614 ++ ++# i386: Bug exists when the `target_xfer_memory' condition ++# `(memaddr + len < region->hi)' operates on 64-bit operands on ++# largecore-patched with 32-bit addresses and so it can get `false' with ++# arbitrary `len'. ++ ++# x86_64: The bug is not present as the operands and calculations have the same ++# bit size. Would would still need to pass there the highest address ++# (`memaddr == 0xffffffffffffffff') but we would need to pass `len == 0' ++# to make the condition `(memaddr + len < region->hi)' false. ++# `len == 0' would get caught eariler. ++ ++# Error in the success case is immediate. ++set timeoutold ${timeout} ++set timeout 10 ++ ++gdb_test "x/xb 0xffffffff" \ ++ "Cannot access memory at address 0xffffffff" \ ++ "Read the last address space byte" ++ ++set timeout ${timeoutold} diff --git a/gdb-6.5-missed-trap-on-step-test.patch b/gdb-6.5-missed-trap-on-step-test.patch new file mode 100644 index 0000000..b4de397 --- /dev/null +++ b/gdb-6.5-missed-trap-on-step-test.patch @@ -0,0 +1,90 @@ +Fix has been committed to: + gdb-6.6-scheduler_locking-step-sw-watchpoints2.patch + +--- /dev/null 2007-12-14 20:45:09.113039517 +0100 ++++ gdb-6.5/gdb/testsuite/gdb.base/watchpoint-during-step.exp 2007-12-24 19:42:00.000000000 +0100 +@@ -0,0 +1,51 @@ ++# Copyright 2007 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile watchpoint-during-step ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++runto_main ++ ++gdb_breakpoint [gdb_get_line_number "var = 2"] ++gdb_continue_to_breakpoint "Find the first var set" ++ ++gdb_test "step" ".*var = 3;" "Step to the next var set" ++ ++gdb_test "watch var" "atchpoint .*: var" "Set the watchpoint" ++ ++# Here is the target point. Be careful to not have breakpoint set on the line ++# we step from as in this case it is a valid upstream KFAIL gdb/38 ++ ++gdb_test "step" ".*Old value = 2.*New value = 3.*" "Catch the watchpoint" +--- /dev/null 2007-12-14 20:45:09.113039517 +0100 ++++ gdb-6.5/gdb/testsuite/gdb.base/watchpoint-during-step.c 2007-12-24 19:38:10.000000000 +0100 +@@ -0,0 +1,30 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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 */ ++ ++static int var; ++ ++int main() ++{ ++ var = 1; ++ var = 2; ++ var = 3; ++ return 0; ++} diff --git a/gdb-6.5-readline-long-line-crash-test.patch b/gdb-6.5-readline-long-line-crash-test.patch new file mode 100644 index 0000000..c563051 --- /dev/null +++ b/gdb-6.5-readline-long-line-crash-test.patch @@ -0,0 +1,136 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=214196 + + +Index: ./gdb/testsuite/gdb.base/readline-overflow.exp +=================================================================== +RCS file: ./gdb/testsuite/gdb.base/readline-overflow.exp +diff -N ./gdb/testsuite/gdb.base/readline-overflow.exp +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/readline-overflow.exp 13 Nov 2006 23:42:50 -0000 +@@ -0,0 +1,125 @@ ++# Copyright 2006 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 Jan Kratochvil ++ ++# This file is part of the gdb testsuite. ++ ++# ++# Tests for readline buffer overflow. ++# ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++# Don't let a .inputrc file or an existing setting of INPUTRC mess up ++# the test results. Even if /dev/null doesn't exist on the particular ++# platform, the readline library will use the default setting just by ++# failing to open the file. OTOH, opening /dev/null successfully will ++# also result in the default settings being used since nothing will be ++# read from this file. ++global env ++if [info exists env(INPUTRC)] { ++ set old_inputrc $env(INPUTRC) ++} ++set env(INPUTRC) "/dev/null" ++ ++set oldtimeout1 $timeout ++set timeout 600 ++ ++if [info exists env(GDBHISTFILE)] { ++ set old_gdbhistfile $env(GDBHISTFILE) ++} ++if [info exists env(HISTSIZE)] { ++ set old_histsize $env(HISTSIZE) ++} ++set env(GDBHISTFILE) "${srcdir}/${subdir}/gdb_history" ++set env(HISTSIZE) "10" ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++ ++ ++set width 11 ++gdb_test "set width $width" \ ++ "" \ ++ "Setting width to $width." ++#gdb_test "set height 1" \ ++# "" \ ++# "Setting height to 1." ++send_gdb "run X" ++set i 0 ++# It crashes using `set width 7' on `set total 3560'. ++# Sometimes it corrupts screen on `set width 7'. ++# Bugreport used `set total 130001': ++# https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=214196 ++# Check also `timeout' above. ++set total 4200 ++gdb_expect { ++ -re X { ++ incr i ++ if {$i <= $total} { ++ send_gdb "X" ++ exp_continue ++ } ++ } ++ -re "\[ \b\r\n\]" { ++ exp_continue ++ } ++ eof { ++ fail "gdb sending total $total characters" ++ note "Failed after sending $i characters, reason: EOF" ++ gdb_clear_suppressed ++ } ++ timeout { ++ fail "gdb sending total $total characters" ++ note "Failed after sending $i characters (timeout $timeout), reason: TIMEOUT" ++ gdb_clear_suppressed ++ } ++ default { ++ fail "gdb sending total $total characters" ++ note "Failed after sending $i characters, reason: 0=\[$expect_out(0,string)\] buffer=\[$expect_out(buffer)\]" ++ gdb_clear_suppressed ++ } ++} ++gdb_test "\r" \ ++ "No executable file specified..*" \ ++ "All the characters transferred" ++ ++ ++# Restore globals modified in this test... ++if [info exists old_inputrc] { ++ set env(INPUTRC) $old_inputrc ++} else { ++ unset env(INPUTRC) ++} ++if [info exists old_gdbhistfile] { ++ set env(GDBHISTFILE) $old_gdbhistfile ++} else { ++ unset env(GDBHISTFILE) ++} ++if [info exists old_histsize] { ++ set env(HISTSIZE) $old_histsize ++} else { ++ unset env(HISTSIZE) ++} ++set timeout $oldtimeout1 ++ ++return 0 diff --git a/gdb-6.5-readline-long-line-crash.patch b/gdb-6.5-readline-long-line-crash.patch new file mode 100644 index 0000000..aa0722d --- /dev/null +++ b/gdb-6.5-readline-long-line-crash.patch @@ -0,0 +1,165 @@ +Fix Valgrind paste of >= 256 * (screen width) characters (as 130001). + +Invalid write of size 4 + at 0x8203BD9: rl_redisplay (display.c:812) + by 0x81F5130: _rl_internal_char_cleanup (readline.c:427) + by 0x81F52B3: readline_internal_char (readline.c:508) + by 0x8209817: rl_callback_read_char (callback.c:184) + by 0x8135312: rl_callback_read_char_wrapper (event-top.c:179) + by 0x8135B7B: stdin_event_handler (event-top.c:432) + by 0x81349F2: handle_file_event (event-loop.c:730) + by 0x81342AB: process_event (event-loop.c:343) + by 0x81342F4: gdb_do_one_event (event-loop.c:380) + by 0x81313AC: catch_errors (exceptions.c:515) + by 0x80CE8CA: tui_command_loop (tui-interp.c:151) + by 0x81318B9: current_interp_command_loop (interps.c:278) + Address 0x43DCEB8 is 0 bytes after a block of size 1,024 alloc'd + at 0x4005400: malloc (vg_replace_malloc.c:149) + by 0x8087084: xmalloc (utils.c:959) + by 0x8202CA7: init_line_structures (display.c:440) + by 0x8202D14: rl_redisplay (display.c:471) + by 0x81F4F53: readline_internal_setup (readline.c:363) + by 0x820958C: _rl_callback_newline (callback.c:89) + by 0x82095BB: rl_callback_handler_install (callback.c:101) + by 0x80CE896: tui_command_loop (tui-interp.c:138) + by 0x81318B9: current_interp_command_loop (interps.c:278) + by 0x807E69A: captured_command_loop (main.c:101) + by 0x81313AC: catch_errors (exceptions.c:515) + by 0x807F55A: captured_main (main.c:826) + + +2006-11-08 Jan Kratochvil + + * readline/display.c (line_state, line_state_array, line_state_visible, + line_state_invisible): Encapsulate _rl_wrapped_line, inv_lbreaks, + inv_lbsize, vis_lbreaks, vis_lbsize, visible_line, invisible_line. + (init_line_structures): Initialize both _rl_wrapped_line ones now. + (rl_redisplay): Fix _rl_wrapped_line handling by using its own size. + Swap whole `line_state_visible' / `line_state_invisible' structures. + (update_line): Update for new `_rl_wrapped_line'. + + +Index: ./readline/display.c +=================================================================== +--- ./readline/display.c 5 May 2006 18:26:12 -0000 1.11 ++++ ./readline/display.c 8 Nov 2006 18:23:33 -0000 +@@ -73,15 +73,31 @@ static void delete_chars PARAMS((int)); + static void insert_some_chars PARAMS((char *, int, int)); + static void cr PARAMS((void)); + ++struct line_state ++ { ++ char *line; ++ int *lbreaks; ++ int lbreaks_size; ++#if defined (HANDLE_MULTIBYTE) ++ int *wrapped_line; ++ int wrapped_line_size; ++#endif ++ }; ++static struct line_state line_state_array[2]; ++static struct line_state *line_state_visible = &line_state_array[0]; ++static struct line_state *line_state_invisible = &line_state_array[1]; ++ + #if defined (HANDLE_MULTIBYTE) + static int _rl_col_width PARAMS((const char *, int, int)); +-static int *_rl_wrapped_line; + #else + # define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) + #endif + +-static int *inv_lbreaks, *vis_lbreaks; +-static int inv_lbsize, vis_lbsize; ++/* FIXME: Backward compatible naming. */ ++#define inv_lbreaks (line_state_invisible->lbreaks) ++#define inv_lbsize (line_state_invisible->lbreaks_size) ++#define vis_lbreaks (line_state_visible->lbreaks) ++#define vis_lbsize (line_state_visible->lbreaks_size) + + /* Heuristic used to decide whether it is faster to move from CUR to NEW + by backing up or outputting a carriage return and moving forward. */ +@@ -150,8 +166,9 @@ static int last_lmargin; + + /* The line display buffers. One is the line currently displayed on + the screen. The other is the line about to be displayed. */ +-static char *visible_line = (char *)NULL; +-static char *invisible_line = (char *)NULL; ++/* FIXME: Backward compatible naming. */ ++#define visible_line (line_state_visible->line) ++#define invisible_line (line_state_invisible->line) + + /* A buffer for `modeline' messages. */ + static char msg_buf[128]; +@@ -437,7 +454,10 @@ init_line_structures (minsize) + inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); + vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); + #if defined (HANDLE_MULTIBYTE) +- _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int)); ++ line_state_visible->wrapped_line_size = vis_lbsize; ++ line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wrapped_line_size * sizeof (int)); ++ line_state_invisible->wrapped_line_size = inv_lbsize; ++ line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wrapped_line_size * sizeof (int)); + #endif + inv_lbreaks[0] = vis_lbreaks[0] = 0; + } +@@ -572,10 +592,15 @@ rl_redisplay () + { \ + inv_lbsize *= 2; \ + inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ +- _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ + } \ + inv_lbreaks[++newlines] = out; \ +- _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \ ++ if (newlines >= (line_state_invisible->wrapped_line_size - 1)) \ ++ { \ ++ line_state_invisible->wrapped_line_size *= 2; \ ++ line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, \ ++ line_state_invisible->wrapped_line_size * sizeof (int)); \ ++ } \ ++ line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \ + lpos = 0; \ + } \ + } while (0) +@@ -605,7 +630,7 @@ rl_redisplay () + #endif + + #if defined (HANDLE_MULTIBYTE) +- memset (_rl_wrapped_line, 0, vis_lbsize); ++ memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wrapped_line_size * sizeof (int)); + num = 0; + #endif + +@@ -1118,17 +1143,10 @@ rl_redisplay () + + /* Swap visible and non-visible lines. */ + { +- char *vtemp = visible_line; +- int *itemp = vis_lbreaks, ntemp = vis_lbsize; +- +- visible_line = invisible_line; +- invisible_line = vtemp; +- +- vis_lbreaks = inv_lbreaks; +- inv_lbreaks = itemp; +- +- vis_lbsize = inv_lbsize; +- inv_lbsize = ntemp; ++ struct line_state *line_state_temp = line_state_visible; ++ ++ line_state_visible = line_state_invisible; ++ line_state_invisible = line_state_temp; + + rl_display_fixed = 0; + /* If we are displaying on a single line, and last_lmargin is > 0, we +@@ -1194,8 +1212,9 @@ update_line (old, new, current_line, oma + /* This fixes only double-column characters, but if the wrapped + character comsumes more than three columns, spaces will be + inserted in the string buffer. */ +- if (_rl_wrapped_line[current_line] > 0) +- _rl_clear_to_eol (_rl_wrapped_line[current_line]); ++ if (current_line < line_state_visible->wrapped_line_size ++ && line_state_visible->wrapped_line[current_line] > 0) ++ _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]); + + memset (&ps, 0, sizeof (mbstate_t)); + ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); diff --git a/gdb-6.5-section-num-fixup-test.patch b/gdb-6.5-section-num-fixup-test.patch new file mode 100644 index 0000000..0f1beb9 --- /dev/null +++ b/gdb-6.5-section-num-fixup-test.patch @@ -0,0 +1,111 @@ +diff -up -ruNp gdb-6.5-orig/gdb/testsuite/gdb.base/datalib-lib.c gdb-6.5/gdb/testsuite/gdb.base/datalib-lib.c +--- gdb-6.5-orig/gdb/testsuite/gdb.base/datalib-lib.c 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.5/gdb/testsuite/gdb.base/datalib-lib.c 2008-05-29 13:51:50.000000000 -0400 +@@ -0,0 +1,22 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 */ ++ ++int var; +diff -up -ruNp gdb-6.5-orig/gdb/testsuite/gdb.base/datalib-main.c gdb-6.5/gdb/testsuite/gdb.base/datalib-main.c +--- gdb-6.5-orig/gdb/testsuite/gdb.base/datalib-main.c 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.5/gdb/testsuite/gdb.base/datalib-main.c 2008-05-29 13:51:39.000000000 -0400 +@@ -0,0 +1,26 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 */ ++ ++int ++main (void) ++{ ++ return 0; ++} +diff -up -ruNp gdb-6.5-orig/gdb/testsuite/gdb.base/datalib.exp gdb-6.5/gdb/testsuite/gdb.base/datalib.exp +--- gdb-6.5-orig/gdb/testsuite/gdb.base/datalib.exp 1969-12-31 19:00:00.000000000 -0500 ++++ gdb-6.5/gdb/testsuite/gdb.base/datalib.exp 2008-05-29 14:58:33.000000000 -0400 +@@ -0,0 +1,51 @@ ++# Copyright 2008 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. ++ ++set testfile datalib ++set srcfilemain ${testfile}-main.c ++set srcfilelib ${testfile}-lib.c ++set libfile ${objdir}/${subdir}/${testfile}-lib.so ++set binfile ${objdir}/${subdir}/${testfile}-main ++if { [gdb_compile "${srcdir}/${subdir}/${srcfilelib}" "${libfile}" executable [list debug {additional_flags=-shared -nostdlib}]] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfilemain}" "${binfile} ${libfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# We must use a separate library as the main executable is compiled to the ++# address 0 by default and it would get fixed up already at the end of ++# INIT_OBJFILE_SECT_INDICES. We also cannot PRELINK it as PRELINK is missing ++# on ia64. The library must be NOSTDLIB as otherwise some stub code would ++# create the `.text' section there. Also DEBUG option is useful as some of ++# the crashes occur in dwarf2read.c. ++ ++# FAIL case: ++# ../../gdb/ia64-tdep.c:2838: internal-error: sect_index_text not initialized ++# A problem internal to GDB has been detected, ++ ++gdb_test "start" \ ++ "main \\(\\) at .*${srcfilemain}.*" \ ++ "start" diff --git a/gdb-6.5-sharedlibrary-path.patch b/gdb-6.5-sharedlibrary-path.patch new file mode 100644 index 0000000..89e397f --- /dev/null +++ b/gdb-6.5-sharedlibrary-path.patch @@ -0,0 +1,171 @@ +If you provided some relative path to the shared library, such as with + export LD_LIBRARY_PATH=. +then gdb would fail to match the shared library name during the TLS lookup. + + +Dropped the workaround/fix for gdb-6.8.50.20081128 - is it still needed? + + +The testsuite needs `gdb-6.3-bz146810-solib_absolute_prefix_is_empty.patch'. +The testsuite needs `gdb-6.5-tls-of-separate-debuginfo.patch'. + + +2006-09-01 Jan Kratochvil + + * solib-svr4.c (svr4_fetch_objfile_link_map): Match even absolute + requested pathnames to the internal loaded relative pathnames. + +2007-10-16 Jan Kratochvil + + Port to GDB-6.7. + +2008-02-27 Jan Kratochvil + + Port to gdb-6.7.50.20080227. + +Index: gdb-6.7.50.20080227/gdb/testsuite/gdb.threads/tls-sepdebug-main.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.7.50.20080227/gdb/testsuite/gdb.threads/tls-sepdebug-main.c 2008-02-27 09:00:15.000000000 +0100 +@@ -0,0 +1,25 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2006 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 */ ++ ++int main() ++{ ++ return 0; ++} +Index: gdb-6.7.50.20080227/gdb/testsuite/gdb.threads/tls-sepdebug-shared.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.7.50.20080227/gdb/testsuite/gdb.threads/tls-sepdebug-shared.c 2008-02-27 09:00:15.000000000 +0100 +@@ -0,0 +1,22 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2006 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 */ ++ ++__thread int var = 42; +--- /dev/null 2009-02-10 00:19:00.494289687 +0100 ++++ gdb-6.8.50.20090209-x/gdb/testsuite/gdb.threads/tls-sepdebug.exp 2009-02-10 00:49:38.000000000 +0100 +@@ -0,0 +1,86 @@ ++# Copyright 2006 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile tls-sepdebug ++set srcmainfile ${testfile}-main.c ++set srcsharedfile ${testfile}-shared.c ++ ++set binmainfile ${objdir}/${subdir}/${testfile}-main ++set binsharedbase ${testfile}-shared.so ++set binsharedfile ${objdir}/${subdir}/${binsharedbase} ++set binshareddebugfile ${objdir}/${subdir}/${binsharedbase}.debug ++ ++# Use explicit -soname as otherwise the full path to the library would get ++# encoded into ${binmainfile} making LD_LIBRARY_PATH tests useless. ++ ++# FIXME: gcc dependency (-Wl,-soname). ++ ++if { [gdb_compile_shlib "${srcdir}/${subdir}/${srcsharedfile}" "${binsharedfile}" [list debug additional_flags=-Wl,-soname=${binsharedbase}]] != "" } { ++ untested "Couldn't compile test library" ++ return -1 ++} ++ ++# eu-strip(1) works fine but it is a part of `elfutils', not `binutils'. ++if 0 then { ++ remote_exec build "eu-strip -f ${binshareddebugfile} ${binsharedfile}" ++} else { ++ remote_exec build "objcopy --only-keep-debug ${binsharedfile} ${binshareddebugfile}" ++ remote_exec build "objcopy --strip-debug ${binsharedfile}" ++ remote_exec build "objcopy --add-gnu-debuglink=${binshareddebugfile} ${binsharedfile}" ++} ++ ++# Do not use `shlib=' as it will automatically add also -rpath for gcc. ++ ++if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcmainfile} ${binsharedfile}" "${binmainfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++# Test also the proper resolving of relative library names to absolute ones. ++# \$PWD is easy - it is the absolute way ++# ${subdir} would fail on "print var" ++ ++foreach ld_library_path [list [pwd]/${subdir} ./${subdir}] name { absolute relative } { ++ ++ gdb_exit ++ gdb_start ++ ###gdb_reinitialize_dir $srcdir/$subdir ++ ++ gdb_test "set env LD_LIBRARY_PATH=$ld_library_path" \ ++ "" \ ++ "set env LD_LIBRARY_PATH is $name" ++ ++ gdb_load ${binmainfile} ++ ++ # For C programs, "start" should stop in main(). ++ ++ gdb_test "start" \ ++ "main \\(\\) at .*${srcmainfile}.*" \ ++ "start" ++ ++ # Check for: Cannot find shared library `/usr/lib/debug/lib/libc-2.4.90.so.debug' in dynamic linker's load module list ++ # as happens with TLS variables and `separate_debug_objfile_backlink'. ++ ++ gdb_test "print var" \ ++ "\\\$1 = \[0-9\].*" \ ++ "print TLS variable from a shared library with $name-directory separate debug info file" ++} diff --git a/gdb-6.5-tls-of-separate-debuginfo.patch b/gdb-6.5-tls-of-separate-debuginfo.patch new file mode 100644 index 0000000..1346c47 --- /dev/null +++ b/gdb-6.5-tls-of-separate-debuginfo.patch @@ -0,0 +1,24 @@ +Dependency on: gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch + + +2006-09-01 Jan Kratochvil + + * target.c (target_translate_tls_address): Fix for separate debuginfo. + + +diff -rup gdb-6.5.orig/gdb/target.c gdb-6.5/gdb/target.c +--- gdb-6.5.orig/gdb/target.c 2006-09-20 17:13:35.000000000 -0400 ++++ gdb-6.5/gdb/target.c 2006-09-20 17:15:53.000000000 -0400 +@@ -769,6 +769,12 @@ target_translate_tls_address (struct obj + ptid_t ptid = inferior_ptid; + volatile struct gdb_exception ex; + ++ /* Resolve: Cannot find shared library ++ `/usr/lib/debug/lib/lib....so.debug' in dynamic linker's load ++ module list */ ++ if (objfile->separate_debug_objfile_backlink != NULL) ++ objfile = objfile->separate_debug_objfile_backlink; ++ + TRY_CATCH (ex, RETURN_MASK_ALL) + { + CORE_ADDR lm_addr; diff --git a/gdb-6.6-buildid-locate-rpm.patch b/gdb-6.6-buildid-locate-rpm.patch new file mode 100644 index 0000000..6a90616 --- /dev/null +++ b/gdb-6.6-buildid-locate-rpm.patch @@ -0,0 +1,1671 @@ +Index: gdb-6.8.50.20090302/gdb/event-top.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/event-top.c 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/event-top.c 2009-03-07 17:25:06.000000000 +0100 +@@ -33,6 +33,7 @@ + #include "cli/cli-script.h" /* for reset_command_nest_depth */ + #include "main.h" + #include "gdbthread.h" ++#include "symfile.h" + + /* For dont_repeat() */ + #include "gdbcmd.h" +@@ -193,6 +194,8 @@ cli_command_loop (void) + char *a_prompt; + char *gdb_prompt = get_prompt (); + ++ debug_flush_missing (); ++ + /* Tell readline what the prompt to display is and what function it + will need to call after a whole line is read. This also displays + the first prompt. */ +@@ -264,6 +267,8 @@ display_gdb_prompt (char *new_prompt) + /* Reset the nesting depth used when trace-commands is set. */ + reset_command_nest_depth (); + ++ debug_flush_missing (); ++ + /* Each interpreter has its own rules on displaying the command + prompt. */ + if (!current_interp_display_prompt_p ()) +Index: gdb-6.8.50.20090302/gdb/symfile.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/symfile.c 2009-03-07 17:22:21.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/symfile.c 2009-03-07 17:26:47.000000000 +0100 +@@ -55,6 +55,7 @@ + #include "solib.h" + #include "remote.h" + #include "libbfd.h" ++#include "elf/external.h" + + #include + #include +@@ -63,6 +64,7 @@ + #include + #include + #include ++#include + + + int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num); +@@ -1684,8 +1686,352 @@ build_id_to_filename (struct build_id *b + return retval; + } + ++#ifdef HAVE_LIBRPM ++ ++#include ++#include ++#include ++#include ++#ifdef DLOPEN_LIBRPM ++#include ++#endif ++ ++/* This MISSING_RPM_HASH tracker is used to collect all the missing rpm files ++ and avoid their duplicities during a single inferior run. */ ++ ++static struct htab *missing_rpm_hash; ++ ++/* This MISSING_RPM_LIST tracker is used to collect and print as a single line ++ all the rpms right before the nearest GDB prompt. It gets cleared after ++ each such print (it is questionable if we should clear it after the print). ++ */ ++ ++struct missing_rpm ++ { ++ struct missing_rpm *next; ++ char rpm[1]; ++ }; ++static struct missing_rpm *missing_rpm_list; ++static int missing_rpm_list_entries; ++ ++/* Returns the count of newly added rpms. */ ++ ++static int ++missing_rpm_enlist (const char *filename) ++{ ++ static int rpm_init_done = 0; ++ rpmts ts; ++ rpmdbMatchIterator mi; ++ int count = 0; ++ ++#ifdef DLOPEN_LIBRPM ++ /* Duplicate here the declarations to verify they match. The same sanity ++ check is present also in `configure.ac'. */ ++ extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); ++ static char *(*headerFormat_p) (Header h, const char * fmt, errmsg_t *errmsg); ++ extern int rpmReadConfigFiles(const char * file, const char * target); ++ static int (*rpmReadConfigFiles_p) (const char * file, const char * target); ++ extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); ++ static rpmdbMatchIterator (*rpmdbFreeIterator_p) (rpmdbMatchIterator mi); ++ extern Header rpmdbNextIterator(rpmdbMatchIterator mi); ++ static Header (*rpmdbNextIterator_p) (rpmdbMatchIterator mi); ++ extern rpmts rpmtsCreate(void); ++ static rpmts (*rpmtsCreate_p) (void); ++ extern rpmts rpmtsFree(rpmts ts); ++ static rpmts (*rpmtsFree_p) (rpmts ts); ++ extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, ++ const void * keyp, size_t keylen); ++ static rpmdbMatchIterator (*rpmtsInitIterator_p) (const rpmts ts, ++ rpmTag rpmtag, ++ const void *keyp, ++ size_t keylen); ++#else /* !DLOPEN_LIBRPM */ ++# define headerFormat_p headerFormat ++# define rpmReadConfigFiles_p rpmReadConfigFiles ++# define rpmdbFreeIterator_p rpmdbFreeIterator ++# define rpmdbNextIterator_p rpmdbNextIterator ++# define rpmtsCreate_p rpmtsCreate ++# define rpmtsFree_p rpmtsFree ++# define rpmtsInitIterator_p rpmtsInitIterator ++#endif /* !DLOPEN_LIBRPM */ ++ ++ if (filename == NULL) ++ return 0; ++ ++ if (!rpm_init_done) ++ { ++ static int init_tried; ++ ++ /* Already failed the initialization before? */ ++ if (init_tried) ++ return 0; ++ init_tried = 1; ++ ++#ifdef DLOPEN_LIBRPM ++ { ++ void *h; ++ ++ h = dlopen (DLOPEN_LIBRPM, RTLD_LAZY); ++ if (!h) ++ { ++ warning (_("Unable to open \"%s\" (%s), " ++ "missing debuginfos notifications will not be displayed"), ++ DLOPEN_LIBRPM, dlerror ()); ++ return 0; ++ } ++ ++ if (!((headerFormat_p = dlsym (h, "headerFormat")) ++ && (rpmReadConfigFiles_p = dlsym (h, "rpmReadConfigFiles")) ++ && (rpmdbFreeIterator_p = dlsym (h, "rpmdbFreeIterator")) ++ && (rpmdbNextIterator_p = dlsym (h, "rpmdbNextIterator")) ++ && (rpmtsCreate_p = dlsym (h, "rpmtsCreate")) ++ && (rpmtsFree_p = dlsym (h, "rpmtsFree")) ++ && (rpmtsInitIterator_p = dlsym (h, "rpmtsInitIterator")))) ++ { ++ warning (_("Opened library \"%s\" is incompatible (%s), " ++ "missing debuginfos notifications will not be displayed"), ++ DLOPEN_LIBRPM, dlerror ()); ++ if (dlclose (h)) ++ warning (_("Error closing library \"%s\": %s\n"), DLOPEN_LIBRPM, ++ dlerror ()); ++ return 0; ++ } ++ } ++#endif /* DLOPEN_LIBRPM */ ++ ++ if (rpmReadConfigFiles_p (NULL, NULL) != 0) ++ { ++ warning (_("Error reading the rpm configuration files")); ++ return 0; ++ } ++ ++ rpm_init_done = 1; ++ } ++ ++ ts = rpmtsCreate_p (); ++ ++ mi = rpmtsInitIterator_p (ts, RPMTAG_BASENAMES, filename, 0); ++ if (mi != NULL) ++ { ++ for (;;) ++ { ++ Header h; ++ char *debuginfo, **slot, *s, *s2; ++ errmsg_t err; ++ size_t srcrpmlen = sizeof (".src.rpm") - 1; ++ size_t debuginfolen = sizeof ("-debuginfo") - 1; ++ rpmdbMatchIterator mi_debuginfo; ++ ++ h = rpmdbNextIterator_p (mi); ++ if (h == NULL) ++ break; ++ ++ /* Verify the debuginfo file is not already installed. */ ++ ++ debuginfo = headerFormat_p (h, "%{sourcerpm}-debuginfo.%{arch}", ++ &err); ++ if (!debuginfo) ++ { ++ warning (_("Error querying the rpm file `%s': %s"), filename, ++ err); ++ continue; ++ } ++ /* s = `.src.rpm-debuginfo.%{arch}' */ ++ s = strrchr (debuginfo, '-') - srcrpmlen; ++ s2 = NULL; ++ if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0) ++ { ++ /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */ ++ s2 = memrchr (debuginfo, '-', s - debuginfo); ++ } ++ if (s2) ++ { ++ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */ ++ s2 = memrchr (debuginfo, '-', s2 - debuginfo); ++ } ++ if (!s2) ++ { ++ warning (_("Error querying the rpm file `%s': %s"), filename, ++ debuginfo); ++ xfree (debuginfo); ++ continue; ++ } ++ /* s = `.src.rpm-debuginfo.%{arch}' */ ++ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */ ++ memmove (s2 + debuginfolen, s2, s - s2); ++ memcpy (s2, "-debuginfo", debuginfolen); ++ /* s = `XXXX.%{arch}' */ ++ /* strlen ("XXXX") == srcrpmlen + debuginfolen */ ++ /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */ ++ /* strlen ("XX") == srcrpmlen */ ++ memmove (s + debuginfolen, s + srcrpmlen + debuginfolen, ++ strlen (s + srcrpmlen + debuginfolen) + 1); ++ /* s = `-debuginfo-%{version}-%{release}.%{arch}' */ ++ ++ /* RPMDBI_PACKAGES requires keylen == sizeof (int). */ ++ /* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */ ++ mi_debuginfo = rpmtsInitIterator_p (ts, RPMDBI_LABEL, debuginfo, 0); ++ xfree (debuginfo); ++ if (mi_debuginfo) ++ { ++ rpmdbFreeIterator_p (mi_debuginfo); ++ count = 0; ++ break; ++ } ++ ++ /* The allocated memory gets utilized below for MISSING_RPM_HASH. */ ++ debuginfo = headerFormat_p (h, ++ "%{name}-%{version}-%{release}.%{arch}", ++ &err); ++ if (!debuginfo) ++ { ++ warning (_("Error querying the rpm file `%s': %s"), filename, ++ err); ++ continue; ++ } ++ ++ /* Base package name for `debuginfo-install'. We do not use the ++ `yum' command directly as the line ++ yum --enablerepo='*-debuginfo' install NAME-debuginfo.ARCH ++ would be more complicated than just: ++ debuginfo-install NAME-VERSION-RELEASE.ARCH ++ Do not supply the rpm base name (derived from .src.rpm name) as ++ debuginfo-install is unable to install the debuginfo package if ++ the base name PKG binary rpm is not installed while for example ++ PKG-libs would be installed (RH Bug 467901). ++ FUTURE: After multiple debuginfo versions simultaneously installed ++ get supported the support for the VERSION-RELEASE tags handling ++ may need an update. */ ++ ++ if (missing_rpm_hash == NULL) ++ { ++ /* DEL_F is passed NULL as MISSING_RPM_LIST's HTAB_DELETE ++ should not deallocate the entries. */ ++ ++ missing_rpm_hash = htab_create_alloc (64, htab_hash_string, ++ (int (*) (const void *, const void *)) streq, ++ NULL, xcalloc, xfree); ++ } ++ slot = (char **) htab_find_slot (missing_rpm_hash, debuginfo, INSERT); ++ /* XCALLOC never returns NULL. */ ++ gdb_assert (slot != NULL); ++ if (*slot == NULL) ++ { ++ struct missing_rpm *missing_rpm; ++ ++ *slot = debuginfo; ++ ++ missing_rpm = xmalloc (sizeof (*missing_rpm) + strlen (debuginfo)); ++ strcpy (missing_rpm->rpm, debuginfo); ++ missing_rpm->next = missing_rpm_list; ++ missing_rpm_list = missing_rpm; ++ missing_rpm_list_entries++; ++ } ++ else ++ xfree (debuginfo); ++ count++; ++ } ++ ++ rpmdbFreeIterator_p (mi); ++ } ++ ++ rpmtsFree_p (ts); ++ ++ return count; ++} ++ ++static int ++missing_rpm_list_compar (const char *const *ap, const char *const *bp) ++{ ++ return strcoll (*ap, *bp); ++} ++ ++/* It returns a NULL-terminated array of strings needing to be FREEd. It may ++ also return only NULL. */ ++ ++static void ++missing_rpm_list_print (void) ++{ ++ char **array, **array_iter; ++ struct missing_rpm *list_iter; ++ struct cleanup *cleanups; ++ ++ if (missing_rpm_list_entries == 0) ++ return; ++ ++ array = xmalloc (sizeof (*array) * missing_rpm_list_entries); ++ cleanups = make_cleanup (xfree, array); ++ ++ array_iter = array; ++ for (list_iter = missing_rpm_list; list_iter != NULL; ++ list_iter = list_iter->next) ++ { ++ *array_iter++ = list_iter->rpm; ++ } ++ gdb_assert (array_iter == array + missing_rpm_list_entries); ++ ++ qsort (array, missing_rpm_list_entries, sizeof (*array), ++ (int (*) (const void *, const void *)) missing_rpm_list_compar); ++ ++ printf_unfiltered (_("Missing separate debuginfos, use: %s"), ++ "debuginfo-install"); ++ for (array_iter = array; array_iter < array + missing_rpm_list_entries; ++ array_iter++) ++ { ++ putchar_unfiltered (' '); ++ puts_unfiltered (*array_iter); ++ } ++ putchar_unfiltered ('\n'); ++ ++ while (missing_rpm_list != NULL) ++ { ++ list_iter = missing_rpm_list; ++ missing_rpm_list = list_iter->next; ++ xfree (list_iter); ++ } ++ missing_rpm_list_entries = 0; ++ ++ do_cleanups (cleanups); ++} ++ ++static void ++missing_rpm_change (void) ++{ ++ debug_flush_missing (); ++ ++ gdb_assert (missing_rpm_list == NULL); ++ if (missing_rpm_hash != NULL) ++ { ++ htab_delete (missing_rpm_hash); ++ missing_rpm_hash = NULL; ++ } ++} ++ ++enum missing_exec ++ { ++ /* Init state. EXEC_BFD also still could be NULL. */ ++ MISSING_EXEC_NOT_TRIED, ++ /* We saw a non-NULL EXEC_BFD but RPM has no info about it. */ ++ MISSING_EXEC_NOT_FOUND, ++ /* We found EXEC_BFD by RPM and we either have its symbols (either embedded ++ or separate) or the main executable's RPM is now contained in ++ MISSING_RPM_HASH. */ ++ MISSING_EXEC_ENLISTED ++ }; ++static enum missing_exec missing_exec = MISSING_EXEC_NOT_TRIED; ++ ++#endif /* HAVE_LIBRPM */ ++ ++void ++debug_flush_missing (void) ++{ ++#ifdef HAVE_LIBRPM ++ missing_rpm_list_print (); ++#endif ++} ++ + /* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages +- Try to install the hash file ... ++ yum --enablerepo='*-debuginfo' install ... + avoidance. */ + + struct missing_filepair +@@ -1739,11 +2085,17 @@ missing_filepair_change (void) + /* All their memory came just from missing_filepair_OBSTACK. */ + missing_filepair_hash = NULL; + } ++#ifdef HAVE_LIBRPM ++ missing_exec = MISSING_EXEC_NOT_TRIED; ++#endif + } + + static void + debug_print_executable_changed (void) + { ++#ifdef HAVE_LIBRPM ++ missing_rpm_change (); ++#endif + missing_filepair_change (); + } + +@@ -1802,14 +2154,33 @@ debug_print_missing (const char *binary, + } + *slot = missing_filepair; + +- /* We do not collect and flush these messages as each such message +- already requires its own separate lines. */ ++#ifdef HAVE_LIBRPM ++ if (missing_exec == MISSING_EXEC_NOT_TRIED) ++ { ++ char *exec_filename; + +- fprintf_unfiltered (gdb_stdlog, +- _("Missing separate debuginfo for %s\n"), binary); +- if (debug != NULL) +- fprintf_unfiltered (gdb_stdlog, _("Try to install the hash file %s\n"), +- debug); ++ exec_filename = get_exec_file (0); ++ if (exec_filename != NULL) ++ { ++ if (missing_rpm_enlist (exec_filename) == 0) ++ missing_exec = MISSING_EXEC_NOT_FOUND; ++ else ++ missing_exec = MISSING_EXEC_ENLISTED; ++ } ++ } ++ if (missing_exec != MISSING_EXEC_ENLISTED) ++ if (missing_rpm_enlist (binary) == 0 && missing_rpm_enlist (debug) == 0) ++#endif /* HAVE_LIBRPM */ ++ { ++ /* We do not collect and flush these messages as each such message ++ already requires its own separate lines. */ ++ ++ fprintf_unfiltered (gdb_stdlog, ++ _("Missing separate debuginfo for %s\n"), binary); ++ if (debug != NULL) ++ fprintf_unfiltered (gdb_stdlog, _("Try: %s %s\n"), ++ "yum --enablerepo='*-debuginfo' install", debug); ++ } + } + + static char * +Index: gdb-6.8.50.20090302/gdb/symfile.h +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/symfile.h 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/symfile.h 2009-03-07 17:25:06.000000000 +0100 +@@ -378,6 +378,7 @@ extern struct build_id *build_id_addr_ge + extern char *build_id_to_filename (struct build_id *build_id, + char **link_return, int add_debug_suffix); + extern void debug_print_missing (const char *binary, const char *debug); ++extern void debug_flush_missing (void); + + /* From dwarf2read.c */ + +Index: gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/testsuite/lib/gdb.exp 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp 2009-03-07 17:25:06.000000000 +0100 +@@ -1230,7 +1230,7 @@ proc default_gdb_start { } { + warning "Couldn't set the width to 0." + } + } +- # Turn off the missing warnings as the testsuite does not expect it. ++ # Turn off the missing RPMs warnings as the testsuite does not expect it. + send_gdb "set build-id-verbose 0\n" + gdb_expect 10 { + -re "$gdb_prompt $" { +--- ./gdb/testsuite/lib/mi-support.exp 2009-03-22 16:37:58.000000000 +0100 ++++ ./gdb/testsuite/lib/mi-support.exp 2009-03-22 16:37:12.000000000 +0100 +@@ -221,7 +221,7 @@ proc default_mi_gdb_start { args } { + } + } + } +- # Turn off the missing warnings as the testsuite does not expect it. ++ # Turn off the missing RPMs warnings as the testsuite does not expect it. + send_gdb "190-gdb-set build-id-verbose 0\n" + gdb_expect 10 { + -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" { +Index: gdb-6.8.50.20090302/gdb/tui/tui-interp.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/tui/tui-interp.c 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/tui/tui-interp.c 2009-03-07 17:25:06.000000000 +0100 +@@ -30,6 +30,7 @@ + #include "tui/tui.h" + #include "tui/tui-io.h" + #include "exceptions.h" ++#include "symfile.h" + + /* Set to 1 when the TUI mode must be activated when we first start + gdb. */ +@@ -128,6 +129,8 @@ tui_command_loop (void *data) + char *a_prompt; + char *gdb_prompt = get_prompt (); + ++ debug_flush_missing (); ++ + /* Tell readline what the prompt to display is and what function + it will need to call after a whole line is read. This also + displays the first prompt. */ +Index: gdb-6.8.50.20090302/gdb/aclocal.m4 +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/aclocal.m4 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/aclocal.m4 2009-03-07 17:25:06.000000000 +0100 +@@ -11,6 +11,162 @@ + # even the implied warranty of MERCHANTABILITY or FITNESS FOR A + # PARTICULAR PURPOSE. + ++# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- ++# ++# Copyright © 2004 Scott James Remnant . ++# ++# 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. ++# ++# As a special exception to the GNU General Public License, if you ++# distribute this file as part of a program that contains a ++# configuration script generated by Autoconf, you may include it under ++# the same distribution terms that you use for the rest of that program. ++ ++# PKG_PROG_PKG_CONFIG([MIN-VERSION]) ++# ---------------------------------- ++AC_DEFUN([PKG_PROG_PKG_CONFIG], ++[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) ++m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) ++AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl ++if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then ++ AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) ++fi ++if test -n "$PKG_CONFIG"; then ++ _pkg_min_version=m4_default([$1], [0.9.0]) ++ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) ++ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then ++ AC_MSG_RESULT([yes]) ++ else ++ AC_MSG_RESULT([no]) ++ PKG_CONFIG="" ++ fi ++ ++fi[]dnl ++])# PKG_PROG_PKG_CONFIG ++ ++# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) ++# ++# Check to see whether a particular set of modules exists. Similar ++# to PKG_CHECK_MODULES(), but does not set variables or print errors. ++# ++# ++# Similar to PKG_CHECK_MODULES, make sure that the first instance of ++# this or PKG_CHECK_MODULES is called, or make sure to call ++# PKG_CHECK_EXISTS manually ++# -------------------------------------------------------------- ++AC_DEFUN([PKG_CHECK_EXISTS], ++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl ++if test -n "$PKG_CONFIG" && \ ++ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then ++ m4_ifval([$2], [$2], [:]) ++m4_ifvaln([$3], [else ++ $3])dnl ++fi]) ++ ++ ++# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) ++# --------------------------------------------- ++m4_define([_PKG_CONFIG], ++[if test -n "$$1"; then ++ pkg_cv_[]$1="$$1" ++ elif test -n "$PKG_CONFIG"; then ++ PKG_CHECK_EXISTS([$3], ++ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], ++ [pkg_failed=yes]) ++ else ++ pkg_failed=untried ++fi[]dnl ++])# _PKG_CONFIG ++ ++# _PKG_SHORT_ERRORS_SUPPORTED ++# ----------------------------- ++AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], ++[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) ++if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then ++ _pkg_short_errors_supported=yes ++else ++ _pkg_short_errors_supported=no ++fi[]dnl ++])# _PKG_SHORT_ERRORS_SUPPORTED ++ ++ ++# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], ++# [ACTION-IF-NOT-FOUND]) ++# ++# ++# Note that if there is a possibility the first call to ++# PKG_CHECK_MODULES might not happen, you should be sure to include an ++# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac ++# ++# ++# -------------------------------------------------------------- ++AC_DEFUN([PKG_CHECK_MODULES], ++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl ++AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl ++AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl ++ ++pkg_failed=no ++AC_MSG_CHECKING([for $1]) ++ ++_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) ++_PKG_CONFIG([$1][_LIBS], [libs], [$2]) ++ ++m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS ++and $1[]_LIBS to avoid the need to call pkg-config. ++See the pkg-config man page for more details.]) ++ ++if test $pkg_failed = yes; then ++ _PKG_SHORT_ERRORS_SUPPORTED ++ if test $_pkg_short_errors_supported = yes; then ++ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` ++ else ++ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` ++ fi ++ # Put the nasty error message in config.log where it belongs ++ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ++ ++ ifelse([$4], , [AC_MSG_ERROR(dnl ++[Package requirements ($2) were not met: ++ ++$$1_PKG_ERRORS ++ ++Consider adjusting the PKG_CONFIG_PATH environment variable if you ++installed software in a non-standard prefix. ++ ++_PKG_TEXT ++])], ++ [AC_MSG_RESULT([no]) ++ $4]) ++elif test $pkg_failed = untried; then ++ ifelse([$4], , [AC_MSG_FAILURE(dnl ++[The pkg-config script could not be found or is too old. Make sure it ++is in your PATH or set the PKG_CONFIG environment variable to the full ++path to pkg-config. ++ ++_PKG_TEXT ++ ++To get pkg-config, see .])], ++ [$4]) ++else ++ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS ++ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS ++ AC_MSG_RESULT([yes]) ++ ifelse([$3], , :, [$3]) ++fi[]dnl ++])# PKG_CHECK_MODULES ++ + # Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + # + # This file is free software; the Free Software Foundation +@@ -468,6 +624,27 @@ AC_DEFUN([AM_PROG_INSTALL_SH], + install_sh=${install_sh-"$am_aux_dir/install-sh"} + AC_SUBST(install_sh)]) + ++# Copyright (C) 2003, 2005 Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# serial 2 ++ ++# Check whether the underlying file-system supports filenames ++# with a leading dot. For instance MS-DOS doesn't. ++AC_DEFUN([AM_SET_LEADING_DOT], ++[rm -rf .tst 2>/dev/null ++mkdir .tst 2>/dev/null ++if test -d .tst; then ++ am__leading_dot=. ++else ++ am__leading_dot=_ ++fi ++rmdir .tst 2>/dev/null ++AC_SUBST([am__leading_dot])]) ++ + # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- + # From Jim Meyering + +@@ -868,7 +1045,4 @@ m4_include([gnulib/m4/onceonly_2_57.m4]) + m4_include([gnulib/m4/stdint.m4]) + m4_include([gnulib/m4/string_h.m4]) + m4_include([gnulib/m4/wchar.m4]) +-m4_include([../config/extensions.m4]) +-m4_include([../config/lead-dot.m4]) +-m4_include([../config/proginstall.m4]) + m4_include([acinclude.m4]) +Index: gdb-6.8.50.20090302/gdb/config.in +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/config.in 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/config.in 2009-03-07 17:25:06.000000000 +0100 +@@ -38,6 +38,9 @@ + /* Define to BFD's default target vector. */ + #undef DEFAULT_BFD_VEC + ++/* librpm version specific library name to dlopen. */ ++#undef DLOPEN_LIBRPM ++ + /* Define to 1 if translation of program messages to the user's native + language is requested. */ + #undef ENABLE_NLS +@@ -211,6 +214,9 @@ + /* Define if Python 2.6 is being used. */ + #undef HAVE_LIBPYTHON2_6 + ++/* Define if librpm library is being used. */ ++#undef HAVE_LIBRPM ++ + /* Define if libunwind library is being used. */ + #undef HAVE_LIBUNWIND + +Index: gdb-6.8.50.20090302/gdb/configure +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/configure 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/configure 2009-03-07 17:25:06.000000000 +0100 +@@ -314,7 +314,7 @@ ac_subdirs_all="$ac_subdirs_all doc test + ac_subdirs_all="$ac_subdirs_all gdbtk" + ac_subdirs_all="$ac_subdirs_all multi-ice" + ac_subdirs_all="$ac_subdirs_all gdbserver" +-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os am__leading_dot DEPDIR CCDEPMODE MAKE GMAKE_TRUE GMAKE_FALSE SET_MAKE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK AMTAR am__tar am__untar am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH am__fastdepCC_TRUE am__fastdepCC_FALSE GDB_DATADIR_PATH pythondir subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG LIBICONV LIBICONV_INCLUDE LIBICONV_LIBDIR READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT PYTHON_CFLAGS ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS' ++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os am__leading_dot DEPDIR CCDEPMODE MAKE GMAKE_TRUE GMAKE_FALSE SET_MAKE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK AMTAR am__tar am__untar am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH am__fastdepCC_TRUE am__fastdepCC_FALSE GDB_DATADIR_PATH pythondir PKG_CONFIG ac_pt_PKG_CONFIG RPM_CFLAGS RPM_LIBS subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG LIBICONV LIBICONV_INCLUDE LIBICONV_LIBDIR READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT PYTHON_CFLAGS ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS' + ac_subst_files='host_makefile_frag' + ac_pwd=`pwd` + +@@ -776,6 +776,18 @@ ac_env_CPP_set=${CPP+set} + ac_env_CPP_value=$CPP + ac_cv_env_CPP_set=${CPP+set} + ac_cv_env_CPP_value=$CPP ++ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} ++ac_env_PKG_CONFIG_value=$PKG_CONFIG ++ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} ++ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG ++ac_env_RPM_CFLAGS_set=${RPM_CFLAGS+set} ++ac_env_RPM_CFLAGS_value=$RPM_CFLAGS ++ac_cv_env_RPM_CFLAGS_set=${RPM_CFLAGS+set} ++ac_cv_env_RPM_CFLAGS_value=$RPM_CFLAGS ++ac_env_RPM_LIBS_set=${RPM_LIBS+set} ++ac_env_RPM_LIBS_value=$RPM_LIBS ++ac_cv_env_RPM_LIBS_set=${RPM_LIBS+set} ++ac_cv_env_RPM_LIBS_value=$RPM_LIBS + + # + # Report the --help message. +@@ -886,6 +898,8 @@ Optional Packages: + [DATADIR/gdb] + --with-pythondir install Python data files in this path + [DATADIR/gdb/python] ++ --with-rpm query rpm database for missing debuginfos ++ [yes/no,], [def.], [auto=librpm.so] + --with-libunwind Use libunwind frame unwinding support + --with-pkgversion=PKG Use PKG in the version string in place of "GDB" + --with-bugurl=URL Direct users to URL to report a bug +@@ -913,6 +927,9 @@ Some influential environment variables: + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor ++ PKG_CONFIG path to pkg-config utility ++ RPM_CFLAGS C compiler flags for RPM, overriding pkg-config ++ RPM_LIBS linker flags for RPM, overriding pkg-config + + Use these variables to override the choices made by `configure' or to help + it to find libraries and programs with nonstandard names/locations. +@@ -6556,7 +6573,6 @@ am__api_version="1.9" + # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" + # OS/2's system install, which has a completely different semantic + # ./install, which can be erroneously created by make from ./install.sh. +-# Reject install programs that cannot install multiple files. + echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 + echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 + if test -z "$INSTALL"; then +@@ -6590,18 +6606,8 @@ case $as_dir/ in + # program-specific install script used by HP pwplus--don't use. + : + else +- rm -rf conftest.one conftest.two conftest.dir +- echo one > conftest.one +- echo two > conftest.two +- mkdir conftest.dir +- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && +- test -s conftest.one && test -s conftest.two && +- test -s conftest.dir/conftest.one && +- test -s conftest.dir/conftest.two +- then +- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" +- break 3 +- fi ++ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" ++ break 3 + fi + fi + done +@@ -6610,16 +6616,15 @@ case $as_dir/ in + esac + done + +-rm -rf conftest.one conftest.two conftest.dir + + fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else +- # As a last resort, use the slow shell script. Don't cache a +- # value for INSTALL within a source directory, because that will ++ # As a last resort, use the slow shell script. We don't cache a ++ # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is +- # removed, or if the value is a relative name. ++ # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi + fi +@@ -7202,6 +7207,559 @@ _ACEOF + fi + + ++# Integration with rpm library to support missing debuginfo suggestions. ++# --without-rpm: Disable any rpm support. ++# --with-rpm=libname.so: Try to dynamically open `libname.so' during runtime. ++# Even with runtime missing `libname.so' GDB will still other run correctly. ++# Missing `libname.so' during ./configure will abort the configuration. ++# --with-rpm=librpm.so: Like `--with-rpm=libname.so' but try to find specific ++# minor version first such as `librpm-4.6.so' as minor version differences ++# mean API+ABI incompatibility. If the specific match versioned library name ++# could not be found still open dynamically at least `librpm.so'. ++# --with-rpm: Like `--with-rpm=librpm.so' but if any of its detection fails try ++# to find librpm for compilation-time linking by pkg-config. GDB binary will ++# be probably linked with the version specific library (as `librpm-4.6.so'). ++# Failure to find librpm by pkg-config will abort the configuration. ++# (default) --with-rpm=auto: Like `--with-rpm=librpm.so' but if even pkg-config ++# cannot find librpm use to the rpmless compilation (like `--without-rpm'). ++ ++ ++# Check whether --with-rpm or --without-rpm was given. ++if test "${with_rpm+set}" = set; then ++ withval="$with_rpm" ++ ++else ++ with_rpm="auto" ++fi; ++ ++ ++ ++if test "x$with_rpm" != "xno"; then ++ if test "x$with_rpm" = "xyes"; then ++ LIBRPM="librpm.so" ++ RPM_REQUIRE=true ++ DLOPEN_REQUIRE=false ++ elif test "x$with_rpm" = "xauto"; then ++ LIBRPM="librpm.so" ++ RPM_REQUIRE=false ++ DLOPEN_REQUIRE=false ++ else ++ LIBRPM="$with_rpm" ++ RPM_REQUIRE=true ++ DLOPEN_REQUIRE=true ++ fi ++ LIBRPM_STRING='"'"$LIBRPM"'"' ++ ++ echo "$as_me:$LINENO: checking specific librpm version" >&5 ++echo $ECHO_N "checking specific librpm version... $ECHO_C" >&6 ++ HAVE_DLOPEN_LIBRPM=false ++ save_LIBS="$LIBS" ++ LIBS="$LIBS -ldl" ++ if test "$cross_compiling" = yes; then ++ { { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 ++echo "$as_me: error: in \`$ac_pwd':" >&2;} ++{ { echo "$as_me:$LINENO: error: cannot run test program while cross compiling ++See \`config.log' for more details." >&5 ++echo "$as_me: error: cannot run test program while cross compiling ++See \`config.log' for more details." >&2;} ++ { (exit 1); exit 1; }; }; } ++else ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++ ++#include ++#include ++#include ++ ++int ++main () ++{ ++ ++ void *h; ++ const char *const *rpmverp; ++ FILE *f; ++ ++ f = fopen ("conftest.out", "w"); ++ if (!f) ++ { ++ fprintf (stderr, "Cannot write \"%s\": %s\n", "conftest.out", ++ strerror (errno)); ++ return 1; ++ } ++ h = dlopen ($LIBRPM_STRING, RTLD_LAZY); ++ if (!h) ++ { ++ fprintf (stderr, "dlopen (\"%s\"): %s\n", $LIBRPM_STRING, dlerror ()); ++ return 1; ++ } ++ rpmverp = dlsym (h, "RPMVERSION"); ++ if (!rpmverp) ++ { ++ fprintf (stderr, "dlsym (\"RPMVERSION\"): %s\n", dlerror ()); ++ return 1; ++ } ++ fprintf (stderr, "RPMVERSION is: \""); ++ fprintf (stderr, "%s\"\n", *rpmverp); ++ ++ /* Try to find the specific librpm version only for "librpm.so" as we do ++ not know how to assemble the version string otherwise. */ ++ ++ if (strcmp ("librpm.so", $LIBRPM_STRING) != 0) ++ { ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ else ++ { ++ char *h2_name; ++ void *h2; ++ int major, minor; ++ ++ if (sscanf (*rpmverp, "%d.%d", &major, &minor) != 2) ++ { ++ fprintf (stderr, "Unable to parse RPMVERSION.\n"); ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ /* Avoid the square brackets by malloc. */ ++ h2_name = malloc (64); ++ sprintf (h2_name, "librpm-%d.%d.so", major, minor); ++ h2 = dlopen (h2_name, RTLD_LAZY); ++ if (!h2) ++ { ++ fprintf (stderr, "dlopen (\"%s\"): %s\n", h2_name, dlerror ()); ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ if (h2 != h) ++ { ++ fprintf (stderr, "dlopen of \"%s\" and \"%s\" are different.\n", ++ $LIBRPM_STRING, h2_name); ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ /* Found the valid .so name with a specific version. */ ++ fprintf (f, "%s\n", h2_name); ++ return 0; ++ } ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest$ac_exeext ++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ++ (eval $ac_link) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && { ac_try='./conftest$ac_exeext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ++ DLOPEN_LIBRPM="`cat conftest.out`" ++ if test "x$DLOPEN_LIBRPM" != "x"; then ++ HAVE_DLOPEN_LIBRPM=true ++ echo "$as_me:$LINENO: result: $DLOPEN_LIBRPM" >&5 ++echo "${ECHO_T}$DLOPEN_LIBRPM" >&6 ++ fi ++ ++else ++ echo "$as_me: program exited with status $ac_status" >&5 ++echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext ++fi ++ rm -f conftest.out ++ ++ ++ ++ if $HAVE_DLOPEN_LIBRPM; then ++ ++ echo "$as_me:$LINENO: checking rpm library API compatibility" >&5 ++echo $ECHO_N "checking rpm library API compatibility... $ECHO_C" >&6 ++ # The compilation requires -Werror to verify anything. ++ save_CFLAGS="$CFLAGS" ++ CFLAGS="$CFLAGS -Werror" ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++ ++/* Duplicate here the declarations to verify they match "symfile.c". */ ++#include ++#include ++#include ++#include ++extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); ++extern int rpmReadConfigFiles(const char * file, const char * target); ++extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); ++extern Header rpmdbNextIterator(rpmdbMatchIterator mi); ++extern rpmts rpmtsCreate(void); ++extern rpmts rpmtsFree(rpmts ts); ++extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, ++ const void * keyp, size_t keylen); ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ++ LIBRPM_COMPAT=true ++ echo "$as_me:$LINENO: result: yes" >&5 ++echo "${ECHO_T}yes" >&6 ++ ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ++ LIBRPM_COMPAT=false ++ echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6 ++ ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++ CFLAGS="$save_CFLAGS" ++ ++ if ! $LIBRPM_COMPAT; then ++ HAVE_DLOPEN_LIBRPM=false ++ fi ++ fi ++ ++ if $HAVE_DLOPEN_LIBRPM; then ++ DLOPEN_LIBRPM_STRING='"'"$DLOPEN_LIBRPM"'"' ++ ++cat >>confdefs.h <<_ACEOF ++#define DLOPEN_LIBRPM $DLOPEN_LIBRPM_STRING ++_ACEOF ++ ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_LIBRPM 1 ++_ACEOF ++ ++ else ++ echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6 ++ LIBS="$save_LIBS" ++ if $DLOPEN_REQUIRE; then ++ { { echo "$as_me:$LINENO: error: Specific name $LIBRPM was requested but it could not be opened." >&5 ++echo "$as_me: error: Specific name $LIBRPM was requested but it could not be opened." >&2;} ++ { (exit 1); exit 1; }; } ++ fi ++ ++ ++if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. ++set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 ++echo "$as_me:$LINENO: checking for $ac_word" >&5 ++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 ++if test "${ac_cv_path_PKG_CONFIG+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ case $PKG_CONFIG in ++ [\\/]* | ?:[\\/]*) ++ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ++ ;; ++ *) ++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" ++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++done ++ ++ ;; ++esac ++fi ++PKG_CONFIG=$ac_cv_path_PKG_CONFIG ++ ++if test -n "$PKG_CONFIG"; then ++ echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 ++echo "${ECHO_T}$PKG_CONFIG" >&6 ++else ++ echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6 ++fi ++ ++fi ++if test -z "$ac_cv_path_PKG_CONFIG"; then ++ ac_pt_PKG_CONFIG=$PKG_CONFIG ++ # Extract the first word of "pkg-config", so it can be a program name with args. ++set dummy pkg-config; ac_word=$2 ++echo "$as_me:$LINENO: checking for $ac_word" >&5 ++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 ++if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ case $ac_pt_PKG_CONFIG in ++ [\\/]* | ?:[\\/]*) ++ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ++ ;; ++ *) ++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" ++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++done ++ ++ ;; ++esac ++fi ++ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG ++ ++if test -n "$ac_pt_PKG_CONFIG"; then ++ echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5 ++echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6 ++else ++ echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6 ++fi ++ ++ PKG_CONFIG=$ac_pt_PKG_CONFIG ++else ++ PKG_CONFIG="$ac_cv_path_PKG_CONFIG" ++fi ++ ++fi ++if test -n "$PKG_CONFIG"; then ++ _pkg_min_version=0.9.0 ++ echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 ++echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 ++ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then ++ echo "$as_me:$LINENO: result: yes" >&5 ++echo "${ECHO_T}yes" >&6 ++ else ++ echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6 ++ PKG_CONFIG="" ++ fi ++ ++fi ++ ++pkg_failed=no ++echo "$as_me:$LINENO: checking for RPM" >&5 ++echo $ECHO_N "checking for RPM... $ECHO_C" >&6 ++ ++if test -n "$RPM_CFLAGS"; then ++ pkg_cv_RPM_CFLAGS="$RPM_CFLAGS" ++ elif test -n "$PKG_CONFIG"; then ++ if test -n "$PKG_CONFIG" && \ ++ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"rpm\"") >&5 ++ ($PKG_CONFIG --exists --print-errors "rpm") 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; then ++ pkg_cv_RPM_CFLAGS=`$PKG_CONFIG --cflags "rpm" 2>/dev/null` ++else ++ pkg_failed=yes ++fi ++ else ++ pkg_failed=untried ++fi ++if test -n "$RPM_LIBS"; then ++ pkg_cv_RPM_LIBS="$RPM_LIBS" ++ elif test -n "$PKG_CONFIG"; then ++ if test -n "$PKG_CONFIG" && \ ++ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"rpm\"") >&5 ++ ($PKG_CONFIG --exists --print-errors "rpm") 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; then ++ pkg_cv_RPM_LIBS=`$PKG_CONFIG --libs "rpm" 2>/dev/null` ++else ++ pkg_failed=yes ++fi ++ else ++ pkg_failed=untried ++fi ++ ++ ++ ++if test $pkg_failed = yes; then ++ ++if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then ++ _pkg_short_errors_supported=yes ++else ++ _pkg_short_errors_supported=no ++fi ++ if test $_pkg_short_errors_supported = yes; then ++ RPM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "rpm" 2>&1` ++ else ++ RPM_PKG_ERRORS=`$PKG_CONFIG --print-errors "rpm" 2>&1` ++ fi ++ # Put the nasty error message in config.log where it belongs ++ echo "$RPM_PKG_ERRORS" >&5 ++ ++ echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6 ++ HAVE_LIBRPM=false ++elif test $pkg_failed = untried; then ++ HAVE_LIBRPM=false ++else ++ RPM_CFLAGS=$pkg_cv_RPM_CFLAGS ++ RPM_LIBS=$pkg_cv_RPM_LIBS ++ echo "$as_me:$LINENO: result: yes" >&5 ++echo "${ECHO_T}yes" >&6 ++ HAVE_LIBRPM=true ++fi ++ ++ if $HAVE_LIBRPM; then ++ ++ echo "$as_me:$LINENO: checking rpm library API compatibility" >&5 ++echo $ECHO_N "checking rpm library API compatibility... $ECHO_C" >&6 ++ # The compilation requires -Werror to verify anything. ++ save_CFLAGS="$CFLAGS" ++ CFLAGS="$CFLAGS -Werror" ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++ ++/* Duplicate here the declarations to verify they match "symfile.c". */ ++#include ++#include ++#include ++#include ++extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); ++extern int rpmReadConfigFiles(const char * file, const char * target); ++extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); ++extern Header rpmdbNextIterator(rpmdbMatchIterator mi); ++extern rpmts rpmtsCreate(void); ++extern rpmts rpmtsFree(rpmts ts); ++extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, ++ const void * keyp, size_t keylen); ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ++ LIBRPM_COMPAT=true ++ echo "$as_me:$LINENO: result: yes" >&5 ++echo "${ECHO_T}yes" >&6 ++ ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ++ LIBRPM_COMPAT=false ++ echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6 ++ ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++ CFLAGS="$save_CFLAGS" ++ ++ if ! $LIBRPM_COMPAT; then ++ HAVE_LIBRPM=false ++ RPM_PKG_ERRORS="Found $LIBRPM API is incompatibile with this GDB" ++ fi ++ fi ++ ++ if $HAVE_LIBRPM; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_LIBRPM 1 ++_ACEOF ++ ++ CFLAGS="$CFLAGS $RPM_CFLAGS" ++ LIBS="$LIBS $RPM_LIBS" ++ else ++ if $RPM_REQUIRE; then ++ { { echo "$as_me:$LINENO: error: $RPM_PKG_ERRORS" >&5 ++echo "$as_me: error: $RPM_PKG_ERRORS" >&2;} ++ { (exit 1); exit 1; }; } ++ else ++ { echo "$as_me:$LINENO: WARNING: $RPM_PKG_ERRORS" >&5 ++echo "$as_me: WARNING: $RPM_PKG_ERRORS" >&2;} ++ fi ++ fi ++ fi ++fi ++ + + + +@@ -8623,7 +9181,6 @@ done + # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" + # OS/2's system install, which has a completely different semantic + # ./install, which can be erroneously created by make from ./install.sh. +-# Reject install programs that cannot install multiple files. + echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 + echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 + if test -z "$INSTALL"; then +@@ -8657,18 +9214,8 @@ case $as_dir/ in + # program-specific install script used by HP pwplus--don't use. + : + else +- rm -rf conftest.one conftest.two conftest.dir +- echo one > conftest.one +- echo two > conftest.two +- mkdir conftest.dir +- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && +- test -s conftest.one && test -s conftest.two && +- test -s conftest.dir/conftest.one && +- test -s conftest.dir/conftest.two +- then +- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" +- break 3 +- fi ++ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" ++ break 3 + fi + fi + done +@@ -8677,16 +9224,15 @@ case $as_dir/ in + esac + done + +-rm -rf conftest.one conftest.two conftest.dir + + fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else +- # As a last resort, use the slow shell script. Don't cache a +- # value for INSTALL within a source directory, because that will ++ # As a last resort, use the slow shell script. We don't cache a ++ # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is +- # removed, or if the value is a relative name. ++ # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi + fi +@@ -22270,6 +22816,10 @@ s,@am__fastdepCC_TRUE@,$am__fastdepCC_TR + s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t + s,@GDB_DATADIR_PATH@,$GDB_DATADIR_PATH,;t t + s,@pythondir@,$pythondir,;t t ++s,@PKG_CONFIG@,$PKG_CONFIG,;t t ++s,@ac_pt_PKG_CONFIG@,$ac_pt_PKG_CONFIG,;t t ++s,@RPM_CFLAGS@,$RPM_CFLAGS,;t t ++s,@RPM_LIBS@,$RPM_LIBS,;t t + s,@subdirs@,$subdirs,;t t + s,@TARGET_OBS@,$TARGET_OBS,;t t + s,@PKGVERSION@,$PKGVERSION,;t t +Index: gdb-6.8.50.20090302/gdb/configure.ac +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/configure.ac 2009-03-07 17:13:33.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/configure.ac 2009-03-07 17:25:06.000000000 +0100 +@@ -162,6 +162,199 @@ else + fi + AC_SUBST(pythondir) + ++# Integration with rpm library to support missing debuginfo suggestions. ++# --without-rpm: Disable any rpm support. ++# --with-rpm=libname.so: Try to dynamically open `libname.so' during runtime. ++# Even with runtime missing `libname.so' GDB will still other run correctly. ++# Missing `libname.so' during ./configure will abort the configuration. ++# --with-rpm=librpm.so: Like `--with-rpm=libname.so' but try to find specific ++# minor version first such as `librpm-4.6.so' as minor version differences ++# mean API+ABI incompatibility. If the specific match versioned library name ++# could not be found still open dynamically at least `librpm.so'. ++# --with-rpm: Like `--with-rpm=librpm.so' but if any of its detection fails try ++# to find librpm for compilation-time linking by pkg-config. GDB binary will ++# be probably linked with the version specific library (as `librpm-4.6.so'). ++# Failure to find librpm by pkg-config will abort the configuration. ++# (default) --with-rpm=auto: Like `--with-rpm=librpm.so' but if even pkg-config ++# cannot find librpm use to the rpmless compilation (like `--without-rpm'). ++ ++AC_ARG_WITH([rpm], ++ [AS_HELP_STRING([--with-rpm], ++ [query rpm database for missing debuginfos [yes/no, def. auto=librpm.so]])], [], [with_rpm="auto"]) ++ ++m4_pattern_allow([^AC_MSG_ERROR$]) ++m4_pattern_allow([^AC_MSG_WARN$]) ++if test "x$with_rpm" != "xno"; then ++ if test "x$with_rpm" = "xyes"; then ++ LIBRPM="librpm.so" ++ RPM_REQUIRE=true ++ DLOPEN_REQUIRE=false ++ elif test "x$with_rpm" = "xauto"; then ++ LIBRPM="librpm.so" ++ RPM_REQUIRE=false ++ DLOPEN_REQUIRE=false ++ else ++ LIBRPM="$with_rpm" ++ RPM_REQUIRE=true ++ DLOPEN_REQUIRE=true ++ fi ++ LIBRPM_STRING='"'"$LIBRPM"'"' ++ ++ AC_MSG_CHECKING([specific librpm version]) ++ HAVE_DLOPEN_LIBRPM=false ++ save_LIBS="$LIBS" ++ LIBS="$LIBS -ldl" ++ AC_RUN_IFELSE(AC_LANG_PROGRAM([[ ++#include ++#include ++#include ++ ]], [[ ++ void *h; ++ const char *const *rpmverp; ++ FILE *f; ++ ++ f = fopen ("conftest.out", "w"); ++ if (!f) ++ { ++ fprintf (stderr, "Cannot write \"%s\": %s\n", "conftest.out", ++ strerror (errno)); ++ return 1; ++ } ++ h = dlopen ($LIBRPM_STRING, RTLD_LAZY); ++ if (!h) ++ { ++ fprintf (stderr, "dlopen (\"%s\"): %s\n", $LIBRPM_STRING, dlerror ()); ++ return 1; ++ } ++ rpmverp = dlsym (h, "RPMVERSION"); ++ if (!rpmverp) ++ { ++ fprintf (stderr, "dlsym (\"RPMVERSION\"): %s\n", dlerror ()); ++ return 1; ++ } ++ fprintf (stderr, "RPMVERSION is: \""); ++ fprintf (stderr, "%s\"\n", *rpmverp); ++ ++ /* Try to find the specific librpm version only for "librpm.so" as we do ++ not know how to assemble the version string otherwise. */ ++ ++ if (strcmp ("librpm.so", $LIBRPM_STRING) != 0) ++ { ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ else ++ { ++ char *h2_name; ++ void *h2; ++ int major, minor; ++ ++ if (sscanf (*rpmverp, "%d.%d", &major, &minor) != 2) ++ { ++ fprintf (stderr, "Unable to parse RPMVERSION.\n"); ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ /* Avoid the square brackets by malloc. */ ++ h2_name = malloc (64); ++ sprintf (h2_name, "librpm-%d.%d.so", major, minor); ++ h2 = dlopen (h2_name, RTLD_LAZY); ++ if (!h2) ++ { ++ fprintf (stderr, "dlopen (\"%s\"): %s\n", h2_name, dlerror ()); ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ if (h2 != h) ++ { ++ fprintf (stderr, "dlopen of \"%s\" and \"%s\" are different.\n", ++ $LIBRPM_STRING, h2_name); ++ fprintf (f, "%s\n", $LIBRPM_STRING); ++ return 0; ++ } ++ /* Found the valid .so name with a specific version. */ ++ fprintf (f, "%s\n", h2_name); ++ return 0; ++ } ++ ]]), [ ++ DLOPEN_LIBRPM="`cat conftest.out`" ++ if test "x$DLOPEN_LIBRPM" != "x"; then ++ HAVE_DLOPEN_LIBRPM=true ++ AC_MSG_RESULT($DLOPEN_LIBRPM) ++ fi ++ ]) ++ rm -f conftest.out ++ ++ m4_define([CHECK_LIBRPM_COMPAT], [ ++ AC_MSG_CHECKING([rpm library API compatibility]) ++ # The compilation requires -Werror to verify anything. ++ save_CFLAGS="$CFLAGS" ++ CFLAGS="$CFLAGS -Werror" ++ AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[ ++/* Duplicate here the declarations to verify they match "symfile.c". */ ++#include ++#include ++#include ++#include ++extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); ++extern int rpmReadConfigFiles(const char * file, const char * target); ++extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); ++extern Header rpmdbNextIterator(rpmdbMatchIterator mi); ++extern rpmts rpmtsCreate(void); ++extern rpmts rpmtsFree(rpmts ts); ++extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, ++ const void * keyp, size_t keylen); ++ ]]), [ ++ LIBRPM_COMPAT=true ++ AC_MSG_RESULT(yes) ++ ], [ ++ LIBRPM_COMPAT=false ++ AC_MSG_RESULT(no) ++ ]) ++ CFLAGS="$save_CFLAGS" ++ ]) ++ ++ if $HAVE_DLOPEN_LIBRPM; then ++ CHECK_LIBRPM_COMPAT ++ if ! $LIBRPM_COMPAT; then ++ HAVE_DLOPEN_LIBRPM=false ++ fi ++ fi ++ ++ if $HAVE_DLOPEN_LIBRPM; then ++ DLOPEN_LIBRPM_STRING='"'"$DLOPEN_LIBRPM"'"' ++ AC_DEFINE_UNQUOTED(DLOPEN_LIBRPM, $DLOPEN_LIBRPM_STRING, [librpm version specific library name to dlopen.]) ++ AC_DEFINE(HAVE_LIBRPM, 1, [Define if librpm library is being used.]) ++ else ++ AC_MSG_RESULT(no) ++ LIBS="$save_LIBS" ++ if $DLOPEN_REQUIRE; then ++ AC_MSG_ERROR([Specific name $LIBRPM was requested but it could not be opened.]) ++ fi ++ PKG_CHECK_MODULES(RPM, rpm, [HAVE_LIBRPM=true], [HAVE_LIBRPM=false]) ++ ++ if $HAVE_LIBRPM; then ++ CHECK_LIBRPM_COMPAT ++ if ! $LIBRPM_COMPAT; then ++ HAVE_LIBRPM=false ++ RPM_PKG_ERRORS="Found $LIBRPM API is incompatibile with this GDB" ++ fi ++ fi ++ ++ if $HAVE_LIBRPM; then ++ AC_DEFINE(HAVE_LIBRPM, 1, [Define if librpm library is being used.]) ++ CFLAGS="$CFLAGS $RPM_CFLAGS" ++ LIBS="$LIBS $RPM_LIBS" ++ else ++ if $RPM_REQUIRE; then ++ AC_MSG_ERROR($RPM_PKG_ERRORS) ++ else ++ AC_MSG_WARN($RPM_PKG_ERRORS) ++ fi ++ fi ++ fi ++fi ++ + + AC_CONFIG_SUBDIRS(doc testsuite) + diff --git a/gdb-6.6-buildid-locate.patch b/gdb-6.6-buildid-locate.patch new file mode 100644 index 0000000..146f787 --- /dev/null +++ b/gdb-6.6-buildid-locate.patch @@ -0,0 +1,1006 @@ +Index: gdb-6.8.50.20090302/gdb/corelow.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/corelow.c 2009-02-23 01:03:48.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/corelow.c 2009-03-07 17:04:57.000000000 +0100 +@@ -45,6 +45,10 @@ + #include "exceptions.h" + #include "solib.h" + #include "filenames.h" ++#include "auxv.h" ++#include "elf/common.h" ++#include "objfiles.h" ++#include "gdbcmd.h" + + + #ifndef O_LARGEFILE +@@ -267,6 +271,56 @@ add_to_thread_list (bfd *abfd, asection + inferior_ptid = ptid; /* Yes, make it current */ + } + ++static int build_id_core_loads = 1; ++ ++static void ++build_id_locate_exec (int from_tty) ++{ ++ CORE_ADDR at_entry; ++ struct build_id *build_id; ++ char *exec_filename, *debug_filename; ++ char *build_id_filename; ++ ++ if (exec_bfd != NULL) ++ return; ++ ++ if (target_auxv_search (¤t_target, AT_ENTRY, &at_entry) <= 0) ++ return; ++ ++ build_id = build_id_addr_get (at_entry); ++ if (build_id == NULL) ++ return; ++ ++ exec_filename = build_id_to_filename (build_id, &build_id_filename, 0); ++ if (exec_filename != NULL) ++ exec_file_attach (exec_filename, from_tty); ++ else ++ debug_print_missing (_("the main executable file"), build_id_filename); ++ xfree (build_id_filename); ++ ++ /* `.note.gnu.build-id' section exists even for files without a separate ++ debuginfo. */ ++ debug_filename = build_id_to_filename (build_id, &build_id_filename, 1); ++ if (debug_filename != NULL) ++ { ++ symbol_file_add_main (debug_filename, from_tty); ++ xfree (debug_filename); ++ } ++ else ++ { ++ if (exec_filename != NULL) ++ symbol_file_add_main (exec_filename, from_tty); ++ /* For EXEC_FILENAME NULL we were already complaining above. */ ++ if (symfile_objfile == NULL && exec_filename != NULL) ++ debug_print_missing (exec_filename, build_id_filename); ++ } ++ xfree (build_id_filename); ++ ++ xfree (exec_filename); ++ ++ /* No automatic SOLIB_ADD as the libraries would get read twice. */ ++} ++ + /* This routine opens and sets up the core file bfd. */ + + static void +@@ -363,6 +417,12 @@ core_open (char *filename, int from_tty) + push_target (&core_ops); + discard_cleanups (old_chain); + ++ /* Find the build_id identifiers. If it gets executed after ++ POST_CREATE_INFERIOR we would clash with asking to discard the already ++ loaded VDSO symbols. */ ++ if (build_id_core_loads != 0) ++ build_id_locate_exec (from_tty); ++ + add_inferior_silent (corelow_pid); + + /* Do this before acknowledging the inferior, so if +@@ -751,4 +811,11 @@ _initialize_corelow (void) + init_core_ops (); + + add_target (&core_ops); ++ ++ add_setshow_boolean_cmd ("build-id-core-loads", class_files, ++ &build_id_core_loads, _("\ ++Set whether CORE-FILE loads the build-id associated files automatically."), _("\ ++Show whether CORE-FILE loads the build-id associated files automatically.."), ++ NULL, NULL, NULL, ++ &setlist, &showlist); + } +Index: gdb-6.8.50.20090302/gdb/doc/gdb.texinfo +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/doc/gdb.texinfo 2009-03-07 17:04:56.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/doc/gdb.texinfo 2009-03-07 17:04:57.000000000 +0100 +@@ -13294,6 +13294,27 @@ information files. + + @end table + ++You can also adjust the current verbosity of the @dfn{build id} locating. ++ ++@table @code ++ ++@kindex set build-id-verbose ++@item set build-id-verbose 0 ++No additional messages are printed. ++ ++@item set build-id-verbose 1 ++Missing separate debug filenames are printed. ++ ++@item set build-id-verbose 2 ++Missing separate debug filenames are printed and also all the parsing of the ++binaries to find their @dfn{build id} content is printed. ++ ++@kindex show build-id-verbose ++@item show build-id-verbose ++Show the current verbosity value for the @dfn{build id} content locating. ++ ++@end table ++ + @cindex @code{.gnu_debuglink} sections + @cindex debug link sections + A debug link is a special section of the executable file named +Index: gdb-6.8.50.20090302/gdb/solib-svr4.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/solib-svr4.c 2009-03-07 17:04:52.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/solib-svr4.c 2009-03-07 17:04:57.000000000 +0100 +@@ -1000,9 +1000,33 @@ 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); ++ struct build_id *build_id; ++ ++ strncpy (new->so_original_name, buffer, SO_NAME_MAX_PATH_SIZE - 1); ++ new->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; ++ /* May get overwritten below. */ ++ strcpy (new->so_name, new->so_original_name); ++ ++ build_id = build_id_addr_get (LM_DYNAMIC_FROM_LINK_MAP (new)); ++ if (build_id != NULL) ++ { ++ char *name, *build_id_filename; ++ ++ /* Missing the build-id matching separate debug info file ++ would be handled while SO_NAME gets loaded. */ ++ name = build_id_to_filename (build_id, &build_id_filename, 0); ++ if (name != NULL) ++ { ++ strncpy (new->so_name, name, SO_NAME_MAX_PATH_SIZE - 1); ++ new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; ++ xfree (name); ++ } ++ else ++ debug_print_missing (new->so_name, build_id_filename); ++ ++ xfree (build_id_filename); ++ xfree (build_id); ++ } + } + xfree (buffer); + +Index: gdb-6.8.50.20090302/gdb/symfile.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/symfile.c 2009-03-07 17:04:53.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/symfile.c 2009-03-07 17:22:21.000000000 +0100 +@@ -54,6 +54,7 @@ + #include "elf-bfd.h" + #include "solib.h" + #include "remote.h" ++#include "libbfd.h" + + #include + #include +@@ -1185,16 +1186,65 @@ symbol_file_clear (int from_tty) + printf_unfiltered (_("No symbol file now.\n")); + } + ++/* Locate NT_GNU_BUILD_ID and return its matching debug filename. ++ FIXME: NOTE decoding should be unified with the BFD core notes decoding. */ ++ ++#define BUILD_ID_VERBOSE_NONE 0 ++#define BUILD_ID_VERBOSE_FILENAMES 1 ++#define BUILD_ID_VERBOSE_BINARY_PARSE 2 ++static int build_id_verbose = BUILD_ID_VERBOSE_FILENAMES; ++static void ++show_build_id_verbose (struct ui_file *file, int from_tty, ++ struct cmd_list_element *c, const char *value) ++{ ++ fprintf_filtered (file, _("Verbosity level of the build-id locator is %s.\n"), ++ value); ++} ++ + struct build_id + { + size_t size; + gdb_byte data[1]; + }; + +-/* Locate NT_GNU_BUILD_ID from ABFD and return its content. */ ++struct build_id * ++build_id_buf_get (bfd *templ, gdb_byte *buf, bfd_size_type size) ++{ ++ bfd_byte *p; ++ ++ p = buf; ++ while (p < buf + size) ++ { ++ /* FIXME: bad alignment assumption. */ ++ Elf_External_Note *xnp = (Elf_External_Note *) p; ++ size_t namesz = H_GET_32 (templ, xnp->namesz); ++ size_t descsz = H_GET_32 (templ, xnp->descsz); ++ bfd_byte *descdata = xnp->name + BFD_ALIGN (namesz, 4); ++ ++ if (H_GET_32 (templ, xnp->type) == NT_GNU_BUILD_ID ++ && namesz == sizeof "GNU" ++ && memcmp (xnp->name, "GNU", sizeof "GNU") == 0) ++ { ++ size_t size = descsz; ++ gdb_byte *data = (void *) descdata; ++ struct build_id *retval; ++ ++ retval = xmalloc (sizeof *retval - 1 + size); ++ retval->size = size; ++ memcpy (retval->data, data, size); ++ ++ return retval; ++ } ++ p = descdata + BFD_ALIGN (descsz, 4); ++ } ++ return NULL; ++} ++ ++/* Separate debuginfo files have corrupted PHDR but SHDR is correct there. ++ Locate NT_GNU_BUILD_ID from ABFD and return its content. */ + + static struct build_id * +-build_id_bfd_get (bfd *abfd) ++build_id_bfd_shdr_get (bfd *abfd) + { + struct build_id *retval; + +@@ -1210,6 +1260,348 @@ build_id_bfd_get (bfd *abfd) + return retval; + } + ++/* Core files may have missing (corrupt) SHDR but PDHR is correct there. ++ bfd_elf_bfd_from_remote_memory () has too much overhead by ++ allocating/reading all the available ELF PT_LOADs. */ ++ ++static struct build_id * ++build_id_phdr_get (bfd *templ, bfd_vma loadbase, unsigned e_phnum, ++ Elf_Internal_Phdr *i_phdr) ++{ ++ int i; ++ struct build_id *retval = NULL; ++ ++ for (i = 0; i < e_phnum; i++) ++ if (i_phdr[i].p_type == PT_NOTE && i_phdr[i].p_filesz > 0) ++ { ++ Elf_Internal_Phdr *hdr = &i_phdr[i]; ++ gdb_byte *buf; ++ int err; ++ ++ buf = xmalloc (hdr->p_filesz); ++ err = target_read_memory (loadbase + i_phdr[i].p_vaddr, buf, ++ hdr->p_filesz); ++ if (err == 0) ++ retval = build_id_buf_get (templ, buf, hdr->p_filesz); ++ else ++ retval = NULL; ++ xfree (buf); ++ if (retval != NULL) ++ break; ++ } ++ return retval; ++} ++ ++/* First we validate the file by reading in the ELF header and checking ++ the magic number. */ ++ ++static inline bfd_boolean ++elf_file_p (Elf64_External_Ehdr *x_ehdrp64) ++{ ++ gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr)); ++ gdb_assert (offsetof (Elf64_External_Ehdr, e_ident) ++ == offsetof (Elf32_External_Ehdr, e_ident)); ++ gdb_assert (sizeof (((Elf64_External_Ehdr *) 0)->e_ident) ++ == sizeof (((Elf32_External_Ehdr *) 0)->e_ident)); ++ ++ return ((x_ehdrp64->e_ident[EI_MAG0] == ELFMAG0) ++ && (x_ehdrp64->e_ident[EI_MAG1] == ELFMAG1) ++ && (x_ehdrp64->e_ident[EI_MAG2] == ELFMAG2) ++ && (x_ehdrp64->e_ident[EI_MAG3] == ELFMAG3)); ++} ++ ++/* Translate an ELF file header in external format into an ELF file header in ++ internal format. */ ++ ++#define H_GET_WORD(bfd, ptr) (is64 ? H_GET_64 (bfd, (ptr)) \ ++ : H_GET_32 (bfd, (ptr))) ++#define H_GET_SIGNED_WORD(bfd, ptr) (is64 ? H_GET_S64 (bfd, (ptr)) \ ++ : H_GET_S32 (bfd, (ptr))) ++ ++static void ++elf_swap_ehdr_in (bfd *abfd, ++ const Elf64_External_Ehdr *src64, ++ Elf_Internal_Ehdr *dst) ++{ ++ int is64 = bfd_get_arch_size (abfd) == 64; ++#define SRC(field) (is64 ? src64->field \ ++ : ((const Elf32_External_Ehdr *) src64)->field) ++ ++ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; ++ memcpy (dst->e_ident, SRC (e_ident), EI_NIDENT); ++ dst->e_type = H_GET_16 (abfd, SRC (e_type)); ++ dst->e_machine = H_GET_16 (abfd, SRC (e_machine)); ++ dst->e_version = H_GET_32 (abfd, SRC (e_version)); ++ if (signed_vma) ++ dst->e_entry = H_GET_SIGNED_WORD (abfd, SRC (e_entry)); ++ else ++ dst->e_entry = H_GET_WORD (abfd, SRC (e_entry)); ++ dst->e_phoff = H_GET_WORD (abfd, SRC (e_phoff)); ++ dst->e_shoff = H_GET_WORD (abfd, SRC (e_shoff)); ++ dst->e_flags = H_GET_32 (abfd, SRC (e_flags)); ++ dst->e_ehsize = H_GET_16 (abfd, SRC (e_ehsize)); ++ dst->e_phentsize = H_GET_16 (abfd, SRC (e_phentsize)); ++ dst->e_phnum = H_GET_16 (abfd, SRC (e_phnum)); ++ dst->e_shentsize = H_GET_16 (abfd, SRC (e_shentsize)); ++ dst->e_shnum = H_GET_16 (abfd, SRC (e_shnum)); ++ dst->e_shstrndx = H_GET_16 (abfd, SRC (e_shstrndx)); ++ ++#undef SRC ++} ++ ++/* Translate an ELF program header table entry in external format into an ++ ELF program header table entry in internal format. */ ++ ++void ++elf_swap_phdr_in (bfd *abfd, ++ const Elf64_External_Phdr *src64, ++ Elf_Internal_Phdr *dst) ++{ ++ int is64 = bfd_get_arch_size (abfd) == 64; ++#define SRC(field) (is64 ? src64->field \ ++ : ((const Elf32_External_Phdr *) src64)->field) ++ ++ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; ++ ++ dst->p_type = H_GET_32 (abfd, SRC (p_type)); ++ dst->p_flags = H_GET_32 (abfd, SRC (p_flags)); ++ dst->p_offset = H_GET_WORD (abfd, SRC (p_offset)); ++ if (signed_vma) ++ { ++ dst->p_vaddr = H_GET_SIGNED_WORD (abfd, SRC (p_vaddr)); ++ dst->p_paddr = H_GET_SIGNED_WORD (abfd, SRC (p_paddr)); ++ } ++ else ++ { ++ dst->p_vaddr = H_GET_WORD (abfd, SRC (p_vaddr)); ++ dst->p_paddr = H_GET_WORD (abfd, SRC (p_paddr)); ++ } ++ dst->p_filesz = H_GET_WORD (abfd, SRC (p_filesz)); ++ dst->p_memsz = H_GET_WORD (abfd, SRC (p_memsz)); ++ dst->p_align = H_GET_WORD (abfd, SRC (p_align)); ++ ++#undef SRC ++} ++ ++#undef H_GET_SIGNED_WORD ++#undef H_GET_WORD ++ ++static Elf_Internal_Phdr * ++elf_get_phdr (bfd *templ, bfd_vma ehdr_vma, unsigned *e_phnum_pointer, ++ bfd_vma *loadbase_pointer) ++{ ++ /* sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr) */ ++ Elf64_External_Ehdr x_ehdr64; /* Elf file header, external form */ ++ Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ ++ bfd_size_type x_phdrs_size; ++ gdb_byte *x_phdrs_ptr; ++ Elf_Internal_Phdr *i_phdrs; ++ int err; ++ unsigned int i; ++ bfd_vma loadbase; ++ int loadbase_set; ++ ++ gdb_assert (templ != NULL); ++ gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr)); ++ ++ /* Read in the ELF header in external format. */ ++ err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr64, sizeof x_ehdr64); ++ if (err) ++ { ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Error reading ELF header at address 0x%lx"), ++ (unsigned long) ehdr_vma); ++ return NULL; ++ } ++ ++ /* Now check to see if we have a valid ELF file, and one that BFD can ++ make use of. The magic number must match, the address size ('class') ++ and byte-swapping must match our XVEC entry. */ ++ ++ if (! elf_file_p (&x_ehdr64) ++ || x_ehdr64.e_ident[EI_VERSION] != EV_CURRENT ++ || !((bfd_get_arch_size (templ) == 64 ++ && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS64) ++ || (bfd_get_arch_size (templ) == 32 ++ && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS32))) ++ { ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Unrecognized ELF header at address 0x%lx"), ++ (unsigned long) ehdr_vma); ++ return NULL; ++ } ++ ++ /* Check that file's byte order matches xvec's */ ++ switch (x_ehdr64.e_ident[EI_DATA]) ++ { ++ case ELFDATA2MSB: /* Big-endian */ ++ if (! bfd_header_big_endian (templ)) ++ { ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Unrecognized " ++ "big-endian ELF header at address 0x%lx"), ++ (unsigned long) ehdr_vma); ++ return NULL; ++ } ++ break; ++ case ELFDATA2LSB: /* Little-endian */ ++ if (! bfd_header_little_endian (templ)) ++ { ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Unrecognized " ++ "little-endian ELF header at address 0x%lx"), ++ (unsigned long) ehdr_vma); ++ return NULL; ++ } ++ break; ++ case ELFDATANONE: /* No data encoding specified */ ++ default: /* Unknown data encoding specified */ ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Unrecognized " ++ "ELF header endianity at address 0x%lx"), ++ (unsigned long) ehdr_vma); ++ return NULL; ++ } ++ ++ elf_swap_ehdr_in (templ, &x_ehdr64, &i_ehdr); ++ ++ /* The file header tells where to find the program headers. ++ These are what we use to actually choose what to read. */ ++ ++ if (i_ehdr.e_phentsize != (bfd_get_arch_size (templ) == 64 ++ ? sizeof (Elf64_External_Phdr) ++ : sizeof (Elf32_External_Phdr)) ++ || i_ehdr.e_phnum == 0) ++ { ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Invalid ELF program headers from the ELF header " ++ "at address 0x%lx"), (unsigned long) ehdr_vma); ++ return NULL; ++ } ++ ++ x_phdrs_size = (bfd_get_arch_size (templ) == 64 ? sizeof (Elf64_External_Phdr) ++ : sizeof (Elf32_External_Phdr)); ++ ++ i_phdrs = xmalloc (i_ehdr.e_phnum * (sizeof *i_phdrs + x_phdrs_size)); ++ x_phdrs_ptr = (void *) &i_phdrs[i_ehdr.e_phnum]; ++ err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs_ptr, ++ i_ehdr.e_phnum * x_phdrs_size); ++ if (err) ++ { ++ free (i_phdrs); ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Error reading " ++ "ELF program headers at address 0x%lx"), ++ (unsigned long) (ehdr_vma + i_ehdr.e_phoff)); ++ return NULL; ++ } ++ ++ loadbase = ehdr_vma; ++ loadbase_set = 0; ++ for (i = 0; i < i_ehdr.e_phnum; ++i) ++ { ++ elf_swap_phdr_in (templ, (Elf64_External_Phdr *) ++ (x_phdrs_ptr + i * x_phdrs_size), &i_phdrs[i]); ++ /* IA-64 vDSO may have two mappings for one segment, where one mapping ++ is executable only, and one is read only. We must not use the ++ executable one (PF_R is the first one, PF_X the second one). */ ++ if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R)) ++ { ++ /* Only the first PT_LOAD segment indicates the file bias. ++ Next segments may have P_VADDR arbitrarily higher. ++ If the first segment has P_VADDR zero any next segment must not ++ confuse us, the first one sets LOADBASE certainly enough. */ ++ if (!loadbase_set && i_phdrs[i].p_offset == 0) ++ { ++ loadbase = ehdr_vma - i_phdrs[i].p_vaddr; ++ loadbase_set = 1; ++ } ++ } ++ } ++ ++ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) ++ warning (_("build-id: Found ELF header at address 0x%lx, loadbase 0x%lx"), ++ (unsigned long) ehdr_vma, (unsigned long) loadbase); ++ ++ *e_phnum_pointer = i_ehdr.e_phnum; ++ *loadbase_pointer = loadbase; ++ return i_phdrs; ++} ++ ++/* BUILD_ID_ADDR_GET gets ADDR located somewhere in the object. ++ Find the first section before ADDR containing an ELF header. ++ We rely on the fact the sections from multiple files do not mix. ++ FIXME: We should check ADDR is contained _inside_ the section with possibly ++ missing content (P_FILESZ < P_MEMSZ). These omitted sections are currently ++ hidden by _BFD_ELF_MAKE_SECTION_FROM_PHDR. */ ++ ++static CORE_ADDR build_id_addr; ++struct build_id_addr_sect ++ { ++ struct build_id_addr_sect *next; ++ asection *sect; ++ }; ++static struct build_id_addr_sect *build_id_addr_sect; ++ ++static void build_id_addr_candidate (bfd *abfd, asection *sect, void *obj) ++{ ++ if (build_id_addr >= bfd_section_vma (abfd, sect)) ++ { ++ struct build_id_addr_sect *candidate; ++ ++ candidate = xmalloc (sizeof *candidate); ++ candidate->next = build_id_addr_sect; ++ build_id_addr_sect = candidate; ++ candidate->sect = sect; ++ } ++} ++ ++struct build_id * ++build_id_addr_get (CORE_ADDR addr) ++{ ++ struct build_id_addr_sect *candidate; ++ struct build_id *retval = NULL; ++ Elf_Internal_Phdr *i_phdr = NULL; ++ bfd_vma loadbase = 0; ++ unsigned e_phnum = 0; ++ ++ if (core_bfd == NULL) ++ return NULL; ++ ++ build_id_addr = addr; ++ gdb_assert (build_id_addr_sect == NULL); ++ bfd_map_over_sections (core_bfd, build_id_addr_candidate, NULL); ++ ++ /* Sections are sorted in the high-to-low VMAs order. ++ Stop the search on the first ELF header we find. ++ Do not continue the search even if it does not contain NT_GNU_BUILD_ID. */ ++ ++ for (candidate = build_id_addr_sect; candidate != NULL; ++ candidate = candidate->next) ++ { ++ i_phdr = elf_get_phdr (core_bfd, ++ bfd_section_vma (core_bfd, candidate->sect), ++ &e_phnum, &loadbase); ++ if (i_phdr != NULL) ++ break; ++ } ++ ++ if (i_phdr != NULL) ++ { ++ retval = build_id_phdr_get (core_bfd, loadbase, e_phnum, i_phdr); ++ xfree (i_phdr); ++ } ++ ++ while (build_id_addr_sect != NULL) ++ { ++ candidate = build_id_addr_sect; ++ build_id_addr_sect = candidate->next; ++ xfree (candidate); ++ } ++ ++ return retval; ++} ++ + /* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value. */ + + static int +@@ -1227,7 +1619,7 @@ build_id_verify (const char *filename, s + if (abfd == NULL) + return 0; + +- found = build_id_bfd_get (abfd); ++ found = build_id_bfd_shdr_get (abfd); + + if (found == NULL) + warning (_("File \"%s\" has no build-id, file skipped"), filename); +@@ -1246,8 +1638,9 @@ build_id_verify (const char *filename, s + return retval; + } + +-static char * +-build_id_to_debug_filename (struct build_id *build_id) ++char * ++build_id_to_filename (struct build_id *build_id, char **link_return, ++ int add_debug_suffix) + { + char *link, *s, *retval = NULL; + gdb_byte *data = build_id->data; +@@ -1255,7 +1648,9 @@ build_id_to_debug_filename (struct build + + /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */ + link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1 +- + 2 * size + (sizeof ".debug" - 1) + 1); ++ + 2 * size ++ + (add_debug_suffix ? sizeof ".debug" - 1 : 0) ++ + 1); + s = link + sprintf (link, "%s/.build-id/", debug_file_directory); + if (size > 0) + { +@@ -1266,12 +1661,14 @@ build_id_to_debug_filename (struct build + *s++ = '/'; + while (size-- > 0) + s += sprintf (s, "%02x", (unsigned) *data++); +- strcpy (s, ".debug"); ++ if (add_debug_suffix) ++ strcpy (s, ".debug"); ++ else ++ *s = 0; + + /* lrealpath() is expensive even for the usually non-existent files. */ + if (access (link, F_OK) == 0) + retval = lrealpath (link); +- xfree (link); + + if (retval != NULL && !build_id_verify (retval, build_id)) + { +@@ -1279,9 +1676,142 @@ build_id_to_debug_filename (struct build + retval = NULL; + } + ++ if (link_return != NULL) ++ *link_return = link; ++ else ++ xfree (link); ++ ++ return retval; ++} ++ ++/* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages ++ Try to install the hash file ... ++ avoidance. */ ++ ++struct missing_filepair ++ { ++ char *binary; ++ char *debug; ++ char data[1]; ++ }; ++ ++static struct htab *missing_filepair_hash; ++static struct obstack missing_filepair_obstack; ++ ++static void * ++missing_filepair_xcalloc (size_t nmemb, size_t nmemb_size) ++{ ++ void *retval; ++ size_t size = nmemb * nmemb_size; ++ ++ retval = obstack_alloc (&missing_filepair_obstack, size); ++ memset (retval, 0, size); + return retval; + } + ++static hashval_t ++missing_filepair_hash_func (const struct missing_filepair *elem) ++{ ++ hashval_t retval = 0; ++ ++ retval ^= htab_hash_string (elem->binary); ++ if (elem->debug != NULL) ++ retval ^= htab_hash_string (elem->debug); ++ ++ return retval; ++} ++ ++static int ++missing_filepair_eq (const struct missing_filepair *elem1, ++ const struct missing_filepair *elem2) ++{ ++ return strcmp (elem1->binary, elem2->binary) == 0 ++ && ((elem1->debug == NULL && elem2->debug == NULL) ++ || strcmp (elem1->debug, elem2->debug) == 0); ++} ++ ++static void ++missing_filepair_change (void) ++{ ++ if (missing_filepair_hash != NULL) ++ { ++ obstack_free (&missing_filepair_obstack, NULL); ++ /* All their memory came just from missing_filepair_OBSTACK. */ ++ missing_filepair_hash = NULL; ++ } ++} ++ ++static void ++debug_print_executable_changed (void) ++{ ++ missing_filepair_change (); ++} ++ ++/* Notify user the file BINARY with (possibly NULL) associated separate debug ++ information file DEBUG is missing. DEBUG may or may not be the build-id ++ file such as would be: ++ /usr/lib/debug/.build-id/dd/b1d2ce632721c47bb9e8679f369e2295ce71be.debug ++ */ ++ ++void ++debug_print_missing (const char *binary, const char *debug) ++{ ++ size_t binary_len0 = strlen (binary) + 1; ++ size_t debug_len0 = debug ? strlen (debug) + 1 : 0; ++ struct missing_filepair *missing_filepair; ++ struct missing_filepair **slot; ++ ++ if (build_id_verbose < BUILD_ID_VERBOSE_FILENAMES) ++ return; ++ ++ if (missing_filepair_hash == NULL) ++ { ++ obstack_init (&missing_filepair_obstack); ++ missing_filepair_hash = htab_create_alloc (64, ++ (hashval_t (*) (const void *)) missing_filepair_hash_func, ++ (int (*) (const void *, const void *)) missing_filepair_eq, NULL, ++ missing_filepair_xcalloc, NULL); ++ } ++ ++ missing_filepair = obstack_alloc (&missing_filepair_obstack, ++ sizeof (*missing_filepair) - 1 ++ + binary_len0 + debug_len0); ++ missing_filepair->binary = missing_filepair->data; ++ memcpy (missing_filepair->binary, binary, binary_len0); ++ if (debug != NULL) ++ { ++ missing_filepair->debug = missing_filepair->binary + binary_len0; ++ memcpy (missing_filepair->debug, debug, debug_len0); ++ } ++ else ++ missing_filepair->debug = NULL; ++ ++ slot = (struct missing_filepair **) htab_find_slot (missing_filepair_hash, ++ missing_filepair, ++ INSERT); ++ ++ /* While it may be still printed duplicitely with the missing debuginfo file ++ * it is due to once printing about the binary file build-id link and once ++ * about the .debug file build-id link as both the build-id symlinks are ++ * located in the debuginfo package. */ ++ ++ if (*slot != NULL) ++ { ++ obstack_free (&missing_filepair_obstack, missing_filepair); ++ return; ++ } ++ *slot = missing_filepair; ++ ++ /* We do not collect and flush these messages as each such message ++ already requires its own separate lines. */ ++ ++ fprintf_unfiltered (gdb_stdlog, ++ _("Missing separate debuginfo for %s\n"), binary); ++ if (debug != NULL) ++ fprintf_unfiltered (gdb_stdlog, _("Try to install the hash file %s\n"), ++ debug); ++} ++ + static char * + get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out) + { +@@ -1364,32 +1894,36 @@ static char * + find_separate_debug_file (struct objfile *objfile) + { + asection *sect; +- char *basename; +- char *dir; +- char *debugfile; ++ char *basename = NULL; ++ char *dir = NULL; ++ char *debugfile = NULL; + char *name_copy; +- char *canon_name; ++ char *canon_name = NULL; + bfd_size_type debuglink_size; + unsigned long crc32; + int i; + struct build_id *build_id; ++ char *build_id_filename = NULL; + +- build_id = build_id_bfd_get (objfile->obfd); ++ build_id = build_id_bfd_shdr_get (objfile->obfd); + if (build_id != NULL) + { + char *build_id_name; + +- build_id_name = build_id_to_debug_filename (build_id); ++ build_id_name = build_id_to_filename (build_id, &build_id_filename, 1); + xfree (build_id); + /* Prevent looping on a stripped .debug file. */ + if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0) + { +- warning (_("\"%s\": separate debug info file has no debug info"), ++ warning (_("\"%s\": The separate debug info file has no debug info"), + build_id_name); + xfree (build_id_name); + } + else if (build_id_name != NULL) +- return build_id_name; ++ { ++ xfree (build_id_filename); ++ return build_id_name; ++ } + } + + basename = get_debug_link_info (objfile, &crc32); +@@ -1397,7 +1931,7 @@ find_separate_debug_file (struct objfile + if (basename == NULL) + /* There's no separate debug info, hence there's no way we could + load it => no warning. */ +- return NULL; ++ goto cleanup_return_debugfile; + + dir = xstrdup (objfile->name); + +@@ -1413,23 +1947,19 @@ find_separate_debug_file (struct objfile + gdb_assert (i >= 0 && IS_DIR_SEPARATOR (dir[i])); + dir[i+1] = '\0'; + +- debugfile = alloca (strlen (debug_file_directory) + 1 +- + strlen (dir) +- + strlen (DEBUG_SUBDIRECTORY) +- + strlen ("/") +- + strlen (basename) +- + 1); ++ debugfile = xmalloc (strlen (debug_file_directory) + 1 ++ + strlen (dir) ++ + strlen (DEBUG_SUBDIRECTORY) ++ + strlen ("/") ++ + strlen (basename) ++ + 1); + + /* First try in the same directory as the original file. */ + strcpy (debugfile, dir); + strcat (debugfile, basename); + + if (separate_debug_file_exists (debugfile, crc32, objfile->name)) +- { +- xfree (basename); +- xfree (dir); +- return xstrdup (debugfile); +- } ++ goto cleanup_return_debugfile; + + /* Then try in the subdirectory named DEBUG_SUBDIRECTORY. */ + strcpy (debugfile, dir); +@@ -1438,11 +1968,7 @@ find_separate_debug_file (struct objfile + strcat (debugfile, basename); + + if (separate_debug_file_exists (debugfile, crc32, objfile->name)) +- { +- xfree (basename); +- xfree (dir); +- return xstrdup (debugfile); +- } ++ goto cleanup_return_debugfile; + + /* Then try in the global debugfile directory. */ + strcpy (debugfile, debug_file_directory); +@@ -1451,11 +1977,7 @@ find_separate_debug_file (struct objfile + strcat (debugfile, basename); + + if (separate_debug_file_exists (debugfile, crc32, objfile->name)) +- { +- xfree (basename); +- xfree (dir); +- return xstrdup (debugfile); +- } ++ goto cleanup_return_debugfile; + + /* If the file is in the sysroot, try using its base path in the + global debugfile directory. */ +@@ -1470,20 +1992,18 @@ find_separate_debug_file (struct objfile + strcat (debugfile, basename); + + if (separate_debug_file_exists (debugfile, crc32, objfile->name)) +- { +- xfree (canon_name); +- xfree (basename); +- xfree (dir); +- return xstrdup (debugfile); +- } ++ goto cleanup_return_debugfile; + } +- +- if (canon_name) +- xfree (canon_name); + ++ debugfile = NULL; ++ debug_print_missing (objfile->name, build_id_filename); ++ ++cleanup_return_debugfile: ++ xfree (build_id_filename); ++ xfree (canon_name); + xfree (basename); + xfree (dir); +- return NULL; ++ return debugfile; + } + + +@@ -4216,4 +4736,16 @@ Show printing of symbol loading messages + NULL, + NULL, + &setprintlist, &showprintlist); ++ ++ add_setshow_zinteger_cmd ("build-id-verbose", no_class, &build_id_verbose, ++ _("\ ++Set debugging level of the build-id locator."), _("\ ++Show debugging level of the build-id locator."), _("\ ++Level 1 (default) enables printing the missing debug filenames,\n\ ++level 2 also prints the parsing of binaries to find the identificators."), ++ NULL, ++ show_build_id_verbose, ++ &setlist, &showlist); ++ ++ observer_attach_executable_changed (debug_print_executable_changed); + } +Index: gdb-6.8.50.20090302/gdb/symfile.h +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/symfile.h 2009-03-07 17:04:52.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/symfile.h 2009-03-07 17:13:33.000000000 +0100 +@@ -372,6 +372,13 @@ extern int symfile_map_offsets_to_segmen + struct symfile_segment_data *get_symfile_segment_data (bfd *abfd); + void free_symfile_segment_data (struct symfile_segment_data *data); + ++/* build-id support. */ ++struct build_id; ++extern struct build_id *build_id_addr_get (CORE_ADDR addr); ++extern char *build_id_to_filename (struct build_id *build_id, ++ char **link_return, int add_debug_suffix); ++extern void debug_print_missing (const char *binary, const char *debug); ++ + /* From dwarf2read.c */ + + extern int dwarf2_has_info (struct objfile *); +Index: gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/testsuite/lib/gdb.exp 2009-03-07 17:04:52.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp 2009-03-07 17:13:33.000000000 +0100 +@@ -1230,6 +1230,16 @@ proc default_gdb_start { } { + warning "Couldn't set the width to 0." + } + } ++ # Turn off the missing warnings as the testsuite does not expect it. ++ send_gdb "set build-id-verbose 0\n" ++ gdb_expect 10 { ++ -re "$gdb_prompt $" { ++ verbose "Disabled the missing debug infos warnings." 2 ++ } ++ timeout { ++ warning "Could not disable the missing debug infos warnings.." ++ } ++ } + return 0; + } + +--- ./gdb/testsuite/lib/mi-support.exp 2009-03-21 21:09:09.000000000 +0100 ++++ ./gdb/testsuite/lib/mi-support.exp 2009-03-22 16:37:58.000000000 +0100 +@@ -221,6 +221,16 @@ proc default_mi_gdb_start { args } { + } + } + } ++ # Turn off the missing warnings as the testsuite does not expect it. ++ send_gdb "190-gdb-set build-id-verbose 0\n" ++ gdb_expect 10 { ++ -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" { ++ verbose "Disabled the missing debug infos warnings." 2 ++ } ++ timeout { ++ warning "Could not disable the missing debug infos warnings.." ++ } ++ } + + detect_async + diff --git a/gdb-6.6-bz225783-gdb-debuginfo-paths.patch b/gdb-6.6-bz225783-gdb-debuginfo-paths.patch new file mode 100644 index 0000000..4274109 --- /dev/null +++ b/gdb-6.6-bz225783-gdb-debuginfo-paths.patch @@ -0,0 +1,33 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=225783 + + +Index: gdb-6.8.50.20081128/gdb/Makefile.in +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/Makefile.in 2008-12-02 23:06:16.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/Makefile.in 2008-12-02 23:28:02.000000000 +0100 +@@ -1490,8 +1490,10 @@ po/$(PACKAGE).pot: force + + .SUFFIXES: .y .l + .y.c: +- $(SHELL) $(YLWRAP) $< y.tab.c $@.tmp -- $(YACC) $(YFLAGS) +- -sed -e '/extern.*malloc/d' \ ++ rm -f $@ $@.tmp ++ $(SHELL) $(YLWRAP) $< y.tab.c $@ -- $(YACC) $(YFLAGS) && mv $@ $@.tmp \ ++ || (rm -f $@; false) ++ sed -e '/extern.*malloc/d' \ + -e '/extern.*realloc/d' \ + -e '/extern.*free/d' \ + -e '/include.*malloc.h/d' \ +@@ -1500,9 +1502,9 @@ po/$(PACKAGE).pot: force + -e 's/\([ \t;,(]\)free\([ \t]*[&(),]\)/\1xfree\2/g' \ + -e 's/\([ \t;,(]\)free$$/\1xfree/g' \ + -e '/^#line.*y.tab.c/d' \ +- < $@.tmp > $@.new +- -rm $@.tmp +- mv $@.new ./$*.c ++ -e "s/^\(#line.*\)`basename $<`/\1`echo $<|sed 's/\//\\\\\//g'`/" \ ++ < $@.tmp > $@ ++ rm -f $@.tmp + .l.c: + if [ "$(FLEX)" ] && $(FLEX) --version >/dev/null 2>&1; then \ + $(FLEX) -o$@ $< && \ diff --git a/gdb-6.6-bz225783-prelink-path.patch b/gdb-6.6-bz225783-prelink-path.patch new file mode 100644 index 0000000..c792209 --- /dev/null +++ b/gdb-6.6-bz225783-prelink-path.patch @@ -0,0 +1,27 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=225783 + +--- gdb-6.8/gdb/testsuite/gdb.base/prelink.exp.orig 2008-07-12 08:56:43.000000000 +0200 ++++ gdb-6.8/gdb/testsuite/gdb.base/prelink.exp 2008-07-12 08:59:59.000000000 +0200 +@@ -55,7 +55,7 @@ if { [gdb_compile "${srcdir}/${subdir}/$ + # single new unprelinked library address without wasting the first one/two + # memory areas. We do not care of the efficiency of loading such resulting + # exec-shield unfriendly prelinked library. +-if {[catch "system \"prelink -qNR --no-exec-shield ${libfile}\""] != 0} { ++if {[catch "system \"/usr/sbin/prelink -qNR --no-exec-shield ${libfile}\""] != 0} { + # Maybe we don't have prelink. + return -1 + } +@@ -96,11 +96,11 @@ if { $found == 0 } { + return 0 + } + +-if {[catch "system \"prelink -uN ${libfile}\""] != 0} { ++if {[catch "system \"/usr/sbin/prelink -uN ${libfile}\""] != 0} { + untested "${testfile}.so was not prelinked, maybe system libraries are not prelinked?" + return 0 + } +-catch "system \"prelink -qNR --no-exec-shield ${libfile}\"" ++catch "system \"/usr/sbin/prelink -qNR --no-exec-shield ${libfile}\"" + + # Start with a fresh gdb + diff --git a/gdb-6.6-bz229517-gcore-without-terminal.patch b/gdb-6.6-bz229517-gcore-without-terminal.patch new file mode 100644 index 0000000..129f1b5 --- /dev/null +++ b/gdb-6.6-bz229517-gcore-without-terminal.patch @@ -0,0 +1,191 @@ +2007-04-22 Jan Kratochvil + + * gdb_gcore.sh: Redirect GDB from ` + + * gdb.base/gcorebg.exp, gdb.base/gcorebg.c: New files. + + +--- gdb-6.6-orig/gdb/gdb_gcore.sh 2005-12-17 17:33:59.000000000 -0500 ++++ gdb-6.6/gdb/gdb_gcore.sh 2007-04-22 05:42:50.000000000 -0400 +@@ -71,7 +71,9 @@ + quit + EOF + +- gdb -x $tmpfile -batch ++ # ` ++#include ++#include ++#include ++#include ++ ++int main (int argc, char **argv) ++{ ++ pid_t pid = 0; ++ pid_t ppid; ++ char buf[256]; ++ ++ if (argc != 4) ++ { ++ fprintf (stderr, "Syntax: %s {standard|detached} \n", ++ argv[0]); ++ exit (1); ++ } ++ ++ pid = fork (); ++ ++ switch (pid) ++ { ++ case 0: ++ if (strcmp (argv[1], "detached") == 0) ++ setpgrp (); ++ ppid = getppid (); ++ sprintf (buf, "sh %s -o %s %d", argv[2], argv[3], (int) ppid); ++ system (buf); ++ kill (ppid, SIGTERM); ++ break; ++ ++ case -1: ++ perror ("fork err\n"); ++ exit (1); ++ break; ++ ++ default: ++ sleep (60); ++ } ++ ++ return 0; ++} +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/gcorebg.exp 25 Feb 2007 12:21:20 -0000 +@@ -0,0 +1,120 @@ ++# Copyright 2007 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 Jan Kratochvil . ++# This is a test for `gdb_gcore.sh' functionality. ++# It also tests a regression with `gdb_gcore.sh' being run without its ++# accessible terminal. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++if ![info exists GCORE] { ++ set GCORE "${srcdir}/../gdb_gcore.sh" ++} ++verbose "using GCORE = $GCORE" 2 ++ ++set testfile "gcorebg" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++set corefile ${objdir}/${subdir}/${testfile}.test ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested gcorebg.exp ++ return -1 ++} ++ ++# Cleanup. ++ ++proc core_clean {} { ++ global corefile ++ ++ foreach file [glob -nocomplain [join [list $corefile *] ""]] { ++ verbose "Delete file $file" 1 ++ remote_file target delete $file ++ } ++} ++core_clean ++remote_file target delete "./gdb" ++ ++# Generate the core file. ++ ++# Provide `./gdb' for `gdb_gcore.sh' running it as a bare `gdb' command. ++# Setup also `$PATH' appropriately. ++# If GDB was not found let `gdb_gcore.sh' to find the system GDB by `$PATH'. ++if {$GDB != "gdb"} { ++ file link ./gdb $GDB ++} ++global env ++set oldpath $env(PATH) ++set env(PATH) [join [list . $env(PATH)] ":"] ++verbose "PATH = $env(PATH)" 2 ++ ++# Test file body. ++# $detached == "standard" || $detached == "detached" ++ ++proc test_body { detached } { ++ global binfile ++ global GCORE ++ global corefile ++ ++ set res [remote_spawn target "$binfile $detached $GCORE $corefile"] ++ if { $res < 0 || $res == "" } { ++ fail "Spawning $detached gcore" ++ return 1 ++ } ++ pass "Spawning $detached gcore" ++ remote_expect target 20 { ++ timeout { ++ fail "Spawned $detached gcore finished" ++ remote_exec target "kill -9 -[exp_pid -i $res]" ++ return 1 ++ } ++ eof { ++ pass "Spawned $detached gcore finished" ++ remote_wait target 20 ++ } ++ } ++ ++ if {1 == [llength [glob -nocomplain [join [list $corefile *] ""]]]} { ++ pass "Core file generated by $detached gcore" ++ } else { ++ fail "Core file generated by $detached gcore" ++ } ++ core_clean ++} ++ ++# First a general `gdb_gcore.sh' spawn with its controlling terminal available. ++ ++test_body standard ++ ++# And now `gdb_gcore.sh' spawn without its controlling terminal available. ++# It is spawned through `gcorebg.c' using setpgrp (). ++ ++test_body detached ++ ++ ++# Cleanup. ++ ++set env(PATH) $oldpath ++remote_file target delete "./gdb" diff --git a/gdb-6.6-bz230000-power6-disassembly-test.patch b/gdb-6.6-bz230000-power6-disassembly-test.patch new file mode 100644 index 0000000..b81c63f --- /dev/null +++ b/gdb-6.6-bz230000-power6-disassembly-test.patch @@ -0,0 +1,83 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=230000 + +The original testcase + https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=230000#c1 +requires too recent GCC. + + +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/powerpc-power6.exp 25 Feb 2007 18:27:39 -0000 +@@ -0,0 +1,54 @@ ++# Copyright 2007 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. ++ ++# Test PowerPC Power6 instructions disassembly. ++ ++if {![istarget "powerpc*-*-*"]} then { ++ verbose "Skipping PowerPC Power6 instructions disassembly." ++ return ++} ++ ++set testfile "powerpc-power6" ++set srcfile ${testfile}.s ++set objfile ${objdir}/${subdir}/${testfile}.o ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}] != "" } { ++ untested "PowerPC prologue tests" ++ return -1 ++} ++ ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${objfile} ++ ++# Disassemble the function. ++ ++gdb_test "disass func" ":\tblr\r\n.*" "Basic disassembly" ++ ++gdb_test "disass func" ":\tdcbzl *r8,r9\r\n.*" "Power5 disassembly dcbzl" ++gdb_test "disass func" ":\tfrsqrtes *f10,f11\r\n.*" "Power5 disassembly frsqrtes" ++gdb_test "disass func" ":\tdadd *f1,f2,f1\r\n.*" "Power6 disassembly dadd" ++gdb_test "disass func" ":\tdaddq *f1,f2,f1\r\n.*" "Power6 disassembly daddq" ++gdb_test "disass func" ":\tdsub *f1,f2,f1\r\n.*" "Power6 disassembly dsub" ++gdb_test "disass func" ":\tdsubq *f1,f2,f1\r\n.*" "Power6 disassembly dsubq" ++gdb_test "disass func" ":\tdmul *f1,f2,f1\r\n.*" "Power6 disassembly dmul" ++gdb_test "disass func" ":\tdmulq *f1,f2,f1\r\n.*" "Power6 disassembly dmulq" ++gdb_test "disass func" ":\tddiv *f1,f2,f1\r\n.*" "Power6 disassembly ddiv" ++gdb_test "disass func" ":\tddivq *f1,f2,f1\r\n.*" "Power6 disassembly ddivq" ++gdb_test "disass func" ":\tdcmpu *cr1,f2,f1\r\n.*" "Power6 disassembly dcmpu" ++gdb_test "disass func" ":\tdcmpuq *cr1,f2,f1\r\n.*" "Power6 disassembly dcmpuq" +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/powerpc-power6.s 25 Feb 2007 18:27:39 -0000 +@@ -0,0 +1,16 @@ ++ .text ++ .globl func ++func: ++ blr ++ .long 0x7c284fec /* dcbzl r8,r9 */ ++ .long 0xed405834 /* frsqrtes f10,f11 */ ++ .long 0xec220804 /* dadd f1,f2,f1 */ ++ .long 0xfc220804 /* daddq f1,f2,f1 */ ++ .long 0xec220c04 /* dsub f1,f2,f1 */ ++ .long 0xfc220c04 /* dsubq f1,f2,f1 */ ++ .long 0xec220844 /* dmul f1,f2,f1 */ ++ .long 0xfc220844 /* dmulq f1,f2,f1 */ ++ .long 0xec220c44 /* ddiv f1,f2,f1 */ ++ .long 0xfc220c44 /* ddivq f1,f2,f1 */ ++ .long 0xec820d04 /* dcmpu cr1,f2,f1 */ ++ .long 0xfc820d04 /* dcmpuq cr1,f2,f1 */ diff --git a/gdb-6.6-bz235197-fork-detach-info.patch b/gdb-6.6-bz235197-fork-detach-info.patch new file mode 100644 index 0000000..311b8a3 --- /dev/null +++ b/gdb-6.6-bz235197-fork-detach-info.patch @@ -0,0 +1,128 @@ +2008-03-01 Jan Kratochvil + + Port to GDB-6.8pre. + Remove the `[' character from the GDB-6.8 default message. + +Index: gdb-6.7.50.20080227/gdb/linux-nat.c +=================================================================== +--- gdb-6.7.50.20080227.orig/gdb/linux-nat.c 2008-03-01 10:30:48.000000000 +0100 ++++ gdb-6.7.50.20080227/gdb/linux-nat.c 2008-03-01 10:48:25.000000000 +0100 +@@ -415,7 +415,7 @@ linux_child_follow_fork (struct target_o + /* Detach new forked process? */ + if (detach_fork) + { +- if (info_verbose || debug_linux_nat) ++ if (1 /* Fedora Bug 235197 */ || info_verbose || debug_linux_nat) + { + target_terminal_ours (); + fprintf_filtered (gdb_stdlog, +Index: gdb-6.7.50.20080227/gdb/testsuite/gdb.base/fork-detach.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.7.50.20080227/gdb/testsuite/gdb.base/fork-detach.c 2008-03-01 10:30:49.000000000 +0100 +@@ -0,0 +1,57 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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 */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void func (void) ++{ ++} ++ ++int main (void) ++{ ++ pid_t child; ++ ++ child = fork (); ++ switch (child) ++ { ++ case -1: ++ abort (); ++ case 0: ++ func (); ++ break; ++ default: ++ { ++/* We do not test the switching to the other fork by GDB `fork 1'. */ ++#if 0 ++ pid_t got; ++ ++ got = waitpid (child, NULL, 0); ++ assert (got == child); ++#endif ++ break; ++ } ++ } ++ return 0; ++} +Index: gdb-6.7.50.20080227/gdb/testsuite/gdb.base/fork-detach.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.7.50.20080227/gdb/testsuite/gdb.base/fork-detach.exp 2008-03-01 10:49:36.000000000 +0100 +@@ -0,0 +1,43 @@ ++# Copyright 2007 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile fork-detach ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_run_cmd ++# `Starting program: .*' prefix is available since gdb-6.7. ++gdb_test "" \ ++ "Detaching after fork from child process.*Program exited normally\\..*" \ ++ "Info message caught" diff --git a/gdb-6.6-bz237572-ppc-atomic-sequence-test.patch b/gdb-6.6-bz237572-ppc-atomic-sequence-test.patch new file mode 100644 index 0000000..bc86662 --- /dev/null +++ b/gdb-6.6-bz237572-ppc-atomic-sequence-test.patch @@ -0,0 +1,270 @@ +2007-06-25 Jan Kratochvil + + * gdb.threads/atomic-seq-threaded.c, + gdb.threads/atomic-seq-threaded.exp: New files. + +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.c 2008-12-08 22:27:01.000000000 +0100 +@@ -0,0 +1,171 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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., 51 Franklin Street, Fifth Floor, Boston, ++ MA 02110-1301, USA. */ ++ ++/* Test stepping over RISC atomic sequences. ++ This variant testcases the code for stepping another thread while skipping ++ over the atomic sequence in the former thread ++ (STEPPING_PAST_SINGLESTEP_BREAKPOINT). ++ Code comes from gcc/testsuite/gcc.dg/sync-2.c */ ++ ++/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ ++/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */ ++ ++/* Test functionality of the intrinsics for 'short' and 'char'. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define LOOPS 2 ++ ++static int unused; ++ ++static char AI[18]; ++static char init_qi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 }; ++static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 }; ++ ++static void ++do_qi (void) ++{ ++ if (__sync_fetch_and_add(AI+4, 1) != 0) ++ abort (); ++ if (__sync_fetch_and_add(AI+5, 4) != 0) ++ abort (); ++ if (__sync_fetch_and_add(AI+6, 22) != 0) ++ abort (); ++ if (__sync_fetch_and_sub(AI+7, 12) != 0) ++ abort (); ++ if (__sync_fetch_and_and(AI+8, 7) != (char)-1) ++ abort (); ++ if (__sync_fetch_and_or(AI+9, 8) != 0) ++ abort (); ++ if (__sync_fetch_and_xor(AI+10, 9) != 0) ++ abort (); ++ if (__sync_fetch_and_nand(AI+11, 7) != 0) ++ abort (); ++ ++ if (__sync_add_and_fetch(AI+12, 1) != 1) ++ abort (); ++ if (__sync_sub_and_fetch(AI+13, 12) != (char)-12) ++ abort (); ++ if (__sync_and_and_fetch(AI+14, 7) != 7) ++ abort (); ++ if (__sync_or_and_fetch(AI+15, 8) != 8) ++ abort (); ++ if (__sync_xor_and_fetch(AI+16, 9) != 9) ++ abort (); ++ if (__sync_nand_and_fetch(AI+17, 7) != 7) ++ abort (); ++} ++ ++static short AL[18]; ++static short init_hi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 }; ++static short test_hi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 }; ++ ++static void ++do_hi (void) ++{ ++ if (__sync_fetch_and_add(AL+4, 1) != 0) ++ abort (); ++ if (__sync_fetch_and_add(AL+5, 4) != 0) ++ abort (); ++ if (__sync_fetch_and_add(AL+6, 22) != 0) ++ abort (); ++ if (__sync_fetch_and_sub(AL+7, 12) != 0) ++ abort (); ++ if (__sync_fetch_and_and(AL+8, 7) != -1) ++ abort (); ++ if (__sync_fetch_and_or(AL+9, 8) != 0) ++ abort (); ++ if (__sync_fetch_and_xor(AL+10, 9) != 0) ++ abort (); ++ if (__sync_fetch_and_nand(AL+11, 7) != 0) ++ abort (); ++ ++ if (__sync_add_and_fetch(AL+12, 1) != 1) ++ abort (); ++ if (__sync_sub_and_fetch(AL+13, 12) != -12) ++ abort (); ++ if (__sync_and_and_fetch(AL+14, 7) != 7) ++ abort (); ++ if (__sync_or_and_fetch(AL+15, 8) != 8) ++ abort (); ++ if (__sync_xor_and_fetch(AL+16, 9) != 9) ++ abort (); ++ if (__sync_nand_and_fetch(AL+17, 7) != 7) ++ abort (); ++} ++ ++static void * ++start1 (void *arg) ++{ ++ unsigned loop; ++ sleep(1); ++ ++ for (loop = 0; loop < LOOPS; loop++) ++ { ++ memcpy(AI, init_qi, sizeof(init_qi)); ++ ++ do_qi (); ++ ++ if (memcmp (AI, test_qi, sizeof(test_qi))) ++ abort (); ++ } ++ ++ return arg; /* _delete1_ */ ++} ++ ++static void * ++start2 (void *arg) ++{ ++ unsigned loop; ++ ++ for (loop = 0; loop < LOOPS; loop++) ++ { ++ memcpy(AL, init_hi, sizeof(init_hi)); ++ ++ do_hi (); ++ ++ if (memcmp (AL, test_hi, sizeof(test_hi))) ++ abort (); ++ } ++ ++ return arg; /* _delete2_ */ ++} ++ ++int ++main (int argc, char **argv) ++{ ++ pthread_t thread; ++ int i; ++ ++ i = pthread_create (&thread, NULL, start1, NULL); /* _create_ */ ++ assert (i == 0); /* _create_after_ */ ++ ++ sleep (1); ++ ++ start2 (NULL); ++ ++ i = pthread_join (thread, NULL); /* _delete_ */ ++ assert (i == 0); ++ ++ return 0; /* _exit_ */ ++} +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.exp 2008-12-08 22:31:01.000000000 +0100 +@@ -0,0 +1,84 @@ ++# atomic-seq-threaded.exp -- Test case for stepping over RISC atomic code seqs. ++# This variant testcases the code for stepping another thread while skipping ++# over the atomic sequence in the former thread ++# (STEPPING_PAST_SINGLESTEP_BREAKPOINT). ++# Copyright (C) 2007 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 ++ ++set testfile atomic-seq-threaded ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++foreach opts {{} {compiler=gcc4} {FAIL}} { ++ if {$opts eq "FAIL"} { ++ return -1 ++ } ++ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $opts]] eq "" } { ++ break ++ } ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++ ++gdb_load ${binfile} ++if ![runto_main] then { ++ fail "Can't run to main" ++ return 0 ++} ++ ++# pthread_create () will not pass even on x86_64 with software watchpoint. ++# Pass after pthread_create () without any watchpoint active. ++set line [gdb_get_line_number "_create_after_"] ++gdb_test "tbreak $line" \ ++ "reakpoint (\[0-9\]+) at .*$srcfile, line $line\..*" \ ++ "set breakpoint after pthread_create ()" ++gdb_test "c" \ ++ ".*/\\* _create_after_ \\*/.*" \ ++ "run till after pthread_create ()" ++ ++# Without a watchpoint being software no single-stepping would be used. ++set test "Start (software) watchpoint" ++gdb_test_multiple "watch unused" $test { ++ -re "Watchpoint \[0-9\]+: unused.*$gdb_prompt $" { ++ pass $test ++ } ++ -re "Hardware watchpoint \[0-9\]+: unused.*$gdb_prompt $" { ++ # We do not test the goal but still the whole testcase should pass. ++ unsupported $test ++ } ++} ++ ++# More thorough testing of the scheduling logic. ++gdb_test "set scheduler-locking step" "" ++ ++# Critical code path is stepped through at this point. ++set line [gdb_get_line_number "_exit_"] ++gdb_test "tbreak $line" \ ++ "reakpoint \[0-9\]+ at .*$srcfile, line $line\..*" \ ++ "set breakpoint at _exit_" ++gdb_test "c" \ ++ ".*/\\* _exit_ \\*/.*" \ ++ "run till _exit_" ++ ++# Just a nonproblematic program exit. ++gdb_test "c" \ ++ ".*Program exited normally\\..*" \ ++ "run till program exit" diff --git a/gdb-6.6-bz247354-leader-exit-fix.patch b/gdb-6.6-bz247354-leader-exit-fix.patch new file mode 100644 index 0000000..26b3661 --- /dev/null +++ b/gdb-6.6-bz247354-leader-exit-fix.patch @@ -0,0 +1,142 @@ +2007-07-08 Jan Kratochvil + + * linux-nat.c (linux_lwp_is_zombie): New function. + (wait_lwp): Fix lockup on exit of the thread group leader. + (linux_xfer_partial): Renamed to ... + (linux_xfer_partial_lwp): ... here. + (linux_xfer_partial): New function wrapping LINUX_XFER_PARTIAL_LWP. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +Index: gdb-6.8.50.20081209/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/linux-nat.c 2008-12-10 01:27:34.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/linux-nat.c 2008-12-10 01:28:14.000000000 +0100 +@@ -1981,6 +1981,31 @@ linux_handle_extended_wait (struct lwp_i + _("unknown ptrace event %d"), event); + } + ++static int ++linux_lwp_is_zombie (long lwp) ++{ ++ char buffer[MAXPATHLEN]; ++ FILE *procfile; ++ int retval = 0; ++ ++ sprintf (buffer, "/proc/%ld/status", lwp); ++ procfile = fopen (buffer, "r"); ++ if (procfile == NULL) ++ { ++ warning (_("unable to open /proc file '%s'"), buffer); ++ return 0; ++ } ++ while (fgets (buffer, sizeof (buffer), procfile) != NULL) ++ if (strcmp (buffer, "State:\tZ (zombie)\n") == 0) ++ { ++ retval = 1; ++ break; ++ } ++ fclose (procfile); ++ ++ return retval; ++} ++ + /* Wait for LP to stop. Returns the wait status, or 0 if the LWP has + exited. */ + +@@ -1988,16 +2013,31 @@ static int + wait_lwp (struct lwp_info *lp) + { + pid_t pid; +- int status; ++ int status = 0; + int thread_dead = 0; + + gdb_assert (!lp->stopped); + gdb_assert (lp->status == 0); + +- pid = my_waitpid (GET_LWP (lp->ptid), &status, 0); +- if (pid == -1 && errno == ECHILD) ++ /* Thread group leader may have exited but we would lock up by WAITPID as it ++ waits on all its threads; __WCLONE is not applicable for the leader. ++ The thread leader restrictions is only a performance optimization here. ++ LINUX_NAT_THREAD_ALIVE cannot be used here as it requires a STOPPED ++ process; it gets ESRCH both for the zombie and for running processes. */ ++ if (is_lwp (lp->ptid) && GET_PID (lp->ptid) == GET_LWP (lp->ptid) ++ && linux_lwp_is_zombie (GET_LWP (lp->ptid))) ++ { ++ thread_dead = 1; ++ if (debug_linux_nat) ++ fprintf_unfiltered (gdb_stdlog, "WL: Threads leader %s vanished.\n", ++ target_pid_to_str (lp->ptid)); ++ } ++ ++ if (!thread_dead) + { +- pid = my_waitpid (GET_LWP (lp->ptid), &status, __WCLONE); ++ pid = my_waitpid (GET_LWP (lp->ptid), &status, 0); ++ if (pid == -1 && errno == ECHILD) ++ pid = my_waitpid (GET_LWP (lp->ptid), &status, __WCLONE); + if (pid == -1 && errno == ECHILD) + { + /* The thread has previously exited. We need to delete it +@@ -4153,8 +4193,10 @@ linux_nat_xfer_osdata (struct target_ops + return len; + } + ++/* Transfer from the specific LWP currently set by PID of INFERIOR_PTID. */ ++ + static LONGEST +-linux_xfer_partial (struct target_ops *ops, enum target_object object, ++linux_xfer_partial_lwp (struct target_ops *ops, enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, LONGEST len) + { +@@ -4201,6 +4243,45 @@ linux_xfer_partial (struct target_ops *o + offset, len); + } + ++/* nptl_db expects being able to transfer memory just by specifying PID. ++ After the thread group leader exists the Linux kernel turns the task ++ into zombie no longer permitting accesses to its memory. ++ Transfer the memory from an arbitrary LWP_LIST entry in such case. */ ++ ++static LONGEST ++linux_xfer_partial (struct target_ops *ops, enum target_object object, ++ const char *annex, gdb_byte *readbuf, ++ const gdb_byte *writebuf, ULONGEST offset, LONGEST len) ++{ ++ LONGEST xfer; ++ struct lwp_info *lp; ++ /* Not using SAVE_INFERIOR_PTID already here for better performance. */ ++ struct cleanup *old_chain = NULL; ++ ptid_t inferior_ptid_orig = inferior_ptid; ++ ++ errno = 0; ++ xfer = linux_xfer_partial_lwp (ops, object, annex, readbuf, writebuf, ++ offset, len); ++ ++ for (lp = lwp_list; xfer == 0 && (errno == EACCES || errno == ESRCH) ++ && lp != NULL; lp = lp->next) ++ { ++ if (!is_lwp (lp->ptid) || ptid_equal (lp->ptid, inferior_ptid_orig)) ++ continue; ++ ++ if (old_chain == NULL) ++ old_chain = save_inferior_ptid (); ++ inferior_ptid = BUILD_LWP (GET_LWP (lp->ptid), GET_LWP (lp->ptid)); ++ errno = 0; ++ xfer = linux_xfer_partial_lwp (ops, object, annex, readbuf, writebuf, ++ offset, len); ++ } ++ ++ if (old_chain != NULL) ++ do_cleanups (old_chain); ++ return xfer; ++} ++ + /* Create a prototype generic GNU/Linux target. The client can override + it with local methods. */ + diff --git a/gdb-6.6-bz247354-leader-exit-test.patch b/gdb-6.6-bz247354-leader-exit-test.patch new file mode 100644 index 0000000..4b5d415 --- /dev/null +++ b/gdb-6.6-bz247354-leader-exit-test.patch @@ -0,0 +1,121 @@ +2007-07-07 Jan Kratochvil + + * gdb.threads/leader-exit.c, gdb.threads/leader-exit.exp: New files. + +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/leader-exit.c 7 Jul 2007 15:21:57 -0000 +@@ -0,0 +1,47 @@ ++/* Clean exit of the thread group leader should not break GDB. ++ ++ Copyright 2007 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. */ ++ ++#include ++#include ++#include ++ ++static void *start (void *arg) ++{ ++ for (;;) ++ pause (); ++ /* NOTREACHED */ ++ assert (0); ++ return arg; ++} ++ ++int main (void) ++{ ++ pthread_t thread; ++ int i; ++ ++ i = pthread_create (&thread, NULL, start, NULL); /* create1 */ ++ assert (i == 0); ++ ++ pthread_exit (NULL); ++ /* NOTREACHED */ ++ assert (0); ++ return 0; ++} +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/leader-exit.exp 7 Jul 2007 15:21:57 -0000 +@@ -0,0 +1,64 @@ ++# Copyright (C) 2007 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. ++ ++# Exit of the thread group leader should not break GDB. ++ ++# This file was written by Jan Kratochvil . ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile "leader-exit" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++gdb_run_cmd ++ ++proc stop_process { description } { ++ global gdb_prompt ++ ++ # For this to work we must be sure to consume the "Continuing." ++ # message first, or GDB's signal handler may not be in place. ++ after 1000 {send_gdb "\003"} ++ gdb_expect { ++ -re "Program received signal SIGINT.*$gdb_prompt $" ++ { ++ pass $description ++ } ++ timeout ++ { ++ fail "$description (timeout)" ++ } ++ } ++} ++ ++# Prevent races. ++sleep 8 ++ ++stop_process "Threads could be stopped" ++ ++gdb_test "info threads" \ ++ "\\* 2 Thread \[^\r\n\]* in \[^\r\n\]*" \ ++ "Single thread has been left" diff --git a/gdb-6.6-gcore32-test.patch b/gdb-6.6-gcore32-test.patch new file mode 100644 index 0000000..733a166 --- /dev/null +++ b/gdb-6.6-gcore32-test.patch @@ -0,0 +1,216 @@ +Test GCORE on 32bit inferiors on 64bit platforms. + +UNSUPPORTED results are valid for `-m64' on 32bit targets. + + +Index: gdb-6.8/gdb/testsuite/gdb.base/gcore.exp +=================================================================== +--- gdb-6.8.orig/gdb/testsuite/gdb.base/gcore.exp 2008-01-01 23:53:19.000000000 +0100 ++++ gdb-6.8/gdb/testsuite/gdb.base/gcore.exp 2008-07-14 10:28:05.000000000 +0200 +@@ -30,9 +30,14 @@ set testfile "gcore" + set srcfile ${testfile}.c + set binfile ${objdir}/${subdir}/${testfile} + +-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { +- untested gcore.exp +- return -1 ++# `-static-libgcc' to avoid dependency on `libgcc.{i386,ppc}'. ++foreach additional_flags {{} {-m32 -static-libgcc} {-m64 -static-libgcc}} { ++ ++set prefix "arch{$additional_flags}:" ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug additional_flags=$additional_flags]] != "" } { ++ unsupported "${prefix} gcore.exp" ++ continue + } + + # Start with a fresh gdb. +@@ -47,23 +52,23 @@ send_gdb "help gcore\n" + gdb_expect { + -re "Undefined command: .gcore.*$gdb_prompt $" { + # gcore command not supported -- nothing to test here. +- unsupported "gdb does not support gcore on this target" +- return -1; ++ unsupported "${prefix} gdb does not support gcore on this target" ++ continue + } + -re "Save a core file .*$gdb_prompt $" { +- pass "help gcore" ++ pass "${prefix} help gcore" + } + -re ".*$gdb_prompt $" { +- fail "help gcore" ++ fail "${prefix} help gcore" + } + timeout { +- fail "help gcore (timeout)" ++ fail "${prefix} help gcore (timeout)" + } + } + + if { ! [ runto_main ] } then { +- untested gcore.exp +- return -1 ++ untested "${prefix} gcore.exp" ++ continue + } + + proc capture_command_output { command prefix } { +@@ -77,7 +82,7 @@ proc capture_command_output { command pr + set output_string $expect_out(1,string) + } + default { +- fail "capture_command_output failed on $command." ++ fail "${prefix} capture_command_output failed on $command." + } + } + return $output_string +@@ -109,22 +114,22 @@ set escapedfilename [string_to_regexp ${ + + set core_supported 0 + gdb_test_multiple "gcore ${objdir}/${subdir}/gcore.test" \ +- "save a corefile" \ ++ "${prefix} save a corefile" \ + { + -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" { +- pass "save a corefile" ++ pass "${prefix} save a corefile" + global core_supported + set core_supported 1 + } + -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" { +- unsupported "save a corefile" ++ unsupported "${prefix} save a corefile" + global core_supported + set core_supported 0 + } + } + + if {!$core_supported} { +- return -1 ++ continue + } + + # Now restart gdb and load the corefile. +@@ -136,31 +141,31 @@ gdb_load ${binfile} + send_gdb "core ${objdir}/${subdir}/gcore.test\n" + gdb_expect { + -re ".* is not a core dump:.*$gdb_prompt $" { +- fail "re-load generated corefile (bad file format)" ++ fail "${prefix} re-load generated corefile (bad file format)" + # No use proceeding from here. +- return; ++ continue + } + -re ".*: No such file or directory.*$gdb_prompt $" { +- fail "re-load generated corefile (file not found)" ++ fail "${prefix} re-load generated corefile (file not found)" + # No use proceeding from here. +- return; ++ continue + } + -re ".*Couldn't find .* registers in core file.*$gdb_prompt $" { +- fail "re-load generated corefile (incomplete note section)" ++ fail "${prefix} re-load generated corefile (incomplete note section)" + } + -re "Core was generated by .*$gdb_prompt $" { +- pass "re-load generated corefile" ++ pass "${prefix} re-load generated corefile" + } + -re ".*$gdb_prompt $" { +- fail "re-load generated corefile" ++ fail "${prefix} re-load generated corefile" + } + timeout { +- fail "re-load generated corefile (timeout)" ++ fail "${prefix} re-load generated corefile (timeout)" + } + } + + send_gdb "where\n" +-gdb_expect_list "where in corefile" ".*$gdb_prompt $" { ++gdb_expect_list "${prefix} where in corefile" ".*$gdb_prompt $" { + ".*\[\r\n\]+#0 .* terminal_func \\(\\) at " + ".*\[\r\n\]+#1 .* array_func \\(\\) at " + ".*\[\r\n\]+#2 .* factorial_func \\(value=1\\) at " +@@ -174,61 +179,64 @@ gdb_expect_list "where in corefile" ".*$ + + set post_corefile_regs [capture_command_output "info registers" ""] + if ![string compare $pre_corefile_regs $post_corefile_regs] then { +- pass "corefile restored general registers" ++ pass "${prefix} corefile restored general registers" + } else { +- fail "corefile restored general registers" ++ fail "${prefix} corefile restored general registers" + } + + set post_corefile_allregs [capture_command_output "info all-reg" ""] + if ![string compare $pre_corefile_allregs $post_corefile_allregs] then { +- pass "corefile restored all registers" ++ pass "${prefix} corefile restored all registers" + } else { +- fail "corefile restored all registers" ++ fail "${prefix} corefile restored all registers" + } + + set post_corefile_extern_array \ + [capture_command_output "print extern_array" "$print_prefix"] + if ![string compare $pre_corefile_extern_array $post_corefile_extern_array] { +- pass "corefile restored extern array" ++ pass "${prefix} corefile restored extern array" + } else { +- fail "corefile restored extern array" ++ fail "${prefix} corefile restored extern array" + } + + set post_corefile_static_array \ + [capture_command_output "print static_array" "$print_prefix"] + if ![string compare $pre_corefile_static_array $post_corefile_static_array] { +- pass "corefile restored static array" ++ pass "${prefix} corefile restored static array" + } else { +- fail "corefile restored static array" ++ fail "${prefix} corefile restored static array" + } + + set post_corefile_uninit_array \ + [capture_command_output "print un_initialized_array" "$print_prefix"] + if ![string compare $pre_corefile_uninit_array $post_corefile_uninit_array] { +- pass "corefile restored un-initialized array" ++ pass "${prefix} corefile restored un-initialized array" + } else { +- fail "corefile restored un-initialized array" ++ fail "${prefix} corefile restored un-initialized array" + } + + set post_corefile_heap_string \ + [capture_command_output "print heap_string" "$print_prefix"] + if ![string compare $pre_corefile_heap_string $post_corefile_heap_string] { +- pass "corefile restored heap array" ++ pass "${prefix} corefile restored heap array" + } else { +- fail "corefile restored heap array" ++ fail "${prefix} corefile restored heap array" + } + + set post_corefile_local_array \ + [capture_command_output "print array_func::local_array" "$print_prefix"] + if ![string compare $pre_corefile_local_array $post_corefile_local_array] { +- pass "corefile restored stack array" ++ pass "${prefix} corefile restored stack array" + } else { +- fail "corefile restored stack array" ++ fail "${prefix} corefile restored stack array" + } + + set post_corefile_backtrace [capture_command_output "backtrace" ""] + if ![string compare $pre_corefile_backtrace $post_corefile_backtrace] { +- pass "corefile restored backtrace" ++ pass "${prefix} corefile restored backtrace" + } else { +- fail "corefile restored backtrace" ++ fail "${prefix} corefile restored backtrace" ++} ++ ++# $additional_flags: + } diff --git a/gdb-6.6-multifork-debugreg.patch b/gdb-6.6-multifork-debugreg.patch new file mode 100644 index 0000000..b0f63a9 --- /dev/null +++ b/gdb-6.6-multifork-debugreg.patch @@ -0,0 +1,1337 @@ +http://sourceware.org/ml/gdb-patches/2008-01/msg00042.html +[ Backported for GDB-6.6 (only removed the new file inclusion). ] + ++ + +2007-09-16 Daniel Jacobowitz + Jeff Johnston + + * gdb.texinfo (Setting Watchpoints): Adjust warning text about + multi-threaded watchpoints. + +2007-12-15 Jan Kratochvil + + * gdb.texinfo (Setting Watchpoints): New paragraph on the software + watchpoints safety wrt `set scheduler-locking'. + +2008-03-01 Jan Kratochvil + + Port to GDB-6.8pre. + +2008-03-31 Jan Kratochvil + + * gdb.threads/watchpoint-fork-forkoff.c (forkoff): New delay after the + parent/child messages to fix a race. + +2008-05-28 Jan Kratochvil + + * s390-nat.c (s390_fix_watch_points): Fix its compilation failure + - rename it to S390_FIX_WATCH_POINTS_LIST. + +Index: gdb-6.8.50.20090209/gdb/amd64-linux-nat.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/amd64-linux-nat.c 2009-02-09 16:02:27.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/amd64-linux-nat.c 2009-02-09 16:03:30.000000000 +0100 +@@ -408,25 +408,43 @@ amd64_linux_dr_set (ptid_t ptid, int reg + void + amd64_linux_dr_set_control (unsigned long control) + { +- struct lwp_info *lp; +- ptid_t ptid; +- + amd64_linux_dr[DR_CONTROL] = control; +- ALL_LWPS (lp, ptid) +- amd64_linux_dr_set (ptid, DR_CONTROL, control); ++ ++ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process ++ not listed for ALL_LWPS. */ ++ ++ if (ptid_get_lwp (inferior_ptid) == 0) ++ amd64_linux_dr_set (inferior_ptid, DR_CONTROL, control); ++ else ++ { ++ struct lwp_info *lp; ++ ptid_t ptid; ++ ++ ALL_LWPS (lp, ptid) ++ amd64_linux_dr_set (ptid, DR_CONTROL, control); ++ } + } + + void + amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr) + { +- struct lwp_info *lp; +- ptid_t ptid; +- + gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); + + amd64_linux_dr[DR_FIRSTADDR + regnum] = addr; +- ALL_LWPS (lp, ptid) +- amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); ++ ++ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process ++ not listed for ALL_LWPS. */ ++ ++ if (ptid_get_lwp (inferior_ptid) == 0) ++ amd64_linux_dr_set (inferior_ptid, DR_FIRSTADDR + regnum, addr); ++ else ++ { ++ struct lwp_info *lp; ++ ptid_t ptid; ++ ++ ALL_LWPS (lp, ptid) ++ amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); ++ } + } + + void +@@ -451,6 +469,41 @@ amd64_linux_new_thread (ptid_t ptid) + + amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]); + } ++ ++/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child ++ process of traced FORK. We must clear such watchpoints only once during ++ DETACH_BREAKPOINTS. */ ++ ++static int amd64_linux_detach_breakpoints_pid; ++ ++/* Remove a watchpoint that watched the memory region which starts at ++ address ADDR, whose length is LEN bytes, and for accesses of the ++ type TYPE. Return 0 on success, -1 on failure. */ ++int ++amd64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) ++{ ++ if (ptid_get_pid (inferior_ptid) == amd64_linux_detach_breakpoints_pid) ++ return 0; ++ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ ++ amd64_linux_detach_breakpoints_pid = 0; ++ ++ return i386_remove_watchpoint (addr, len, type); ++} ++ ++static void ++amd64_linux_detach_breakpoints (int detached_pid) ++{ ++ struct cleanup *old_chain = save_inferior_ptid (); ++ int i; ++ ++ amd64_linux_detach_breakpoints_pid = detached_pid; ++ /* Depend on `!is_lwp (inferior_ptid)' for the I386_* macros. */ ++ inferior_ptid = pid_to_ptid (detached_pid); ++ ++ i386_detach_breakpoints (detached_pid); ++ ++ do_cleanups (old_chain); ++} + + + /* This function is called by libthread_db as part of its handling of +@@ -755,6 +808,42 @@ amd64_linux_siginfo_fixup (struct siginf + return 0; + } + ++static int (*amd64_linux_super_follow_fork) (struct target_ops *ops, ++ int follow_child); ++ ++/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its ++ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ ++ ++static int ++amd64_linux_follow_fork (struct target_ops *ops, int follow_child) ++{ ++ ptid_t last_ptid; ++ struct target_waitstatus last_status; ++ int has_vforked; ++ int parent_pid, child_pid; ++ ++ get_last_target_status (&last_ptid, &last_status); ++ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); ++ parent_pid = ptid_get_lwp (last_ptid); ++ if (parent_pid == 0) ++ parent_pid = ptid_get_pid (last_ptid); ++ child_pid = ptid_get_lwp (last_status.value.related_pid); ++ if (child_pid == 0) ++ child_pid = ptid_get_pid (last_status.value.related_pid); ++ ++ if (! follow_child) ++ { ++ amd64_linux_detach_breakpoints (child_pid); ++ } ++ else ++ { ++ if (! has_vforked) ++ amd64_linux_detach_breakpoints (child_pid); ++ } ++ ++ return (*amd64_linux_super_follow_fork) (ops, follow_child); ++} ++ + /* Provide a prototype to silence -Wmissing-prototypes. */ + void _initialize_amd64_linux_nat (void); + +@@ -791,6 +880,9 @@ _initialize_amd64_linux_nat (void) + linux_elfcore_write_prstatus = amd64_linux_elfcore_write_prstatus; + linux_elfcore_write_prfpreg = amd64_linux_elfcore_write_prfpreg; + ++ amd64_linux_super_follow_fork = t->to_follow_fork; ++ t->to_follow_fork = amd64_linux_follow_fork; ++ + /* Register the target. */ + linux_nat_add_target (t); + linux_nat_set_new_thread (t, amd64_linux_new_thread); +Index: gdb-6.8.50.20090209/gdb/config/i386/nm-i386.h +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/config/i386/nm-i386.h 2009-01-03 06:57:54.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/config/i386/nm-i386.h 2009-02-09 16:02:42.000000000 +0100 +@@ -120,6 +120,8 @@ extern int i386_stopped_by_watchpoint (v + + #endif /* I386_WATCHPOINTS_IN_TARGET_VECTOR */ + ++extern void i386_detach_breakpoints (int detached_pid); ++ + #endif /* I386_USE_GENERIC_WATCHPOINTS */ + + #endif /* NM_I386_H */ +Index: gdb-6.8.50.20090209/gdb/i386-linux-nat.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/i386-linux-nat.c 2009-01-03 06:57:51.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/i386-linux-nat.c 2009-02-09 16:02:42.000000000 +0100 +@@ -634,21 +634,42 @@ i386_linux_dr_set_control (unsigned long + ptid_t ptid; + + i386_linux_dr[DR_CONTROL] = control; +- ALL_LWPS (lp, ptid) +- i386_linux_dr_set (ptid, DR_CONTROL, control); ++ ++ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process ++ not listed for ALL_LWPS. */ ++ ++ if (ptid_get_lwp (inferior_ptid) == 0) ++ i386_linux_dr_set (inferior_ptid, DR_CONTROL, control); ++ else ++ { ++ struct lwp_info *lp; ++ ptid_t ptid; ++ ++ ALL_LWPS (lp, ptid) ++ i386_linux_dr_set (ptid, DR_CONTROL, control); ++ } + } + + void + i386_linux_dr_set_addr (int regnum, CORE_ADDR addr) + { +- struct lwp_info *lp; +- ptid_t ptid; +- + gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); + + i386_linux_dr[DR_FIRSTADDR + regnum] = addr; +- ALL_LWPS (lp, ptid) +- i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); ++ ++ /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process ++ not listed for ALL_LWPS. */ ++ ++ if (ptid_get_lwp (inferior_ptid) == 0) ++ i386_linux_dr_set (inferior_ptid, DR_FIRSTADDR + regnum, addr); ++ else ++ { ++ struct lwp_info *lp; ++ ptid_t ptid; ++ ++ ALL_LWPS (lp, ptid) ++ i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); ++ } + } + + void +@@ -673,6 +694,41 @@ i386_linux_new_thread (ptid_t ptid) + + i386_linux_dr_set (ptid, DR_CONTROL, i386_linux_dr[DR_CONTROL]); + } ++ ++/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child ++ process of traced FORK. We must clear such watchpoints only once during ++ DETACH_BREAKPOINTS. */ ++ ++static int i386_linux_detach_breakpoints_pid; ++ ++/* Remove a watchpoint that watched the memory region which starts at ++ address ADDR, whose length is LEN bytes, and for accesses of the ++ type TYPE. Return 0 on success, -1 on failure. */ ++int ++i386_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) ++{ ++ if (ptid_get_pid (inferior_ptid) == i386_linux_detach_breakpoints_pid) ++ return 0; ++ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ ++ i386_linux_detach_breakpoints_pid = 0; ++ ++ return i386_remove_watchpoint (addr, len, type); ++} ++ ++static void ++i386_linux_detach_breakpoints (int detached_pid) ++{ ++ struct cleanup *old_chain = save_inferior_ptid (); ++ int i; ++ ++ i386_linux_detach_breakpoints_pid = detached_pid; ++ /* Depend on `!is_lwp (inferior_ptid)' for the I386_* macros. */ ++ inferior_ptid = pid_to_ptid (detached_pid); ++ ++ i386_detach_breakpoints (detached_pid); ++ ++ do_cleanups (old_chain); ++} + + + /* Called by libthread_db. Returns a pointer to the thread local +@@ -812,6 +868,40 @@ i386_linux_child_post_startup_inferior ( + super_post_startup_inferior (ptid); + } + ++static int (*i386_linux_super_follow_fork) (struct target_ops *ops, ++ int follow_child); ++ ++/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its ++ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ ++ ++static int ++i386_linux_follow_fork (struct target_ops *ops, int follow_child) ++{ ++ ptid_t last_ptid; ++ struct target_waitstatus last_status; ++ int has_vforked; ++ int parent_pid, child_pid; ++ ++ get_last_target_status (&last_ptid, &last_status); ++ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); ++ parent_pid = ptid_get_lwp (last_ptid); ++ if (parent_pid == 0) ++ parent_pid = ptid_get_pid (last_ptid); ++ child_pid = ptid_get_pid (last_status.value.related_pid); ++ ++ if (! follow_child) ++ { ++ i386_linux_detach_breakpoints (child_pid); ++ } ++ else ++ { ++ if (! has_vforked) ++ i386_linux_detach_breakpoints (child_pid); ++ } ++ ++ return (*i386_linux_super_follow_fork) (ops, follow_child); ++} ++ + void + _initialize_i386_linux_nat (void) + { +@@ -833,6 +923,9 @@ _initialize_i386_linux_nat (void) + t->to_fetch_registers = i386_linux_fetch_inferior_registers; + t->to_store_registers = i386_linux_store_inferior_registers; + ++ i386_linux_super_follow_fork = t->to_follow_fork; ++ t->to_follow_fork = i386_linux_follow_fork; ++ + /* Register the target. */ + linux_nat_add_target (t); + linux_nat_set_new_thread (t, i386_linux_new_thread); +Index: gdb-6.8.50.20090209/gdb/i386-nat.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/i386-nat.c 2009-01-03 06:57:51.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/i386-nat.c 2009-02-09 16:02:42.000000000 +0100 +@@ -546,6 +546,17 @@ i386_remove_watchpoint (CORE_ADDR addr, + return retval; + } + ++void ++i386_detach_breakpoints (int detached_pid) ++{ ++ int i; ++ ++ /* Do not touch any DR_MIRROR or DR_CONTROL_MIRROR mirrors here. */ ++ I386_DR_LOW_SET_CONTROL (0); ++ ALL_DEBUG_REGISTERS(i) ++ I386_DR_LOW_RESET_ADDR (i); ++} ++ + /* Return non-zero if we can watch a memory region that starts at + address ADDR and whose length is LEN bytes. */ + +Index: gdb-6.8.50.20090209/gdb/ia64-linux-nat.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/ia64-linux-nat.c 2009-02-09 15:48:43.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/ia64-linux-nat.c 2009-02-09 16:02:42.000000000 +0100 +@@ -583,6 +583,12 @@ ia64_linux_insert_watchpoint (CORE_ADDR + return 0; + } + ++/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child ++ process of traced FORK. We must clear such watchpoints only once during ++ DETACH_BREAKPOINTS. */ ++ ++static int ia64_linux_detach_breakpoints_pid; ++ + static int + ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) + { +@@ -590,6 +596,11 @@ ia64_linux_remove_watchpoint (CORE_ADDR + long dbr_addr, dbr_mask; + int max_watchpoints = 4; + ++ if (ptid_get_pid (inferior_ptid) == ia64_linux_detach_breakpoints_pid) ++ return 0; ++ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ ++ ia64_linux_detach_breakpoints_pid = 0; ++ + if (len <= 0 || !is_power_of_2 (len)) + return -1; + +@@ -617,6 +628,22 @@ ia64_linux_remove_watchpoint (CORE_ADDR + } + + static void ++ia64_linux_detach_breakpoints (int detached_pid) ++{ ++ int idx, i; ++ long dbr_addr, dbr_mask; ++ int max_watchpoints = 4; ++ ++ ia64_linux_detach_breakpoints_pid = detached_pid; ++ ++ /* Do not touch any DEBUG_REGISTERS mirrors here. */ ++ dbr_addr = 0; ++ dbr_mask = 0; ++ for (idx = 0; idx < max_watchpoints; idx++) ++ store_debug_register_pair (ptid_build (detached_pid, 0, 0), idx, &dbr_addr, &dbr_mask); ++} ++ ++static void + ia64_linux_new_thread (ptid_t ptid) + { + int i, any; +@@ -805,6 +832,40 @@ ia64_linux_xfer_partial (struct target_o + offset, len); + } + ++static int (*ia64_linux_super_follow_fork) (struct target_ops *ops, ++ int follow_child); ++ ++/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its ++ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ ++ ++int ++ia64_linux_follow_fork (struct target_ops *ops, int follow_child) ++{ ++ ptid_t last_ptid; ++ struct target_waitstatus last_status; ++ int has_vforked; ++ int parent_pid, child_pid; ++ ++ get_last_target_status (&last_ptid, &last_status); ++ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); ++ parent_pid = ptid_get_lwp (last_ptid); ++ if (parent_pid == 0) ++ parent_pid = ptid_get_pid (last_ptid); ++ child_pid = ptid_get_pid (last_status.value.related_pid); ++ ++ if (! follow_child) ++ { ++ ia64_linux_detach_breakpoints (child_pid); ++ } ++ else ++ { ++ if (! has_vforked) ++ ia64_linux_detach_breakpoints (child_pid); ++ } ++ ++ return (*ia64_linux_super_follow_fork) (ops, follow_child); ++} ++ + void _initialize_ia64_linux_nat (void); + + /* +@@ -899,6 +960,9 @@ _initialize_ia64_linux_nat (void) + t->to_insert_watchpoint = ia64_linux_insert_watchpoint; + t->to_remove_watchpoint = ia64_linux_remove_watchpoint; + ++ ia64_linux_super_follow_fork = t->to_follow_fork; ++ t->to_follow_fork = ia64_linux_follow_fork; ++ + /* Register the target. */ + linux_nat_add_target (t); + linux_nat_set_new_thread (t, ia64_linux_new_thread); +Index: gdb-6.8.50.20090209/gdb/ppc-linux-nat.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/ppc-linux-nat.c 2009-01-03 06:57:52.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/ppc-linux-nat.c 2009-02-09 16:02:42.000000000 +0100 +@@ -1118,6 +1118,12 @@ ppc_linux_insert_watchpoint (CORE_ADDR a + return 0; + } + ++/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child ++ process of traced FORK. We must clear such watchpoints only once during ++ DETACH_BREAKPOINTS. */ ++ ++static int ppc_linux_detach_breakpoints_pid; ++ + static int + ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw) + { +@@ -1125,6 +1131,11 @@ ppc_linux_remove_watchpoint (CORE_ADDR a + ptid_t ptid; + long dabr_value = 0; + ++ if (ptid_get_pid (inferior_ptid) == ppc_linux_detach_breakpoints_pid) ++ return 0; ++ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ ++ ppc_linux_detach_breakpoints_pid = 0; ++ + saved_dabr_value = 0; + ALL_LWPS (lp, ptid) + if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0) +@@ -1138,6 +1149,15 @@ ppc_linux_new_thread (ptid_t ptid) + ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value); + } + ++static void ++ppc_linux_detach_breakpoints (int detached_pid) ++{ ++ ppc_linux_detach_breakpoints_pid = detached_pid; ++ ++ /* Do not touch the SAVED_DABR_VALUE mirror here. */ ++ ptrace (PTRACE_SET_DEBUGREG, detached_pid, 0, 0); ++} ++ + static int + ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p) + { +@@ -1318,6 +1338,40 @@ ppc_linux_read_description (struct targe + return isa205? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l; + } + ++static int (*ppc_linux_super_follow_fork) (struct target_ops *ops, ++ int follow_child); ++ ++/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its ++ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ ++ ++int ++ppc_linux_follow_fork (struct target_ops *ops, int follow_child) ++{ ++ ptid_t last_ptid; ++ struct target_waitstatus last_status; ++ int has_vforked; ++ int parent_pid, child_pid; ++ ++ get_last_target_status (&last_ptid, &last_status); ++ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); ++ parent_pid = ptid_get_lwp (last_ptid); ++ if (parent_pid == 0) ++ parent_pid = ptid_get_pid (last_ptid); ++ child_pid = ptid_get_pid (last_status.value.related_pid); ++ ++ if (! follow_child) ++ { ++ ppc_linux_detach_breakpoints (child_pid); ++ } ++ else ++ { ++ if (! has_vforked) ++ ppc_linux_detach_breakpoints (child_pid); ++ } ++ ++ return (*ppc_linux_super_follow_fork) (ops, follow_child); ++} ++ + void _initialize_ppc_linux_nat (void); + + void +@@ -1343,6 +1397,9 @@ _initialize_ppc_linux_nat (void) + + t->to_read_description = ppc_linux_read_description; + ++ ppc_linux_super_follow_fork = t->to_follow_fork; ++ t->to_follow_fork = ppc_linux_follow_fork; ++ + /* Register the target. */ + linux_nat_add_target (t); + linux_nat_set_new_thread (t, ppc_linux_new_thread); +Index: gdb-6.8.50.20090209/gdb/s390-nat.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/s390-nat.c 2007-11-07 07:36:57.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/s390-nat.c 2009-02-09 16:02:42.000000000 +0100 +@@ -283,21 +283,15 @@ s390_stopped_by_watchpoint (void) + } + + static void +-s390_fix_watch_points (ptid_t ptid) ++s390_fix_watch_points_list (int tid, struct watch_area *area_list) + { +- int tid; +- + per_struct per_info; + ptrace_area parea; + + CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0; + struct watch_area *area; + +- tid = TIDGET (ptid); +- if (tid == 0) +- tid = PIDGET (ptid); +- +- for (area = watch_base; area; area = area->next) ++ for (area = area_list; area; area = area->next) + { + watch_lo_addr = min (watch_lo_addr, area->lo_addr); + watch_hi_addr = max (watch_hi_addr, area->hi_addr); +@@ -309,7 +303,7 @@ s390_fix_watch_points (ptid_t ptid) + if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0) + perror_with_name (_("Couldn't retrieve watchpoint status")); + +- if (watch_base) ++ if (area_list) + { + per_info.control_regs.bits.em_storage_alteration = 1; + per_info.control_regs.bits.storage_alt_space_ctl = 1; +@@ -326,6 +320,18 @@ s390_fix_watch_points (ptid_t ptid) + perror_with_name (_("Couldn't modify watchpoint status")); + } + ++static void ++s390_fix_watch_points (ptid_t ptid) ++{ ++ int tid; ++ ++ tid = TIDGET (ptid); ++ if (tid == 0) ++ tid = PIDGET (ptid); ++ ++ s390_fix_watch_points_list (tid, watch_base); ++} ++ + static int + s390_insert_watchpoint (CORE_ADDR addr, int len, int type) + { +@@ -347,6 +353,12 @@ s390_insert_watchpoint (CORE_ADDR addr, + return 0; + } + ++/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child ++ process of traced FORK. We must clear such watchpoints only once during ++ DETACH_BREAKPOINTS. */ ++ ++static int s390_detach_breakpoints_pid; ++ + static int + s390_remove_watchpoint (CORE_ADDR addr, int len, int type) + { +@@ -354,6 +366,11 @@ s390_remove_watchpoint (CORE_ADDR addr, + ptid_t ptid; + struct watch_area *area, **parea; + ++ if (ptid_get_pid (inferior_ptid) == s390_detach_breakpoints_pid) ++ return 0; ++ /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ ++ s390_detach_breakpoints_pid = 0; ++ + for (parea = &watch_base; *parea; parea = &(*parea)->next) + if ((*parea)->lo_addr == addr + && (*parea)->hi_addr == addr + len - 1) +@@ -361,8 +378,10 @@ s390_remove_watchpoint (CORE_ADDR addr, + + if (!*parea) + { ++#if 0 /* Red Hat fork/threads watchpoints changes may trigger it. */ + fprintf_unfiltered (gdb_stderr, + "Attempt to remove nonexistent watchpoint.\n"); ++#endif + return -1; + } + +@@ -375,6 +394,15 @@ s390_remove_watchpoint (CORE_ADDR addr, + return 0; + } + ++static void ++s390_detach_breakpoints (int detached_pid) ++{ ++ s390_detach_breakpoints_pid = detached_pid; ++ ++ /* Do not touch the WATCH_BASE here. */ ++ s390_fix_watch_points_list (detached_pid, NULL); ++} ++ + static int + s390_can_use_hw_breakpoint (int type, int cnt, int othertype) + { +@@ -387,6 +415,39 @@ s390_region_ok_for_hw_watchpoint (CORE_A + return 1; + } + ++static int (*s390_super_follow_fork) (struct target_ops *ops, int follow_child); ++ ++/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its ++ called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ ++ ++int ++s390_follow_fork (struct target_ops *ops, int follow_child) ++{ ++ ptid_t last_ptid; ++ struct target_waitstatus last_status; ++ int has_vforked; ++ int parent_pid, child_pid; ++ ++ get_last_target_status (&last_ptid, &last_status); ++ has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); ++ parent_pid = ptid_get_lwp (last_ptid); ++ if (parent_pid == 0) ++ parent_pid = ptid_get_pid (last_ptid); ++ child_pid = ptid_get_pid (last_status.value.related_pid); ++ ++ if (! follow_child) ++ { ++ s390_detach_breakpoints (child_pid); ++ } ++ else ++ { ++ if (! has_vforked) ++ s390_detach_breakpoints (child_pid); ++ } ++ ++ return (*s390_super_follow_fork) (ops, follow_child); ++} ++ + + void _initialize_s390_nat (void); + +@@ -410,6 +471,9 @@ _initialize_s390_nat (void) + t->to_insert_watchpoint = s390_insert_watchpoint; + t->to_remove_watchpoint = s390_remove_watchpoint; + ++ s390_super_follow_fork = t->to_follow_fork; ++ t->to_follow_fork = s390_follow_fork; ++ + /* Register the target. */ + linux_nat_add_target (t); + linux_nat_set_new_thread (t, s390_fix_watch_points); +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c 2009-02-09 16:02:42.000000000 +0100 +@@ -0,0 +1,172 @@ ++/* Test case for forgotten hw-watchpoints after fork()-off of a process. ++ ++ Copyright 2008 ++ 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. */ ++ ++#include ++#include ++ ++static void delay (void) ++{ ++ int i = usleep (1000000 / 100); ++ assert (i == 0 || errno == EINTR); ++} ++ ++#if defined FOLLOW_PARENT ++ ++static void forkoff (int nr) ++{ ++ pid_t child, pid_got; ++ int exit_code = 42 + nr; ++ int status, i; ++ ++ child = fork (); ++ switch (child) ++ { ++ case -1: ++ assert (0); ++ case 0: ++ printf ("child%d: %d\n", nr, (int) getpid ()); ++ /* Delay to get both the "child%d" and "parent%d" message printed without ++ a race breaking expect by its endless wait on `$gdb_prompt$': ++ Breakpoint 3, breakpoint () at ../../../gdb/testsuite/gdb.threads/watchpoint-fork.c:33 ++ 33 } ++ (gdb) parent2: 14223 */ ++ i = sleep (1); ++ assert (i == 0); ++ ++ /* We must not get caught here (against a forgotten breakpoint). */ ++ var++; ++ breakpoint (); ++ ++ _exit (exit_code); ++ default: ++ printf ("parent%d: %d\n", nr, (int) child); ++ /* Delay to get both the "child%d" and "parent%d" message printed, see ++ above. */ ++ i = sleep (1); ++ assert (i == 0); ++ ++ pid_got = wait (&status); ++ assert (pid_got == child); ++ assert (WIFEXITED (status)); ++ assert (WEXITSTATUS (status) == exit_code); ++ ++ /* We must get caught here (against a false watchpoint removal). */ ++ breakpoint (); ++ } ++} ++ ++#elif defined FOLLOW_CHILD ++ ++static volatile int usr1_got; ++ ++static void handler_usr1 (int signo) ++{ ++ usr1_got++; ++} ++ ++static void forkoff (int nr) ++{ ++ pid_t child; ++ int i, loop; ++ struct sigaction act, oldact; ++#ifdef THREAD ++ void *thread_result; ++#endif ++ ++ memset (&act, 0, sizeof act); ++ act.sa_flags = SA_RESTART; ++ act.sa_handler = handler_usr1; ++ sigemptyset (&act.sa_mask); ++ i = sigaction (SIGUSR1, &act, &oldact); ++ assert (i == 0); ++ ++ child = fork (); ++ switch (child) ++ { ++ case -1: ++ assert (0); ++ default: ++ printf ("parent%d: %d\n", nr, (int) child); ++ ++ /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB ++ tracing the child fork with no longer valid thread/lwp entries of the ++ parent. */ ++ ++ i = sleep (2); ++ assert (i == 0); ++ ++ /* We must not get caught here (against a forgotten breakpoint). */ ++ ++ var++; ++ breakpoint (); ++ ++#ifdef THREAD ++ /* And neither got caught our thread. */ ++ ++ step = 99; ++ i = pthread_join (thread, &thread_result); ++ assert (i == 0); ++ assert (thread_result == (void *) 99UL); ++#endif ++ ++ /* Be sure our child knows we did not get caught above. */ ++ ++ i = kill (child, SIGUSR1); ++ assert (i == 0); ++ ++ /* Sleep for a while to check GDB's `info threads' no longer tracks us in ++ the child fork. */ ++ ++ i = sleep (2); ++ assert (i == 0); ++ ++ _exit (0); ++ case 0: ++ printf ("child%d: %d\n", nr, (int) getpid ()); ++ ++ /* Let the parent signal us about its success. Be careful of races. */ ++ ++ for (loop = 0; loop < 1000; loop++) ++ { ++ /* Parent either died (and USR1_GOT is zero) or it succeeded. */ ++ if (kill (getppid (), 0) != 0) ++ break; ++ /* Parent succeeded? */ ++ if (usr1_got) ++ break; ++ ++ delay (); ++ } ++ assert (usr1_got); ++ ++ /* We must get caught here (against a false watchpoint removal). */ ++ ++ breakpoint (); ++ } ++ ++ i = sigaction (SIGUSR1, &oldact, NULL); ++ assert (i == 0); ++} ++ ++#else ++# error "!FOLLOW_PARENT && !FOLLOW_CHILD" ++#endif +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c 2009-02-09 16:02:42.000000000 +0100 +@@ -0,0 +1,154 @@ ++/* Test case for forgotten hw-watchpoints after fork()-off of a process. ++ ++ Copyright 2008 ++ 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. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#define gettid() syscall (__NR_gettid) ++ ++/* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP ++ variable. Hit-comments need to be duplicite there to catch both at-stops ++ and behind-stops, depending on the target. */ ++ ++static volatile int var; ++ ++static void dummy (void) ++{ ++} ++ ++static void breakpoint (void) ++{ ++} ++ ++/* Include here the functions: ++ static void forkoff (int nr); ++ static void delay (void); */ ++ ++static pthread_t thread; ++static volatile int step; ++#define THREAD ++ ++#include "watchpoint-fork-forkoff.c" ++ ++static void *start (void *arg) ++{ ++ if (step >= 3) ++ goto step_3; ++ ++ while (step != 1) ++ delay (); ++ ++ var++; /* validity-thread-B */ ++ dummy (); /* validity-thread-B */ ++ step = 2; ++ while (step != 3) ++ { ++ if (step == 99) ++ goto step_99; ++ delay (); ++ } ++ ++step_3: ++ if (step >= 5) ++ goto step_5; ++ ++ var++; /* after-fork1-B */ ++ dummy (); /* after-fork1-B */ ++ step = 4; ++ while (step != 5) ++ { ++ if (step == 99) ++ goto step_99; ++ delay (); ++ } ++ ++step_5: ++ var++; /* after-fork2-B */ ++ dummy (); /* after-fork2-B */ ++ return (void *) 5UL; ++ ++step_99: ++ /* We must not get caught here (against a forgotten breakpoint). */ ++ var++; ++ breakpoint (); ++ return (void *) 99UL; ++} ++ ++int main (void) ++{ ++ int i; ++ void *thread_result; ++ ++ setbuf (stdout, NULL); ++ printf ("main: %d\n", (int) gettid ()); ++ ++ /* General watchpoints validity. */ ++ var++; /* validity-first */ ++ dummy (); /* validity-first */ ++ ++ i = pthread_create (&thread, NULL, start, NULL); ++ assert (i == 0); ++ ++ var++; /* validity-thread-A */ ++ dummy (); /* validity-thread-A */ ++ step = 1; ++ while (step != 2) ++ delay (); ++ ++ /* Hardware watchpoints got disarmed here. */ ++ forkoff (1); ++ ++ var++; /* after-fork1-A */ ++ dummy (); /* after-fork1-A */ ++ step = 3; ++#ifdef FOLLOW_CHILD ++ /* Spawn new thread as it was deleted in the child of FORK. */ ++ i = pthread_create (&thread, NULL, start, NULL); ++ assert (i == 0); ++#endif ++ while (step != 4) ++ delay (); ++ ++ /* A sanity check for double hardware watchpoints removal. */ ++ forkoff (2); ++ ++ var++; /* after-fork2-A */ ++ dummy (); /* after-fork2-A */ ++ step = 5; ++#ifdef FOLLOW_CHILD ++ /* Spawn new thread as it was deleted in the child of FORK. */ ++ i = pthread_create (&thread, NULL, start, NULL); ++ assert (i == 0); ++#endif ++ ++ i = pthread_join (thread, &thread_result); ++ assert (i == 0); ++ assert (thread_result == (void *) 5UL); ++ ++ return 0; ++} +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.c 2009-02-09 16:02:42.000000000 +0100 +@@ -0,0 +1,56 @@ ++/* Test case for forgotten hw-watchpoints after fork()-off of a process. ++ ++ Copyright 2008 ++ 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. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static volatile int var; ++ ++static void breakpoint (void) ++{ ++} ++ ++/* Include here the function: ++ static void forkoff (int nr); */ ++ ++#include "watchpoint-fork-forkoff.c" ++ ++int main (void) ++{ ++ setbuf (stdout, NULL); ++ printf ("main: %d\n", (int) getpid ()); ++ ++ /* General watchpoints validity. */ ++ var++; ++ /* Hardware watchpoints got disarmed here. */ ++ forkoff (1); ++ /* This watchpoint got lost before. */ ++ var++; ++ /* A sanity check for double hardware watchpoints removal. */ ++ forkoff (2); ++ var++; ++ ++ return 0; ++} +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.exp 2009-02-09 16:02:42.000000000 +0100 +@@ -0,0 +1,140 @@ ++# Copyright 2008 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 3 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, see . ++ ++# Test case for forgotten hw-watchpoints after fork()-off of a process. ++ ++proc test {type symbol} { ++ global objdir subdir srcdir ++ ++ global pf_prefix ++ set prefix_test $pf_prefix ++ lappend pf_prefix "$type:" ++ set prefix_mt $pf_prefix ++ ++ # no threads ++ ++ set pf_prefix $prefix_mt ++ lappend pf_prefix "singlethreaded:" ++ ++ set testfile watchpoint-fork ++ set srcfile ${testfile}.c ++ set binfile ${objdir}/${subdir}/${testfile} ++ ++ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug additional_flags=-D$symbol"] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++ } ++ ++ gdb_exit ++ gdb_start ++ gdb_reinitialize_dir $srcdir/$subdir ++ gdb_load ${binfile} ++ ++ gdb_test "set follow-fork-mode $type" ++ # Testcase uses it for the `follow-fork-mode child' type. ++ gdb_test "handle SIGUSR1 nostop noprint pass" ++ ++ if { ![runto_main] } then { ++ gdb_suppress_tests ++ return ++ } ++ ++ # Install the watchpoint only after getting into MAIN - workaround some PPC ++ # problem. ++ gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint" ++ ++ # It is never hit but it should not be left over in the fork()ed-off child. ++ gdb_breakpoint "breakpoint" ++ ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 0.*New value = 1.*forkoff *\\(1\\).*" "watchpoints work" ++ gdb_test "continue" \ ++ "reakpoint 3, breakpoint.*" "breakpoint after the first fork" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 1.*New value = 2.*forkoff *\\(2\\).*" "watchpoint after the first fork" ++ gdb_test "continue" \ ++ "reakpoint 3, breakpoint.*" "breakpoint after the second fork" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 2.*New value = 3.*return *0;" "watchpoint after the second fork" ++ gdb_test "continue" "Continuing..*Program exited normally." "finish" ++ ++ ++ # threads ++ ++ set pf_prefix $prefix_mt ++ lappend pf_prefix "multithreaded:" ++ ++ set testfile watchpoint-fork-mt ++ set srcfile ${testfile}.c ++ set binfile ${objdir}/${subdir}/${testfile} ++ ++ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug additional_flags=-D$symbol"] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++ } ++ ++ gdb_exit ++ gdb_start ++ gdb_reinitialize_dir $srcdir/$subdir ++ gdb_load ${binfile} ++ ++ gdb_test "set follow-fork-mode $type" ++ # Testcase uses it for the `follow-fork-mode child' type. ++ gdb_test "handle SIGUSR1 nostop noprint pass" ++ ++ if { ![runto_main] } then { ++ gdb_suppress_tests ++ return ++ } ++ ++ # Install the watchpoint only after getting into MAIN - workaround some PPC ++ # problem. ++ gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint" ++ ++ # It is never hit but it should not be left over in the fork()ed-off child. ++ gdb_breakpoint "breakpoint" ++ ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 0.*New value = 1.*validity-first.*" "singlethread watchpoints work" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 1.*New value = 2.*validity-thread-A.*" "multithreaded watchpoints work at A" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 2.*New value = 3.*validity-thread-B.*" "multithreaded watchpoints work at B" ++ gdb_test "continue" \ ++ "reakpoint 3, breakpoint.*" "breakpoint (A) after the first fork" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 3.*New value = 4.*after-fork1-A.*" "watchpoint A after the first fork" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 4.*New value = 5.*after-fork1-B.*" "watchpoint B after the first fork" ++ gdb_test "continue" \ ++ "reakpoint 3, breakpoint.*" "breakpoint (A) after the second fork" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 5.*New value = 6.*after-fork2-A.*" "watchpoint A after the second fork" ++ gdb_test "continue" \ ++ "atchpoint 2: var.*Old value = 6.*New value = 7.*after-fork2-B.*" "watchpoint B after the second fork" ++ gdb_test "continue" "Continuing..*Program exited normally." "finish" ++ ++ ++ # cleanup ++ ++ set pf_prefix $prefix_test ++} ++ ++test parent FOLLOW_PARENT ++ ++# Only GNU/Linux is known to support `set follow-fork-mode child'. ++if {[istarget "*-*-linux*"]} { ++ test child FOLLOW_CHILD ++} +Index: gdb-6.8.50.20090209/gdb/doc/gdb.texinfo +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/doc/gdb.texinfo 2009-02-09 16:02:35.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/doc/gdb.texinfo 2009-02-09 16:02:42.000000000 +0100 +@@ -3588,6 +3588,14 @@ confident that no other thread can becom + software watchpoints as usual. However, @value{GDBN} may not notice + when a non-current thread's activity changes the expression. (Hardware + watchpoints, in contrast, watch an expression in all threads.) ++ ++Software watchpoints single-step the current thread to track the changes. ++Other threads are left freely running on @code{continue}; therefore, their ++changes cannot be caught. To get more reliable software watchpoints, please ++use @code{set scheduler-locking on}. The default for Red Hat/Fedora ++@value{GDBN} is @code{set scheduler-locking step}, which makes the software ++watchpoints safe for the @code{step} command, but not for the @code{continue} ++command. @xref{Thread Stops}. + @end quotation + + @xref{set remote hardware-watchpoint-limit}. +Index: gdb-6.8.50.20090209/gdb/config/i386/nm-linux.h +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/config/i386/nm-linux.h 2009-01-03 06:57:54.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/config/i386/nm-linux.h 2009-02-09 16:02:42.000000000 +0100 +@@ -46,6 +46,16 @@ extern void i386_linux_dr_reset_addr (in + extern unsigned long i386_linux_dr_get_status (void); + #define I386_DR_LOW_GET_STATUS() \ + i386_linux_dr_get_status () ++ ++/* Remove a watchpoint that watched the memory region which starts at ++ * address ADDR, whose length is LEN bytes, and for accesses of the ++ * type TYPE. Return 0 on success, -1 on failure. */ ++extern int i386_linux_remove_watchpoint (CORE_ADDR addr, int len, int type); ++ ++/* Override basic i386 macros for watchpoint and hardware breakpoint ++ insertion/removal to support threads. */ ++#define target_remove_watchpoint(addr, len, type) \ ++ i386_linux_remove_watchpoint (addr, len, type) + + + #ifdef HAVE_PTRACE_GETFPXREGS +Index: gdb-6.8.50.20090209/gdb/config/i386/nm-linux64.h +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/config/i386/nm-linux64.h 2009-01-03 06:57:54.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/config/i386/nm-linux64.h 2009-02-09 16:02:42.000000000 +0100 +@@ -51,4 +51,14 @@ extern unsigned long amd64_linux_dr_get_ + #define I386_DR_LOW_GET_STATUS() \ + amd64_linux_dr_get_status () + ++/* Remove a watchpoint that watched the memory region which starts at ++ * address ADDR, whose length is LEN bytes, and for accesses of the ++ * type TYPE. Return 0 on success, -1 on failure. */ ++extern int amd64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type); ++ ++/* Override basic amd64 macros for watchpoint and hardware breakpoint ++ insertion/removal to support threads. */ ++#define target_remove_watchpoint(addr, len, type) \ ++ amd64_linux_remove_watchpoint (addr, len, type) ++ + #endif /* nm-linux64.h */ +Index: gdb-6.8.50.20090209/gdb/target.h +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/target.h 2009-02-09 15:49:25.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/target.h 2009-02-09 16:02:42.000000000 +0100 +@@ -1113,7 +1113,9 @@ extern char *normal_pid_to_str (ptid_t p + #ifndef target_insert_watchpoint + #define target_insert_watchpoint(addr, len, type) \ + (*current_target.to_insert_watchpoint) (addr, len, type) ++#endif + ++#ifndef target_remove_watchpoint + #define target_remove_watchpoint(addr, len, type) \ + (*current_target.to_remove_watchpoint) (addr, len, type) + #endif diff --git a/gdb-6.6-readline-system.patch b/gdb-6.6-readline-system.patch new file mode 100644 index 0000000..9bc748e --- /dev/null +++ b/gdb-6.6-readline-system.patch @@ -0,0 +1,116 @@ +2007-10-16 Jan Kratochvil + + Port to GDB-6.7. + +Index: gdb-6.7/gdb/doc/Makefile.in +=================================================================== +--- gdb-6.7.orig/gdb/doc/Makefile.in 2007-07-26 12:34:00.000000000 +0200 ++++ gdb-6.7/gdb/doc/Makefile.in 2007-10-16 16:31:08.000000000 +0200 +@@ -109,9 +109,7 @@ DVIPS = dvips + GDB_DOC_SOURCE_INCLUDES = \ + $(srcdir)/fdl.texi \ + $(srcdir)/gpl.texi \ +- $(srcdir)/agentexpr.texi \ +- $(READLINE_DIR)/rluser.texi \ +- $(READLINE_DIR)/inc-hist.texinfo ++ $(srcdir)/agentexpr.texi + GDB_DOC_BUILD_INCLUDES = \ + gdb-cfg.texi \ + GDBvn.texi +Index: gdb-6.7/gdb/doc/gdb.texinfo +=================================================================== +--- gdb-6.7.orig/gdb/doc/gdb.texinfo 2007-10-16 16:19:19.000000000 +0200 ++++ gdb-6.7/gdb/doc/gdb.texinfo 2007-10-16 16:32:10.000000000 +0200 +@@ -158,8 +158,8 @@ software in general. We will miss him. + + * GDB Bugs:: Reporting bugs in @value{GDBN} + +-* Command Line Editing:: Command Line Editing +-* Using History Interactively:: Using History Interactively ++* Command Line Editing: (rluserman). Command Line Editing ++* Using History Interactively: (history). Using History Interactively + * Formatting Documentation:: How to format and print @value{GDBN} documentation + * Installing GDB:: Installing GDB + * Maintenance Commands:: Maintenance Commands +@@ -15533,7 +15533,7 @@ Disable command line editing. + Show whether command line editing is enabled. + @end table + +-@xref{Command Line Editing}, for more details about the Readline ++@xref{Command Line Editing, , , rluserman, GNU Readline Library}, for more details about the Readline + interface. Users unfamiliar with @sc{gnu} Emacs or @code{vi} are + encouraged to read that chapter. + +@@ -15548,7 +15548,8 @@ history facility. + + @value{GDBN} uses the @sc{gnu} History library, a part of the Readline + package, to provide the history facility. @xref{Using History +-Interactively}, for the detailed description of the History library. ++Interactively, , , history, GNU History Library}, for the detailed description ++of the History library. + + To issue a command to @value{GDBN} without affecting certain aspects of + the state which is seen by users, prefix it with @samp{server } +@@ -15600,7 +15601,7 @@ This defaults to the value of the enviro + @end table + + History expansion assigns special meaning to the character @kbd{!}. +-@xref{Event Designators}, for more details. ++@xref{Event Designators, , , history, GNU History Library}, for more details. + + @cindex history expansion, turn on/off + Since @kbd{!} is also the logical not operator in C, history expansion +@@ -16660,7 +16661,8 @@ Indicates the current program counter ad + @cindex TUI key bindings + + The TUI installs several key bindings in the readline keymaps +-(@pxref{Command Line Editing}). The following key bindings ++(@pxref{Command Line Editing, , , rluserman, GNU Readline Library}). ++The following key bindings + are installed for both TUI mode and the @value{GDBN} standard mode. + + @table @kbd +@@ -21937,15 +21939,6 @@ Such guesses are usually wrong. Even we + things without first using the debugger to find the facts. + @end itemize + +-@c The readline documentation is distributed with the readline code +-@c and consists of the two following files: +-@c rluser.texinfo +-@c inc-hist.texinfo +-@c Use -I with makeinfo to point to the appropriate directory, +-@c environment var TEXINPUTS with TeX. +-@include rluser.texi +-@include inc-hist.texinfo +- + + @node Formatting Documentation + @appendix Formatting Documentation +@@ -22115,9 +22108,6 @@ source for the @samp{-liberty} free soft + @item gdb-@value{GDBVN}/opcodes + source for the library of opcode tables and disassemblers + +-@item gdb-@value{GDBVN}/readline +-source for the @sc{gnu} command-line interface +- + @item gdb-@value{GDBVN}/glob + source for the @sc{gnu} filename pattern-matching subroutine + +@@ -22149,7 +22139,7 @@ where @var{host} is an identifier such a + correct value by examining your system.) + + Running @samp{configure @var{host}} and then running @code{make} builds the +-@file{bfd}, @file{readline}, @file{mmalloc}, and @file{libiberty} ++@file{bfd}, @file{mmalloc}, and @file{libiberty} + libraries, then @code{gdb} itself. The configured source files, and the + binaries, are left in the corresponding source directories. + +@@ -22175,7 +22165,7 @@ source tree, the @file{gdb-@var{version- + that subdirectory. That is usually not what you want. In particular, + if you run the first @file{configure} from the @file{gdb} subdirectory + of the @file{gdb-@var{version-number}} directory, you will omit the +-configuration of @file{bfd}, @file{readline}, and other sibling ++configuration of @file{bfd}, and other sibling + directories of the @file{gdb} subdirectory. This leads to build errors + about missing include files such as @file{bfd/bfd.h}. + diff --git a/gdb-6.6-scheduler_locking-step-is-default.patch b/gdb-6.6-scheduler_locking-step-is-default.patch new file mode 100644 index 0000000..c91d360 --- /dev/null +++ b/gdb-6.6-scheduler_locking-step-is-default.patch @@ -0,0 +1,41 @@ +Index: gdb-6.8.50.20081128/gdb/infrun.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/infrun.c 2008-12-09 15:56:16.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/infrun.c 2008-12-09 15:56:59.000000000 +0100 +@@ -931,7 +931,7 @@ static const char *scheduler_enums[] = { + schedlock_step, + NULL + }; +-static const char *scheduler_mode = schedlock_off; ++static const char *scheduler_mode = schedlock_step; + static void + show_scheduler_mode (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.mi/mi-console.exp +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.mi/mi-console.exp 2008-08-06 14:52:08.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.mi/mi-console.exp 2008-12-09 15:59:34.000000000 +0100 +@@ -47,6 +47,9 @@ if { [gdb_compile "${srcdir}/${subdir}/ + + mi_run_to_main + ++# thread-id=\"all\" vs. thread-id=\"1\" below: ++mi_gdb_test "210-gdb-set scheduler-locking off" "210\\^done" "set scheduler-locking off" ++ + # Next over the hello() call which will produce lots of output + mi_gdb_test "220-exec-next" \ + "220\\^running(\r\n\\*running,thread-id=\"all\")?" \ +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.mi/mi2-console.exp +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.mi/mi2-console.exp 2008-08-06 14:52:08.000000000 +0200 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.mi/mi2-console.exp 2008-12-09 16:00:33.000000000 +0100 +@@ -47,6 +47,9 @@ if { [gdb_compile "${srcdir}/${subdir}/ + + mi_run_to_main + ++# thread-id=\"all\" vs. thread-id=\"1\" below: ++mi_gdb_test "210-gdb-set scheduler-locking off" "210\\^done" "set scheduler-locking off" ++ + # Next over the hello() call which will produce lots of output + send_gdb "220-exec-next\n" + gdb_expect { diff --git a/gdb-6.6-scheduler_locking-step-sw-watchpoints2.patch b/gdb-6.6-scheduler_locking-step-sw-watchpoints2.patch new file mode 100644 index 0000000..f6bc0cf --- /dev/null +++ b/gdb-6.6-scheduler_locking-step-sw-watchpoints2.patch @@ -0,0 +1,202 @@ +2007-06-25 Jan Kratochvil + + * inferior.h (enum resume_step): New definition. + (resume): Change STEP parameter type to ENUM RESUME_STEP. + * infrun.c (resume): Likewise. Extend debug printing of the STEP + parameter. Lock the scheduler only for intentional stepping. + (proceed): Replace the variable ONESTEP with tristate RESUME_STEP. + Set the third RESUME_STEP state according to BPSTAT_SHOULD_STEP. + (currently_stepping): Change the return type to ENUM RESUME_STEP. + Return RESUME_STEP_NEEDED if it is just due to BPSTAT_SHOULD_STEP. + * linux-nat.c (select_singlestep_lwp_callback): Do not focus on + the software watchpoint events. + * linux-nat.h (struct lwp_info): Redeclare STEP as ENUM RESUME_STEP. + +2007-10-19 Jan Kratochvil + + * infrun.c (proceed): RESUME_STEP initialized for non-stepping. + RESUME_STEP set according to STEP only at the end of the function. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +Index: gdb-6.8.50.20081209/gdb/inferior.h +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/inferior.h 2008-11-20 01:35:23.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/inferior.h 2008-12-10 01:22:23.000000000 +0100 +@@ -168,7 +168,15 @@ extern void reopen_exec_file (void); + /* The `resume' routine should only be called in special circumstances. + Normally, use `proceed', which handles a lot of bookkeeping. */ + +-extern void resume (int, enum target_signal); ++enum resume_step ++ { ++ /* currently_stepping () should return non-zero for non-continue. */ ++ RESUME_STEP_CONTINUE = 0, ++ RESUME_STEP_USER, /* Stepping is intentional by the user. */ ++ RESUME_STEP_NEEDED /* Stepping only for software watchpoints. */ ++ }; ++ ++extern void resume (enum resume_step, enum target_signal); + + /* From misc files */ + +Index: gdb-6.8.50.20081209/gdb/infrun.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/infrun.c 2008-12-02 20:20:23.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/infrun.c 2008-12-10 01:23:46.000000000 +0100 +@@ -73,7 +73,7 @@ static int follow_fork (void); + static void set_schedlock_func (char *args, int from_tty, + struct cmd_list_element *c); + +-static int currently_stepping (struct thread_info *tp); ++static enum resume_step currently_stepping (struct thread_info *tp); + + static int currently_stepping_callback (struct thread_info *tp, void *data); + +@@ -961,7 +961,7 @@ set_schedlock_func (char *args, int from + STEP nonzero if we should step (zero to continue instead). + SIG is the signal to give the inferior (zero for none). */ + void +-resume (int step, enum target_signal sig) ++resume (enum resume_step step, enum target_signal sig) + { + int should_resume = 1; + struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0); +@@ -975,10 +975,12 @@ resume (int step, enum target_signal sig + QUIT; + + if (debug_infrun) +- fprintf_unfiltered (gdb_stdlog, +- "infrun: resume (step=%d, signal=%d), " +- "trap_expected=%d\n", +- step, sig, tp->trap_expected); ++ fprintf_unfiltered (gdb_stdlog, "infrun: resume (step=%s, signal=%d), " ++ "trap_expected=%d\n", ++ (step == RESUME_STEP_CONTINUE ? "RESUME_STEP_CONTINUE" ++ : (step == RESUME_STEP_USER ? "RESUME_STEP_USER" ++ : "RESUME_STEP_NEEDED")), ++ sig, tp->trap_expected); + + /* Some targets (e.g. Solaris x86) have a kernel bug when stepping + over an instruction that causes a page fault without triggering +@@ -1127,9 +1129,10 @@ a command like `return' or `jump' to con + individually. */ + resume_ptid = inferior_ptid; + } +- else if ((scheduler_mode == schedlock_on) ++ else if (scheduler_mode == schedlock_on + || (scheduler_mode == schedlock_step +- && (step || singlestep_breakpoints_inserted_p))) ++ && (step == RESUME_STEP_USER ++ || singlestep_breakpoints_inserted_p))) + { + /* User-settable 'scheduler' mode requires solo thread resume. */ + resume_ptid = inferior_ptid; +@@ -1302,7 +1305,7 @@ proceed (CORE_ADDR addr, enum target_sig + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct thread_info *tp; + CORE_ADDR pc = regcache_read_pc (regcache); +- int oneproc = 0; ++ enum resume_step resume_step = RESUME_STEP_CONTINUE; + + if (step > 0) + step_start_function = find_pc_function (pc); +@@ -1322,13 +1325,13 @@ proceed (CORE_ADDR addr, enum target_sig + actually be executing the breakpoint insn anyway. + We'll be (un-)executing the previous instruction. */ + +- oneproc = 1; ++ resume_step = RESUME_STEP_USER; + else if (gdbarch_single_step_through_delay_p (gdbarch) + && gdbarch_single_step_through_delay (gdbarch, + get_current_frame ())) + /* We stepped onto an instruction that needs to be stepped + again before re-inserting the breakpoint, do so. */ +- oneproc = 1; ++ resume_step = RESUME_STEP_USER; + } + else + { +@@ -1359,13 +1362,13 @@ proceed (CORE_ADDR addr, enum target_sig + is required it returns TRUE and sets the current thread to + the old thread. */ + if (prepare_to_proceed (step)) +- oneproc = 1; ++ resume_step = RESUME_STEP_USER; + } + + /* prepare_to_proceed may change the current thread. */ + tp = inferior_thread (); + +- if (oneproc) ++ if (resume_step == RESUME_STEP_USER) + { + tp->trap_expected = 1; + /* If displaced stepping is enabled, we can step over the +@@ -1451,8 +1454,13 @@ proceed (CORE_ADDR addr, enum target_sig + /* Reset to normal state. */ + init_infwait_state (); + ++ if (step) ++ resume_step = RESUME_STEP_USER; ++ if (resume_step == RESUME_STEP_CONTINUE && bpstat_should_step ()) ++ resume_step = RESUME_STEP_NEEDED; ++ + /* Resume inferior. */ +- resume (oneproc || step || bpstat_should_step (), tp->stop_signal); ++ resume (resume_step, tp->stop_signal); + + /* Wait for it to stop (if not standalone) + and in any case decode why it stopped, and act accordingly. */ +@@ -3690,10 +3698,16 @@ currently_stepping_callback (struct thre + return tp != data && currently_stepping_thread (tp); + } + +-static int ++static enum resume_step + currently_stepping (struct thread_info *tp) + { +- return currently_stepping_thread (tp) || bpstat_should_step (); ++ if (currently_stepping_thread (tp)) ++ return RESUME_STEP_USER; ++ ++ if (bpstat_should_step ()) ++ return RESUME_STEP_NEEDED; ++ ++ return RESUME_STEP_CONTINUE; + } + + /* Inferior has stepped into a subroutine call with source code that +Index: gdb-6.8.50.20081209/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/linux-nat.c 2008-12-02 08:57:36.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/linux-nat.c 2008-12-10 01:22:23.000000000 +0100 +@@ -2343,7 +2343,10 @@ count_events_callback (struct lwp_info * + static int + select_singlestep_lwp_callback (struct lwp_info *lp, void *data) + { +- if (lp->step && lp->status != 0) ++ /* We do not focus on software watchpoints as we would not catch ++ STEPPING_PAST_SINGLESTEP_BREAKPOINT breakpoints in some other thread ++ as they would remain pending due to `Push back breakpoint for %s'. */ ++ if (lp->step == RESUME_STEP_USER && lp->status != 0) + return 1; + else + return 0; +Index: gdb-6.8.50.20081209/gdb/linux-nat.h +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/linux-nat.h 2008-07-27 23:12:40.000000000 +0200 ++++ gdb-6.8.50.20081209/gdb/linux-nat.h 2008-12-10 01:22:23.000000000 +0100 +@@ -55,8 +55,8 @@ struct lwp_info + /* If non-zero, a pending wait status. */ + int status; + +- /* Non-zero if we were stepping this LWP. */ +- int step; ++ /* The kind of stepping of this LWP. */ ++ enum resume_step step; + + /* Non-zero si_signo if this LWP stopped with a trap. si_addr may + be the address of a hardware watchpoint. */ diff --git a/gdb-6.6-step-thread-exit.patch b/gdb-6.6-step-thread-exit.patch new file mode 100644 index 0000000..05c678e --- /dev/null +++ b/gdb-6.6-step-thread-exit.patch @@ -0,0 +1,61 @@ +Index: gdb-6.8.50.20090226/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20090226.orig/gdb/linux-nat.c 2009-02-27 00:04:35.000000000 +0100 ++++ gdb-6.8.50.20090226/gdb/linux-nat.c 2009-02-27 07:51:44.000000000 +0100 +@@ -1790,15 +1790,17 @@ resume_set_callback (struct lwp_info *lp + + static void + linux_nat_resume (struct target_ops *ops, +- ptid_t ptid, int step, enum target_signal signo) ++ ptid_t ptid, int step_int, enum target_signal signo) + { + struct lwp_info *lp; + int resume_all; ++ enum resume_step step = step_int; + + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "LLR: Preparing to %s %s, %s, inferior_ptid %s\n", +- step ? "step" : "resume", ++ (step == RESUME_STEP_NEEDED ++ ? "needed" : (step ? "step" : "resume")), + target_pid_to_str (ptid), + signo ? strsignal (signo) : "0", + target_pid_to_str (inferior_ptid)); +@@ -2740,6 +2742,9 @@ linux_nat_filter_event (int lwpid, int s + /* Check if the thread has exited. */ + if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1) + { ++ enum resume_step step = lp->step; ++ pid_t pid = GET_PID (lp->ptid); ++ + /* If this is the main thread, we must stop all threads and + verify if they are still alive. This is because in the nptl + thread model, there is no signal issued for exiting LWPs +@@ -2763,6 +2768,26 @@ linux_nat_filter_event (int lwpid, int s + + exit_lwp (lp); + ++ if (step == RESUME_STEP_USER) ++ { ++ /* Now stop the closest LWP's ... */ ++ lp = find_lwp_pid (pid_to_ptid (pid)); ++ if (!lp) ++ lp = lwp_list; ++ gdb_assert (lp != NULL); ++ errno = 0; ++ ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, ++ (void *) (unsigned long) SIGSTOP); ++ if (debug_linux_nat) ++ fprintf_unfiltered (gdb_stdlog, ++ "PTRACE_CONT %s, 0, 0 (%s)\n", ++ target_pid_to_str (lp->ptid), ++ errno ? safe_strerror (errno) ++ : "OK"); ++ /* Avoid the silent `delayed SIGSTOP' handling. */ ++ lp->signalled = 0; ++ } ++ + /* If there is at least one more LWP, then the exit signal was + not the end of the debugged application and should be + ignored. */ diff --git a/gdb-6.6-testsuite-timeouts.patch b/gdb-6.6-testsuite-timeouts.patch new file mode 100644 index 0000000..3e716ae --- /dev/null +++ b/gdb-6.6-testsuite-timeouts.patch @@ -0,0 +1,42 @@ +--- ./gdb/testsuite/gdb.base/annota1.exp 10 Jan 2007 03:23:04 -0000 1.23 ++++ ./gdb/testsuite/gdb.base/annota1.exp 10 May 2007 12:54:11 -0000 +@@ -57,6 +57,8 @@ if [target_info exists gdb_stub] { + gdb_step_for_stub; + } + ++gdb_test "set breakpoint pending off" "" "Avoid lockup on nonexisting functions" ++ + # + # the line at which break main will put the breakpoint + # +--- ./gdb/testsuite/gdb.base/annota3.exp 9 Jan 2007 17:59:09 -0000 1.12 ++++ ./gdb/testsuite/gdb.base/annota3.exp 10 May 2007 12:54:11 -0000 +@@ -56,6 +56,8 @@ if [target_info exists gdb_stub] { + gdb_step_for_stub; + } + ++gdb_test "set breakpoint pending off" "" "Avoid lockup on nonexisting functions" ++ + # + # the line at which break main will put the breakpoint + # +--- gdb-6.6/gdb/testsuite/gdb.threads/step-thread-exit.exp-orig 2007-05-10 15:03:15.000000000 +0200 ++++ gdb-6.6/gdb/testsuite/gdb.threads/step-thread-exit.exp 2007-05-10 15:04:24.000000000 +0200 +@@ -58,6 +58,9 @@ gdb_test "continue" "Break.*thread_funct + # thread to be stopped and a message printed to tell us we have stepped + # over the thread exit. + set test "step over thread exit 1" ++# ppc64 is currently failing: ++set timeout_old $timeout ++set timeout 60 + gdb_test_multiple "next" "$test" { + -re "\}.*$gdb_prompt $" { + send_gdb "next\n" +@@ -71,6 +74,7 @@ gdb_test_multiple "next" "$test" { + exp_continue + } + } ++set timeout $timeout_old + + # Without this fixup we could end up in: + # #0 0x00110416 in __kernel_vsyscall () diff --git a/gdb-6.6-threads-static-test.patch b/gdb-6.6-threads-static-test.patch new file mode 100644 index 0000000..0303d5d --- /dev/null +++ b/gdb-6.6-threads-static-test.patch @@ -0,0 +1,25 @@ +--- gdb-6.6/gdb/testsuite/gdb.threads/staticthreads.exp-orig 2005-04-30 21:56:47.000000000 +0200 ++++ gdb-6.6/gdb/testsuite/gdb.threads/staticthreads.exp 2008-01-11 14:30:15.000000000 +0100 +@@ -44,9 +44,21 @@ gdb_load ${binfile} + gdb_test "set print sevenbit-strings" "" + + ++runto_main ++ ++# See if we get excessive LWP there (patched glibc with unpatched GDB): ++# * 2 Thread 135661664 (LWP 3856) main () at threadloop.c:41 ++# 1 process 3856 main () at threadloop.c:41 ++ ++set test "info threads on start" ++gdb_test_multiple "info threads" "$test" { ++ -re "^info threads\r?\n\[^\r\n\]* Thread \[^\r\n\]*\r?\n$gdb_prompt" { ++ pass "$test" ++ } ++} ++ + # See if the static multi-threaded program runs. + +-runto_main + gdb_test "break sem_post" + set test "Continue to main's call of sem_post" + gdb_test_multiple "continue" "$test" { diff --git a/gdb-6.7-bz426600-DW_TAG_interface_type-fix.patch b/gdb-6.7-bz426600-DW_TAG_interface_type-fix.patch new file mode 100644 index 0000000..14866e2 --- /dev/null +++ b/gdb-6.7-bz426600-DW_TAG_interface_type-fix.patch @@ -0,0 +1,41 @@ +Original patch was: +http://sourceware.org/ml/gdb-patches/2007-12/msg00397.html +http://sourceware.org/ml/gdb-cvs/2007-12/msg00123.html + +extended for the RHEL safety: + +2007-12-28 Jan Kratochvil + + * dwarf2read.c (fixup_partial_die): Provide full + `DW_TAG_class_type'-type backing for `DW_TAG_interface_type', even for + namespaces which should not apply for Java `DW_TAG_interface_type'. + +2008-02-24 Jan Kratochvil + + Port to GDB-6.8pre. + +Index: ./gdb/dwarf2read.c +=================================================================== +RCS file: /cvs/src/src/gdb/dwarf2read.c,v +retrieving revision 1.245 +diff -u -p -r1.245 dwarf2read.c +--- ./gdb/dwarf2read.c 26 Dec 2007 12:36:18 -0000 1.245 ++++ ./gdb/dwarf2read.c 27 Dec 2007 23:25:49 -0000 +@@ -5887,7 +5887,8 @@ fixup_partial_die (struct partial_die_in + + /* Set default names for some unnamed DIEs. */ + if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type +- || part_die->tag == DW_TAG_class_type)) ++ || part_die->tag == DW_TAG_class_type ++ || part_die->tag == DW_TAG_interface_type)) + part_die->name = "(anonymous class)"; + + if (part_die->name == NULL && part_die->tag == DW_TAG_namespace) +@@ -5895,6 +5896,7 @@ fixup_partial_die (struct partial_die_in + + if (part_die->tag == DW_TAG_structure_type + || part_die->tag == DW_TAG_class_type ++ || part_die->tag == DW_TAG_interface_type + || part_die->tag == DW_TAG_union_type) + guess_structure_name (part_die, cu); + } diff --git a/gdb-6.7-bz426600-DW_TAG_interface_type-test.patch b/gdb-6.7-bz426600-DW_TAG_interface_type-test.patch new file mode 100644 index 0000000..0b44faf --- /dev/null +++ b/gdb-6.7-bz426600-DW_TAG_interface_type-test.patch @@ -0,0 +1,710 @@ +http://sourceware.org/ml/gdb-patches/2007-12/msg00397.html + +2007-12-22 Jan Kratochvil + + * gdb.arch/i386-interface.S, gdb.arch/i386-interface.exp: New files. + +2008-03-02 Jan Kratochvil + + * gdb.arch/i386-interface.exp: Fix a testcase race. + +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/i386-interface.S 22 Dec 2007 19:07:28 -0000 +@@ -0,0 +1,628 @@ ++/* Copyright 2007 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 3 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, see . ++ ++ Please email any bugs, comments, and/or additions to this file to: ++ bug-gdb@gnu.org ++ ++ This file is part of the gdb testsuite. ++ ++ This file was produced by: ++ $ gcj -S interface.java -ggdb2 -Wall -m32 ++ from the .java file: ++ interface Interface ++ { ++ } ++ class Class implements Interface ++ { ++ } ++*/ ++ ++ .file "cc28Pp2B.jar" ++ .section .debug_abbrev,"",@progbits ++.Ldebug_abbrev0: ++ .section .debug_info,"",@progbits ++.Ldebug_info0: ++ .section .debug_line,"",@progbits ++.Ldebug_line0: ++ .text ++.Ltext0: ++ .local _MT_Interface ++ .comm _MT_Interface,0,4 ++ .data ++ .align 4 ++ .type _catch_classes_Interface, @object ++ .size _catch_classes_Interface, 24 ++_catch_classes_Interface: ++ .zero 24 ++ .section .rodata ++ .align 2 ++ .type _Utf1, @object ++ .size _Utf1, 4 ++_Utf1: ++ .value 36121 ++ .value 9 ++ .ascii "Interface" ++ .zero 1 ++.globl _ZN9Interface6class$E ++ .data ++ .align 32 ++ .type _ZN9Interface6class$E, @object ++ .size _ZN9Interface6class$E, 144 ++_ZN9Interface6class$E: ++ .long _ZTVN4java4lang5ClassE+8 ++ .long 403000 ++ .long _Utf1 ++ .value 1536 ++ .zero 2 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long _MT_Interface ++ .value 0 ++ .value 6 ++ .long 0 ++ .long 4 ++ .value 0 ++ .value 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long _catch_classes_Interface ++ .long 0 ++ .long 0 ++ .value 0 ++ .byte 1 ++ .zero 1 ++ .long 0 ++ .value 0 ++ .zero 2 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .hidden _ZN9Interface7class$$E ++.globl _ZN9Interface7class$$E ++ .section .rodata ++ .align 4 ++ .type _ZN9Interface7class$$E, @object ++ .size _ZN9Interface7class$$E, 4 ++_ZN9Interface7class$$E: ++ .long _ZN9Interface6class$E ++ .text ++ .align 2 ++.globl _ZN5ClassC1Ev ++ .type _ZN5ClassC1Ev, @function ++_ZN5ClassC1Ev: ++.LFB2: ++ pushl %ebp ++.LCFI0: ++ movl %esp, %ebp ++.LCFI1: ++ subl $24, %esp ++.LCFI2: ++.LBB2: ++#if 0 ++ .file 1 "interface.java" ++#else ++ .file "interface.java" ++#endif ++ .loc 1 4 0 ++ movl 8(%ebp), %eax ++ movl %eax, -4(%ebp) ++ movl -4(%ebp), %eax ++ movl %eax, (%esp) ++ call _ZN4java4lang6ObjectC1Ev ++.LBE2: ++ leave ++ ret ++.LFE2: ++ .size _ZN5ClassC1Ev, .-_ZN5ClassC1Ev ++ .hidden _ZTVN5ClassE ++.globl _ZTVN5ClassE ++ .data ++ .align 32 ++ .type _ZTVN5ClassE, @object ++ .size _ZTVN5ClassE, 40 ++_ZTVN5ClassE: ++ .long 0 ++ .long 0 ++ .long _ZN5Class6class$E ++ .long 4 ++ .long _ZN4java4lang6Object8finalizeEJvv ++ .long _ZN4java4lang6Object8hashCodeEJiv ++ .long _ZN4java4lang6Object6equalsEJbPS1_ ++ .long _ZN4java4lang6Object8toStringEJPNS0_6StringEv ++ .long _ZN4java4lang6Object5cloneEJPS1_v ++ .long _ZN4java4lang6Object22throwNoSuchMethodErrorEJvv ++ .set .L_ZN5ClassC1Ev0,_ZN5ClassC1Ev ++ .section .rodata ++ .align 2 ++ .type _Utf2, @object ++ .size _Utf2, 4 ++_Utf2: ++ .value 626 ++ .value 6 ++ .ascii "" ++ .zero 1 ++ .align 2 ++ .type _Utf3, @object ++ .size _Utf3, 4 ++_Utf3: ++ .value 39797 ++ .value 3 ++ .ascii "()V" ++ .zero 1 ++ .data ++ .align 4 ++ .type _MT_Class, @object ++ .size _MT_Class, 20 ++_MT_Class: ++ .long _Utf2 ++ .long _Utf3 ++ .value 16384 ++ .value -1 ++ .long .L_ZN5ClassC1Ev0 ++ .long 0 ++ .align 4 ++ .type _IF_Class, @object ++ .size _IF_Class, 4 ++_IF_Class: ++ .long _ZN9Interface6class$E ++ .align 4 ++ .type _catch_classes_Class, @object ++ .size _catch_classes_Class, 24 ++_catch_classes_Class: ++ .zero 24 ++ .section .rodata ++ .align 2 ++ .type _Utf4, @object ++ .size _Utf4, 4 ++_Utf4: ++ .value 47448 ++ .value 5 ++ .ascii "Class" ++ .zero 1 ++.globl _ZN5Class6class$E ++ .data ++ .align 32 ++ .type _ZN5Class6class$E, @object ++ .size _ZN5Class6class$E, 144 ++_ZN5Class6class$E: ++ .long _ZTVN4java4lang5ClassE+8 ++ .long 403000 ++ .long _Utf4 ++ .value 32 ++ .zero 2 ++ .long _ZN4java4lang6Object6class$E ++ .long 0 ++ .long 0 ++ .long 0 ++ .long _MT_Class ++ .value 1 ++ .value 6 ++ .long 0 ++ .long 4 ++ .value 0 ++ .value 0 ++ .long _ZTVN5ClassE+8 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long _catch_classes_Class ++ .long _IF_Class ++ .long 0 ++ .value 1 ++ .byte 1 ++ .zero 1 ++ .long 0 ++ .value 0 ++ .zero 2 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .long 0 ++ .hidden _ZN5Class7class$$E ++.globl _ZN5Class7class$$E ++ .section .rodata ++ .align 4 ++ .type _ZN5Class7class$$E, @object ++ .size _ZN5Class7class$$E, 4 ++_ZN5Class7class$$E: ++ .long _ZN5Class6class$E ++ .section .jcr,"aw",@progbits ++ .align 4 ++ .long _ZN9Interface6class$E ++ .long _ZN5Class6class$E ++ .section .debug_frame,"",@progbits ++.Lframe0: ++ .long .LECIE0-.LSCIE0 ++.LSCIE0: ++ .long 0xffffffff ++ .byte 0x1 ++ .string "" ++ .uleb128 0x1 ++ .sleb128 -4 ++ .byte 0x8 ++ .byte 0xc ++ .uleb128 0x4 ++ .uleb128 0x4 ++ .byte 0x88 ++ .uleb128 0x1 ++ .align 4 ++.LECIE0: ++.LSFDE0: ++ .long .LEFDE0-.LASFDE0 ++.LASFDE0: ++ .long .Lframe0 ++ .long .LFB2 ++ .long .LFE2-.LFB2 ++ .byte 0x4 ++ .long .LCFI0-.LFB2 ++ .byte 0xe ++ .uleb128 0x8 ++ .byte 0x85 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x5 ++ .align 4 ++.LEFDE0: ++ .section .eh_frame,"a",@progbits ++.Lframe1: ++ .long .LECIE1-.LSCIE1 ++.LSCIE1: ++ .long 0x0 ++ .byte 0x1 ++.globl __gcj_personality_v0 ++ .string "zP" ++ .uleb128 0x1 ++ .sleb128 -4 ++ .byte 0x8 ++ .uleb128 0x5 ++ .byte 0x0 ++ .long __gcj_personality_v0 ++ .byte 0xc ++ .uleb128 0x4 ++ .uleb128 0x4 ++ .byte 0x88 ++ .uleb128 0x1 ++ .align 4 ++.LECIE1: ++.LSFDE1: ++ .long .LEFDE1-.LASFDE1 ++.LASFDE1: ++ .long .LASFDE1-.Lframe1 ++ .long .LFB2 ++ .long .LFE2-.LFB2 ++ .uleb128 0x0 ++ .byte 0x4 ++ .long .LCFI0-.LFB2 ++ .byte 0xe ++ .uleb128 0x8 ++ .byte 0x85 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x5 ++ .align 4 ++.LEFDE1: ++ .text ++.Letext0: ++ .section .debug_loc,"",@progbits ++.Ldebug_loc0: ++.LLST0: ++ .long .LFB2-.Ltext0 ++ .long .LCFI0-.Ltext0 ++ .value 0x2 ++ .byte 0x74 ++ .sleb128 4 ++ .long .LCFI0-.Ltext0 ++ .long .LCFI1-.Ltext0 ++ .value 0x2 ++ .byte 0x74 ++ .sleb128 8 ++ .long .LCFI1-.Ltext0 ++ .long .LFE2-.Ltext0 ++ .value 0x2 ++ .byte 0x75 ++ .sleb128 8 ++ .long 0x0 ++ .long 0x0 ++ .section .debug_info ++ .long 0x117 ++ .value 0x2 ++ .long .Ldebug_abbrev0 ++ .byte 0x4 ++ .uleb128 0x1 ++ .string "GNU Java 4.3.0 20071221 (experimental)" ++ .byte 0xb ++ .string "interface.java" ++ .string "/home/jkratoch/redhat/bz371831" ++ .long .Ltext0 ++ .long .Letext0 ++ .long .Ldebug_line0 ++ .uleb128 0x2 ++ .string "Interface" ++ .byte 0x4 ++ .byte 0x1 ++ .byte 0x0 ++ .long 0x8e ++ .long 0x8e ++ .uleb128 0x3 ++ .long 0x8e ++ .byte 0x2 ++ .byte 0x23 ++ .uleb128 0x0 ++ .byte 0x1 ++ .byte 0x0 ++ .uleb128 0x4 ++ .string "java.lang.Object" ++ .byte 0x1 ++ .uleb128 0x5 ++ .string "Class" ++ .byte 0x4 ++ .byte 0x1 ++ .byte 0x0 ++ .long 0x8e ++ .long 0xe8 ++ .uleb128 0x3 ++ .long 0x8e ++ .byte 0x2 ++ .byte 0x23 ++ .uleb128 0x0 ++ .byte 0x1 ++ .uleb128 0x6 ++ .long 0x6e ++ .byte 0x2 ++ .byte 0x23 ++ .uleb128 0x0 ++ .byte 0x1 ++ .byte 0x1 ++ .uleb128 0x7 ++ .byte 0x1 ++ .string "" ++ .byte 0x1 ++ .byte 0x0 ++ .string "_ZN5ClassC1Ev" ++ .byte 0x1 ++ .uleb128 0x8 ++ .long 0xe8 ++ .byte 0x1 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x9 ++ .byte 0x4 ++ .long 0xa1 ++ .uleb128 0xa ++ .long 0xc6 ++ .long .LFB2 ++ .long .LFE2 ++ .long .LLST0 ++ .long 0x114 ++ .uleb128 0xb ++ .long 0xe8 ++ .byte 0x2 ++ .byte 0x91 ++ .sleb128 0 ++ .uleb128 0xc ++ .long 0x114 ++ .byte 0x2 ++ .byte 0x91 ++ .sleb128 -12 ++ .byte 0x0 ++ .uleb128 0x9 ++ .byte 0x4 ++ .long 0x8e ++ .byte 0x0 ++ .section .debug_abbrev ++ .uleb128 0x1 ++ .uleb128 0x11 ++ .byte 0x1 ++ .uleb128 0x25 ++ .uleb128 0x8 ++ .uleb128 0x13 ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x1b ++ .uleb128 0x8 ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x10 ++ .uleb128 0x6 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x2 ++ .uleb128 0x38 ++ .byte 0x1 ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x1d ++ .uleb128 0x13 ++ .uleb128 0x1 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x1c ++ .byte 0x0 ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x38 ++ .uleb128 0xa ++ .uleb128 0x32 ++ .uleb128 0xb ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x4 ++ .uleb128 0x2 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x3c ++ .uleb128 0xc ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x5 ++ .uleb128 0x2 ++ .byte 0x1 ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x1d ++ .uleb128 0x13 ++ .uleb128 0x1 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x6 ++ .uleb128 0x1c ++ .byte 0x0 ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x38 ++ .uleb128 0xa ++ .uleb128 0x4c ++ .uleb128 0xb ++ .uleb128 0x32 ++ .uleb128 0xb ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x7 ++ .uleb128 0x2e ++ .byte 0x1 ++ .uleb128 0x3f ++ .uleb128 0xc ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x2007 ++ .uleb128 0x8 ++ .uleb128 0x3c ++ .uleb128 0xc ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x8 ++ .uleb128 0x5 ++ .byte 0x0 ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x34 ++ .uleb128 0xc ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x9 ++ .uleb128 0xf ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0xa ++ .uleb128 0x2e ++ .byte 0x1 ++ .uleb128 0x47 ++ .uleb128 0x13 ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x40 ++ .uleb128 0x6 ++ .uleb128 0x1 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0x5 ++ .byte 0x0 ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0xc ++ .uleb128 0x34 ++ .byte 0x0 ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .byte 0x0 ++ .section .debug_pubnames,"",@progbits ++ .long 0x15 ++ .value 0x2 ++ .long .Ldebug_info0 ++ .long 0x11b ++ .long 0xee ++ .string "()" ++ .long 0x0 ++ .section .debug_aranges,"",@progbits ++ .long 0x1c ++ .value 0x2 ++ .long .Ldebug_info0 ++ .byte 0x4 ++ .byte 0x0 ++ .value 0x0 ++ .value 0x0 ++ .long .Ltext0 ++ .long .Letext0-.Ltext0 ++ .long 0x0 ++ .long 0x0 ++ .ident "GCC: (GNU) 4.3.0 20071221 (experimental)" ++ .section .note.GNU-stack,"",@progbits +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/i386-interface.exp 22 Dec 2007 19:07:28 -0000 +@@ -0,0 +1,66 @@ ++# Copyright 2007 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 3 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, see . ++ ++# Please email any bugs, comments, and/or additions to this file to: ++# bug-gdb@gnu.org ++ ++# This file is part of the gdb testsuite. ++ ++# Test basis recognization of DW_TAG_interface_type. ++# GCC java_classify_record() produces it if returns RECORD_IS_INTERFACE. ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++if {![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"]} then { ++ verbose "Skipping i386 Java DW_TAG_interface_type test." ++ return ++} ++ ++set testfile "i386-interface" ++set srcfile ${testfile}.S ++set binfile ${objdir}/${subdir}/${testfile}.o ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" object {debug additional_flags=-m32}] != "" } { ++ untested i386-gnu-cfi.exp ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_test "set language java" ++ ++set test "ptype Interface" ++gdb_test_multiple $test $test { ++ -re "type = class Interface *extends java.lang.Object \{.*$gdb_prompt $" { ++ pass $test ++ } ++} ++ ++set test "ptype Class" ++gdb_test_multiple $test $test { ++ -re "type = class Class *extends java.lang.Object implements Interface \{.*$gdb_prompt $" { ++ pass $test ++ } ++} diff --git a/gdb-6.7-charsign-test.patch b/gdb-6.7-charsign-test.patch new file mode 100644 index 0000000..b539d0d --- /dev/null +++ b/gdb-6.7-charsign-test.patch @@ -0,0 +1,125 @@ +https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=224128 + +2007-01-25 Jan Kratochvil + + * gdb.base/charsign.exp, gdb.base/charsign.c: New files. + [ stripped ] + +2007-10-19 Jan Kratochvil + + Port to GDB-6.7 - only the testcase left, patch has been reverted, + char-vectors restricted. + +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/charsign.c 26 Jan 2007 10:32:00 -0000 +@@ -0,0 +1,37 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007 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 */ ++ ++int main() ++{ ++ return 0; ++} ++ ++char n[]="A"; ++signed char s[]="A"; ++unsigned char u[]="A"; ++ ++typedef char char_n; ++typedef signed char char_s; ++typedef unsigned char char_u; ++ ++char_n n_typed[]="A"; ++char_s s_typed[]="A"; ++char_u u_typed[]="A"; +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/charsign.exp 26 Jan 2007 10:32:00 -0000 +@@ -0,0 +1,70 @@ ++# Copyright 2007 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. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile charsign ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++proc do_test { cflags } { ++ global srcdir ++ global binfile ++ global subdir ++ global srcfile ++ global gdb_prompt ++ ++ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug additional_flags=$cflags]] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++ } ++ ++ # Get things started. ++ ++ gdb_exit ++ gdb_start ++ gdb_reinitialize_dir $srcdir/$subdir ++ gdb_load ${binfile} ++ ++ # For C programs, "start" should stop in main(). ++ ++ gdb_test "p n" \ ++ "= \"A\"" ++ gdb_test "p s" \ ++ "= \\{65 'A', 0 '\\\\0'\\}" ++ gdb_test "p u" \ ++ "= \\{65 'A', 0 '\\\\0'\\}" ++ gdb_test "p n_typed" \ ++ "= \"A\"" ++ gdb_test "p s_typed" \ ++ "= \\{65 'A', 0 '\\\\0'\\}" ++ gdb_test "p u_typed" \ ++ "= \\{65 'A', 0 '\\\\0'\\}" ++} ++ ++# The string identification works despite the compiler flags below due to ++# gdbtypes.c: ++# if (name && strcmp (name, "char") == 0) ++# TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN; ++ ++do_test {} ++do_test {-fsigned-char} ++do_test {-funsigned-char} diff --git a/gdb-6.7-kernel-headers-compat.patch b/gdb-6.7-kernel-headers-compat.patch new file mode 100644 index 0000000..309e0d7 --- /dev/null +++ b/gdb-6.7-kernel-headers-compat.patch @@ -0,0 +1,24 @@ +kernel-headers-2.6.25-0.40.rc1.git2.fc9.x86_64 + +In file included from /usr/include/asm/ptrace.h:4, + from ../../gdb/amd64-linux-nat.c:44: +/usr/include/asm/ptrace-abi.h:92: error: expected specifier-qualifier-list before ‘u32’ + +--- gdb-6.7.1-13.fc9.x86_64/gdb/amd64-linux-nat.c-orig 2008-02-15 15:37:28.000000000 -0500 ++++ gdb-6.7.1-13.fc9.x86_64/gdb/amd64-linux-nat.c 2008-02-15 15:40:13.000000000 -0500 +@@ -35,13 +35,13 @@ + #include + #include + /* FIXME ezannoni-2003-07-09: we need to be included after +- because the latter redefines FS and GS for no apparent ++ because the latter redefines FS and GS for no apparent + reason, and those definitions don't match the ones that libpthread_db + uses, which come from . */ + /* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have + been removed from ptrace.h in the kernel. However, better safe than + sorry. */ +-#include ++#include + #include + #include "gdb_proc_service.h" + diff --git a/gdb-6.7-ppc-clobbered-registers-O2-test.patch b/gdb-6.7-ppc-clobbered-registers-O2-test.patch new file mode 100644 index 0000000..78c158b --- /dev/null +++ b/gdb-6.7-ppc-clobbered-registers-O2-test.patch @@ -0,0 +1,103 @@ +2007-11-04 Jan Kratochvil + + * gdb.arch/ppc-clobbered-registers-O2.exp: `powerpc64' changed to + `powerpc*'. + +Testcase for: + +http://sourceware.org/ml/gdb-patches/2007-09/msg00228.html + +2007-10-21 Luis Machado + + * rs6000-tdep.c (ppc_dwarf2_frame_init_reg): New function. + * (rs6000_gdbarch_init): Install ppc_dwarf2_frame_init_reg as + default dwarf2_frame_set_init_reg function. + +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/ppc-clobbered-registers-O2.c 3 Nov 2007 22:22:28 -0000 +@@ -0,0 +1,21 @@ ++ ++unsigned * __attribute__((noinline)) ++start_sequence (unsigned * x, unsigned * y) ++{ ++ return (unsigned *)0xdeadbeef; ++}; ++ ++unsigned __attribute__((noinline)) ++gen_movsd (unsigned * operand0, unsigned * operand1) ++{ ++ return *start_sequence(operand0, operand1); ++} ++ ++int main(void) ++{ ++ unsigned x, y; ++ ++ x = 13; ++ y = 14; ++ return (int)gen_movsd (&x, &y); ++} +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/ppc-clobbered-registers-O2.exp 3 Nov 2007 22:22:28 -0000 +@@ -0,0 +1,61 @@ ++# Copyright 2006 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. ++# ++# This file is part of the gdb testsuite. ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++# Test displaying call clobbered registers in optimized binaries for ppc. ++# GDB should not show incorrect values. ++ ++set prms_id 0 ++set bug_id 0 ++ ++if ![istarget "powerpc*-*"] then { ++ verbose "Skipping powerpc* call clobbered registers testing." ++ return ++} ++ ++set testfile "ppc-clobbered-registers-O2" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++set compile_flags "debug additional_flags=-O2" ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ${compile_flags}] != "" } { ++ unsupported "Testcase compile failed." ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto_main] then { ++ perror "Couldn't run to breakpoint" ++ continue ++} ++ ++gdb_test "b start_sequence" ".*Breakpoint 2 at.*line 6.*" \ ++ "Insert breakpoint at problematic function" ++ ++gdb_test continue ".*Breakpoint 2.*in start_sequence.*" \ ++ "Run until problematic function" ++ ++gdb_test backtrace ".*operand0=.*operand1=.*" \ ++ "Check value of call clobbered registers" diff --git a/gdb-6.7-testsuite-stable-results.patch b/gdb-6.7-testsuite-stable-results.patch new file mode 100644 index 0000000..8e57248 --- /dev/null +++ b/gdb-6.7-testsuite-stable-results.patch @@ -0,0 +1,208 @@ +gdb/testsuite/gdb.base/fileio.c: +gdb/testsuite/gdb.base/fileio.exp: +2007-12-08 Jan Kratochvil + + * gdb.base/fileio.c (ROOTSUBDIR): New macro. + (main): CHDIR into ROOTSUBDIR. CHOWN ROOTSUBDIR and CHDIR into + ROOTSUBDIR if we are being run as root. + * gdb.base/fileio.exp: Change the startup and finish cleanup. + Change the test file reference to be into the `fileio.dir' directory. + + +sources/gdb/testsuite/gdb.base/dump.exp: +Found on RHEL-5.s390x. + + +gdb-6.8.50.20090209/gdb/testsuite/gdb.base/auxv.exp: +random FAIL: gdb.base/auxv.exp: matching auxv data from live and gcore + + +gdb-6.8.50.20090209/gdb/testsuite/gdb.base/annota1.exp: +frames-invalid can happen asynchronously. + +--- ./gdb/testsuite/gdb.base/fileio.c 13 Jun 2006 08:55:22 -0000 1.10 ++++ ./gdb/testsuite/gdb.base/fileio.c 8 Dec 2007 16:04:10 -0000 +@@ -58,6 +58,8 @@ system (const char * string); + 1) Invalid string/command. - returns 127. */ + static const char *strerrno (int err); + ++#define ROOTSUBDIR "fileio.dir" ++ + #define FILENAME "foo.fileio.test" + #define RENAMED "bar.fileio.test" + #define NONEXISTANT "nofoo.fileio.test" +@@ -542,6 +544,37 @@ strerrno (int err) + int + main () + { ++ /* ROOTSUBDIR is already prepared by fileio.exp. We use it for easy cleanup ++ (by fileio.exp) if we are run by multiple users in the same directory. */ ++ ++ if (chdir (ROOTSUBDIR) != 0) ++ { ++ printf ("chdir " ROOTSUBDIR ": %s\n", strerror (errno)); ++ exit (1); ++ } ++ ++ /* These tests ++ Open for write but no write permission returns EACCES ++ Unlinking a file in a directory w/o write access returns EACCES ++ fail if we are being run as root - drop the privileges here. */ ++ ++ if (geteuid () == 0) ++ { ++ uid_t uid = 99; ++ ++ if (chown (".", uid, uid) != 0) ++ { ++ printf ("chown %d.%d " ROOTSUBDIR ": %s\n", (int) uid, (int) uid, ++ strerror (errno)); ++ exit (1); ++ } ++ if (setuid (uid) || geteuid () == 0) ++ { ++ printf ("setuid %d: %s\n", (int) uid, strerror (errno)); ++ exit (1); ++ } ++ } ++ + /* Don't change the order of the calls. They partly depend on each other */ + test_open (); + test_write (); +--- ./gdb/testsuite/gdb.base/fileio.exp 23 Aug 2007 18:14:16 -0000 1.12 ++++ ./gdb/testsuite/gdb.base/fileio.exp 8 Dec 2007 16:04:10 -0000 +@@ -46,8 +46,8 @@ if [get_compiler_info ${binfile}] { + return -1; + } + +-remote_exec build {sh -xc test\ -r\ dir2.fileio.test\ &&\ chmod\ -f\ +w\ dir2.fileio.test} +-remote_exec build {sh -xc rm\ -rf\ *.fileio.test} ++remote_exec build {sh -xc rm\ -rf\ fileio.dir} ++remote_exec build {sh -xc mkdir\ -m777\ fileio.dir} + + set oldtimeout $timeout + set timeout [expr "$timeout + 60"] +@@ -88,7 +88,7 @@ gdb_test continue \ + "Opening nonexistant file returns ENOENT" + + send_gdb "continue\n" ; gdb_expect -re "$gdb_prompt $" +-catch "system \"chmod -f -w nowrt.fileio.test\"" ++catch "system \"chmod -f -w fileio.dir/nowrt.fileio.test\"" + + gdb_test continue \ + "Continuing\\..*open 5:.*EACCES$stop_msg" \ +@@ -252,8 +252,8 @@ gdb_test continue \ + send_gdb "quit\n" + send_gdb "y\n" + +-remote_exec build {sh -xc test\ -r\ dir2.fileio.test\ &&\ chmod\ -f\ +w\ dir2.fileio.test} +-remote_exec build {sh -xc rm\ -rf\ *.fileio.test} ++remote_exec build {sh -xc test\ -r\ fileio.dir/dir2.fileio.test\ &&\ chmod\ -f\ +w\ fileio.dir/dir2.fileio.test} ++remote_exec build {sh -xc rm\ -rf\ fileio.dir} + + set timeout $oldtimeout + return 0 +--- sources/gdb/testsuite/gdb.base/dump.exp-orig 2008-08-28 11:44:40.000000000 +0200 ++++ sources/gdb/testsuite/gdb.base/dump.exp 2008-08-28 11:44:49.000000000 +0200 +@@ -493,8 +493,10 @@ if ![string compare $is64bitonly "no"] t + gdb_test "print zero_all ()" "" "" + + # restore with expressions ++ # Address may fit in int32 but its negative result would be 0xffffxxxx for ++ # 64-bit LONGEST addresses. + test_restore_saved_value \ +- "intarr3.srec ${array2_start}-${array_start} &intarray\[3\] &intarray\[4\]" \ ++ "intarr3.srec (long)${array2_start}-${array_start} &intarray\[3\] &intarray\[4\]" \ + "array partial with expressions" 4 "intarray2\[3\]" + + gdb_test "print intarray2\[2\] == 0" " = 1" "element 2 not changed, == 4" +--- gdb-6.8.50.20090209/gdb/testsuite/gdb.base/annota1.exp-orig 2009-02-09 16:31:11.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.base/annota1.exp 2009-02-09 21:27:38.000000000 +0100 +@@ -286,7 +286,7 @@ if [target_info exists gdb,nosignals] { + } else { + send_gdb "signal SIGUSR1\n" + gdb_expect { +- -re "\r\n\032\032post-prompt\r\nContinuing with signal SIGUSR1.\r\n\r\n\032\032starting\r\n\r\n\032\032frames-invalid\r\n\r\n\032\032breakpoint 2\r\n\r\nBreakpoint 2, \r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nhandle_USR1\r\n\032\032frame-args\r\n \\(\r\n\032\032arg-begin\r\nsig\r\n\032\032arg-name-end\r\n=\r\n\032\032arg-value -\r\n$decimal\r\n\032\032arg-end\r\n\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n${escapedsrcfile}\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n.*\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source.*annota1.c:.*:.*:beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \ ++ -re "\r\n\032\032post-prompt\r\nContinuing with signal SIGUSR1.\r\n\r\n\032\032starting\r\n(\r\n\032\032frames-invalid\r\n)*\r\n\032\032breakpoint 2\r\n\r\nBreakpoint 2, \r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nhandle_USR1\r\n\032\032frame-args\r\n \\(\r\n\032\032arg-begin\r\nsig\r\n\032\032arg-name-end\r\n=\r\n\032\032arg-value -\r\n$decimal\r\n\032\032arg-end\r\n\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n${escapedsrcfile}\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n.*\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source.*annota1.c:.*:.*:beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \ + { pass "send SIGUSR1" } + -re "\r\n\032\032post-prompt\r\nContinuing with signal SIGUSR1.\r\n\r\n\032\032starting\r\n\r\n\032\032frames-invalid\r\n\r\n\032\032breakpoint 2\r\n\r\nBreakpoint 2, \r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nhandle_USR1\r\n\032\032frame-args\r\n \\(\r\n\032\032arg-begin\r\nsig\r\n\032\032arg-name-end\r\n=\r\n\032\032arg-value -\r\n$decimal\r\n\032\032arg-end\r\n\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n.*${srcfile}\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n.*\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source.*annota1.c:.*:.*:beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \ + { setup_xfail "*-*-*" 1270 +--- ./gdb/testsuite/gdb.base/auxv.exp 2009-02-11 00:54:54.000000000 +0100 ++++ ./gdb/testsuite/gdb.base/auxv.exp 2009-02-11 00:51:30.000000000 +0100 +@@ -78,8 +78,10 @@ proc fetch_auxv {test} { + + set auxv_lines {} + set bad -1 ++ # Former trailing `\[\r\n\]+' may eat just \r leaving \n in the buffer ++ # corrupting the next matches. + if {[gdb_test_multiple "info auxv" $test { +- -re "info auxv\[\r\n\]+" { ++ -re "info auxv\r\n" { + exp_continue + } + -ex "The program has no auxiliary information now" { +@@ -94,20 +96,20 @@ proc fetch_auxv {test} { + set bad 1 + exp_continue + } +- -re "^\[0-9\]+\[ \t\]+(AT_\[^ \t\]+)\[^\r\n\]+\[\r\n\]+" { ++ -re "^\[0-9\]+\[ \t\]+(AT_\[^ \t\]+)\[^\r\n\]+\r\n" { + lappend auxv_lines $expect_out(0,string) + exp_continue + } +- -re "^\[0-9\]+\[ \t\]+\\?\\?\\?\[^\r\n\]+\[\r\n\]+" { ++ -re "^\[0-9\]+\[ \t\]+\\?\\?\\?\[^\r\n\]+\r\n" { + warning "Unrecognized tag value: $expect_out(0,string)" + set bad 1 + lappend auxv_lines $expect_out(0,string) + exp_continue + } +- -re ".*$gdb_prompt $" { ++ -re "$gdb_prompt $" { + incr bad + } +- -re "^\[^\r\n\]+\[\r\n\]+" { ++ -re "^\[^\r\n\]+\r\n" { + if {!$bad} { + warning "Unrecognized output: $expect_out(0,string)" + set bad 1 +--- ./gdb/testsuite/gdb.base/callfuncs.exp 2009-01-03 06:58:03.000000000 +0100 ++++ ./gdb/testsuite/gdb.base/callfuncs.exp 2009-02-11 00:51:42.000000000 +0100 +@@ -249,15 +249,17 @@ proc fetch_all_registers {test} { + + set all_registers_lines {} + set bad -1 ++ # Former trailing `\[\r\n\]+' may eat just \r leaving \n in the buffer ++ # corrupting the next matches. + if {[gdb_test_multiple "info all-registers" $test { +- -re "info all-registers\[\r\n\]+" { ++ -re "info all-registers\r\n" { + exp_continue + } + -ex "The program has no registers now" { + set bad 1 + exp_continue + } +- -re "^bspstore\[ \t\]+\[^\r\n\]+\[\r\n\]+" { ++ -re "^bspstore\[ \t\]+\[^\r\n\]+\r\n" { + if [istarget "ia64-*-*"] { + # Filter out bspstore which is specially tied to bsp, + # giving spurious differences. +@@ -266,14 +268,14 @@ proc fetch_all_registers {test} { + } + exp_continue + } +- -re "^\[^ \t\]+\[ \t\]+\[^\r\n\]+\[\r\n\]+" { ++ -re "^\[^ \t\]+\[ \t\]+\[^\r\n\]+\r\n" { + lappend all_registers_lines $expect_out(0,string) + exp_continue + } +- -re ".*$gdb_prompt $" { ++ -re "$gdb_prompt $" { + incr bad + } +- -re "^\[^\r\n\]+\[\r\n\]+" { ++ -re "^\[^\r\n\]+\r\n" { + if {!$bad} { + warning "Unrecognized output: $expect_out(0,string)" + set bad 1 diff --git a/gdb-6.8-attach-signalled-detach-stopped.patch b/gdb-6.8-attach-signalled-detach-stopped.patch new file mode 100644 index 0000000..e040b07 --- /dev/null +++ b/gdb-6.8-attach-signalled-detach-stopped.patch @@ -0,0 +1,183 @@ +Index: gdb-6.8.50.20090209/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/linux-nat.c 2009-02-09 16:12:23.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/linux-nat.c 2009-02-09 16:15:30.000000000 +0100 +@@ -204,6 +204,9 @@ blocked. */ + static struct target_ops *linux_ops; + static struct target_ops linux_ops_saved; + ++/* PID of the inferior stopped by SIGSTOP before attaching (or zero). */ ++static pid_t pid_was_stopped; ++ + /* The method to call, if any, when a new thread is attached. */ + static void (*linux_nat_new_thread) (ptid_t); + +@@ -902,7 +905,14 @@ linux_child_follow_fork (struct target_o + fork_save_infrun_state (fp, 0); + } + else +- target_detach (NULL, 0); ++ { ++ /* We should check PID_WAS_STOPPED and detach it stopped accordingly. ++ In this point of code it cannot be 1 as we would not get FORK ++ executed without CONTINUE first which resets PID_WAS_STOPPED. ++ We would have to first TARGET_STOP and WAITPID it as with running ++ inferior PTRACE_DETACH, SIGSTOP will ignore the signal. */ ++ target_detach (NULL, 0); ++ } + + inferior_ptid = ptid_build (child_pid, child_pid, 0); + +@@ -1229,6 +1239,7 @@ linux_nat_post_attach_wait (ptid_t ptid, + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "LNPAW: Attaching to a stopped process\n"); ++ pid_was_stopped = GET_PID (ptid); + + /* The process is definitely stopped. It is in a job control + stop, unless the kernel predates the TASK_STOPPED / +@@ -1561,6 +1572,9 @@ GPT: lwp %s had signal %s, but it is in + *status = lp->status; + } + ++ if (*status == 0 && GET_PID (lp->ptid) == pid_was_stopped) ++ *status = W_STOPCODE (SIGSTOP); ++ + return 0; + } + +@@ -1671,6 +1685,8 @@ linux_nat_detach (struct target_ops *ops + } + else + linux_ops->to_detach (ops, args, from_tty); ++ ++ pid_was_stopped = 0; + } + + /* Resume LP. */ +@@ -1825,6 +1841,14 @@ linux_nat_resume (ptid_t ptid, int step_ + resume_callback. */ + lp->stopped = 0; + ++ /* At this point, we are going to resume the inferior and if we ++ have attached to a stopped process, we no longer should leave ++ it as stopped if the user detaches. PTID variable has PID set to LWP ++ while we need to check the real PID here. */ ++ ++ if (!step && lp && pid_was_stopped == GET_PID (lp->ptid)) ++ pid_was_stopped = 0; ++ + if (resume_all) + iterate_over_lwps (resume_callback, NULL); + +@@ -3316,6 +3340,8 @@ linux_nat_mourn_inferior (struct target_ + there are other viable forks to debug. Delete the exiting + one and context-switch to the first available. */ + linux_fork_mourn_inferior (); ++ ++ pid_was_stopped = 0; + } + + /* Convert a native/host siginfo object, into/from the siginfo in the +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/attach-stopped.exp +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/testsuite/gdb.threads/attach-stopped.exp 2009-01-03 06:58:07.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/attach-stopped.exp 2009-02-09 16:12:41.000000000 +0100 +@@ -62,7 +62,65 @@ proc corefunc { threadtype } { + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + +- # Verify that we can attach to the stopped process. ++ # 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. ++ ++ set test "$threadtype: set file, before attach1 to stopped process" ++ gdb_test_multiple "file $binfile" "$test" { ++ -re "Load new symbol table from.*y or n. $" { ++ gdb_test "y" "Reading symbols from $escapedbinfile\.\.\.*done." \ ++ "$test (re-read)" ++ } ++ -re "Reading symbols from $escapedbinfile\.\.\.*done.*$gdb_prompt $" { ++ pass "$test" ++ } ++ } ++ ++ set test "$threadtype: attach1 to stopped, after setting file" ++ gdb_test_multiple "attach $testpid" "$test" { ++ -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" { ++ pass "$test" ++ } ++ } ++ ++ # ".*sleep.*clone.*" would fail on s390x as bt stops at START_THREAD there. ++ if {[string equal $threadtype threaded]} { ++ gdb_test "thread apply all bt" ".*sleep.*start_thread.*" "$threadtype: attach1 to stopped bt" ++ } else { ++ gdb_test "bt" ".*sleep.*main.*" "$threadtype: attach1 to stopped bt" ++ } ++ ++ # Exit and detach the process. ++ ++ gdb_exit ++ ++ # Avoid some race: ++ sleep 2 ++ ++ if [catch {open /proc/${testpid}/status r} fileid] { ++ set line2 "NOTFOUND" ++ } else { ++ gets $fileid line1; ++ gets $fileid line2; ++ close $fileid; ++ } ++ ++ set test "$threadtype: attach1, exit leaves process stopped" ++ if {[string match "*(stopped)*" $line2]} { ++ pass $test ++ } else { ++ fail $test ++ } ++ ++ # At this point, the process should still be stopped ++ ++ gdb_start ++ gdb_reinitialize_dir $srcdir/$subdir ++ gdb_load ${binfile} ++ ++ # Verify that we can attach to the process just by giving the ++ # process ID. + + set test "$threadtype: attach2 to stopped, after setting file" + gdb_test_multiple "attach $testpid" "$test" { +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/attachstop-mt.exp +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/testsuite/gdb.threads/attachstop-mt.exp 2009-01-03 06:58:07.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/attachstop-mt.exp 2009-02-09 16:12:41.000000000 +0100 +@@ -176,12 +176,23 @@ gdb_test "bt" ".*sleep.*(func|main).*" " + # Exit and detach the process. + gdb_exit + +-# Stop the program +-remote_exec build "kill -s STOP ${testpid}" +- + # No race + sleep 2 + ++set fileid3 [open $status2 r]; ++gets $fileid3 line1; ++gets $fileid3 line2; ++close $fileid3; ++ ++set test "attach3, exit leaves process stopped" ++if {[string match "*(stopped)*" $line2]} { ++ pass $test ++} else { ++ fail $test ++} ++ ++# At this point, the process should still be stopped ++ + # Continue the test as we would hit another expected bug regarding + # Program received signal SIGSTOP, Stopped (signal). + # across NPTL threads. diff --git a/gdb-6.8-bz254229-gcore-prpsinfo.patch b/gdb-6.8-bz254229-gcore-prpsinfo.patch new file mode 100644 index 0000000..7339e77 --- /dev/null +++ b/gdb-6.8-bz254229-gcore-prpsinfo.patch @@ -0,0 +1,351 @@ +Index: gdb-6.8.50.20081209/bfd/elf-bfd.h +=================================================================== +--- gdb-6.8.50.20081209.orig/bfd/elf-bfd.h 2008-12-03 15:50:57.000000000 +0100 ++++ gdb-6.8.50.20081209/bfd/elf-bfd.h 2008-12-10 01:35:08.000000000 +0100 +@@ -2154,7 +2154,7 @@ extern Elf_Internal_Phdr * _bfd_elf_find + extern char *elfcore_write_note + (bfd *, char *, int *, const char *, int, const void *, int); + extern char *elfcore_write_prpsinfo +- (bfd *, char *, int *, const char *, const char *); ++ (bfd *, char *, int *, void *, const char *, const char *); + extern char *elfcore_write_prstatus + (bfd *, char *, int *, long, int, const void *); + extern char * elfcore_write_pstatus +Index: gdb-6.8.50.20081209/bfd/elf.c +=================================================================== +--- gdb-6.8.50.20081209.orig/bfd/elf.c 2008-12-03 15:50:57.000000000 +0100 ++++ gdb-6.8.50.20081209/bfd/elf.c 2008-12-10 01:35:08.000000000 +0100 +@@ -8345,6 +8345,7 @@ char * + elfcore_write_prpsinfo (bfd *abfd, + char *buf, + int *bufsiz, ++ void *info, + const char *fname, + const char *psargs) + { +@@ -8371,9 +8372,15 @@ elfcore_write_prpsinfo (bfd *abfd, + int note_type = NT_PRPSINFO; + #endif + +- memset (&data, 0, sizeof (data)); +- strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); +- strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); ++ if (info) ++ memcpy (&data, info, sizeof (data)); ++ else ++ { ++ memset (&data, 0, sizeof (data)); ++ strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); ++ strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); ++ } ++ + return elfcore_write_note (abfd, buf, bufsiz, + note_name, note_type, &data, sizeof (data)); + } +@@ -8388,9 +8395,15 @@ elfcore_write_prpsinfo (bfd *abfd, + int note_type = NT_PRPSINFO; + #endif + +- memset (&data, 0, sizeof (data)); +- strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); +- strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); ++ if (info) ++ memcpy (&data, info, sizeof (data)); ++ else ++ { ++ memset (&data, 0, sizeof (data)); ++ strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); ++ strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); ++ } ++ + return elfcore_write_note (abfd, buf, bufsiz, + note_name, note_type, &data, sizeof (data)); + } +Index: gdb-6.8.50.20081209/gdb/amd64-linux-nat.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/amd64-linux-nat.c 2008-12-10 01:28:28.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/amd64-linux-nat.c 2008-12-10 01:35:08.000000000 +0100 +@@ -139,6 +139,7 @@ static int amd64_linux_gregset32_reg_off + + static char * + amd64_linux_elfcore_write_prpsinfo (bfd *abfd, char *buf, int *bufsiz, ++ void *info, + const char *fname, const char *psargs) + { + if (gdbarch_ptr_bit(current_gdbarch) == 32) +@@ -148,14 +149,20 @@ amd64_linux_elfcore_write_prpsinfo (bfd + struct elf_prpsinfo32 data; + note_type = NT_PRPSINFO; + +- memset (&data, 0, sizeof (data)); +- strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); +- strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); ++ if (info) ++ memcpy (&data, info, sizeof (data)); ++ else ++ { ++ memset (&data, 0, sizeof (data)); ++ strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); ++ strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); ++ } ++ + return elfcore_write_note (abfd, buf, bufsiz, + note_name, note_type, &data, sizeof (data)); + } + else +- return elfcore_write_prpsinfo (abfd, buf, bufsiz, fname, psargs); ++ return elfcore_write_prpsinfo (abfd, buf, bufsiz, info, fname, psargs); + } + + static void +Index: gdb-6.8.50.20081209/gdb/fbsd-nat.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/fbsd-nat.c 2008-10-28 16:22:12.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/fbsd-nat.c 2008-12-10 01:35:08.000000000 +0100 +@@ -210,6 +210,7 @@ fbsd_make_corefile_notes (bfd *obfd, int + psargs = reconcat (psargs, psargs, " ", get_inferior_args (), NULL); + + note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, ++ NULL, + fname, psargs); + } + +Index: gdb-6.8.50.20081209/gdb/linux-nat.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/linux-nat.c 2008-12-10 01:28:14.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/linux-nat.c 2008-12-10 01:35:25.000000000 +0100 +@@ -53,6 +53,7 @@ + #include + #include "gdb_dirent.h" + #include "xml-support.h" ++#include "gdb_procfs32.h" /* for struct elf_prpsinfo32 */ + + #ifdef HAVE_PERSONALITY + # include +@@ -216,7 +217,7 @@ static LONGEST (*super_xfer_partial) (st + /* This functions make elfcore note sections. + They may get overriden by code adjusting data for multi-target builds. */ + char *(*linux_elfcore_write_prpsinfo) +- (bfd *, char *, int *, const char *, const char *) = elfcore_write_prpsinfo; ++ (bfd *, char *, int *, void *, const char *, const char *) = elfcore_write_prpsinfo; + char *(*linux_elfcore_write_prstatus) + (bfd *, char *, int *, long, int, const void *) = elfcore_write_prstatus; + static char * +@@ -3614,6 +3615,159 @@ linux_nat_corefile_thread_callback (stru + return 0; + } + ++/* Should be always true for Linux */ ++#define HAVE_PRPSINFO_T 1 ++ ++#if defined (HAVE_PRPSINFO_T) ++ ++/* Fills struct elf_prpsinfo{32,64} as much as possible, imitate Linux kernel ++ binfmt_elf.c. Unknown values are filled with zeroes. The structure is ++ malloced. */ ++ ++static void* ++fill_prpsinfo (void) ++{ ++ struct stat sb; ++ char filename[sizeof ("/proc//cmdline") + sizeof (int) * 3 + 2]; ++ char buf[1024]; ++ char proc_state[5]; ++ char proc_cmdline[sizeof (((struct elf_prpsinfo*)0)->pr_psargs) + 1]; ++ unsigned flags; ++ long proc_nice; ++ unsigned proc_ppid; ++ unsigned proc_pgid; ++ unsigned proc_sid; ++ pid_t pid; ++ int fd, n; ++ char *cp, *proc_comm, *state_s; ++ /* String comes from Linux kernel binfmt_elf.c FILL_PSINFO but it is already ++ obsolete there to TASK_* constants. */ ++ const char state_string[] = "RSDTZW"; ++ int state_num; ++ ++ /* Get /proc/$PID/stat. */ ++ pid = ptid_get_pid (inferior_ptid); ++ sprintf (filename, "/proc/%u/stat", (unsigned)pid); ++ fd = open (filename, O_RDONLY); ++ if (fd < 0) ++ return NULL; ++ fstat (fd, &sb); /* No error checking (can it ever happen?). */ ++ n = read (fd, buf, sizeof (buf) - 1); ++ close (fd); ++ if (n < 0) ++ return NULL; ++ buf[n] = 0; ++ ++ cp = strrchr (buf, ')'); /* Split into "PID (COMM" and "". */ ++ if (!cp) ++ return NULL; ++ *cp = 0; ++ ++ /* Grab COMM. */ ++ proc_comm = strchr (buf, '('); ++ if (!proc_comm) ++ return NULL; ++ proc_comm++; ++ ++ /* Read /proc/$PID/cmdline. */ ++ proc_cmdline[0] = 0; ++ strcpy (strrchr (filename, '/'), "/cmdline"); ++ fd = open (filename, O_RDONLY); ++ if (fd >= 0) ++ { ++ int n; ++ ++ n = read (fd, proc_cmdline, sizeof (proc_cmdline) - 1); ++ if (n < 0) ++ n = 0; ++ proc_cmdline[n] = 0; ++ while (n--) /* Replace NULs with spaces. */ ++ if (proc_cmdline[n] == 0) ++ proc_cmdline[n] = ' '; ++ close (fd); ++ } ++ ++ /* Parse /proc/$PID/stat. */ ++ n = sscanf (cp + 2, /* skip ") " */ ++ "%4s %u " /* state, ppid */ ++ "%u %u %*s %*s " /* pgid, sid, tty, tpgid */ ++ "%u %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt */ ++ "%*s " /* cmaj_flt */ ++ "%*s %*s " /* utime, stime */ ++ "%*s %*s %*s " /* cutime, cstime, priority */ ++ "%ld " /* nice */ ++ /*"%*s %*s " timeout, it_real_value */ ++ /*"%lu " start_time */ ++ /*"%lu " vsize */ ++ /*"%lu " rss */ ++ /*"%lu %lu %lu " rss_rlim, start_code, end_code */ ++ /*"%lu %lu %lu " start_stack, kstk_esp, kstk_eip */ ++ /*"%u %u %u %u " signal, blocked, sigignore, sigcatch */ ++ /*"%lu %lu %lu" wchan, nswap, cnswap */ ++ , proc_state, &proc_ppid, ++ &proc_pgid, &proc_sid, ++ &flags, ++ &proc_nice); ++ if (n != 6) ++ return NULL; ++ ++ state_s = strchr (state_string, proc_state[0]); ++ if (state_s != NULL) ++ state_num = state_s - state_string; ++ else ++ { ++ /* 0 means Running, some more unusal state would be better. */ ++ state_num = 0; ++ } ++ ++#if ULONG_MAX > 0xffffffffU ++ /* We skip this code on 32-bit gdb. */ ++ if (gdbarch_ptr_bit (current_gdbarch) == 64) ++ { ++ struct elf_prpsinfo *info = xzalloc (sizeof (*info)); ++ ++ info->pr_state = state_num; ++ info->pr_sname = proc_state[0]; ++ info->pr_zomb = (proc_state[0] == 'Z'); ++ info->pr_nice = proc_nice; ++ info->pr_flag = flags; ++ info->pr_uid = sb.st_uid; ++ info->pr_gid = sb.st_gid; ++ info->pr_pid = pid; ++ info->pr_ppid = proc_ppid; ++ info->pr_pgrp = proc_pgid; ++ info->pr_sid = proc_sid; ++ strncpy (info->pr_fname, proc_comm, sizeof (info->pr_fname)); ++ strncpy (info->pr_psargs, proc_cmdline, sizeof (info->pr_psargs)); ++ ++ return info; ++ } ++#endif ++ if (gdbarch_ptr_bit (current_gdbarch) == 32) ++ { ++ struct elf_prpsinfo32 *info = xzalloc (sizeof (*info)); ++ ++ info->pr_state = state_num; ++ info->pr_sname = proc_state[0]; ++ info->pr_zomb = (proc_state[0] == 'Z'); ++ info->pr_nice = proc_nice; ++ info->pr_flag = flags; ++ info->pr_uid = sb.st_uid; ++ info->pr_gid = sb.st_gid; ++ info->pr_pid = pid; ++ info->pr_ppid = proc_ppid; ++ info->pr_pgrp = proc_pgid; ++ info->pr_sid = proc_sid; ++ strncpy (info->pr_fname, proc_comm, sizeof (info->pr_fname)); ++ strncpy (info->pr_psargs, proc_cmdline, sizeof (info->pr_psargs)); ++ ++ return info; ++ } ++ ++ return NULL; ++} ++#endif ++ + /* Fills the "to_make_corefile_note" target vector. Builds the note + section for a corefile, and returns it in a malloc buffer. */ + +@@ -3633,8 +3787,14 @@ linux_nat_make_corefile_notes (bfd *obfd + + if (get_exec_file (0)) + { ++#if defined (HAVE_PRPSINFO_T) ++ void *data = fill_prpsinfo (); ++#define DATAPTR data ++#else ++#define DATAPTR NULL + strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname)); + strncpy (psargs, get_exec_file (0), sizeof (psargs)); ++#endif + if (get_inferior_args ()) + { + char *string_end; +@@ -3650,9 +3810,15 @@ linux_nat_make_corefile_notes (bfd *obfd + psargs_end - string_end); + } + } +- note_data = (char *) linux_elfcore_write_prpsinfo (obfd, note_data, +- note_size, fname, ++ note_data = (char *) linux_elfcore_write_prpsinfo (obfd, ++ note_data, note_size, ++ DATAPTR, ++ fname, + psargs); ++#if defined (HAVE_PRPSINFO_T) ++ xfree (DATAPTR); ++#endif ++#undef DATAPTR + } + + /* Dump information for threads. */ +Index: gdb-6.8.50.20081209/gdb/linux-nat.h +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/linux-nat.h 2008-12-10 01:27:33.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/linux-nat.h 2008-12-10 01:35:08.000000000 +0100 +@@ -138,7 +138,7 @@ struct siginfo *linux_nat_get_siginfo (p + /* These functions make elfcore note sections. + They may get overriden by code adjusting data for multi-target builds. */ + extern char *(*linux_elfcore_write_prpsinfo) +- (bfd *, char *, int *, const char *, const char *); ++ (bfd *, char *, int *, void *, const char *, const char *); + extern char *(*linux_elfcore_write_prstatus) + (bfd *, char *, int *, long, int, const void *); + extern char *(*linux_elfcore_write_prfpreg) +Index: gdb-6.8.50.20081209/gdb/procfs.c +=================================================================== +--- gdb-6.8.50.20081209.orig/gdb/procfs.c 2008-11-09 12:27:17.000000000 +0100 ++++ gdb-6.8.50.20081209/gdb/procfs.c 2008-12-10 01:35:08.000000000 +0100 +@@ -6181,6 +6181,7 @@ procfs_make_note_section (bfd *obfd, int + note_data = (char *) elfcore_write_prpsinfo (obfd, + note_data, + note_size, ++ NULL, + fname, + psargs); + diff --git a/gdb-6.8-bz377541-vla.patch b/gdb-6.8-bz377541-vla.patch deleted file mode 100644 index 9b3e886..0000000 --- a/gdb-6.8-bz377541-vla.patch +++ /dev/null @@ -1,5062 +0,0 @@ -diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c -index a6d5757..5c44b52 100644 ---- a/gdb/ada-lang.c -+++ b/gdb/ada-lang.c -@@ -1666,8 +1666,8 @@ ada_type_of_array (struct value *arr, int bounds) - return NULL; - while (arity > 0) - { -- struct type *range_type = alloc_type (objf); -- struct type *array_type = alloc_type (objf); -+ struct type *range_type = alloc_type (objf, NULL); -+ struct type *array_type = alloc_type (objf, NULL); - struct value *low = desc_one_bound (descriptor, arity, 0); - struct value *high = desc_one_bound (descriptor, arity, 1); - arity -= 1; -@@ -1774,9 +1774,9 @@ packed_array_type (struct type *type, long *elt_bits) - if (TYPE_CODE (type) != TYPE_CODE_ARRAY) - return type; - -- new_type = alloc_type (TYPE_OBJFILE (type)); - new_elt_type = packed_array_type (ada_check_typedef (TYPE_TARGET_TYPE (type)), - elt_bits); -+ new_type = alloc_type (TYPE_OBJFILE (type), new_elt_type); - create_array_type (new_type, new_elt_type, TYPE_INDEX_TYPE (type)); - TYPE_FIELD_BITSIZE (new_type, 0) = *elt_bits; - TYPE_NAME (new_type) = ada_type_name (type); -@@ -6790,7 +6790,7 @@ variant_field_index (struct type *type) - static struct type * - empty_record (struct objfile *objfile) - { -- struct type *type = alloc_type (objfile); -+ struct type *type = alloc_type (objfile, NULL); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - TYPE_NFIELDS (type) = 0; - TYPE_FIELDS (type) = NULL; -@@ -6847,7 +6847,7 @@ ada_template_to_fixed_record_type_1 (struct type *type, - nfields++; - } - -- rtype = alloc_type (TYPE_OBJFILE (type)); -+ rtype = alloc_type (TYPE_OBJFILE (type), NULL); - TYPE_CODE (rtype) = TYPE_CODE_STRUCT; - INIT_CPLUS_SPECIFIC (rtype); - TYPE_NFIELDS (rtype) = nfields; -@@ -7034,7 +7034,8 @@ template_to_static_fixed_type (struct type *type0) - new_type = static_unwrap_type (field_type); - if (type == type0 && new_type != field_type) - { -- TYPE_TARGET_TYPE (type0) = type = alloc_type (TYPE_OBJFILE (type0)); -+ TYPE_TARGET_TYPE (type0) = type = alloc_type (TYPE_OBJFILE (type0), -+ NULL); - TYPE_CODE (type) = TYPE_CODE (type0); - INIT_CPLUS_SPECIFIC (type); - TYPE_NFIELDS (type) = nfields; -@@ -7079,7 +7080,7 @@ to_record_with_fixed_variant_part (struct type *type, const gdb_byte *valaddr, - else - dval = dval0; - -- rtype = alloc_type (TYPE_OBJFILE (type)); -+ rtype = alloc_type (TYPE_OBJFILE (type), NULL); - TYPE_CODE (rtype) = TYPE_CODE_STRUCT; - INIT_CPLUS_SPECIFIC (rtype); - TYPE_NFIELDS (rtype) = nfields; -@@ -7251,7 +7252,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, - if (elt_type0 == elt_type) - result = type0; - else -- result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), -+ result = create_array_type (alloc_type (TYPE_OBJFILE (type0), NULL), - elt_type, TYPE_INDEX_TYPE (type0)); - } - else -@@ -7281,7 +7282,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, - struct type *range_type = - to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i), - dval, TYPE_OBJFILE (type0)); -- result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), -+ result = create_array_type (alloc_type (TYPE_OBJFILE (type0), NULL), - result, range_type); - } - if (!ignore_too_big && TYPE_LENGTH (result) > varsize_limit) -@@ -9546,7 +9547,7 @@ to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile) - if (L < INT_MIN || U > INT_MAX) - return raw_type; - else -- return create_range_type (alloc_type (objfile), raw_type, -+ return create_range_type (alloc_type (objfile, NULL), raw_type, - discrete_type_low_bound (raw_type), - discrete_type_high_bound (raw_type)); - } -@@ -9611,7 +9612,7 @@ to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile) - - if (objfile == NULL) - objfile = TYPE_OBJFILE (base_type); -- type = create_range_type (alloc_type (objfile), base_type, L, U); -+ type = create_range_type (alloc_type (objfile, NULL), base_type, L, U); - TYPE_NAME (type) = name; - return type; - } -diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c -index 0929516..2aaf9ad 100644 ---- a/gdb/c-typeprint.c -+++ b/gdb/c-typeprint.c -@@ -559,7 +559,12 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, - fprintf_filtered (stream, ")"); - - fprintf_filtered (stream, "["); -- if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 -+ if (TYPE_ARRAY_BOUND_IS_DWARF_BLOCK (type, 1)) -+ { -+ /* No _() - printed sources should not be locale dependent. */ -+ fprintf_filtered (stream, "variable"); -+ } -+ else if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 - && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) - fprintf_filtered (stream, "%d", - (TYPE_LENGTH (type) -diff --git a/gdb/coffread.c b/gdb/coffread.c -index 6059d68..6a24c2c 100644 ---- a/gdb/coffread.c -+++ b/gdb/coffread.c -@@ -346,7 +346,7 @@ coff_alloc_type (int index) - We will fill it in later if we find out how. */ - if (type == NULL) - { -- type = alloc_type (current_objfile); -+ type = alloc_type (current_objfile, NULL); - *type_addr = type; - } - return type; -diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c -index 75a4ec7..aa8ab33 100644 ---- a/gdb/dwarf2expr.c -+++ b/gdb/dwarf2expr.c -@@ -752,6 +752,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, - ctx->initialized = 0; - goto no_push; - -+ case DW_OP_push_object_address: -+ if (ctx->get_object_address == NULL) -+ error (_("DWARF-2 expression error: DW_OP_push_object_address must " -+ "have a value to push.")); -+ result = (ctx->get_object_address) (ctx->baton); -+ break; -+ - default: - error (_("Unhandled dwarf expression opcode 0x%x"), op); - } -diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h -index 7047922..a287b6f 100644 ---- a/gdb/dwarf2expr.h -+++ b/gdb/dwarf2expr.h -@@ -67,10 +67,10 @@ struct dwarf_expr_context - The result must be live until the current expression evaluation - is complete. */ - unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length); -+#endif - - /* Return the `object address' for DW_OP_push_object_address. */ - CORE_ADDR (*get_object_address) (void *baton); --#endif - - /* The current depth of dwarf expression recursion, via DW_OP_call*, - DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum -diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c -index cad3db8..65751a4 100644 ---- a/gdb/dwarf2loc.c -+++ b/gdb/dwarf2loc.c -@@ -107,6 +107,9 @@ struct dwarf_expr_baton - { - struct frame_info *frame; - struct objfile *objfile; -+ /* From DW_TAG_variable's DW_AT_location (not DW_TAG_type's -+ DW_AT_data_location) for DW_OP_push_object_address. */ -+ CORE_ADDR object_address; - }; - - /* Helper functions for dwarf2_evaluate_loc_desc. */ -@@ -163,22 +166,32 @@ dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length) - *start = find_location_expression (symbaton, length, - get_frame_address_in_block (frame)); - } -- else -+ else if (SYMBOL_OPS (framefunc) == &dwarf2_locexpr_funcs) - { - struct dwarf2_locexpr_baton *symbaton; -+ - symbaton = SYMBOL_LOCATION_BATON (framefunc); -- if (symbaton != NULL) -- { -- *length = symbaton->size; -- *start = symbaton->data; -- } -- else -- *start = NULL; -+ gdb_assert (symbaton != NULL); -+ *start = symbaton->data; -+ *length = symbaton->size; -+ } -+ else if (SYMBOL_OPS (framefunc) == &dwarf2_missing_funcs) -+ { -+ struct dwarf2_locexpr_baton *symbaton; -+ -+ symbaton = SYMBOL_LOCATION_BATON (framefunc); -+ gdb_assert (symbaton == NULL); -+ *start = NULL; -+ *length = 0; /* unused */ - } -+ else -+ internal_error (__FILE__, __LINE__, -+ _("Unsupported SYMBOL_OPS %p for \"%s\""), -+ SYMBOL_OPS (framefunc), SYMBOL_PRINT_NAME (framefunc)); - - if (*start == NULL) - error (_("Could not find the frame base for \"%s\"."), -- SYMBOL_NATURAL_NAME (framefunc)); -+ SYMBOL_PRINT_NAME (framefunc)); - } - - /* Using the objfile specified in BATON, find the address for the -@@ -191,6 +204,119 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset) - return target_translate_tls_address (debaton->objfile, offset); - } - -+static CORE_ADDR -+dwarf_expr_object_address (void *baton) -+{ -+ struct dwarf_expr_baton *debaton = baton; -+ -+ /* The message is suppressed in DWARF_BLOCK_EXEC. */ -+ if (debaton->object_address == 0) -+ error (_("Cannot resolve DW_OP_push_object_address for a missing object")); -+ -+ return debaton->object_address; -+} -+ -+/* Address of the variable we are currently referring to. It is set from -+ DW_TAG_variable's DW_AT_location (not DW_TAG_type's DW_AT_data_location) for -+ DW_OP_push_object_address. */ -+ -+static CORE_ADDR object_address; -+ -+/* Callers use object_address_set while their callers use the result set so we -+ cannot run the cleanup at the local block of our direct caller. Still we -+ should reset OBJECT_ADDRESS at least for the next GDB command. */ -+ -+static void -+object_address_cleanup (void *prev_save_voidp) -+{ -+ CORE_ADDR *prev_save = prev_save_voidp; -+ -+ object_address = *prev_save; -+ xfree (prev_save); -+} -+ -+/* Set the base address - DW_AT_location - of a variable. It is being later -+ used to derive other object addresses by DW_OP_push_object_address. -+ -+ It would be useful to sanity check ADDRESS - such as for some objects with -+ unset VALUE_ADDRESS - but some valid addresses may be zero (such as first -+ objects in relocatable .o files). */ -+ -+void -+object_address_set (CORE_ADDR address) -+{ -+ CORE_ADDR *prev_save; -+ -+ prev_save = xmalloc (sizeof *prev_save); -+ *prev_save = object_address; -+ make_cleanup (object_address_cleanup, prev_save); -+ -+ object_address = address; -+} -+ -+/* Evaluate DWARF expression at DATA ... DATA + SIZE with its result readable -+ by dwarf_expr_fetch (RETVAL, 0). FRAME parameter can be NULL to call -+ get_selected_frame to find it. Returned dwarf_expr_context freeing is -+ pushed on the cleanup chain. */ -+ -+static struct dwarf_expr_context * -+dwarf_expr_prep_ctx (struct frame_info *frame, gdb_byte *data, -+ unsigned short size, struct dwarf2_per_cu_data *per_cu) -+{ -+ struct dwarf_expr_context *ctx; -+ struct dwarf_expr_baton baton; -+ -+ if (!frame) -+ frame = get_selected_frame (NULL); -+ -+ baton.frame = frame; -+ baton.objfile = dwarf2_per_cu_objfile (per_cu); -+ baton.object_address = object_address; -+ -+ ctx = new_dwarf_expr_context (); -+ ctx->gdbarch = get_objfile_arch (baton.objfile); -+ ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); -+ ctx->baton = &baton; -+ ctx->read_reg = dwarf_expr_read_reg; -+ ctx->read_mem = dwarf_expr_read_mem; -+ ctx->get_frame_base = dwarf_expr_frame_base; -+ ctx->get_tls_address = dwarf_expr_tls_address; -+ ctx->get_object_address = dwarf_expr_object_address; -+ -+ make_cleanup ((make_cleanup_ftype *) free_dwarf_expr_context, ctx); -+ -+ dwarf_expr_eval (ctx, data, size); -+ -+ /* It was used only during dwarf_expr_eval. */ -+ ctx->baton = NULL; -+ -+ return ctx; -+} -+ -+/* Evaluate DWARF expression at DLBATON expecting it produces exactly one -+ CORE_ADDR result on the DWARF stack stack. */ -+ -+CORE_ADDR -+dwarf_locexpr_baton_eval (struct dwarf2_locexpr_baton *dlbaton) -+{ -+ struct dwarf_expr_context *ctx; -+ CORE_ADDR retval; -+ struct cleanup *back_to = make_cleanup (null_cleanup, 0); -+ -+ ctx = dwarf_expr_prep_ctx (NULL, dlbaton->data, dlbaton->size, -+ dlbaton->per_cu); -+ if (ctx->num_pieces > 0) -+ error (_("DW_OP_*piece is unsupported for DW_FORM_block")); -+ else if (ctx->in_reg) -+ error (_("Register result is unsupported for DW_FORM_block")); -+ -+ retval = dwarf_expr_fetch (ctx, 0); -+ -+ do_cleanups (back_to); -+ -+ return retval; -+} -+ - /* Evaluate a location description, starting at DATA and with length - SIZE, to find the current location of variable VAR in the context - of FRAME. */ -@@ -200,8 +326,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, - struct dwarf2_per_cu_data *per_cu) - { - struct value *retval; -- struct dwarf_expr_baton baton; - struct dwarf_expr_context *ctx; -+ struct cleanup *back_to = make_cleanup (null_cleanup, 0); - - if (size == 0) - { -@@ -211,19 +337,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, - return retval; - } - -- baton.frame = frame; -- baton.objfile = dwarf2_per_cu_objfile (per_cu); -+ ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu); - -- ctx = new_dwarf_expr_context (); -- ctx->gdbarch = get_objfile_arch (baton.objfile); -- ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); -- ctx->baton = &baton; -- ctx->read_reg = dwarf_expr_read_reg; -- ctx->read_mem = dwarf_expr_read_mem; -- ctx->get_frame_base = dwarf_expr_frame_base; -- ctx->get_tls_address = dwarf_expr_tls_address; -- -- dwarf_expr_eval (ctx, data, size); - if (ctx->num_pieces > 0) - { - int i; -@@ -261,6 +376,10 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, - { - CORE_ADDR address = dwarf_expr_fetch (ctx, 0); - -+ /* object_address_set called here is required in ALLOCATE_VALUE's -+ CHECK_TYPEDEF for the object's possible DW_OP_push_object_address. */ -+ object_address_set (address); -+ - retval = allocate_value (SYMBOL_TYPE (var)); - VALUE_LVAL (retval) = lval_memory; - set_value_lazy (retval, 1); -@@ -269,7 +388,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, - - set_value_initialized (retval, ctx->initialized); - -- free_dwarf_expr_context (ctx); -+ do_cleanups (back_to); - - return retval; - } -@@ -587,7 +706,7 @@ static int - loclist_describe_location (struct symbol *symbol, struct ui_file *stream) - { - /* FIXME: Could print the entire list of locations. */ -- fprintf_filtered (stream, "a variable with multiple locations"); -+ fprintf_filtered (stream, _("a variable with multiple locations")); - return 1; - } - -@@ -603,16 +722,56 @@ loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax, - - data = find_location_expression (dlbaton, &size, ax->scope); - if (data == NULL) -- error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol)); -+ error (_("Variable \"%s\" is not available."), SYMBOL_PRINT_NAME (symbol)); - - dwarf2_tracepoint_var_ref (symbol, ax, value, data, size); - } - --/* The set of location functions used with the DWARF-2 expression -- evaluator and location lists. */ -+/* The set of location functions used with the DWARF-2 location lists. */ - const struct symbol_ops dwarf2_loclist_funcs = { - loclist_read_variable, - loclist_read_needs_frame, - loclist_describe_location, - loclist_tracepoint_var_ref - }; -+ -+static struct value * -+missing_read_variable (struct symbol *symbol, struct frame_info *frame) -+{ -+ struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); -+ -+ gdb_assert (dlbaton == NULL); -+ error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol)); -+} -+ -+static int -+missing_read_needs_frame (struct symbol *symbol) -+{ -+ return 0; -+} -+ -+static int -+missing_describe_location (struct symbol *symbol, struct ui_file *stream) -+{ -+ fprintf_filtered (stream, _("a variable we are unable to resolve")); -+ return 1; -+} -+ -+static void -+missing_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax, -+ struct axs_value *value) -+{ -+ struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); -+ -+ gdb_assert (dlbaton == NULL); -+ error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol)); -+} -+ -+/* The set of location functions used with the DWARF-2 evaluator when we are -+ unable to resolve the symbols. */ -+const struct symbol_ops dwarf2_missing_funcs = { -+ missing_read_variable, -+ missing_read_needs_frame, -+ missing_describe_location, -+ missing_tracepoint_var_ref -+}; -diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h -index 76577f1..bf46761 100644 ---- a/gdb/dwarf2loc.h -+++ b/gdb/dwarf2loc.h -@@ -71,5 +71,11 @@ struct dwarf2_loclist_baton - - extern const struct symbol_ops dwarf2_locexpr_funcs; - extern const struct symbol_ops dwarf2_loclist_funcs; -+extern const struct symbol_ops dwarf2_missing_funcs; -+ -+extern void object_address_set (CORE_ADDR address); -+ -+extern CORE_ADDR dwarf_locexpr_baton_eval -+ (struct dwarf2_locexpr_baton *dlbaton); - - #endif /* dwarf2loc.h */ -diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c -index 925cfd0..481cdfc 100644 ---- a/gdb/dwarf2read.c -+++ b/gdb/dwarf2read.c -@@ -1024,7 +1024,14 @@ static void store_in_ref_table (struct die_info *, - - static unsigned int dwarf2_get_ref_die_offset (struct attribute *); - --static int dwarf2_get_attr_constant_value (struct attribute *, int); -+enum dwarf2_get_attr_constant_value -+ { -+ dwarf2_attr_unknown, -+ dwarf2_attr_const, -+ dwarf2_attr_block -+ }; -+static enum dwarf2_get_attr_constant_value dwarf2_get_attr_constant_value -+ (struct attribute *attr, int *val_return); - - static struct die_info *follow_die_ref (struct die_info *, - struct attribute *, -@@ -1079,6 +1086,9 @@ static void age_cached_comp_units (void); - - static void free_one_cached_comp_unit (void *); - -+static void fetch_die_type_attrs (struct die_info *die, struct type *type, -+ struct dwarf2_cu *cu); -+ - static struct type *set_die_type (struct die_info *, struct type *, - struct dwarf2_cu *); - -@@ -1098,6 +1108,9 @@ static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); - - static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu); - -+static struct dwarf2_locexpr_baton *dwarf2_attr_to_locexpr_baton -+ (struct attribute *attr, struct dwarf2_cu *cu); -+ - /* Try to locate the sections we need for DWARF 2 debugging - information and return true if we have enough to do something. */ - -@@ -3900,7 +3913,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, - /* The name is already allocated along with this objfile, so we don't - need to duplicate it for the type. */ - fnp->physname = physname ? physname : ""; -- fnp->type = alloc_type (objfile); -+ fnp->type = alloc_type (objfile, NULL); - this_type = read_type_die (die, cu); - if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) - { -@@ -4084,7 +4097,7 @@ quirk_gcc_member_function_pointer (struct die_info *die, struct dwarf2_cu *cu) - return NULL; - - domain_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0)); -- type = alloc_type (objfile); -+ type = alloc_type (objfile, NULL); - smash_to_method_type (type, domain_type, TYPE_TARGET_TYPE (pfn_type), - TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type), - TYPE_VARARGS (pfn_type)); -@@ -4121,7 +4134,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) - if (type) - return type; - -- type = alloc_type (objfile); -+ type = alloc_type (objfile, NULL); - INIT_CPLUS_SPECIFIC (type); - name = dwarf2_name (die, cu); - if (name != NULL) -@@ -4334,7 +4347,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) - struct attribute *attr; - const char *name; - -- type = alloc_type (objfile); -+ type = alloc_type (objfile, NULL); - - TYPE_CODE (type) = TYPE_CODE_ENUM; - name = dwarf2_full_name (die, cu); -@@ -4484,6 +4497,29 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) - new_symbol (die, this_type, cu); - } - -+/* Create a new array dimension referencing its target type TYPE. -+ -+ Multidimensional arrays are internally represented as a stack of -+ singledimensional arrays being referenced by their TYPE_TARGET_TYPE. */ -+ -+static struct type * -+create_single_array_dimension (struct type *type, struct type *range_type, -+ struct die_info *die, struct dwarf2_cu *cu) -+{ -+ type = create_array_type (NULL, type, range_type); -+ -+ /* These generic type attributes need to be fetched by -+ evaluate_subexp_standard 's call of -+ value_subscripted_rvalue only for the innermost array type. */ -+ fetch_die_type_attrs (die, type, cu); -+ -+ /* These generic type attributes are checked for allocated/associated -+ validity while accessing FIELD_LOC_KIND_DWARF_BLOCK. */ -+ fetch_die_type_attrs (die, range_type, cu); -+ -+ return type; -+} -+ - /* Extract all information from a DW_TAG_array_type DIE and put it in - the DIE's type field. For now, this only handles one dimensional - arrays. */ -@@ -4497,7 +4533,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) - struct type *element_type, *range_type, *index_type; - struct type **range_types = NULL; - struct attribute *attr; -- int ndim = 0; -+ int ndim = 0, i; - struct cleanup *back_to; - char *name; - -@@ -4544,16 +4580,11 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) - type = element_type; - - if (read_array_order (die, cu) == DW_ORD_col_major) -- { -- int i = 0; -- while (i < ndim) -- type = create_array_type (NULL, type, range_types[i++]); -- } -- else -- { -- while (ndim-- > 0) -- type = create_array_type (NULL, type, range_types[ndim]); -- } -+ for (i = 0; i < ndim; i++) -+ type = create_single_array_dimension (type, range_types[i], die, cu); -+ else /* (read_array_order (die, cu) == DW_ORD_row_major) */ -+ for (i = ndim - 1; i >= 0; i--) -+ type = create_single_array_dimension (type, range_types[i], die, cu); - - /* Understand Dwarf2 support for vector types (like they occur on - the PowerPC w/ AltiVec). Gcc just adds another attribute to the -@@ -4909,29 +4940,95 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) - struct objfile *objfile = cu->objfile; - struct type *type, *range_type, *index_type, *char_type; - struct attribute *attr; -- unsigned int length; -+ int length; -+ -+ index_type = builtin_type_int32; -+ /* RANGE_TYPE is allocated from OBJFILE, not OBJFILE_INTERNAL. */ -+ range_type = alloc_type (objfile, index_type); -+ /* LOW_BOUND and HIGH_BOUND are set for real below. */ -+ range_type = create_range_type (range_type, index_type, 0, -1); -+ -+ /* C/C++ should probably have the low bound 0 but C/C++ does not use -+ DW_TAG_string_type. */ -+ TYPE_LOW_BOUND (range_type) = 1; - - attr = dwarf2_attr (die, DW_AT_string_length, cu); -- if (attr) -- { -- length = DW_UNSND (attr); -- } -- else -- { -- /* check for the DW_AT_byte_size attribute */ -+ switch (dwarf2_get_attr_constant_value (attr, &length)) -+ { -+ case dwarf2_attr_const: -+ /* We currently do not support a constant address where the location -+ should be read from - DWARF2_ATTR_BLOCK is expected instead. See -+ DWARF for the DW_AT_STRING_LENGTH vs. DW_AT_BYTE_SIZE difference. */ -+ /* PASSTHRU */ -+ case dwarf2_attr_unknown: - attr = dwarf2_attr (die, DW_AT_byte_size, cu); -- if (attr) -- { -- length = DW_UNSND (attr); -- } -- else -- { -- length = 1; -- } -+ switch (dwarf2_get_attr_constant_value (attr, &length)) -+ { -+ case dwarf2_attr_unknown: -+ length = 1; -+ /* PASSTHRU */ -+ case dwarf2_attr_const: -+ TYPE_HIGH_BOUND (range_type) = length; -+ break; -+ case dwarf2_attr_block: -+ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); -+ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = -+ dwarf2_attr_to_locexpr_baton (attr, cu); -+ TYPE_DYNAMIC (range_type) = 1; -+ break; -+ } -+ break; -+ case dwarf2_attr_block: -+ /* Security check for a size overflow. */ -+ if (DW_BLOCK (attr)->size + 2 < DW_BLOCK (attr)->size) -+ { -+ TYPE_HIGH_BOUND (range_type) = 1; -+ break; -+ } -+ /* Extend the DWARF block by a new DW_OP_deref/DW_OP_deref_size -+ instruction as DW_AT_string_length specifies the length location, not -+ its value. */ -+ { -+ struct dwarf2_locexpr_baton *length_baton; -+ struct attribute *size_attr; -+ -+ length_baton = obstack_alloc (&cu->comp_unit_obstack, -+ sizeof (*length_baton)); -+ length_baton->per_cu = cu->per_cu; -+ length_baton->data = obstack_alloc (&cu->comp_unit_obstack, -+ DW_BLOCK (attr)->size + 2); -+ memcpy (length_baton->data, DW_BLOCK (attr)->data, -+ DW_BLOCK (attr)->size); -+ -+ /* DW_AT_BYTE_SIZE existing together with DW_AT_STRING_LENGTH specifies -+ the size of an integer to fetch. */ -+ -+ size_attr = dwarf2_attr (die, DW_AT_byte_size, cu); -+ if (size_attr) -+ { -+ length_baton->size = DW_BLOCK (attr)->size + 2; -+ length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref_size; -+ length_baton->data[DW_BLOCK (attr)->size + 1] -+ = DW_UNSND (size_attr); -+ if (length_baton->data[DW_BLOCK (attr)->size + 1] -+ != DW_UNSND (size_attr)) -+ complaint (&symfile_complaints, -+ _("DW_AT_string_length's DW_AT_byte_size integer " -+ "exceeds the byte size storage")); -+ } -+ else -+ { -+ length_baton->size = DW_BLOCK (attr)->size + 1; -+ length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref; -+ } -+ -+ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); -+ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = length_baton; -+ TYPE_DYNAMIC (range_type) = 1; -+ } -+ break; - } - -- index_type = builtin_type_int32; -- range_type = create_range_type (NULL, index_type, 1, length); - type = create_string_type (NULL, range_type); - - return set_die_type (die, type, cu); -@@ -5025,7 +5122,6 @@ static struct type * - read_typedef (struct die_info *die, struct dwarf2_cu *cu) - { - struct objfile *objfile = cu->objfile; -- struct attribute *attr; - const char *name = NULL; - struct type *this_type; - -@@ -5131,8 +5227,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) - struct type *base_type; - struct type *range_type; - struct attribute *attr; -- int low = 0; -- int high = -1; -+ int low, high, byte_stride_int; -+ enum dwarf2_get_attr_constant_value high_type; - char *name; - - base_type = die_type (die, cu); -@@ -5145,42 +5241,90 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) - 0, NULL, cu->objfile); - } - -- if (cu->language == language_fortran) -- { -- /* FORTRAN implies a lower bound of 1, if not given. */ -- low = 1; -- } -+ /* LOW_BOUND and HIGH_BOUND are set for real below. */ -+ range_type = create_range_type (NULL, base_type, 0, -1); - -- /* FIXME: For variable sized arrays either of these could be -- a variable rather than a constant value. We'll allow it, -- but we don't know how to handle it. */ - attr = dwarf2_attr (die, DW_AT_lower_bound, cu); -- if (attr) -- low = dwarf2_get_attr_constant_value (attr, 0); -+ switch (dwarf2_get_attr_constant_value (attr, &low)) -+ { -+ case dwarf2_attr_unknown: -+ if (cu->language == language_fortran) -+ { -+ /* FORTRAN implies a lower bound of 1, if not given. */ -+ low = 1; -+ } -+ else -+ { -+ /* According to DWARF we should assume the value 0 only for -+ LANGUAGE_C and LANGUAGE_CPLUS. */ -+ low = 0; -+ } -+ /* PASSTHRU */ -+ case dwarf2_attr_const: -+ TYPE_LOW_BOUND (range_type) = low; -+ if (low >= 0) -+ TYPE_UNSIGNED (range_type) = 1; -+ break; -+ case dwarf2_attr_block: -+ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 0); -+ TYPE_FIELD_DWARF_BLOCK (range_type, 0) = dwarf2_attr_to_locexpr_baton -+ (attr, cu); -+ TYPE_DYNAMIC (range_type) = 1; -+ /* For setting a default if DW_AT_UPPER_BOUND would be missing. */ -+ low = 0; -+ break; -+ } - - attr = dwarf2_attr (die, DW_AT_upper_bound, cu); -- if (attr) -- { -- if (attr->form == DW_FORM_block1) -- { -- /* GCC encodes arrays with unspecified or dynamic length -- with a DW_FORM_block1 attribute. -- FIXME: GDB does not yet know how to handle dynamic -- arrays properly, treat them as arrays with unspecified -- length for now. -- -- FIXME: jimb/2003-09-22: GDB does not really know -- how to handle arrays of unspecified length -- either; we just represent them as zero-length -- arrays. Choose an appropriate upper bound given -- the lower bound we've computed above. */ -- high = low - 1; -- } -- else -- high = dwarf2_get_attr_constant_value (attr, 1); -+ high_type = dwarf2_get_attr_constant_value (attr, &high); -+ if (high_type == dwarf2_attr_unknown) -+ { -+ attr = dwarf2_attr (die, DW_AT_count, cu); -+ high_type = dwarf2_get_attr_constant_value (attr, &high); -+ /* It does not hurt but it is needlessly ineffective in check_typedef. */ -+ if (high_type != dwarf2_attr_unknown) -+ { -+ TYPE_RANGE_HIGH_BOUND_IS_COUNT (range_type) = 1; -+ TYPE_DYNAMIC (range_type) = 1; -+ } -+ /* Pass it now as the regular DW_AT_upper_bound. */ -+ } -+ switch (high_type) -+ { -+ case dwarf2_attr_unknown: -+ TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type) = 1; -+ high = low - 1; -+ /* PASSTHRU */ -+ case dwarf2_attr_const: -+ TYPE_HIGH_BOUND (range_type) = high; -+ break; -+ case dwarf2_attr_block: -+ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); -+ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = dwarf2_attr_to_locexpr_baton -+ (attr, cu); -+ TYPE_DYNAMIC (range_type) = 1; -+ break; - } - -- range_type = create_range_type (NULL, base_type, low, high); -+ /* DW_AT_bit_stride is currently unsupported as we count in bytes. */ -+ attr = dwarf2_attr (die, DW_AT_byte_stride, cu); -+ switch (dwarf2_get_attr_constant_value (attr, &byte_stride_int)) -+ { -+ case dwarf2_attr_unknown: -+ break; -+ case dwarf2_attr_const: -+ if (byte_stride_int == 0) -+ complaint (&symfile_complaints, -+ _("Found DW_AT_byte_stride with unsupported value 0")); -+ TYPE_BYTE_STRIDE (range_type) = byte_stride_int; -+ break; -+ case dwarf2_attr_block: -+ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 2); -+ TYPE_FIELD_DWARF_BLOCK (range_type, 2) = dwarf2_attr_to_locexpr_baton -+ (attr, cu); -+ TYPE_DYNAMIC (range_type) = 1; -+ break; -+ } - - name = dwarf2_name (die, cu); - if (name) -@@ -7468,10 +7612,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym, - (i.e. when the value of a register or memory location is - referenced, or a thread-local block, etc.). Then again, it might - not be worthwhile. I'm assuming that it isn't unless performance -- or memory numbers show me otherwise. */ -+ or memory numbers show me otherwise. -+ -+ SYMBOL_CLASS may get overriden by dwarf2_symbol_mark_computed. */ - -- dwarf2_symbol_mark_computed (attr, sym, cu); - SYMBOL_CLASS (sym) = LOC_COMPUTED; -+ dwarf2_symbol_mark_computed (attr, sym, cu); - } - - /* Given a pointer to a DWARF information entry, figure out if we need -@@ -7504,6 +7650,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) - sizeof (struct symbol)); - OBJSTAT (objfile, n_syms++); - memset (sym, 0, sizeof (struct symbol)); -+ /* Some methods are called without checking SYMBOL_OPS validity. */ -+ SYMBOL_OPS (sym) = &dwarf2_missing_funcs; - - /* Cache this symbol's name and the name's demangled form (if any). */ - SYMBOL_LANGUAGE (sym) = cu->language; -@@ -9309,26 +9457,35 @@ dwarf2_get_ref_die_offset (struct attribute *attr) - return result; - } - --/* Return the constant value held by the given attribute. Return -1 -- if the value held by the attribute is not constant. */ -+/* (*val_return) is filled only if returning dwarf2_attr_const. */ - --static int --dwarf2_get_attr_constant_value (struct attribute *attr, int default_value) -+static enum dwarf2_get_attr_constant_value -+dwarf2_get_attr_constant_value (struct attribute *attr, int *val_return) - { -+ if (attr == NULL) -+ return dwarf2_attr_unknown; - if (attr->form == DW_FORM_sdata) -- return DW_SND (attr); -- else if (attr->form == DW_FORM_udata -- || attr->form == DW_FORM_data1 -- || attr->form == DW_FORM_data2 -- || attr->form == DW_FORM_data4 -- || attr->form == DW_FORM_data8) -- return DW_UNSND (attr); -- else - { -- complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), -- dwarf_form_name (attr->form)); -- return default_value; -+ *val_return = DW_SND (attr); -+ return dwarf2_attr_const; - } -+ if (attr->form == DW_FORM_udata -+ || attr->form == DW_FORM_data1 -+ || attr->form == DW_FORM_data2 -+ || attr->form == DW_FORM_data4 -+ || attr->form == DW_FORM_data8) -+ { -+ *val_return = DW_UNSND (attr); -+ return dwarf2_attr_const; -+ } -+ if (attr->form == DW_FORM_block -+ || attr->form == DW_FORM_block1 -+ || attr->form == DW_FORM_block2 -+ || attr->form == DW_FORM_block4) -+ return dwarf2_attr_block; -+ complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), -+ dwarf_form_name (attr->form)); -+ return dwarf2_attr_unknown; - } - - /* THIS_CU has a reference to PER_CU. If necessary, load the new compilation -@@ -10106,6 +10263,34 @@ attr_form_is_constant (struct attribute *attr) - } - } - -+/* Convert DW_BLOCK into struct dwarf2_locexpr_baton. ATTR must be a DW_BLOCK -+ attribute type. */ -+ -+static struct dwarf2_locexpr_baton * -+dwarf2_attr_to_locexpr_baton (struct attribute *attr, struct dwarf2_cu *cu) -+{ -+ struct dwarf2_locexpr_baton *baton; -+ -+ gdb_assert (attr_form_is_block (attr)); -+ -+ baton = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (*baton)); -+ baton->per_cu = cu->per_cu; -+ gdb_assert (baton->per_cu); -+ -+ /* Note that we're just copying the block's data pointer -+ here, not the actual data. We're still pointing into the -+ info_buffer for SYM's objfile; right now we never release -+ that buffer, but when we do clean up properly this may -+ need to change. */ -+ baton->size = DW_BLOCK (attr)->size; -+ baton->data = DW_BLOCK (attr)->data; -+ gdb_assert (baton->size == 0 || baton->data != NULL); -+ -+ return baton; -+} -+ -+/* SYM may get its SYMBOL_CLASS overriden on invalid ATTR content. */ -+ - static void - dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, - struct dwarf2_cu *cu) -@@ -10135,35 +10320,24 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, - SYMBOL_OPS (sym) = &dwarf2_loclist_funcs; - SYMBOL_LOCATION_BATON (sym) = baton; - } -+ else if (attr_form_is_block (attr)) -+ { -+ SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs; -+ SYMBOL_LOCATION_BATON (sym) = dwarf2_attr_to_locexpr_baton (attr, cu); -+ } - else - { -- struct dwarf2_locexpr_baton *baton; -+ dwarf2_invalid_attrib_class_complaint ("location description", -+ SYMBOL_NATURAL_NAME (sym)); - -- baton = obstack_alloc (&cu->objfile->objfile_obstack, -- sizeof (struct dwarf2_locexpr_baton)); -- baton->per_cu = cu->per_cu; -- gdb_assert (baton->per_cu); -+ /* Some methods are called without checking SYMBOL_OPS validity. */ -+ SYMBOL_OPS (sym) = &dwarf2_missing_funcs; -+ SYMBOL_LOCATION_BATON (sym) = NULL; - -- if (attr_form_is_block (attr)) -- { -- /* Note that we're just copying the block's data pointer -- here, not the actual data. We're still pointing into the -- info_buffer for SYM's objfile; right now we never release -- that buffer, but when we do clean up properly this may -- need to change. */ -- baton->size = DW_BLOCK (attr)->size; -- baton->data = DW_BLOCK (attr)->data; -- } -- else -- { -- dwarf2_invalid_attrib_class_complaint ("location description", -- SYMBOL_NATURAL_NAME (sym)); -- baton->size = 0; -- baton->data = NULL; -- } -- -- SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs; -- SYMBOL_LOCATION_BATON (sym) = baton; -+ /* For functions a missing DW_AT_frame_base does not optimize out the -+ whole function definition, only its frame base resolving. */ -+ if (attr->name == DW_AT_location) -+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; - } - } - -@@ -10438,6 +10612,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) - return ofs_lhs->offset == ofs_rhs->offset; - } - -+/* Fill in generic attributes applicable for type DIEs. */ -+ -+static void -+fetch_die_type_attrs (struct die_info *die, struct type *type, -+ struct dwarf2_cu *cu) -+{ -+ struct attribute *attr; -+ -+ attr = dwarf2_attr (die, DW_AT_data_location, cu); -+ if (attr_form_is_block (attr)) -+ TYPE_DATA_LOCATION_DWARF_BLOCK (type) = dwarf2_attr_to_locexpr_baton (attr, -+ cu); -+ gdb_assert (!TYPE_DATA_LOCATION_IS_ADDR (type)); -+ -+ attr = dwarf2_attr (die, DW_AT_allocated, cu); -+ if (attr_form_is_block (attr)) -+ TYPE_ALLOCATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu); -+ gdb_assert (!TYPE_NOT_ALLOCATED (type)); -+ -+ attr = dwarf2_attr (die, DW_AT_associated, cu); -+ if (attr_form_is_block (attr)) -+ TYPE_ASSOCIATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu); -+ gdb_assert (!TYPE_NOT_ASSOCIATED (type)); -+} -+ - /* Set the type associated with DIE to TYPE. Save it in CU's hash - table if necessary. For convenience, return TYPE. */ - -@@ -10446,6 +10645,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) - { - struct dwarf2_offset_and_type **slot, ofs; - -+ fetch_die_type_attrs (die, type, cu); -+ - if (cu->type_hash == NULL) - { - gdb_assert (cu->per_cu != NULL); -diff --git a/gdb/eval.c b/gdb/eval.c -index 038334b..3e2c320 100644 ---- a/gdb/eval.c -+++ b/gdb/eval.c -@@ -40,6 +40,7 @@ - #include "regcache.h" - #include "user-regs.h" - #include "valprint.h" -+#include "dwarf2loc.h" - - #include "gdb_assert.h" - -@@ -671,6 +672,7 @@ evaluate_subexp_standard (struct type *expect_type, - long mem_offset; - struct type **arg_types; - int save_pos1; -+ struct cleanup *old_chain; - - pc = (*pos)++; - op = exp->elts[pc].opcode; -@@ -1529,7 +1531,10 @@ evaluate_subexp_standard (struct type *expect_type, - - /* First determine the type code we are dealing with. */ - arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); -+ old_chain = make_cleanup (null_cleanup, 0); -+ object_address_set (VALUE_ADDRESS (arg1)); - type = check_typedef (value_type (arg1)); -+ do_cleanups (old_chain); - code = TYPE_CODE (type); - - if (code == TYPE_CODE_PTR) -@@ -1963,13 +1968,19 @@ evaluate_subexp_standard (struct type *expect_type, - { - int subscript_array[MAX_FORTRAN_DIMS]; - int array_size_array[MAX_FORTRAN_DIMS]; -+ int byte_stride_array[MAX_FORTRAN_DIMS]; - int ndimensions = 1, i; - struct type *tmp_type; - int offset_item; /* The array offset where the item lives */ -+ CORE_ADDR offset_byte; /* byte_stride based offset */ -+ unsigned element_size; - - if (nargs > MAX_FORTRAN_DIMS) - error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS); - -+ old_chain = make_cleanup (null_cleanup, 0); -+ object_address_set (VALUE_ADDRESS (arg1)); -+ - tmp_type = check_typedef (value_type (arg1)); - ndimensions = calc_f77_array_dims (type); - -@@ -1999,6 +2010,9 @@ evaluate_subexp_standard (struct type *expect_type, - upper = f77_get_upperbound (tmp_type); - lower = f77_get_lowerbound (tmp_type); - -+ byte_stride_array[nargs - i - 1] = -+ TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type); -+ - array_size_array[nargs - i - 1] = upper - lower + 1; - - /* Zero-normalize subscripts so that offsetting will work. */ -@@ -2017,17 +2031,25 @@ evaluate_subexp_standard (struct type *expect_type, - tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type)); - } - -- /* Now let us calculate the offset for this item */ -+ /* Kept for the f77_get_upperbound / f77_get_lowerbound calls above. */ -+ do_cleanups (old_chain); - -- offset_item = subscript_array[ndimensions - 1]; -+ /* Now let us calculate the offset for this item */ - -- for (i = ndimensions - 1; i > 0; --i) -- offset_item = -- array_size_array[i - 1] * offset_item + subscript_array[i - 1]; -+ offset_item = 0; -+ offset_byte = 0; - -- /* Construct a value node with the value of the offset */ -+ for (i = ndimensions - 1; i >= 0; --i) -+ { -+ offset_item *= array_size_array[i]; -+ if (byte_stride_array[i] == 0) -+ offset_item += subscript_array[i]; -+ else -+ offset_byte += subscript_array[i] * byte_stride_array[i]; -+ } - -- arg2 = value_from_longest (builtin_type_int32, offset_item); -+ element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tmp_type)); -+ offset_byte += offset_item * element_size; - - /* Let us now play a dirty trick: we will take arg1 - which is a value node pointing to the topmost level -@@ -2037,7 +2059,7 @@ evaluate_subexp_standard (struct type *expect_type, - returns the correct type value */ - - deprecated_set_value_type (arg1, tmp_type); -- return value_subscripted_rvalue (arg1, arg2, 0); -+ return value_subscripted_rvalue (arg1, offset_byte); - } - - case BINOP_LOGICAL_AND: -@@ -2624,12 +2646,13 @@ evaluate_subexp_with_coercion (struct expression *exp, - { - case OP_VAR_VALUE: - var = exp->elts[pc + 2].symbol; -+ /* address_of_variable will call object_address_set for check_typedef. */ -+ val = address_of_variable (var, exp->elts[pc + 1].block); - type = check_typedef (SYMBOL_TYPE (var)); - if (TYPE_CODE (type) == TYPE_CODE_ARRAY - && CAST_IS_CONVERSION) - { - (*pos) += 4; -- val = address_of_variable (var, exp->elts[pc + 1].block); - return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)), - val); - } -@@ -2681,9 +2704,13 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos) - - case OP_VAR_VALUE: - (*pos) += 4; -- type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol)); -- return -- value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); -+ /* We do not need to call read_var_value but the object evaluation may -+ need to have executed object_address_set which needs valid -+ SYMBOL_VALUE_ADDRESS of the symbol. Still VALUE returned by -+ read_var_value we left as lazy. */ -+ type = value_type (read_var_value (exp->elts[pc + 2].symbol, -+ deprecated_safe_get_selected_frame ())); -+ return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); - - default: - val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); -diff --git a/gdb/f-lang.h b/gdb/f-lang.h -index 711bdba..123a783 100644 ---- a/gdb/f-lang.h -+++ b/gdb/f-lang.h -@@ -28,6 +28,10 @@ extern void f_error (char *); /* Defined in f-exp.y */ - extern void f_print_type (struct type *, char *, struct ui_file *, int, - int); - -+extern const char *f_object_address_data_valid_print_to_stream -+ (struct type *type, struct ui_file *stream); -+extern void f_object_address_data_valid_or_error (struct type *type); -+ - extern int f_val_print (struct type *, const gdb_byte *, int, CORE_ADDR, - struct ui_file *, int, - const struct value_print_options *); -diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c -index 6c9668f..852b9a8 100644 ---- a/gdb/f-typeprint.c -+++ b/gdb/f-typeprint.c -@@ -31,7 +31,7 @@ - #include "gdbcore.h" - #include "target.h" - #include "f-lang.h" -- -+#include "dwarf2loc.h" - #include "gdb_string.h" - #include - -@@ -48,6 +48,34 @@ void f_type_print_varspec_prefix (struct type *, struct ui_file *, - void f_type_print_base (struct type *, struct ui_file *, int, int); - - -+const char * -+f_object_address_data_valid_print_to_stream (struct type *type, -+ struct ui_file *stream) -+{ -+ const char *msg; -+ -+ msg = object_address_data_not_valid (type); -+ if (msg != NULL) -+ { -+ /* Assuming the content printed to STREAM should not be localized. */ -+ fprintf_filtered (stream, "<%s>", msg); -+ } -+ -+ return msg; -+} -+ -+void -+f_object_address_data_valid_or_error (struct type *type) -+{ -+ const char *msg; -+ -+ msg = object_address_data_not_valid (type); -+ if (msg != NULL) -+ { -+ error (_("Cannot access it because the %s."), _(msg)); -+ } -+} -+ - /* LEVEL is the depth to indent lines by. */ - - void -@@ -57,6 +85,9 @@ f_print_type (struct type *type, char *varstring, struct ui_file *stream, - enum type_code code; - int demangled_args; - -+ if (f_object_address_data_valid_print_to_stream (type, stream) != NULL) -+ return; -+ - f_type_print_base (type, stream, show, level); - code = TYPE_CODE (type); - if ((varstring != NULL && *varstring != '\0') -@@ -166,6 +197,9 @@ f_type_print_varspec_suffix (struct type *type, struct ui_file *stream, - - QUIT; - -+ if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF) -+ CHECK_TYPEDEF (type); -+ - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: -diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c -index 5721041..a4d69fb 100644 ---- a/gdb/f-valprint.c -+++ b/gdb/f-valprint.c -@@ -54,15 +54,17 @@ int f77_array_offset_tbl[MAX_FORTRAN_DIMS + 1][2]; - /* The following macro gives us the size of the nth dimension, Where - n is 1 based. */ - --#define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1]) -+#define F77_DIM_COUNT(n) (f77_array_offset_tbl[n][1]) - --/* The following gives us the offset for row n where n is 1-based. */ -+/* The following gives us the element size for row n where n is 1-based. */ - --#define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0]) -+#define F77_DIM_BYTE_STRIDE(n) (f77_array_offset_tbl[n][0]) - - int - f77_get_lowerbound (struct type *type) - { -+ f_object_address_data_valid_or_error (type); -+ - if (TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED (type)) - error (_("Lower bound may not be '*' in F77")); - -@@ -72,14 +74,17 @@ f77_get_lowerbound (struct type *type) - int - f77_get_upperbound (struct type *type) - { -+ f_object_address_data_valid_or_error (type); -+ - if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) - { -- /* We have an assumed size array on our hands. Assume that -- upper_bound == lower_bound so that we show at least 1 element. -- If the user wants to see more elements, let him manually ask for 'em -- and we'll subscript the array and show him. */ -+ /* We have an assumed size array on our hands. As type_length_get -+ already assumes a length zero of arrays with underfined bounds VALADDR -+ passed to the Fortran functions does not contained the real inferior -+ memory content. User should request printing of specific array -+ elements instead. */ - -- return f77_get_lowerbound (type); -+ return f77_get_lowerbound (type) - 1; - } - - return TYPE_ARRAY_UPPER_BOUND_VALUE (type); -@@ -135,24 +140,29 @@ f77_create_arrayprint_offset_tbl (struct type *type, struct ui_file *stream) - upper = f77_get_upperbound (tmp_type); - lower = f77_get_lowerbound (tmp_type); - -- F77_DIM_SIZE (ndimen) = upper - lower + 1; -+ F77_DIM_COUNT (ndimen) = upper - lower + 1; -+ -+ F77_DIM_BYTE_STRIDE (ndimen) = -+ TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type); - - tmp_type = TYPE_TARGET_TYPE (tmp_type); - ndimen++; - } - -- /* Now we multiply eltlen by all the offsets, so that later we -+ /* Now we multiply eltlen by all the BYTE_STRIDEs, so that later we - can print out array elements correctly. Up till now we -- know an offset to apply to get the item but we also -+ know an eltlen to apply to get the item but we also - have to know how much to add to get to the next item */ - - ndimen--; - eltlen = TYPE_LENGTH (tmp_type); -- F77_DIM_OFFSET (ndimen) = eltlen; -+ if (F77_DIM_BYTE_STRIDE (ndimen) == 0) -+ F77_DIM_BYTE_STRIDE (ndimen) = eltlen; - while (--ndimen > 0) - { -- eltlen *= F77_DIM_SIZE (ndimen + 1); -- F77_DIM_OFFSET (ndimen) = eltlen; -+ eltlen *= F77_DIM_COUNT (ndimen + 1); -+ if (F77_DIM_BYTE_STRIDE (ndimen) == 0) -+ F77_DIM_BYTE_STRIDE (ndimen) = eltlen; - } - } - -@@ -172,34 +182,34 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type, - - if (nss != ndimensions) - { -- for (i = 0; (i < F77_DIM_SIZE (nss) && (*elts) < options->print_max); i++) -+ for (i = 0; (i < F77_DIM_COUNT (nss) && (*elts) < options->print_max); i++) - { - fprintf_filtered (stream, "( "); - f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type), -- valaddr + i * F77_DIM_OFFSET (nss), -- address + i * F77_DIM_OFFSET (nss), -+ valaddr + i * F77_DIM_BYTE_STRIDE (nss), -+ address + i * F77_DIM_BYTE_STRIDE (nss), - stream, recurse, options, elts); - fprintf_filtered (stream, ") "); - } -- if (*elts >= options->print_max && i < F77_DIM_SIZE (nss)) -+ if (*elts >= options->print_max && i < F77_DIM_COUNT (nss)) - fprintf_filtered (stream, "..."); - } - else - { -- for (i = 0; i < F77_DIM_SIZE (nss) && (*elts) < options->print_max; -+ for (i = 0; i < F77_DIM_COUNT (nss) && (*elts) < options->print_max; - i++, (*elts)++) - { - val_print (TYPE_TARGET_TYPE (type), -- valaddr + i * F77_DIM_OFFSET (ndimensions), -+ valaddr + i * F77_DIM_BYTE_STRIDE (ndimensions), - 0, -- address + i * F77_DIM_OFFSET (ndimensions), -+ address + i * F77_DIM_BYTE_STRIDE (ndimensions), - stream, recurse, options, current_language); - -- if (i != (F77_DIM_SIZE (nss) - 1)) -+ if (i != (F77_DIM_COUNT (nss) - 1)) - fprintf_filtered (stream, ", "); - - if ((*elts == options->print_max - 1) -- && (i != (F77_DIM_SIZE (nss) - 1))) -+ && (i != (F77_DIM_COUNT (nss) - 1))) - fprintf_filtered (stream, "..."); - } - } -@@ -251,6 +261,9 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, - CORE_ADDR addr; - int index; - -+ if (f_object_address_data_valid_print_to_stream (type, stream) != NULL) -+ return 0; -+ - CHECK_TYPEDEF (type); - switch (TYPE_CODE (type)) - { -diff --git a/gdb/findvar.c b/gdb/findvar.c -index 1048887..b9e7711 100644 ---- a/gdb/findvar.c -+++ b/gdb/findvar.c -@@ -35,6 +35,7 @@ - #include "user-regs.h" - #include "block.h" - #include "objfiles.h" -+#include "dwarf2loc.h" - - /* Basic byte-swapping routines. GDB has needed these for a long time... - All extract a target-format integer at ADDR which is LEN bytes long. */ -@@ -382,27 +383,16 @@ symbol_read_needs_frame (struct symbol *sym) - /* Given a struct symbol for a variable, - and a stack frame id, read the value of the variable - and return a (pointer to a) struct value containing the value. -- If the variable cannot be found, return a zero pointer. */ -+ If the variable cannot be found, return a zero pointer. -+ We have to first find the address of the variable before allocating struct -+ value to return as its size may depend on DW_OP_PUSH_OBJECT_ADDRESS possibly -+ used by its type. */ - - struct value * - read_var_value (struct symbol *var, struct frame_info *frame) - { -- struct value *v; - struct type *type = SYMBOL_TYPE (var); - CORE_ADDR addr; -- int len; -- -- if (SYMBOL_CLASS (var) == LOC_COMPUTED -- || SYMBOL_CLASS (var) == LOC_REGISTER) -- /* These cases do not use V. */ -- v = NULL; -- else -- { -- v = allocate_value (type); -- VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */ -- } -- -- len = TYPE_LENGTH (type); - - if (symbol_read_needs_frame (var)) - gdb_assert (frame); -@@ -410,31 +400,39 @@ read_var_value (struct symbol *var, struct frame_info *frame) - switch (SYMBOL_CLASS (var)) - { - case LOC_CONST: -- /* Put the constant back in target format. */ -- store_signed_integer (value_contents_raw (v), len, -- (LONGEST) SYMBOL_VALUE (var)); -- VALUE_LVAL (v) = not_lval; -- return v; -+ { -+ /* Put the constant back in target format. */ -+ struct value *v = allocate_value (type); -+ VALUE_LVAL (v) = not_lval; -+ store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type), -+ (LONGEST) SYMBOL_VALUE (var)); -+ return v; -+ } - - case LOC_LABEL: -- /* Put the constant back in target format. */ -- if (overlay_debugging) -- { -- CORE_ADDR addr -- = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), -- SYMBOL_OBJ_SECTION (var)); -- store_typed_address (value_contents_raw (v), type, addr); -- } -- else -- store_typed_address (value_contents_raw (v), type, -- SYMBOL_VALUE_ADDRESS (var)); -- VALUE_LVAL (v) = not_lval; -- return v; -+ { -+ /* Put the constant back in target format. */ -+ struct value *v = allocate_value (type); -+ VALUE_LVAL (v) = not_lval; -+ if (overlay_debugging) -+ { -+ CORE_ADDR addr -+ = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), -+ SYMBOL_OBJ_SECTION (var)); -+ store_typed_address (value_contents_raw (v), type, addr); -+ } -+ else -+ store_typed_address (value_contents_raw (v), type, -+ SYMBOL_VALUE_ADDRESS (var)); -+ return v; -+ } - - case LOC_CONST_BYTES: - { -- memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), len); -+ struct value *v = allocate_value (type); - VALUE_LVAL (v) = not_lval; -+ memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), -+ TYPE_LENGTH (type)); - return v; - } - -@@ -476,12 +474,23 @@ read_var_value (struct symbol *var, struct frame_info *frame) - break; - - case LOC_BLOCK: -- if (overlay_debugging) -- VALUE_ADDRESS (v) = symbol_overlayed_address -- (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)); -- else -- VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); -- return v; -+ { -+ CORE_ADDR addr; -+ struct value *v; -+ -+ if (overlay_debugging) -+ addr = symbol_overlayed_address -+ (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)); -+ else -+ addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); -+ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for -+ DW_OP_push_object_address. */ -+ object_address_set (addr); -+ v = allocate_value (type); -+ VALUE_ADDRESS (v) = addr; -+ VALUE_LVAL (v) = lval_memory; -+ return v; -+ } - - case LOC_REGISTER: - case LOC_REGPARM_ADDR: -@@ -499,7 +508,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) - error (_("Value of register variable not available.")); - - addr = value_as_address (regval); -- VALUE_LVAL (v) = lval_memory; - } - else - { -@@ -542,18 +550,33 @@ read_var_value (struct symbol *var, struct frame_info *frame) - break; - - case LOC_OPTIMIZED_OUT: -- VALUE_LVAL (v) = not_lval; -- set_value_optimized_out (v, 1); -- return v; -+ { -+ struct value *v = allocate_value (type); -+ -+ VALUE_LVAL (v) = not_lval; -+ set_value_optimized_out (v, 1); -+ return v; -+ } - - default: - error (_("Cannot look up value of a botched symbol.")); - break; - } - -- VALUE_ADDRESS (v) = addr; -- set_value_lazy (v, 1); -- return v; -+ { -+ struct value *v; -+ -+ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for -+ DW_OP_PUSH_OBJECT_ADDRESS. */ -+ object_address_set (addr); -+ v = allocate_value (type); -+ VALUE_ADDRESS (v) = addr; -+ VALUE_LVAL (v) = lval_memory; -+ -+ set_value_lazy (v, 1); -+ -+ return v; -+ } - } - - /* Install default attributes for register values. */ -@@ -590,10 +613,11 @@ struct value * - value_from_register (struct type *type, int regnum, struct frame_info *frame) - { - struct gdbarch *gdbarch = get_frame_arch (frame); -- struct type *type1 = check_typedef (type); - struct value *v; - -- if (gdbarch_convert_register_p (gdbarch, regnum, type1)) -+ type = check_typedef (type); -+ -+ if (gdbarch_convert_register_p (gdbarch, regnum, type)) - { - /* The ISA/ABI need to something weird when obtaining the - specified value from this register. It might need to -@@ -607,7 +631,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame) - VALUE_FRAME_ID (v) = get_frame_id (frame); - VALUE_REGNUM (v) = regnum; - gdbarch_register_to_value (gdbarch, -- frame, regnum, type1, value_contents_raw (v)); -+ frame, regnum, type, value_contents_raw (v)); - } - else - { -diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c -index 8102321..e6190cf 100644 ---- a/gdb/gdbtypes.c -+++ b/gdb/gdbtypes.c -@@ -38,6 +38,8 @@ - #include "cp-abi.h" - #include "gdb_assert.h" - #include "hashtab.h" -+#include "dwarf2expr.h" -+#include "dwarf2loc.h" - - /* These variables point to the objects - representing the predefined C data types. */ -@@ -146,6 +148,23 @@ static void print_bit_vector (B_TYPE *, int); - static void print_arg_types (struct field *, int, int); - static void dump_fn_fieldlists (struct type *, int); - static void print_cplus_stuff (struct type *, int); -+static void type_init_refc (struct type *new_type, struct type *parent_type); -+ -+/* A reference count structure for the type reference count map. Each -+ type in a hierarchy of types is mapped to the same reference -+ count. */ -+struct type_refc_entry -+{ -+ /* One type in the hierarchy. Each type in the hierarchy gets its -+ own slot. */ -+ struct type *type; -+ -+ /* A pointer to the shared reference count. */ -+ int *refc; -+}; -+ -+/* The hash table holding all reference counts. */ -+static htab_t type_refc_table; - - - /* Alloc a new type structure and fill it with some defaults. If -@@ -154,23 +173,25 @@ static void print_cplus_stuff (struct type *, int); - structure by xmalloc () (for permanent types). */ - - struct type * --alloc_type (struct objfile *objfile) -+alloc_type (struct objfile *objfile, struct type *parent) - { - struct type *type; - - /* Alloc the structure and start off with all fields zeroed. */ - -- if (objfile == NULL) -+ switch ((long) objfile) - { -+ case (long) OBJFILE_INTERNAL: -+ case (long) OBJFILE_MALLOC: - type = XZALLOC (struct type); - TYPE_MAIN_TYPE (type) = XZALLOC (struct main_type); -- } -- else -- { -+ break; -+ default: - type = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct type); - TYPE_MAIN_TYPE (type) = OBSTACK_ZALLOC (&objfile->objfile_obstack, - struct main_type); - OBJSTAT (objfile, n_types++); -+ break; - } - - /* Initialize the fields that might not be zero. */ -@@ -180,6 +201,9 @@ alloc_type (struct objfile *objfile) - TYPE_VPTR_FIELDNO (type) = -1; - TYPE_CHAIN (type) = type; /* Chain back to itself. */ - -+ if (objfile == NULL) -+ type_init_refc (type, parent); -+ - return (type); - } - -@@ -194,16 +218,24 @@ alloc_type_instance (struct type *oldtype) - - /* Allocate the structure. */ - -- if (TYPE_OBJFILE (oldtype) == NULL) -- type = XZALLOC (struct type); -- else -- type = OBSTACK_ZALLOC (&TYPE_OBJFILE (oldtype)->objfile_obstack, -- struct type); -- -+ switch ((long) TYPE_OBJFILE (oldtype)) -+ { -+ case (long) OBJFILE_INTERNAL: -+ case (long) OBJFILE_MALLOC: -+ type = XZALLOC (struct type); -+ break; -+ default: -+ type = OBSTACK_ZALLOC (&TYPE_OBJFILE (oldtype)->objfile_obstack, -+ struct type); -+ break; -+ } - TYPE_MAIN_TYPE (type) = TYPE_MAIN_TYPE (oldtype); - - TYPE_CHAIN (type) = type; /* Chain back to itself for now. */ - -+ if (TYPE_OBJFILE (oldtype) == NULL) -+ type_init_refc (type, oldtype); -+ - return (type); - } - -@@ -248,7 +280,7 @@ make_pointer_type (struct type *type, struct type **typeptr) - - if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ - { -- ntype = alloc_type (TYPE_OBJFILE (type)); -+ ntype = alloc_type (TYPE_OBJFILE (type), type); - if (typeptr) - *typeptr = ntype; - } -@@ -260,6 +292,9 @@ make_pointer_type (struct type *type, struct type **typeptr) - smash_type (ntype); - TYPE_CHAIN (ntype) = chain; - TYPE_OBJFILE (ntype) = objfile; -+ -+ /* Callers may only supply storage if there is an objfile. */ -+ gdb_assert (objfile); - } - - TYPE_TARGET_TYPE (ntype) = type; -@@ -328,7 +363,7 @@ make_reference_type (struct type *type, struct type **typeptr) - - if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ - { -- ntype = alloc_type (TYPE_OBJFILE (type)); -+ ntype = alloc_type (TYPE_OBJFILE (type), type); - if (typeptr) - *typeptr = ntype; - } -@@ -340,6 +375,9 @@ make_reference_type (struct type *type, struct type **typeptr) - smash_type (ntype); - TYPE_CHAIN (ntype) = chain; - TYPE_OBJFILE (ntype) = objfile; -+ -+ /* Callers may only supply storage if there is an objfile. */ -+ gdb_assert (objfile); - } - - TYPE_TARGET_TYPE (ntype) = type; -@@ -388,7 +426,7 @@ make_function_type (struct type *type, struct type **typeptr) - - if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ - { -- ntype = alloc_type (TYPE_OBJFILE (type)); -+ ntype = alloc_type (TYPE_OBJFILE (type), type); - if (typeptr) - *typeptr = ntype; - } -@@ -398,6 +436,9 @@ make_function_type (struct type *type, struct type **typeptr) - objfile = TYPE_OBJFILE (ntype); - smash_type (ntype); - TYPE_OBJFILE (ntype) = objfile; -+ -+ /* Callers may only supply storage if there is an objfile. */ -+ gdb_assert (objfile); - } - - TYPE_TARGET_TYPE (ntype) = type; -@@ -643,7 +684,7 @@ lookup_memberptr_type (struct type *type, struct type *domain) - { - struct type *mtype; - -- mtype = alloc_type (TYPE_OBJFILE (type)); -+ mtype = alloc_type (TYPE_OBJFILE (type), NULL); - smash_to_memberptr_type (mtype, domain, type); - return (mtype); - } -@@ -655,7 +696,7 @@ lookup_methodptr_type (struct type *to_type) - { - struct type *mtype; - -- mtype = alloc_type (TYPE_OBJFILE (to_type)); -+ mtype = alloc_type (TYPE_OBJFILE (to_type), NULL); - TYPE_TARGET_TYPE (mtype) = to_type; - TYPE_DOMAIN_TYPE (mtype) = TYPE_DOMAIN_TYPE (to_type); - TYPE_LENGTH (mtype) = cplus_method_ptr_size (to_type); -@@ -696,19 +737,20 @@ create_range_type (struct type *result_type, struct type *index_type, - int low_bound, int high_bound) - { - if (result_type == NULL) -- result_type = alloc_type (TYPE_OBJFILE (index_type)); -+ result_type = alloc_type (TYPE_OBJFILE (index_type), index_type); - TYPE_CODE (result_type) = TYPE_CODE_RANGE; - TYPE_TARGET_TYPE (result_type) = index_type; - if (TYPE_STUB (index_type)) - TYPE_TARGET_STUB (result_type) = 1; - else - TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type)); -- TYPE_NFIELDS (result_type) = 2; -+ TYPE_NFIELDS (result_type) = 3; - TYPE_FIELDS (result_type) = TYPE_ZALLOC (result_type, - TYPE_NFIELDS (result_type) - * sizeof (struct field)); - TYPE_LOW_BOUND (result_type) = low_bound; - TYPE_HIGH_BOUND (result_type) = high_bound; -+ TYPE_BYTE_STRIDE (result_type) = 0; - - if (low_bound >= 0) - TYPE_UNSIGNED (result_type) = 1; -@@ -727,6 +769,9 @@ get_discrete_bounds (struct type *type, LONGEST *lowp, LONGEST *highp) - switch (TYPE_CODE (type)) - { - case TYPE_CODE_RANGE: -+ if (TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (type) -+ || TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (type)) -+ return -1; - *lowp = TYPE_LOW_BOUND (type); - *highp = TYPE_HIGH_BOUND (type); - return 1; -@@ -805,30 +850,65 @@ create_array_type (struct type *result_type, - - if (result_type == NULL) - { -- result_type = alloc_type (TYPE_OBJFILE (range_type)); -+ result_type = alloc_type (TYPE_OBJFILE (range_type), range_type); - } -+ else -+ { -+ /* Callers may only supply storage if there is an objfile. */ -+ gdb_assert (TYPE_OBJFILE (result_type)); -+ } -+ - TYPE_CODE (result_type) = TYPE_CODE_ARRAY; - TYPE_TARGET_TYPE (result_type) = element_type; -- if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) -- low_bound = high_bound = 0; -- CHECK_TYPEDEF (element_type); -- /* Be careful when setting the array length. Ada arrays can be -- empty arrays with the high_bound being smaller than the low_bound. -- In such cases, the array length should be zero. */ -- if (high_bound < low_bound) -- TYPE_LENGTH (result_type) = 0; -- else -- TYPE_LENGTH (result_type) = -- TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); - TYPE_NFIELDS (result_type) = 1; - TYPE_FIELDS (result_type) = - (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field)); -+ /* FIXME: type alloc. */ - TYPE_INDEX_TYPE (result_type) = range_type; - TYPE_VPTR_FIELDNO (result_type) = -1; - -- /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays */ -+ /* DWARF blocks may depend on runtime information like -+ DW_OP_PUSH_OBJECT_ADDRESS not being available during the -+ CREATE_ARRAY_TYPE time. */ -+ if (TYPE_RANGE_BOUND_IS_DWARF_BLOCK (range_type, 0) -+ || TYPE_RANGE_BOUND_IS_DWARF_BLOCK (range_type, 1) -+ || TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type) -+ || TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (range_type) -+ || get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) -+ { -+ low_bound = 0; -+ high_bound = -1; -+ } -+ -+ /* Be careful when setting the array length. Ada arrays can be -+ empty arrays with the high_bound being smaller than the low_bound. -+ In such cases, the array length should be zero. TYPE_TARGET_STUB needs to -+ be checked as it may have dependencies on DWARF blocks depending on -+ runtime information not available during the CREATE_ARRAY_TYPE time. */ -+ if (high_bound < low_bound || TYPE_TARGET_STUB (element_type)) -+ TYPE_LENGTH (result_type) = 0; -+ else -+ { -+ CHECK_TYPEDEF (element_type); -+ TYPE_LENGTH (result_type) = -+ TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); -+ } -+ -+ if (TYPE_DYNAMIC (range_type)) -+ TYPE_DYNAMIC (result_type) = 1; -+ -+ /* Multidimensional dynamic arrays need to have all the outer dimensions -+ dynamic to update the outer TYPE_TARGET_TYPE pointer with the new type -+ with statically evaluated dimensions. */ -+ if (TYPE_DYNAMIC (element_type)) -+ TYPE_DYNAMIC (result_type) = 1; -+ - if (TYPE_LENGTH (result_type) == 0) -- TYPE_TARGET_STUB (result_type) = 1; -+ { -+ /* The real size will be computed for specific instances by -+ CHECK_TYPEDEF. */ -+ TYPE_TARGET_STUB (result_type) = 1; -+ } - - return (result_type); - } -@@ -865,7 +945,12 @@ create_set_type (struct type *result_type, struct type *domain_type) - { - if (result_type == NULL) - { -- result_type = alloc_type (TYPE_OBJFILE (domain_type)); -+ result_type = alloc_type (TYPE_OBJFILE (domain_type), domain_type); -+ } -+ else -+ { -+ /* Callers may only supply storage if there is an objfile. */ -+ gdb_assert (TYPE_OBJFILE (result_type)); - } - TYPE_CODE (result_type) = TYPE_CODE_SET; - TYPE_NFIELDS (result_type) = 1; -@@ -1368,6 +1453,65 @@ stub_noname_complaint (void) - complaint (&symfile_complaints, _("stub type has NULL name")); - } - -+/* Calculate the memory length of array TYPE. -+ -+ TARGET_TYPE should be set to `check_typedef (TYPE_TARGET_TYPE (type))' as -+ a performance hint. Feel free to pass NULL. Set FULL_SPAN to return the -+ size incl. the possible padding of the last element - it may differ from the -+ cleared FULL_SPAN return value (the expected SIZEOF) for non-zero -+ TYPE_BYTE_STRIDE values. */ -+ -+static CORE_ADDR -+type_length_get (struct type *type, struct type *target_type, int full_span) -+{ -+ struct type *range_type; -+ int count; -+ CORE_ADDR byte_stride = 0; /* `= 0' for a false GCC warning. */ -+ CORE_ADDR element_size; -+ -+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY -+ && TYPE_CODE (type) != TYPE_CODE_STRING) -+ return TYPE_LENGTH (type); -+ -+ /* Avoid executing TYPE_HIGH_BOUND for invalid (unallocated/unassociated) -+ Fortran arrays. The allocated data will never be used so they can be -+ zero-length. */ -+ if (object_address_data_not_valid (type)) -+ return 0; -+ -+ range_type = TYPE_INDEX_TYPE (type); -+ if (TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (range_type) -+ || TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type)) -+ return 0; -+ count = TYPE_HIGH_BOUND (range_type) - TYPE_LOW_BOUND (range_type) + 1; -+ /* It may happen for wrong DWARF annotations returning garbage data. */ -+ if (count < 0) -+ warning (_("Range for type %s has invalid bounds %d..%d"), -+ TYPE_NAME (type), TYPE_LOW_BOUND (range_type), -+ TYPE_HIGH_BOUND (range_type)); -+ /* The code below does not handle count == 0 right. */ -+ if (count <= 0) -+ return 0; -+ if (full_span || count > 1) -+ { -+ /* We do not use TYPE_ARRAY_BYTE_STRIDE_VALUE (type) here as we want to -+ force FULL_SPAN to 1. */ -+ byte_stride = TYPE_BYTE_STRIDE (range_type); -+ if (byte_stride == 0) -+ { -+ if (target_type == NULL) -+ target_type = check_typedef (TYPE_TARGET_TYPE (type)); -+ byte_stride = type_length_get (target_type, NULL, 1); -+ } -+ } -+ if (full_span) -+ return count * byte_stride; -+ if (target_type == NULL) -+ target_type = check_typedef (TYPE_TARGET_TYPE (type)); -+ element_size = type_length_get (target_type, NULL, 1); -+ return (count - 1) * byte_stride + element_size; -+} -+ - /* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989. - - If this is a stubbed struct (i.e. declared as struct foo *), see if -@@ -1384,7 +1528,8 @@ stub_noname_complaint (void) - /* Find the real type of TYPE. This function returns the real type, - after removing all layers of typedefs and completing opaque or stub - types. Completion changes the TYPE argument, but stripping of -- typedefs does not. */ -+ typedefs does not. Still original passed TYPE will have TYPE_LENGTH -+ updated. FIXME: Remove this dependency (only ada_to_fixed_type?). */ - - struct type * - check_typedef (struct type *type) -@@ -1420,7 +1565,7 @@ check_typedef (struct type *type) - if (sym) - TYPE_TARGET_TYPE (type) = SYMBOL_TYPE (sym); - else /* TYPE_CODE_UNDEF */ -- TYPE_TARGET_TYPE (type) = alloc_type (NULL); -+ TYPE_TARGET_TYPE (type) = alloc_type (NULL, NULL); - } - type = TYPE_TARGET_TYPE (type); - } -@@ -1494,34 +1639,37 @@ check_typedef (struct type *type) - } - } - -- if (TYPE_TARGET_STUB (type)) -+ /* copy_type_recursive automatically makes the resulting type containing only -+ constant values expected by the callers of this function. */ -+ if (TYPE_DYNAMIC (type)) -+ { -+ htab_t copied_types; -+ struct type *type_old = type; -+ -+ copied_types = create_copied_types_hash (NULL); -+ type = copy_type_recursive (type, copied_types); -+ htab_delete (copied_types); -+ -+ gdb_assert (TYPE_DYNAMIC (type) == 0); -+ } -+ -+ if (!currently_reading_symtab -+ && (TYPE_TARGET_STUB (type) || TYPE_DYNAMIC (type))) - { -- struct type *range_type; - struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type)); - -+ if (TYPE_DYNAMIC (type)) -+ TYPE_TARGET_TYPE (type) = target_type; - if (TYPE_STUB (target_type) || TYPE_TARGET_STUB (target_type)) - { - /* Empty. */ - } - else if (TYPE_CODE (type) == TYPE_CODE_ARRAY -- && TYPE_NFIELDS (type) == 1 -- && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type)) -- == TYPE_CODE_RANGE)) -+ || TYPE_CODE (type) == TYPE_CODE_STRING) - { - /* Now recompute the length of the array type, based on its -- number of elements and the target type's length. -- Watch out for Ada null Ada arrays where the high bound -- is smaller than the low bound. */ -- const int low_bound = TYPE_LOW_BOUND (range_type); -- const int high_bound = TYPE_HIGH_BOUND (range_type); -- int nb_elements; -- -- if (high_bound < low_bound) -- nb_elements = 0; -- else -- nb_elements = high_bound - low_bound + 1; -- -- TYPE_LENGTH (type) = nb_elements * TYPE_LENGTH (target_type); -+ number of elements and the target type's length. */ -+ TYPE_LENGTH (type) = type_length_get (type, target_type, 0); - TYPE_TARGET_STUB (type) = 0; - } - else if (TYPE_CODE (type) == TYPE_CODE_RANGE) -@@ -1529,9 +1677,12 @@ check_typedef (struct type *type) - TYPE_LENGTH (type) = TYPE_LENGTH (target_type); - TYPE_TARGET_STUB (type) = 0; - } -+ TYPE_DYNAMIC (type) = 0; - } -+ - /* Cache TYPE_LENGTH for future use. */ - TYPE_LENGTH (orig_type) = TYPE_LENGTH (type); -+ - return type; - } - -@@ -1753,7 +1904,7 @@ init_type (enum type_code code, int length, int flags, - { - struct type *type; - -- type = alloc_type (objfile); -+ type = alloc_type (objfile, NULL); - TYPE_CODE (type) = code; - TYPE_LENGTH (type) = length; - -@@ -1783,15 +1934,24 @@ init_type (enum type_code code, int length, int flags, - if (flags & TYPE_FLAG_FIXED_INSTANCE) - TYPE_FIXED_INSTANCE (type) = 1; - -- if ((name != NULL) && (objfile != NULL)) -- { -- TYPE_NAME (type) = obsavestring (name, strlen (name), -- &objfile->objfile_obstack); -- } -- else -- { -- TYPE_NAME (type) = name; -- } -+ if (name) -+ switch ((long) objfile) -+ { -+ case (long) OBJFILE_INTERNAL: -+ TYPE_NAME (type) = name; -+ break; -+ case (long) OBJFILE_MALLOC: -+ TYPE_NAME (type) = xstrdup (name); -+ break; -+#if 0 /* OBJFILE_MALLOC duplication now. */ -+ case (long) NULL: -+ internal_error (__FILE__, __LINE__, -+ _("OBJFILE pointer NULL should be OBJFILE_* instead")); -+#endif -+ default: -+ TYPE_NAME (type) = obsavestring (name, strlen (name), -+ &objfile->objfile_obstack); -+ } - - /* C++ fancies. */ - -@@ -1803,6 +1963,10 @@ init_type (enum type_code code, int length, int flags, - { - INIT_CPLUS_SPECIFIC (type); - } -+ -+ if (!objfile) -+ type_incref (type); -+ - return (type); - } - -@@ -2916,33 +3080,47 @@ type_pair_eq (const void *item_lhs, const void *item_rhs) - } - - /* Allocate the hash table used by copy_type_recursive to walk -- types without duplicates. We use OBJFILE's obstack, because -- OBJFILE is about to be deleted. */ -+ types without duplicates. */ - - htab_t - create_copied_types_hash (struct objfile *objfile) - { -- return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, -- NULL, &objfile->objfile_obstack, -- hashtab_obstack_allocate, -- dummy_obstack_deallocate); -+ if (objfile == NULL) -+ { -+ /* NULL OBJFILE is for TYPE_DYNAMIC types already contained in -+ OBJFILE_MALLOC memory, such as those from VALUE_HISTORY_CHAIN. Table -+ element entries get allocated by xmalloc - so use xfree. */ -+ return htab_create (1, type_pair_hash, type_pair_eq, xfree); -+ } -+ else -+ { -+ /* Use OBJFILE's obstack, because OBJFILE is about to be deleted. Table -+ element entries get allocated by xmalloc - so use xfree. */ -+ return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, -+ xfree, &objfile->objfile_obstack, -+ hashtab_obstack_allocate, -+ dummy_obstack_deallocate); -+ } - } - --/* Recursively copy (deep copy) TYPE, if it is associated with -- OBJFILE. Return a new type allocated using malloc, a saved type if -- we have already visited TYPE (using COPIED_TYPES), or TYPE if it is -- not associated with OBJFILE. */ -+/* A helper for copy_type_recursive. This does all the work. -+ REPRESENTATIVE is a pointer to a type. This is used to register -+ newly-created types in the type_refc_table. Initially it pointer -+ to a NULL pointer, but it is filled in the first time a type is -+ copied. OBJFILE is used only for an assertion checking. */ - --struct type * --copy_type_recursive (struct objfile *objfile, -- struct type *type, -- htab_t copied_types) -+static struct type * -+copy_type_recursive_1 (struct objfile *objfile, -+ struct type *type, -+ htab_t copied_types, -+ struct type **representative) - { - struct type_pair *stored, pair; - void **slot; - struct type *new_type; - -- if (TYPE_OBJFILE (type) == NULL) -+ if (TYPE_OBJFILE (type) == OBJFILE_INTERNAL -+ || (objfile == OBJFILE_MALLOC && !TYPE_DYNAMIC (type))) - return type; - - /* This type shouldn't be pointing to any types in other objfiles; -@@ -2954,11 +3132,15 @@ copy_type_recursive (struct objfile *objfile, - if (*slot != NULL) - return ((struct type_pair *) *slot)->new; - -- new_type = alloc_type (NULL); -+ new_type = alloc_type (OBJFILE_MALLOC, *representative); -+ if (!*representative) -+ *representative = new_type; - - /* We must add the new type to the hash table immediately, in case -- we encounter this type again during a recursive call below. */ -- stored = obstack_alloc (&objfile->objfile_obstack, sizeof (struct type_pair)); -+ we encounter this type again during a recursive call below. Memory could -+ be allocated from OBJFILE in the case we will be removing OBJFILE, this -+ optimization is missed and xfree is called for it from COPIED_TYPES. */ -+ stored = xmalloc (sizeof (*stored)); - stored->old = type; - stored->new = new_type; - *slot = stored; -@@ -2968,6 +3150,13 @@ copy_type_recursive (struct objfile *objfile, - *TYPE_MAIN_TYPE (new_type) = *TYPE_MAIN_TYPE (type); - TYPE_OBJFILE (new_type) = NULL; - -+ /* Pre-clear the fields processed by delete_main_type. If DWARF block -+ evaluations below call error we would leave an unfreeable TYPE. */ -+ TYPE_TARGET_TYPE (new_type) = NULL; -+ TYPE_VPTR_BASETYPE (new_type) = NULL; -+ TYPE_NFIELDS (new_type) = 0; -+ TYPE_FIELDS (new_type) = NULL; -+ - if (TYPE_NAME (type)) - TYPE_NAME (new_type) = xstrdup (TYPE_NAME (type)); - if (TYPE_TAG_NAME (type)) -@@ -2976,12 +3165,45 @@ copy_type_recursive (struct objfile *objfile, - TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); - TYPE_LENGTH (new_type) = TYPE_LENGTH (type); - -+ if (TYPE_ALLOCATED (new_type)) -+ { -+ gdb_assert (!TYPE_NOT_ALLOCATED (new_type)); -+ -+ if (!dwarf_locexpr_baton_eval (TYPE_ALLOCATED (new_type))) -+ TYPE_NOT_ALLOCATED (new_type) = 1; -+ TYPE_ALLOCATED (new_type) = NULL; -+ } -+ -+ if (TYPE_ASSOCIATED (new_type)) -+ { -+ gdb_assert (!TYPE_NOT_ASSOCIATED (new_type)); -+ -+ if (!dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (new_type))) -+ TYPE_NOT_ASSOCIATED (new_type) = 1; -+ TYPE_ASSOCIATED (new_type) = NULL; -+ } -+ -+ if (!TYPE_DATA_LOCATION_IS_ADDR (new_type) -+ && TYPE_DATA_LOCATION_DWARF_BLOCK (new_type)) -+ { -+ if (TYPE_NOT_ALLOCATED (new_type) -+ || TYPE_NOT_ASSOCIATED (new_type)) -+ TYPE_DATA_LOCATION_DWARF_BLOCK (new_type) = NULL; -+ else -+ { -+ TYPE_DATA_LOCATION_IS_ADDR (new_type) = 1; -+ TYPE_DATA_LOCATION_ADDR (new_type) = dwarf_locexpr_baton_eval -+ (TYPE_DATA_LOCATION_DWARF_BLOCK (new_type)); -+ } -+ } -+ - /* Copy the fields. */ - if (TYPE_NFIELDS (type)) - { - int i, nfields; - - nfields = TYPE_NFIELDS (type); -+ TYPE_NFIELDS (new_type) = nfields; - TYPE_FIELDS (new_type) = XCALLOC (nfields, struct field); - for (i = 0; i < nfields; i++) - { -@@ -2990,8 +3212,8 @@ copy_type_recursive (struct objfile *objfile, - TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i); - if (TYPE_FIELD_TYPE (type, i)) - TYPE_FIELD_TYPE (new_type, i) -- = copy_type_recursive (objfile, TYPE_FIELD_TYPE (type, i), -- copied_types); -+ = copy_type_recursive_1 (objfile, TYPE_FIELD_TYPE (type, i), -+ copied_types, representative); - if (TYPE_FIELD_NAME (type, i)) - TYPE_FIELD_NAME (new_type, i) = - xstrdup (TYPE_FIELD_NAME (type, i)); -@@ -3010,6 +3232,16 @@ copy_type_recursive (struct objfile *objfile, - xstrdup (TYPE_FIELD_STATIC_PHYSNAME (type, - i))); - break; -+ case FIELD_LOC_KIND_DWARF_BLOCK: -+ /* `struct dwarf2_locexpr_baton' is too bound to its objfile so -+ it is expected to be made constant by CHECK_TYPEDEF. */ -+ if (TYPE_NOT_ALLOCATED (new_type) -+ || TYPE_NOT_ASSOCIATED (new_type)) -+ SET_FIELD_DWARF_BLOCK (TYPE_FIELD (new_type, i), NULL); -+ else -+ SET_FIELD_BITPOS (TYPE_FIELD (new_type, i), -+ dwarf_locexpr_baton_eval (TYPE_FIELD_DWARF_BLOCK (type, i))); -+ break; - default: - internal_error (__FILE__, __LINE__, - _("Unexpected type field location kind: %d"), -@@ -3018,17 +3250,32 @@ copy_type_recursive (struct objfile *objfile, - } - } - -+ /* Convert TYPE_RANGE_HIGH_BOUND_IS_COUNT into a regular bound. */ -+ if (TYPE_CODE (type) == TYPE_CODE_RANGE -+ && TYPE_RANGE_HIGH_BOUND_IS_COUNT (type)) -+ { -+ TYPE_RANGE_HIGH_BOUND_IS_COUNT (new_type) = 0; -+ TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (type) -+ + TYPE_HIGH_BOUND (type) - 1; -+ } -+ -+ /* Both FIELD_LOC_KIND_DWARF_BLOCK and TYPE_RANGE_HIGH_BOUND_IS_COUNT were -+ possibly converted. */ -+ TYPE_DYNAMIC (new_type) = 0; -+ - /* Copy pointers to other types. */ - if (TYPE_TARGET_TYPE (type)) - TYPE_TARGET_TYPE (new_type) = -- copy_type_recursive (objfile, -- TYPE_TARGET_TYPE (type), -- copied_types); -+ copy_type_recursive_1 (objfile, -+ TYPE_TARGET_TYPE (type), -+ copied_types, -+ representative); - if (TYPE_VPTR_BASETYPE (type)) - TYPE_VPTR_BASETYPE (new_type) = -- copy_type_recursive (objfile, -- TYPE_VPTR_BASETYPE (type), -- copied_types); -+ copy_type_recursive_1 (objfile, -+ TYPE_VPTR_BASETYPE (type), -+ copied_types, -+ representative); - /* Maybe copy the type_specific bits. - - NOTE drow/2005-12-09: We do not copy the C++-specific bits like -@@ -3046,6 +3293,20 @@ copy_type_recursive (struct objfile *objfile, - return new_type; - } - -+/* Recursively copy (deep copy) TYPE. Return a new type allocated using -+ malloc, a saved type if we have already visited TYPE (using COPIED_TYPES), -+ or TYPE if it is not associated with OBJFILE. */ -+ -+struct type * -+copy_type_recursive (struct type *type, -+ htab_t copied_types) -+{ -+ struct type *representative = NULL; -+ -+ return copy_type_recursive_1 (TYPE_OBJFILE (type), type, copied_types, -+ &representative); -+} -+ - /* Make a copy of the given TYPE, except that the pointer & reference - types are not preserved. - -@@ -3059,7 +3320,7 @@ copy_type (const struct type *type) - - gdb_assert (TYPE_OBJFILE (type) != NULL); - -- new_type = alloc_type (TYPE_OBJFILE (type)); -+ new_type = alloc_type (TYPE_OBJFILE (type), NULL); - TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); - TYPE_LENGTH (new_type) = TYPE_LENGTH (type); - memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type), -@@ -3068,6 +3329,242 @@ copy_type (const struct type *type) - return new_type; - } - -+static void delete_type (struct type *type); -+ -+/* A helper for delete_type which deletes a main_type and the things to which -+ it refers. TYPE is a type whose main_type we wish to destroy. */ -+ -+static void -+delete_main_type (struct main_type *main_type) -+{ -+ int i; -+ void **slot; -+ struct -+ { -+ struct main_type *main_type; -+ } type_local = { main_type }, *type = &type_local; -+ -+ gdb_assert (TYPE_OBJFILE (type) == OBJFILE_MALLOC); -+ -+ xfree (TYPE_NAME (type)); -+ xfree (TYPE_TAG_NAME (type)); -+ -+ for (i = 0; i < TYPE_NFIELDS (type); ++i) -+ { -+ xfree (TYPE_FIELD_NAME (type, i)); -+ -+ if (TYPE_FIELD_LOC_KIND (type, i) == FIELD_LOC_KIND_PHYSNAME) -+ xfree (TYPE_FIELD_STATIC_PHYSNAME (type, i)); -+ } -+ xfree (TYPE_FIELDS (type)); -+ -+ /* Strangely, HAVE_CPLUS_STRUCT will return true when there isn't -+ one at all. */ -+ gdb_assert (!HAVE_CPLUS_STRUCT (type) || !TYPE_CPLUS_SPECIFIC (type)); -+ -+ xfree (TYPE_MAIN_TYPE (type)); -+} -+ -+/* Store `struct main_type *' entries which got `struct type *' deleted. */ -+ -+static htab_t deleted_main_types_hash; -+ -+/* To be called before any call of delete_type. */ -+ -+static void -+delete_type_begin (void) -+{ -+ gdb_assert (deleted_main_types_hash == NULL); -+ -+ deleted_main_types_hash = htab_create_alloc (10, htab_hash_pointer, -+ htab_eq_pointer, NULL, xcalloc, xfree); -+} -+ -+/* Helper for delete_type_finish. */ -+ -+static int -+delete_type_finish_traverse (void **slot, void *unused) -+{ -+ struct main_type *main_type = *slot; -+ -+ delete_main_type (main_type); -+ -+ return 1; -+} -+ -+/* To be called after all the calls of delete_type. Each MAIN_TYPE must have -+ either none or all of its TYPE entries deleted. */ -+ -+static void -+delete_type_finish (void) -+{ -+ htab_traverse (deleted_main_types_hash, delete_type_finish_traverse, NULL); -+ -+ htab_delete (deleted_main_types_hash); -+ deleted_main_types_hash = NULL; -+} -+ -+/* Delete TYPE and remember MAIN_TYPE it references. TYPE must have been -+ allocated using xmalloc -- not using an objfile. You must wrap calls of -+ this function by delete_type_begin and delete_type_finish. */ -+ -+static void -+delete_type (struct type *type) -+{ -+ void **slot; -+ -+ if (!type) -+ return; -+ -+ if (TYPE_OBJFILE (type) == OBJFILE_INTERNAL) -+ return; -+ gdb_assert (TYPE_OBJFILE (type) == OBJFILE_MALLOC); -+ -+ slot = htab_find_slot (deleted_main_types_hash, TYPE_MAIN_TYPE (type), -+ INSERT); -+ gdb_assert (!*slot); -+ *slot = TYPE_MAIN_TYPE (type); -+ -+ xfree (type); -+} -+ -+/* Hash function for type_refc_table. */ -+ -+static hashval_t -+type_refc_hash (const void *p) -+{ -+ const struct type_refc_entry *entry = p; -+ return htab_hash_pointer (entry->type); -+} -+ -+/* Equality function for type_refc_table. */ -+ -+static int -+type_refc_equal (const void *a, const void *b) -+{ -+ const struct type_refc_entry *left = a; -+ const struct type_refc_entry *right = b; -+ return left->type == right->type; -+} -+ -+/* Insert the new type NEW_TYPE into the table. Does nothing if -+ NEW_TYPE has an objfile. If PARENT_TYPE is not NULL, then NEW_TYPE -+ will be inserted into the same hierarchy as PARENT_TYPE. In this -+ case, PARENT_TYPE must already exist in the reference count map. -+ If PARENT_TYPE is NULL, a new reference count is allocated and set -+ to one. */ -+ -+static void -+type_init_refc (struct type *new_type, struct type *parent_type) -+{ -+ int *refc; -+ void **slot; -+ struct type_refc_entry *new_entry; -+ -+ if (TYPE_OBJFILE (new_type)) -+ return; -+ -+ if (parent_type) -+ { -+ struct type_refc_entry entry, *found; -+ entry.type = parent_type; -+ found = htab_find (type_refc_table, &entry); -+ gdb_assert (found); -+ refc = found->refc; -+ } -+ else -+ { -+ refc = xmalloc (sizeof (int)); -+ *refc = 0; -+ } -+ -+ new_entry = XNEW (struct type_refc_entry); -+ new_entry->type = new_type; -+ new_entry->refc = refc; -+ -+ slot = htab_find_slot (type_refc_table, new_entry, INSERT); -+ gdb_assert (!*slot); -+ *slot = new_entry; -+} -+ -+/* Increment the reference count for TYPE. */ -+ -+void -+type_incref (struct type *type) -+{ -+ struct type_refc_entry entry, *found; -+ -+ if (TYPE_OBJFILE (type)) -+ return; -+ -+ entry.type = type; -+ found = htab_find (type_refc_table, &entry); -+ gdb_assert (found); -+ ++*(found->refc); -+} -+ -+/* A traverse callback for type_refc_table which removes any entry -+ whose reference count pointer is REFC. REFC may be NULL to delete all the -+ unused entries - use such cleanup only in the GDB idle state as GDB code -+ does not necessarily reference county TYPEs during its processing. */ -+ -+static int -+type_refc_remove (void **slot, void *refc) -+{ -+ struct type_refc_entry *entry = *slot; -+ -+ if (entry->refc == refc || (refc == NULL && *entry->refc == 0)) -+ { -+ delete_type (entry->type); -+ -+ xfree (entry); -+ htab_clear_slot (type_refc_table, slot); -+ } -+ -+ return 1; -+} -+ -+/* Decrement the reference count for TYPE. If TYPE has no more -+ references, delete it. */ -+ -+void -+type_decref (struct type *type) -+{ -+ struct type_refc_entry entry, *found; -+ -+ if (TYPE_OBJFILE (type)) -+ return; -+ -+ entry.type = type; -+ found = htab_find (type_refc_table, &entry); -+ gdb_assert (found); -+ --*(found->refc); -+ if (*(found->refc) == 0) -+ { -+ void *refc = found->refc; -+ -+ /* Clear all table entries referring to this count. CHECK: Should not be -+ the deletion delayed till free_all_types? */ -+ delete_type_begin (); -+ htab_traverse (type_refc_table, type_refc_remove, refc); -+ delete_type_finish (); -+ -+ /* Delete the reference count itself. */ -+ xfree (refc); -+ } -+} -+ -+/* Free all the types that have been allocated (except for those released). -+ Called after each command, successful or not. */ -+ -+void -+free_all_types (void) -+{ -+ delete_type_begin (); -+ htab_traverse (type_refc_table, type_refc_remove, NULL); -+ delete_type_finish (); -+} -+ - static struct type * - build_flt (int bit, char *name, const struct floatformat **floatformats) - { -@@ -3105,7 +3602,7 @@ build_complex (int bit, char *name, struct type *target_type) - return builtin_type_error; - } - t = init_type (TYPE_CODE_COMPLEX, 2 * bit / TARGET_CHAR_BIT, -- 0, name, (struct objfile *) NULL); -+ 0, name, OBJFILE_INTERNAL); - TYPE_TARGET_TYPE (t) = target_type; - return t; - } -@@ -3119,56 +3616,56 @@ gdbtypes_post_init (struct gdbarch *gdbarch) - builtin_type->builtin_void = - init_type (TYPE_CODE_VOID, 1, - 0, -- "void", (struct objfile *) NULL); -+ "void", OBJFILE_INTERNAL); - builtin_type->builtin_char = - init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - (TYPE_FLAG_NOSIGN - | (gdbarch_char_signed (gdbarch) ? 0 : TYPE_FLAG_UNSIGNED)), -- "char", (struct objfile *) NULL); -+ "char", OBJFILE_INTERNAL); - builtin_type->builtin_signed_char = - init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - 0, -- "signed char", (struct objfile *) NULL); -+ "signed char", OBJFILE_INTERNAL); - builtin_type->builtin_unsigned_char = - init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, -- "unsigned char", (struct objfile *) NULL); -+ "unsigned char", OBJFILE_INTERNAL); - builtin_type->builtin_short = - init_type (TYPE_CODE_INT, - gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, -- 0, "short", (struct objfile *) NULL); -+ 0, "short", OBJFILE_INTERNAL); - builtin_type->builtin_unsigned_short = - init_type (TYPE_CODE_INT, - gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, "unsigned short", -- (struct objfile *) NULL); -+ OBJFILE_INTERNAL); - builtin_type->builtin_int = - init_type (TYPE_CODE_INT, - gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, -- 0, "int", (struct objfile *) NULL); -+ 0, "int", OBJFILE_INTERNAL); - builtin_type->builtin_unsigned_int = - init_type (TYPE_CODE_INT, - gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, "unsigned int", -- (struct objfile *) NULL); -+ OBJFILE_INTERNAL); - builtin_type->builtin_long = - init_type (TYPE_CODE_INT, - gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT, -- 0, "long", (struct objfile *) NULL); -+ 0, "long", OBJFILE_INTERNAL); - builtin_type->builtin_unsigned_long = - init_type (TYPE_CODE_INT, - gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, "unsigned long", -- (struct objfile *) NULL); -+ OBJFILE_INTERNAL); - builtin_type->builtin_long_long = - init_type (TYPE_CODE_INT, - gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT, -- 0, "long long", (struct objfile *) NULL); -+ 0, "long long", OBJFILE_INTERNAL); - builtin_type->builtin_unsigned_long_long = - init_type (TYPE_CODE_INT, - gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, "unsigned long long", -- (struct objfile *) NULL); -+ OBJFILE_INTERNAL); - builtin_type->builtin_float - = build_flt (gdbarch_float_bit (gdbarch), "float", - gdbarch_float_format (gdbarch)); -@@ -3187,26 +3684,26 @@ gdbtypes_post_init (struct gdbarch *gdbarch) - builtin_type->builtin_string = - init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - 0, -- "string", (struct objfile *) NULL); -+ "string", OBJFILE_INTERNAL); - builtin_type->builtin_bool = - init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - 0, -- "bool", (struct objfile *) NULL); -+ "bool", OBJFILE_INTERNAL); - - /* The following three are about decimal floating point types, which - are 32-bits, 64-bits and 128-bits respectively. */ - builtin_type->builtin_decfloat - = init_type (TYPE_CODE_DECFLOAT, 32 / 8, - 0, -- "_Decimal32", (struct objfile *) NULL); -+ "_Decimal32", OBJFILE_INTERNAL); - builtin_type->builtin_decdouble - = init_type (TYPE_CODE_DECFLOAT, 64 / 8, - 0, -- "_Decimal64", (struct objfile *) NULL); -+ "_Decimal64", OBJFILE_INTERNAL); - builtin_type->builtin_declong - = init_type (TYPE_CODE_DECFLOAT, 128 / 8, - 0, -- "_Decimal128", (struct objfile *) NULL); -+ "_Decimal128", OBJFILE_INTERNAL); - - /* Pointer/Address types. */ - -@@ -3245,27 +3742,28 @@ gdbtypes_post_init (struct gdbarch *gdbarch) - init_type (TYPE_CODE_INT, - gdbarch_addr_bit (gdbarch) / 8, - TYPE_FLAG_UNSIGNED, -- "__CORE_ADDR", (struct objfile *) NULL); -+ "__CORE_ADDR", OBJFILE_INTERNAL); - - - /* The following set of types is used for symbols with no - debug information. */ - builtin_type->nodebug_text_symbol = - init_type (TYPE_CODE_FUNC, 1, 0, -- "", NULL); -+ "", OBJFILE_INTERNAL); - TYPE_TARGET_TYPE (builtin_type->nodebug_text_symbol) = - builtin_type->builtin_int; - builtin_type->nodebug_data_symbol = - init_type (TYPE_CODE_INT, - gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, -- "", NULL); -+ "", OBJFILE_INTERNAL); - builtin_type->nodebug_unknown_symbol = - init_type (TYPE_CODE_INT, 1, 0, -- "", NULL); -+ "", -+ OBJFILE_INTERNAL); - builtin_type->nodebug_tls_symbol = - init_type (TYPE_CODE_INT, - gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, -- "", NULL); -+ "", OBJFILE_INTERNAL); - - return builtin_type; - } -@@ -3276,6 +3774,9 @@ _initialize_gdbtypes (void) - { - gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init); - -+ type_refc_table = htab_create_alloc (20, type_refc_hash, type_refc_equal, -+ NULL, xcalloc, xfree); -+ - /* FIXME: The following types are architecture-neutral. However, - they contain pointer_type and reference_type fields potentially - caching pointer or reference types that *are* architecture -@@ -3284,47 +3785,47 @@ _initialize_gdbtypes (void) - builtin_type_int0 = - init_type (TYPE_CODE_INT, 0 / 8, - 0, -- "int0_t", (struct objfile *) NULL); -+ "int0_t", OBJFILE_INTERNAL); - builtin_type_int8 = - init_type (TYPE_CODE_INT, 8 / 8, - TYPE_FLAG_NOTTEXT, -- "int8_t", (struct objfile *) NULL); -+ "int8_t", OBJFILE_INTERNAL); - builtin_type_uint8 = - init_type (TYPE_CODE_INT, 8 / 8, - TYPE_FLAG_UNSIGNED | TYPE_FLAG_NOTTEXT, -- "uint8_t", (struct objfile *) NULL); -+ "uint8_t", OBJFILE_INTERNAL); - builtin_type_int16 = - init_type (TYPE_CODE_INT, 16 / 8, - 0, -- "int16_t", (struct objfile *) NULL); -+ "int16_t", OBJFILE_INTERNAL); - builtin_type_uint16 = - init_type (TYPE_CODE_INT, 16 / 8, - TYPE_FLAG_UNSIGNED, -- "uint16_t", (struct objfile *) NULL); -+ "uint16_t", OBJFILE_INTERNAL); - builtin_type_int32 = - init_type (TYPE_CODE_INT, 32 / 8, - 0, -- "int32_t", (struct objfile *) NULL); -+ "int32_t", OBJFILE_INTERNAL); - builtin_type_uint32 = - init_type (TYPE_CODE_INT, 32 / 8, - TYPE_FLAG_UNSIGNED, -- "uint32_t", (struct objfile *) NULL); -+ "uint32_t", OBJFILE_INTERNAL); - builtin_type_int64 = - init_type (TYPE_CODE_INT, 64 / 8, - 0, -- "int64_t", (struct objfile *) NULL); -+ "int64_t", OBJFILE_INTERNAL); - builtin_type_uint64 = - init_type (TYPE_CODE_INT, 64 / 8, - TYPE_FLAG_UNSIGNED, -- "uint64_t", (struct objfile *) NULL); -+ "uint64_t", OBJFILE_INTERNAL); - builtin_type_int128 = - init_type (TYPE_CODE_INT, 128 / 8, - 0, -- "int128_t", (struct objfile *) NULL); -+ "int128_t", OBJFILE_INTERNAL); - builtin_type_uint128 = - init_type (TYPE_CODE_INT, 128 / 8, - TYPE_FLAG_UNSIGNED, -- "uint128_t", (struct objfile *) NULL); -+ "uint128_t", OBJFILE_INTERNAL); - - builtin_type_ieee_single = - build_flt (-1, "builtin_type_ieee_single", floatformats_ieee_single); -@@ -3344,15 +3845,15 @@ _initialize_gdbtypes (void) - builtin_type_void = - init_type (TYPE_CODE_VOID, 1, - 0, -- "void", (struct objfile *) NULL); -+ "void", OBJFILE_INTERNAL); - builtin_type_true_char = - init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - 0, -- "true character", (struct objfile *) NULL); -+ "true character", OBJFILE_INTERNAL); - builtin_type_true_unsigned_char = - init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, -- "true character", (struct objfile *) NULL); -+ "true character", OBJFILE_INTERNAL); - - add_setshow_zinteger_cmd ("overload", no_class, &overload_debug, _("\ - Set debugging of C++ overloading."), _("\ -diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h -index c90b6d7..86df022 100644 ---- a/gdb/gdbtypes.h -+++ b/gdb/gdbtypes.h -@@ -209,6 +209,11 @@ enum type_instance_flag_value - - #define TYPE_TARGET_STUB(t) (TYPE_MAIN_TYPE (t)->flag_target_stub) - -+/* Type needs to be evaluated on each CHECK_TYPEDEF and its results must not be -+ sticky. */ -+ -+#define TYPE_DYNAMIC(t) (TYPE_MAIN_TYPE (t)->flag_dynamic) -+ - /* Static type. If this is set, the corresponding type had - * a static modifier. - * Note: This may be unnecessary, since static data members -@@ -266,6 +271,36 @@ enum type_instance_flag_value - - #define TYPE_NOTTEXT(t) (TYPE_MAIN_TYPE (t)->flag_nottext) - -+/* Is HIGH_BOUND a low-bound relative count (1) or the high bound itself (0)? */ -+ -+#define TYPE_RANGE_HIGH_BOUND_IS_COUNT(range_type) \ -+ (TYPE_MAIN_TYPE (range_type)->flag_range_high_bound_is_count) -+ -+/* Not allocated. TYPE_ALLOCATED(t) must be NULL in such case. If this flag -+ is unset and TYPE_ALLOCATED(t) is NULL then the type is allocated. If this -+ flag is unset and TYPE_ALLOCATED(t) is not NULL then its DWARF block -+ determines the actual allocation state. */ -+ -+#define TYPE_NOT_ALLOCATED(t) (TYPE_MAIN_TYPE (t)->flag_not_allocated) -+ -+/* Not associated. TYPE_ASSOCIATED(t) must be NULL in such case. If this flag -+ is unset and TYPE_ASSOCIATED(t) is NULL then the type is associated. If -+ this flag is unset and TYPE_ASSOCIATED(t) is not NULL then its DWARF block -+ determines the actual association state. */ -+ -+#define TYPE_NOT_ASSOCIATED(t) (TYPE_MAIN_TYPE (t)->flag_not_associated) -+ -+/* Address of the actual data as for DW_AT_data_location. Its dwarf block must -+ not be evaluated unless both TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are -+ false. If TYPE_DATA_LOCATION_IS_ADDR set then TYPE_DATA_LOCATION_ADDR value -+ is the actual data address value. If unset and -+ TYPE_DATA_LOCATION_DWARF_BLOCK is NULL then the value is the normal -+ VALUE_ADDRESS copy. If unset and TYPE_DATA_LOCATION_DWARF_BLOCK is not NULL -+ then its DWARF block determines the actual data address. */ -+ -+#define TYPE_DATA_LOCATION_IS_ADDR(t) \ -+ (TYPE_MAIN_TYPE (t)->flag_data_location_is_addr) -+ - /* Constant type. If this is set, the corresponding type has a - * const modifier. - */ -@@ -352,6 +387,11 @@ struct main_type - unsigned int flag_stub_supported : 1; - unsigned int flag_nottext : 1; - unsigned int flag_fixed_instance : 1; -+ unsigned int flag_dynamic : 1; -+ unsigned int flag_range_high_bound_is_count : 1; -+ unsigned int flag_not_allocated : 1; -+ unsigned int flag_not_associated : 1; -+ unsigned int flag_data_location_is_addr : 1; - - /* Number of fields described for this type. This field appears at - this location because it packs nicely here. */ -@@ -414,6 +454,20 @@ struct main_type - - struct type *target_type; - -+ /* For DW_AT_data_location. */ -+ union -+ { -+ struct dwarf2_locexpr_baton *dwarf_block; -+ CORE_ADDR addr; -+ } -+ data_location; -+ -+ /* For DW_AT_allocated. */ -+ struct dwarf2_locexpr_baton *allocated; -+ -+ /* For DW_AT_associated. */ -+ struct dwarf2_locexpr_baton *associated; -+ - /* For structure and union types, a description of each field. - For set and pascal array types, there is one "field", - whose type is the domain type of the set or array. -@@ -795,9 +849,9 @@ extern void allocate_cplus_struct_type (struct type *); - #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type - #define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type - #define TYPE_CHAIN(thistype) (thistype)->chain --/* Note that if thistype is a TYPEDEF type, you have to call check_typedef. -- But check_typedef does set the TYPE_LENGTH of the TYPEDEF type, -- so you only have to call check_typedef once. Since allocate_value -+/* Note that if thistype is a TYPEDEF, ARRAY or STRING type, you have to call -+ check_typedef. But check_typedef does set the TYPE_LENGTH of the TYPEDEF -+ type, so you only have to call check_typedef once. Since allocate_value - calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */ - #define TYPE_LENGTH(thistype) (thistype)->length - #define TYPE_OBJFILE(thistype) TYPE_MAIN_TYPE(thistype)->objfile -@@ -807,23 +861,44 @@ extern void allocate_cplus_struct_type (struct type *); - #define TYPE_NFIELDS(thistype) TYPE_MAIN_TYPE(thistype)->nfields - #define TYPE_FIELDS(thistype) TYPE_MAIN_TYPE(thistype)->fields - #define TYPE_TEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->template_args -+#define TYPE_DATA_LOCATION_DWARF_BLOCK(thistype) TYPE_MAIN_TYPE (thistype)->data_location.dwarf_block -+#define TYPE_DATA_LOCATION_ADDR(thistype) TYPE_MAIN_TYPE (thistype)->data_location.addr -+#define TYPE_ALLOCATED(thistype) TYPE_MAIN_TYPE (thistype)->allocated -+#define TYPE_ASSOCIATED(thistype) TYPE_MAIN_TYPE (thistype)->associated - - #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0) - #define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0) - #define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1) -- --/* Moto-specific stuff for FORTRAN arrays */ -- --#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \ -- (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),1)) -+#define TYPE_BYTE_STRIDE(range_type) TYPE_FIELD_BITPOS (range_type, 2) -+ -+/* Whether we should use TYPE_FIELD_DWARF_BLOCK (and not TYPE_FIELD_BITPOS). */ -+#define TYPE_RANGE_BOUND_IS_DWARF_BLOCK(range_type, fieldno) \ -+ (TYPE_FIELD_LOC_KIND (range_type, fieldno) == FIELD_LOC_KIND_DWARF_BLOCK) -+#define TYPE_RANGE_BOUND_SET_DWARF_BLOCK(range_type, fieldno) \ -+ (TYPE_FIELD_LOC_KIND (range_type, fieldno) = FIELD_LOC_KIND_DWARF_BLOCK) -+#define TYPE_ARRAY_BOUND_IS_DWARF_BLOCK(array_type, fieldno) \ -+ TYPE_RANGE_BOUND_IS_DWARF_BLOCK (TYPE_INDEX_TYPE (array_type), fieldno) -+ -+/* Unbound arrays, such as GCC array[]; at end of struct. */ -+#define TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED(rangetype) \ -+ TYPE_FIELD_ARTIFICIAL((rangetype),0) -+#define TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED(rangetype) \ -+ TYPE_FIELD_ARTIFICIAL((rangetype),1) - #define TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED(arraytype) \ -- (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),0)) -- --#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \ -- (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE((arraytype)))) -+ TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype)) -+#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \ -+ TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype)) - - #define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \ -- (TYPE_LOW_BOUND(TYPE_INDEX_TYPE((arraytype)))) -+ TYPE_LOW_BOUND (TYPE_INDEX_TYPE (arraytype)) -+#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \ -+ TYPE_HIGH_BOUND (TYPE_INDEX_TYPE (arraytype)) -+/* TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) with a fallback to the -+ element size if no specific stride value is known. */ -+#define TYPE_ARRAY_BYTE_STRIDE_VALUE(arraytype) \ -+ (TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) == 0 \ -+ ? TYPE_LENGTH (TYPE_TARGET_TYPE (arraytype)) \ -+ : TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype))) - - /* C++ */ - -@@ -1078,6 +1153,16 @@ extern struct type *builtin_type_error; - (TYPE_UNSIGNED(t) ? UMIN_OF_SIZE(TYPE_LENGTH(t)) \ - : MIN_OF_SIZE(TYPE_LENGTH(t))) - -+/* Virtual OBJFILE used for builtin types. */ -+#define OBJFILE_INTERNAL ((struct objfile *) 1L) -+ -+/* Virtual OBJFILE used for types allocated by malloc. FIXME: Currently -+ backward compatible with the old NULL value; fix then also init_type. */ -+#define OBJFILE_MALLOC ((struct objfile *) 0L) -+ -+#define OBJFILE_IS_VIRTUAL(objfile) ((objfile) == OBJFILE_INTERNAL \ -+ || (objfile) == OBJFILE_MALLOC) -+ - /* Allocate space for storing data associated with a particular type. - We ensure that the space is allocated using the same mechanism that - was used to allocate the space for the type structure itself. I.E. -@@ -1087,18 +1172,18 @@ extern struct type *builtin_type_error; - builtin types), then the data space will be allocated with xmalloc, - the same as for the type structure. */ - --#define TYPE_ALLOC(t,size) \ -- (TYPE_OBJFILE (t) != NULL \ -- ? obstack_alloc (&TYPE_OBJFILE (t) -> objfile_obstack, size) \ -- : xmalloc (size)) -+#define TYPE_ALLOC(t,size) \ -+ (OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (t)) \ -+ ? xmalloc (size) \ -+ : obstack_alloc (&TYPE_OBJFILE (t) -> objfile_obstack, size)) - --#define TYPE_ZALLOC(t,size) \ -- (TYPE_OBJFILE (t) != NULL \ -- ? memset (obstack_alloc (&TYPE_OBJFILE (t)->objfile_obstack, size), \ -- 0, size) \ -- : xzalloc (size)) -+#define TYPE_ZALLOC(t,size) \ -+ (OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (t)) \ -+ ? xzalloc (size) \ -+ : memset (obstack_alloc (&TYPE_OBJFILE (t)->objfile_obstack, size), \ -+ 0, size)) - --extern struct type *alloc_type (struct objfile *); -+extern struct type *alloc_type (struct objfile *, struct type *); - - extern struct type *init_type (enum type_code, int, int, char *, - struct objfile *); -@@ -1172,6 +1257,16 @@ extern struct type *create_range_type (struct type *, struct type *, int, - extern struct type *create_array_type (struct type *, struct type *, - struct type *); - -+extern CORE_ADDR type_range_any_field_internal (struct type *range_type, -+ int fieldno); -+ -+extern int type_range_high_bound_internal (struct type *range_type); -+ -+extern int type_range_count_bound_internal (struct type *range_type); -+ -+extern CORE_ADDR type_range_byte_stride_internal (struct type *range_type, -+ struct type *element_type); -+ - extern struct type *create_string_type (struct type *, struct type *); - - extern struct type *create_set_type (struct type *, struct type *); -@@ -1263,10 +1358,15 @@ extern void maintenance_print_type (char *, int); - - extern htab_t create_copied_types_hash (struct objfile *objfile); - --extern struct type *copy_type_recursive (struct objfile *objfile, -- struct type *type, -+extern struct type *copy_type_recursive (struct type *type, - htab_t copied_types); - - extern struct type *copy_type (const struct type *type); - -+extern void type_incref (struct type *type); -+ -+extern void type_decref (struct type *type); -+ -+extern void free_all_types (void); -+ - #endif /* GDBTYPES_H */ -diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c -index 0728866..cc82cb4 100644 ---- a/gdb/jv-lang.c -+++ b/gdb/jv-lang.c -@@ -302,7 +302,7 @@ type_from_class (struct value *clas) - if (type != NULL) - return type; - -- type = alloc_type (objfile); -+ type = alloc_type (objfile, NULL); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - INIT_CPLUS_SPECIFIC (type); - -diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c -index 7cbcc59..e507c3b 100644 ---- a/gdb/mdebugread.c -+++ b/gdb/mdebugread.c -@@ -4696,7 +4696,7 @@ new_type (char *name) - { - struct type *t; - -- t = alloc_type (current_objfile); -+ t = alloc_type (current_objfile, NULL); - TYPE_NAME (t) = name; - TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default; - return t; -diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c -index b905a9e..83c6b48 100644 ---- a/gdb/mi/mi-main.c -+++ b/gdb/mi/mi-main.c -@@ -1317,6 +1317,7 @@ mi_cmd_execute (struct mi_parse *parse) - struct cleanup *cleanup; - int i; - free_all_values (); -+ free_all_types (); - - current_token = xstrdup (parse->token); - cleanup = make_cleanup (free_current_contents, ¤t_token); -diff --git a/gdb/printcmd.c b/gdb/printcmd.c -index a51ba68..55a39f5 100644 ---- a/gdb/printcmd.c -+++ b/gdb/printcmd.c -@@ -878,6 +878,11 @@ print_command_1 (char *exp, int inspect, int voidprint) - else - val = access_value_history (0); - -+ /* Do not try to OBJECT_ADDRESS_SET here anything. We are interested in the -+ source variable base addresses as found by READ_VAR_VALUE. The value here -+ can be already a calculated expression address inappropriate for -+ DW_OP_push_object_address. */ -+ - if (voidprint || (val && value_type (val) && - TYPE_CODE (value_type (val)) != TYPE_CODE_VOID)) - { -diff --git a/gdb/stabsread.c b/gdb/stabsread.c -index 3457784..976a5a7 100644 ---- a/gdb/stabsread.c -+++ b/gdb/stabsread.c -@@ -322,7 +322,7 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) - - if (typenums[0] == -1) - { -- return (alloc_type (objfile)); -+ return (alloc_type (objfile, NULL)); - } - - type_addr = dbx_lookup_type (typenums); -@@ -332,7 +332,7 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) - We will fill it in later if we find out how. */ - if (*type_addr == 0) - { -- *type_addr = alloc_type (objfile); -+ *type_addr = alloc_type (objfile, NULL); - } - - return (*type_addr); -diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S -new file mode 100644 -index 0000000..66f7a39 ---- /dev/null -+++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S -@@ -0,0 +1,455 @@ -+ .file "x86_64-vla-typedef.c" -+ .section .debug_abbrev,"",@progbits -+.Ldebug_abbrev0: -+ .section .debug_info,"",@progbits -+.Ldebug_info0: -+ .section .debug_line,"",@progbits -+.Ldebug_line0: -+ .text -+.Ltext0: -+.globl foo -+ .type foo, @function -+foo: -+.LFB2: -+ .file 1 "x86_64-vla-typedef.c" -+ .loc 1 22 0 -+ pushq %rbp -+.LCFI0: -+ movq %rsp, %rbp -+.LCFI1: -+ subq $64, %rsp -+.LCFI2: -+ movl %edi, -36(%rbp) -+ .loc 1 22 0 -+ movq %rsp, %rax -+ movq %rax, -48(%rbp) -+ .loc 1 23 0 -+ movl -36(%rbp), %edx -+ movslq %edx,%rax -+ subq $1, %rax -+ movq %rax, -24(%rbp) -+ .loc 1 24 0 -+ movslq %edx,%rax -+ addq $15, %rax -+ addq $15, %rax -+ shrq $4, %rax -+ salq $4, %rax -+ subq %rax, %rsp -+ movq %rsp, -56(%rbp) -+ movq -56(%rbp), %rax -+ addq $15, %rax -+ shrq $4, %rax -+ salq $4, %rax -+ movq %rax, -56(%rbp) -+ movq -56(%rbp), %rax -+ movq %rax, -16(%rbp) -+ .loc 1 27 0 -+ movl $0, -4(%rbp) -+ jmp .L2 -+.L3: -+ .loc 1 28 0 -+ movl -4(%rbp), %esi -+ movl -4(%rbp), %eax -+ movl %eax, %ecx -+ movq -16(%rbp), %rdx -+ movslq %esi,%rax -+ movb %cl, (%rdx,%rax) -+ .loc 1 27 0 -+ addl $1, -4(%rbp) -+.L2: -+ movl -4(%rbp), %eax -+ cmpl -36(%rbp), %eax -+ jl .L3 -+ .loc 1 30 0 -+ .globl break_here -+break_here: -+ movq -16(%rbp), %rax -+ movb $0, (%rax) -+ movq -48(%rbp), %rsp -+ .loc 1 31 0 -+ leave -+ ret -+.LFE2: -+ .size foo, .-foo -+ .section .debug_frame,"",@progbits -+.Lframe0: -+ .long .LECIE0-.LSCIE0 -+.LSCIE0: -+ .long 0xffffffff -+ .byte 0x1 -+ .string "" -+ .uleb128 0x1 -+ .sleb128 -8 -+ .byte 0x10 -+ .byte 0xc -+ .uleb128 0x7 -+ .uleb128 0x8 -+ .byte 0x90 -+ .uleb128 0x1 -+ .align 8 -+.LECIE0: -+.LSFDE0: -+ .long .LEFDE0-.LASFDE0 -+.LASFDE0: -+ .long .Lframe0 -+ .quad .LFB2 -+ .quad .LFE2-.LFB2 -+ .byte 0x4 -+ .long .LCFI0-.LFB2 -+ .byte 0xe -+ .uleb128 0x10 -+ .byte 0x86 -+ .uleb128 0x2 -+ .byte 0x4 -+ .long .LCFI1-.LCFI0 -+ .byte 0xd -+ .uleb128 0x6 -+ .align 8 -+.LEFDE0: -+ .section .eh_frame,"a",@progbits -+.Lframe1: -+ .long .LECIE1-.LSCIE1 -+.LSCIE1: -+ .long 0x0 -+ .byte 0x1 -+ .string "zR" -+ .uleb128 0x1 -+ .sleb128 -8 -+ .byte 0x10 -+ .uleb128 0x1 -+ .byte 0x3 -+ .byte 0xc -+ .uleb128 0x7 -+ .uleb128 0x8 -+ .byte 0x90 -+ .uleb128 0x1 -+ .align 8 -+.LECIE1: -+.LSFDE1: -+ .long .LEFDE1-.LASFDE1 -+.LASFDE1: -+ .long .LASFDE1-.Lframe1 -+ .long .LFB2 -+ .long .LFE2-.LFB2 -+ .uleb128 0x0 -+ .byte 0x4 -+ .long .LCFI0-.LFB2 -+ .byte 0xe -+ .uleb128 0x10 -+ .byte 0x86 -+ .uleb128 0x2 -+ .byte 0x4 -+ .long .LCFI1-.LCFI0 -+ .byte 0xd -+ .uleb128 0x6 -+ .align 8 -+.LEFDE1: -+ .text -+.Letext0: -+ .section .debug_loc,"",@progbits -+.Ldebug_loc0: -+.LLST0: -+ .quad .LFB2-.Ltext0 -+ .quad .LCFI0-.Ltext0 -+ .value 0x2 -+ .byte 0x77 -+ .sleb128 8 -+ .quad .LCFI0-.Ltext0 -+ .quad .LCFI1-.Ltext0 -+ .value 0x2 -+ .byte 0x77 -+ .sleb128 16 -+ .quad .LCFI1-.Ltext0 -+ .quad .LFE2-.Ltext0 -+ .value 0x2 -+ .byte 0x76 -+ .sleb128 16 -+ .quad 0x0 -+ .quad 0x0 -+ .section .debug_info -+ .long .Ldebug_end - .Ldebug_start -+.Ldebug_start: -+ .value 0x2 -+ .long .Ldebug_abbrev0 -+ .byte 0x8 -+ .uleb128 0x1 -+ .long .LASF2 -+ .byte 0x1 -+ .long .LASF3 -+ .long .LASF4 -+ .quad .Ltext0 -+ .quad .Letext0 -+ .long .Ldebug_line0 -+ .uleb128 0x2 -+ .byte 0x1 -+ .string "foo" -+ .byte 0x1 -+ .byte 0x16 -+ .byte 0x1 -+ .quad .LFB2 -+ .quad .LFE2 -+ .long .LLST0 -+ .long 0x83 -+ .uleb128 0x3 -+ .long .LASF5 -+ .byte 0x1 -+ .byte 0x15 -+ .long 0x83 -+ .byte 0x2 -+ .byte 0x91 -+ .sleb128 -52 -+.Ltag_typedef: -+ .uleb128 0x4 -+ .long .LASF6 -+ .byte 0x1 -+ .byte 0x17 -+ .long .Ltag_array_type - .debug_info -+ .uleb128 0x5 /* Abbrev Number: 5 (DW_TAG_variable) */ -+ .long .LASF0 -+ .byte 0x1 -+ .byte 0x18 -+#if 1 -+ .long .Ltag_typedef - .debug_info -+#else -+ /* Debugging only: Skip the typedef indirection. */ -+ .long .Ltag_array_type - .debug_info -+#endif -+ /* DW_AT_location: DW_FORM_block1: start */ -+ .byte 0x3 -+ .byte 0x91 -+ .sleb128 -32 -+#if 0 -+ .byte 0x6 /* DW_OP_deref */ -+#else -+ .byte 0x96 /* DW_OP_nop */ -+#endif -+ /* DW_AT_location: DW_FORM_block1: end */ -+ .uleb128 0x6 -+ .string "i" -+ .byte 0x1 -+ .byte 0x19 -+ .long 0x83 -+ .byte 0x2 -+ .byte 0x91 -+ .sleb128 -20 -+ .byte 0x0 -+ .uleb128 0x7 -+ .byte 0x4 -+ .byte 0x5 -+ .string "int" -+.Ltag_array_type: -+ .uleb128 0x8 /* Abbrev Number: 8 (DW_TAG_array_type) */ -+ .long 0xa0 + (2f - 1f) /* DW_AT_type: DW_FORM_ref4 */ -+ .long 0x9d + (2f - 1f) /* DW_AT_sibling: DW_FORM_ref4 */ -+1: /* DW_AT_data_location: DW_FORM_block1: start */ -+ .byte 2f - 3f /* length */ -+3: -+ .byte 0x97 /* DW_OP_push_object_address */ -+ .byte 0x6 /* DW_OP_deref */ -+2: /* DW_AT_data_location: DW_FORM_block1: end */ -+ .uleb128 0x9 -+ .long 0x9d + (2b - 1b) /* DW_AT_type: DW_FORM_ref4 */ -+ .byte 0x3 -+ .byte 0x91 -+ .sleb128 -40 -+ .byte 0x6 -+ .byte 0x0 -+ .uleb128 0xa -+ .byte 0x8 -+ .byte 0x7 -+ .uleb128 0xb -+ .byte 0x1 -+ .byte 0x6 -+ .long .LASF1 -+ .byte 0x0 -+.Ldebug_end: -+ .section .debug_abbrev -+ .uleb128 0x1 -+ .uleb128 0x11 -+ .byte 0x1 -+ .uleb128 0x25 -+ .uleb128 0xe -+ .uleb128 0x13 -+ .uleb128 0xb -+ .uleb128 0x3 -+ .uleb128 0xe -+ .uleb128 0x1b -+ .uleb128 0xe -+ .uleb128 0x11 -+ .uleb128 0x1 -+ .uleb128 0x12 -+ .uleb128 0x1 -+ .uleb128 0x10 -+ .uleb128 0x6 -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x2 -+ .uleb128 0x2e -+ .byte 0x1 -+ .uleb128 0x3f -+ .uleb128 0xc -+ .uleb128 0x3 -+ .uleb128 0x8 -+ .uleb128 0x3a -+ .uleb128 0xb -+ .uleb128 0x3b -+ .uleb128 0xb -+ .uleb128 0x27 -+ .uleb128 0xc -+ .uleb128 0x11 -+ .uleb128 0x1 -+ .uleb128 0x12 -+ .uleb128 0x1 -+ .uleb128 0x40 -+ .uleb128 0x6 -+ .uleb128 0x1 -+ .uleb128 0x13 -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x3 -+ .uleb128 0x5 -+ .byte 0x0 -+ .uleb128 0x3 -+ .uleb128 0xe -+ .uleb128 0x3a -+ .uleb128 0xb -+ .uleb128 0x3b -+ .uleb128 0xb -+ .uleb128 0x49 -+ .uleb128 0x13 -+ .uleb128 0x2 -+ .uleb128 0xa -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x4 -+ .uleb128 0x16 -+ .byte 0x0 -+ .uleb128 0x3 -+ .uleb128 0xe -+ .uleb128 0x3a -+ .uleb128 0xb -+ .uleb128 0x3b -+ .uleb128 0xb -+ .uleb128 0x49 -+ .uleb128 0x13 -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x5 -+ .uleb128 0x34 -+ .byte 0x0 -+ .uleb128 0x3 -+ .uleb128 0xe -+ .uleb128 0x3a -+ .uleb128 0xb -+ .uleb128 0x3b -+ .uleb128 0xb -+ .uleb128 0x49 -+ .uleb128 0x13 -+ .uleb128 0x2 -+ .uleb128 0xa -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x6 -+ .uleb128 0x34 -+ .byte 0x0 -+ .uleb128 0x3 -+ .uleb128 0x8 -+ .uleb128 0x3a -+ .uleb128 0xb -+ .uleb128 0x3b -+ .uleb128 0xb -+ .uleb128 0x49 -+ .uleb128 0x13 -+ .uleb128 0x2 -+ .uleb128 0xa -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x7 -+ .uleb128 0x24 -+ .byte 0x0 -+ .uleb128 0xb -+ .uleb128 0xb -+ .uleb128 0x3e -+ .uleb128 0xb -+ .uleb128 0x3 -+ .uleb128 0x8 -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x8 /* Abbrev Number: 8 (DW_TAG_array_type) */ -+ .uleb128 0x1 -+ .byte 0x1 -+ .uleb128 0x49 /* DW_AT_type */ -+ .uleb128 0x13 /* DW_FORM_ref4 */ -+ .uleb128 0x1 /* DW_AT_sibling */ -+ .uleb128 0x13 /* DW_FORM_ref4 */ -+ .uleb128 0x50 /* DW_AT_data_location */ -+ .uleb128 0xa /* DW_FORM_block1 */ -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0x9 -+ .uleb128 0x21 -+ .byte 0x0 -+ .uleb128 0x49 /* DW_AT_type */ -+ .uleb128 0x13 /* DW_FORM_ref4 */ -+ .uleb128 0x2f -+ .uleb128 0xa -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0xa -+ .uleb128 0x24 -+ .byte 0x0 -+ .uleb128 0xb -+ .uleb128 0xb -+ .uleb128 0x3e -+ .uleb128 0xb -+ .byte 0x0 -+ .byte 0x0 -+ .uleb128 0xb -+ .uleb128 0x24 -+ .byte 0x0 -+ .uleb128 0xb -+ .uleb128 0xb -+ .uleb128 0x3e -+ .uleb128 0xb -+ .uleb128 0x3 -+ .uleb128 0xe -+ .byte 0x0 -+ .byte 0x0 -+ .byte 0x0 -+ .section .debug_pubnames,"",@progbits -+ .long 0x16 -+ .value 0x2 -+ .long .Ldebug_info0 -+ .long 0xa8 -+ .long 0x2d -+ .string "foo" -+ .long 0x0 -+ .section .debug_aranges,"",@progbits -+ .long 0x2c -+ .value 0x2 -+ .long .Ldebug_info0 -+ .byte 0x8 -+ .byte 0x0 -+ .value 0x0 -+ .value 0x0 -+ .quad .Ltext0 -+ .quad .Letext0-.Ltext0 -+ .quad 0x0 -+ .quad 0x0 -+ .section .debug_str,"MS",@progbits,1 -+.LASF0: -+ .string "array" -+.LASF5: -+ .string "size" -+.LASF3: -+ .string "x86_64-vla-typedef.c" -+.LASF6: -+ .string "array_t" -+.LASF1: -+ .string "char" -+.LASF4: -+ .string "gdb.arch" -+.LASF2: -+ .string "GNU C 4.3.2 20081105 (Red Hat 4.3.2-7)" -+ .ident "GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)" -+ .section .note.GNU-stack,"",@progbits -diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c -new file mode 100644 -index 0000000..b809c4e ---- /dev/null -+++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c -@@ -0,0 +1,43 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2008 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 3 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, see . */ -+ -+#if 0 -+ -+void -+foo (int size) -+{ -+ typedef char array_t[size]; -+ array_t array; -+ int i; -+ -+ for (i = 0; i < size; i++) -+ array[i] = i; -+ -+ array[0] = 0; /* break-here */ -+} -+ -+#else -+ -+int -+main (void) -+{ -+ foo (26); -+ foo (78); -+ return 0; -+} -+ -+#endif -diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp -new file mode 100644 -index 0000000..b05411e ---- /dev/null -+++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp -@@ -0,0 +1,64 @@ -+# Copyright 2009 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 3 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, see . -+ -+# Test DW_AT_data_location accessed through DW_TAG_typedef intermediate. -+ -+if ![istarget "x86_64-*-*"] then { -+ verbose "Skipping over gdb.arch/x86_64-vla-typedef.exp test made only for x86_64." -+ return -+} -+ -+set testfile x86_64-vla-typedef -+set srcasmfile ${testfile}-foo.S -+set srcfile ${testfile}.c -+set binfile ${objdir}/${subdir}/${testfile} -+set binobjfile ${objdir}/${subdir}/${testfile}-foo.o -+if { [gdb_compile "${srcdir}/${subdir}/${srcasmfile}" "${binobjfile}" object {}] != "" } { -+ untested "Couldn't compile test program" -+ return -1 -+} -+if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${binobjfile}" "${binfile}" executable {debug}] != "" } { -+ untested "Couldn't compile test program" -+ return -1 -+} -+ -+gdb_exit -+gdb_start -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+if ![runto_main] { -+ untested x86_64-vla-typedef -+ return -1 -+} -+ -+gdb_breakpoint "break_here" -+ -+gdb_continue_to_breakpoint "break_here" -+ -+gdb_test "whatis array" "type = array_t" "first: whatis array" -+ -+gdb_test "ptype array" "type = char \\\[26\\\]" "first: ptype array" -+ -+gdb_test "p array\[1\]" "\\$\[0-9\] = 1 '\\\\001'" -+gdb_test "p array\[2\]" "\\$\[0-9\] = 2 '\\\\002'" -+gdb_test "p array\[3\]" "\\$\[0-9\] = 3 '\\\\003'" -+gdb_test "p array\[4\]" "\\$\[0-9\] = 4 '\\\\004'" -+ -+gdb_continue_to_breakpoint "break_here" -+ -+gdb_test "whatis array" "type = array_t" "second: whatis array" -+ -+gdb_test "ptype array" "type = char \\\[78\\\]" "second: ptype array" -diff --git a/gdb/testsuite/gdb.base/vla-overflow.c b/gdb/testsuite/gdb.base/vla-overflow.c -new file mode 100644 -index 0000000..c5d5ee0 ---- /dev/null -+++ b/gdb/testsuite/gdb.base/vla-overflow.c -@@ -0,0 +1,30 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2008 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 3 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, see . */ -+ -+#include -+ -+int -+main (int argc, char **argv) -+{ -+ int array[argc]; -+ -+ array[0] = array[0]; -+ -+ abort (); -+ -+ return 0; -+} -diff --git a/gdb/testsuite/gdb.base/vla-overflow.exp b/gdb/testsuite/gdb.base/vla-overflow.exp -new file mode 100644 -index 0000000..7203a48 ---- /dev/null -+++ b/gdb/testsuite/gdb.base/vla-overflow.exp -@@ -0,0 +1,108 @@ -+# Copyright 2008 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 3 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, see . -+ -+# We could crash in: -+# #0 block_linkage_function (bl=0x0) at ../../gdb/block.c:69 -+# #1 in dwarf_block_get_frame_base (...) at ../../gdb/dwarf2block.c:97 -+# 97 framefunc = block_linkage_function (get_frame_block (frame, NULL)); -+# #2 in execute_stack_op (...) at ../../gdb/dwarf2expr.c:496 -+# #3 in dwarf_block_exec_core () at ../../gdb/dwarf2block.c:156 -+# #4 dwarf_block_exec (...) at ../../gdb/dwarf2block.c:206 -+# #5 in range_type_count_bound_internal (...) at ../../gdb/gdbtypes.c:1430 -+# #6 in create_array_type (...) at ../../gdb/gdbtypes.c:840 -+# ... -+# #21 in psymtab_to_symtab (...) at ../../gdb/symfile.c:292 -+# ... -+# #29 in backtrace_command_1 () at ../../gdb/stack.c:1273 -+ -+set testfile vla-overflow -+set shfile ${objdir}/${subdir}/${testfile}-gdb.sh -+set srcfile ${testfile}.c -+set binfile ${objdir}/${subdir}/${testfile} -+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { -+ untested "Couldn't compile test program" -+ return -1 -+} -+ -+set f [open "|getconf PAGESIZE" "r"] -+gets $f pagesize -+close $f -+ -+gdb_exit -+gdb_start -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+set pid_of_gdb [exp_pid -i [board_info host fileid]] -+ -+if { [runto_main] < 0 } { -+ untested vla-overflow -+ return -1 -+} -+ -+# Get the GDB memory size when we stay at main. -+ -+proc memory_v_pages_get {} { -+ global pid_of_gdb pagesize -+ set fd [open "/proc/$pid_of_gdb/statm"] -+ gets $fd line -+ close $fd -+ # number of pages of virtual memory -+ scan $line "%d" drs -+ return $drs -+} -+ -+set pages_found [memory_v_pages_get] -+ -+set mb_reserve 10 -+verbose -log "pages_found = $pages_found, mb_reserve = $mb_reserve" -+set kb_found [expr $pages_found * $pagesize / 1024] -+set kb_permit [expr $kb_found + 1 * 1024 + $mb_reserve * 1024] -+verbose -log "kb_found = $kb_found, kb_permit = $kb_permit" -+ -+# Create the ulimit wrapper. -+set f [open $shfile "w"] -+puts $f "#! /bin/sh" -+puts $f "ulimit -v $kb_permit" -+puts $f "exec $GDB \"\$@\"" -+close $f -+remote_exec host "chmod +x $shfile" -+ -+gdb_exit -+set GDBold $GDB -+set GDB "$shfile" -+gdb_start -+set GDB $GDBold -+ -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+set pid_of_gdb [exp_pid -i [board_info host fileid]] -+ -+# Check the size again after the second run. -+# We must not stop in main as it would cache `array' and never crash later. -+ -+gdb_run_cmd -+ -+verbose -log "kb_found before abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" -+ -+gdb_test "" "Program received signal SIGABRT, Aborted..*" "Enter abort()" -+ -+verbose -log "kb_found in abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" -+ -+# `abort' can get expressed as `*__GI_abort'. -+gdb_test "bt" "in \[^ \]*abort \\(.* in main \\(.*" "Backtrace after abort()" -+ -+verbose -log "kb_found in bt after abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" -diff --git a/gdb/testsuite/gdb.base/vla.c b/gdb/testsuite/gdb.base/vla.c -new file mode 100644 -index 0000000..e1f3ed1 ---- /dev/null -+++ b/gdb/testsuite/gdb.base/vla.c -@@ -0,0 +1,55 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2008 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 3 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, see . */ -+ -+#include -+ -+void -+marker (void) -+{ -+} -+ -+void -+bar (char *a, char *b, char *c, int size) -+{ -+ memset (a, '1', size); -+ memset (b, '2', size); -+ memset (c, '3', 48); -+} -+ -+void -+foo (int size) -+{ -+ char temp1[size]; -+ char temp3[48]; -+ -+ temp1[size - 1] = '\0'; -+ { -+ char temp2[size]; -+ -+ bar (temp1, temp2, temp3, size); -+ -+ marker (); /* break-here */ -+ } -+} -+ -+int -+main (void) -+{ -+ foo (26); -+ foo (78); -+ return 0; -+} -diff --git a/gdb/testsuite/gdb.base/vla.exp b/gdb/testsuite/gdb.base/vla.exp -new file mode 100644 -index 0000000..5da7378 ---- /dev/null -+++ b/gdb/testsuite/gdb.base/vla.exp -@@ -0,0 +1,62 @@ -+# Copyright 2008 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 3 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, see . -+ -+set testfile vla -+set srcfile ${testfile}.c -+set binfile ${objdir}/${subdir}/${testfile} -+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { -+ untested "Couldn't compile test program" -+ return -1 -+} -+ -+gdb_exit -+gdb_start -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+if ![runto_main] { -+ untested vla -+ return -1 -+} -+ -+gdb_breakpoint [gdb_get_line_number "break-here"] -+ -+gdb_continue_to_breakpoint "break-here" -+ -+gdb_test "whatis temp1" "type = char \\\[variable\\\]" "first: whatis temp1" -+gdb_test "whatis temp2" "type = char \\\[variable\\\]" "first: whatis temp2" -+gdb_test "whatis temp3" "type = char \\\[48\\\]" "first: whatis temp3" -+ -+gdb_test "ptype temp1" "type = char \\\[26\\\]" "first: ptype temp1" -+gdb_test "ptype temp2" "type = char \\\[26\\\]" "first: ptype temp2" -+gdb_test "ptype temp3" "type = char \\\[48\\\]" "first: ptype temp3" -+ -+gdb_test "p temp1" " = '1' " "first: print temp1" -+gdb_test "p temp2" " = '2' " "first: print temp2" -+gdb_test "p temp3" " = '3' " "first: print temp3" -+ -+gdb_continue_to_breakpoint "break-here" -+ -+gdb_test "whatis temp1" "type = char \\\[variable\\\]" "second: whatis temp1" -+gdb_test "whatis temp2" "type = char \\\[variable\\\]" "second: whatis temp2" -+gdb_test "whatis temp3" "type = char \\\[48\\\]" "second: whatis temp3" -+ -+gdb_test "ptype temp1" "type = char \\\[78\\\]" "second: ptype temp1" -+gdb_test "ptype temp2" "type = char \\\[78\\\]" "second: ptype temp2" -+gdb_test "ptype temp3" "type = char \\\[48\\\]" "second: ptype temp3" -+ -+gdb_test "p temp1" " = '1' " "second: print temp1" -+gdb_test "p temp2" " = '2' " "second: print temp2" -+gdb_test "p temp3" " = '3' " "second: print temp3" -diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.c b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c -new file mode 100644 -index 0000000..1f02d90 ---- /dev/null -+++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c -@@ -0,0 +1,42 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 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. */ -+ -+ -+/* The function `func1' traced into must have debug info on offset > 0; -+ (DW_UNSND (attr)). This is the reason of `func0' existence. */ -+ -+void -+func0(int a, int b) -+{ -+} -+ -+/* `func1' being traced into must have some arguments to dump. */ -+ -+void -+func1(int a, int b) -+{ -+ func0 (a,b); -+} -+ -+int -+main(void) -+{ -+ func1 (1, 2); -+ return 0; -+} -diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp -new file mode 100644 -index 0000000..1c6e84a ---- /dev/null -+++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp -@@ -0,0 +1,79 @@ -+# Copyright 2006 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. -+ -+# Minimal DWARF-2 unit test -+ -+# This test can only be run on targets which support DWARF-2. -+# For now pick a sampling of likely targets. -+if {![istarget *-*-linux*] -+ && ![istarget *-*-gnu*] -+ && ![istarget *-*-elf*] -+ && ![istarget *-*-openbsd*] -+ && ![istarget arm-*-eabi*] -+ && ![istarget powerpc-*-eabi*]} { -+ return 0 -+} -+ -+set testfile "dw2-stripped" -+set srcfile ${testfile}.c -+set binfile ${objdir}/${subdir}/${testfile}.x -+ -+remote_exec build "rm -f ${binfile}" -+ -+# get the value of gcc_compiled -+if [get_compiler_info ${binfile}] { -+ return -1 -+} -+ -+# This test can only be run on gcc as we use additional_flags=FIXME -+if {$gcc_compiled == 0} { -+ return 0 -+} -+ -+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-ggdb3}] != "" } { -+ return -1 -+} -+ -+remote_exec build "objcopy -R .debug_loc ${binfile}" -+set strip_output [remote_exec build "objdump -h ${binfile}"] -+ -+set test "stripping test file preservation" -+if [ regexp ".debug_info " $strip_output] { -+ pass "$test (.debug_info preserved)" -+} else { -+ fail "$test (.debug_info got also stripped)" -+} -+ -+set test "stripping test file functionality" -+if [ regexp ".debug_loc " $strip_output] { -+ fail "$test (.debug_loc still present)" -+} else { -+ pass "$test (.debug_loc stripped)" -+} -+ -+gdb_exit -+gdb_start -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+# For C programs, "start" should stop in main(). -+ -+gdb_test "start" \ -+ ".*main \\(\\) at .*" \ -+ "start" -+gdb_test "step" \ -+ "func.* \\(.*\\) at .*" \ -+ "step" -diff --git a/gdb/testsuite/gdb.fortran/dynamic.exp b/gdb/testsuite/gdb.fortran/dynamic.exp -new file mode 100644 -index 0000000..77a1203 ---- /dev/null -+++ b/gdb/testsuite/gdb.fortran/dynamic.exp -@@ -0,0 +1,156 @@ -+# Copyright 2007 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. -+ -+# This file was written by Jan Kratochvil . -+ -+# This file is part of the gdb testsuite. It contains tests for dynamically -+# allocated Fortran arrays. -+# It depends on the GCC dynamic Fortran arrays DWARF support: -+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22244 -+ -+set testfile "dynamic" -+set srcfile ${testfile}.f90 -+set binfile ${objdir}/${subdir}/${testfile} -+ -+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { -+ untested "Couldn't compile ${srcfile}" -+ return -1 -+} -+ -+gdb_exit -+gdb_start -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+if ![runto MAIN__] then { -+ perror "couldn't run to breakpoint MAIN__" -+ continue -+} -+ -+gdb_breakpoint [gdb_get_line_number "varx-init"] -+gdb_continue_to_breakpoint "varx-init" -+gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx unallocated" -+gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx unallocated" -+gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) unallocated" -+gdb_test "p varx(1,5,17)=1" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17)=1 unallocated" -+gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) unallocated" -+ -+gdb_breakpoint [gdb_get_line_number "varx-allocated"] -+gdb_continue_to_breakpoint "varx-allocated" -+# $1 = (( ( 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0) --- , 0) ) ( ( 0, 0, ...) ...) ...) -+gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx allocated" -+# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1. -+gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varx allocated" -+ -+gdb_breakpoint [gdb_get_line_number "varx-filled"] -+gdb_continue_to_breakpoint "varx-filled" -+gdb_test "p varx(2, 5, 17)" "\\$\[0-9\]* = 6" -+gdb_test "p varx(1, 5, 17)" "\\$\[0-9\]* = 7" -+gdb_test "p varx(2, 6, 18)" "\\$\[0-9\]* = 8" -+gdb_test "p varx(6, 15, 28)" "\\$\[0-9\]* = 9" -+# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type. -+gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv unassociated" -+gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv unassociated" -+ -+gdb_breakpoint [gdb_get_line_number "varv-associated"] -+gdb_continue_to_breakpoint "varv-associated" -+gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 6" "p varx(3, 7, 19) with varv associated" -+gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 6" "p varv(3, 7, 19) associated" -+# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1. -+gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varv associated" -+gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx with varv associated" -+# Intel Fortran Compiler 10.1.008 uses the pointer type. -+gdb_test "ptype varv" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)\\)?" "ptype varv associated" -+ -+gdb_breakpoint [gdb_get_line_number "varv-filled"] -+gdb_continue_to_breakpoint "varv-filled" -+gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 10" "p varx(3, 7, 19) with varv filled" -+gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 10" "p varv(3, 7, 19) filled" -+ -+gdb_breakpoint [gdb_get_line_number "varv-deassociated"] -+gdb_continue_to_breakpoint "varv-deassociated" -+# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type. -+gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv deassociated" -+gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv deassociated" -+gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varv deassociated" -+gdb_test "p varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\." -+gdb_test "ptype varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\." -+ -+gdb_breakpoint [gdb_get_line_number "varx-deallocated"] -+gdb_continue_to_breakpoint "varx-deallocated" -+gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx deallocated" -+gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx deallocated" -+gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varx deallocated" -+gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) deallocated" -+gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) deallocated" -+ -+gdb_breakpoint [gdb_get_line_number "vary-passed"] -+gdb_continue_to_breakpoint "vary-passed" -+# $1 = (( ( 1, 1, 1, 1, 1, 1) ( 1, 1, 1, 1, 1, 1) --- , 1) ) ( ( 1, 1, ...) ...) ...) -+gdb_test "p vary" "\\$\[0-9\]* = \\(\[()1, .\]*\\)" -+ -+gdb_breakpoint [gdb_get_line_number "vary-filled"] -+gdb_continue_to_breakpoint "vary-filled" -+gdb_test "ptype vary" "type = real(\\(kind=4\\)|\\*4) \\(10,10\\)" -+gdb_test "p vary(1, 1)" "\\$\[0-9\]* = 8" -+gdb_test "p vary(2, 2)" "\\$\[0-9\]* = 9" -+gdb_test "p vary(1, 3)" "\\$\[0-9\]* = 10" -+# $1 = (( ( 3, 3, 3, 3, 3, 3) ( 3, 3, 3, 3, 3, 3) --- , 3) ) ( ( 3, 3, ...) ...) ...) -+gdb_test "p varw" "\\$\[0-9\]* = \\(\[()3, .\]*\\)" -+ -+gdb_breakpoint [gdb_get_line_number "varw-almostfilled"] -+gdb_continue_to_breakpoint "varw-almostfilled" -+gdb_test "ptype varw" "type = real(\\(kind=4\\)|\\*4) \\(5,4,3\\)" -+gdb_test "p varw(3,1,1)=1" "\\$\[0-9\]* = 1" -+# $1 = (( ( 6, 5, 1, 5, 5, 5) ( 5, 5, 5, 5, 5, 5) --- , 5) ) ( ( 5, 5, ...) ...) ...) -+gdb_test "p varw" "\\$\[0-9\]* = \\( *\\( *\\( *6, *5, *1,\[()5, .\]*\\)" "p varw filled" -+# "up" works with GCC but other Fortran compilers may copy the values into the -+# outer function only on the exit of the inner function. -+gdb_test "finish" ".*call bar \\(y, x\\)" -+gdb_test "p z(2,4,5)" "\\$\[0-9\]* = 3" -+gdb_test "p z(2,4,6)" "\\$\[0-9\]* = 6" -+gdb_test "p z(2,4,7)" "\\$\[0-9\]* = 5" -+gdb_test "p z(4,4,6)" "\\$\[0-9\]* = 1" -+ -+gdb_breakpoint [gdb_get_line_number "varz-almostfilled"] -+gdb_continue_to_breakpoint "varz-almostfilled" -+# GCC uses the pointer type here, Intel Fortran Compiler 10.1.008 does not. -+gdb_test "ptype varz" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(\\*\\)\\)?" -+# Intel Fortran Compiler 10.1.008 has a bug here - (2:11,7:7) -+# as it produces DW_AT_lower_bound == DW_AT_upper_bound == 7. -+gdb_test "ptype vart" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(2:11,7:\\*\\)\\)?" -+gdb_test "p varz" "\\$\[0-9\]* = \\(\\)" -+gdb_test "p vart" "\\$\[0-9\]* = \\(\\)" -+gdb_test "p varz(3)" "\\$\[0-9\]* = 4" -+# maps to foo::vary(1,1) -+gdb_test "p vart(2,7)" "\\$\[0-9\]* = 8" -+# maps to foo::vary(2,2) -+gdb_test "p vart(3,8)" "\\$\[0-9\]* = 9" -+# maps to foo::vary(1,3) -+gdb_test "p vart(2,9)" "\\$\[0-9\]* = 10" -+ -+set test "quit #1" -+gdb_test_multiple "quit" $test { -+ -re "The program is running. Quit anyway \\(and kill it\\)\\? \\(y or n\\) " { -+ pass $test -+ } -+} -+set test "quit #2" -+gdb_test_multiple "y" $test { -+ eof { -+ pass $test -+ } -+} -diff --git a/gdb/testsuite/gdb.fortran/dynamic.f90 b/gdb/testsuite/gdb.fortran/dynamic.f90 -new file mode 100644 -index 0000000..0f43564 ---- /dev/null -+++ b/gdb/testsuite/gdb.fortran/dynamic.f90 -@@ -0,0 +1,98 @@ -+! Copyright 2007 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. -+! -+! Ihis file is the Fortran source file for dynamic.exp. -+! Original file written by Jakub Jelinek . -+! Modified for the GDB testcase by Jan Kratochvil . -+ -+subroutine baz -+ real, target, allocatable :: varx (:, :, :) -+ real, pointer :: varv (:, :, :) -+ real, target :: varu (1, 2, 3) -+ logical :: l -+ allocate (varx (1:6, 5:15, 17:28)) ! varx-init -+ l = allocated (varx) -+ varx(:, :, :) = 6 ! varx-allocated -+ varx(1, 5, 17) = 7 -+ varx(2, 6, 18) = 8 -+ varx(6, 15, 28) = 9 -+ varv => varx ! varx-filled -+ l = associated (varv) -+ varv(3, 7, 19) = 10 ! varv-associated -+ varv => null () ! varv-filled -+ l = associated (varv) -+ deallocate (varx) ! varv-deassociated -+ l = allocated (varx) -+ varu(:, :, :) = 10 ! varx-deallocated -+ allocate (varv (1:6, 5:15, 17:28)) -+ l = associated (varv) -+ varv(:, :, :) = 6 -+ varv(1, 5, 17) = 7 -+ varv(2, 6, 18) = 8 -+ varv(6, 15, 28) = 9 -+ deallocate (varv) -+ l = associated (varv) -+ varv => varu -+ varv(1, 1, 1) = 6 -+ varv(1, 2, 3) = 7 -+ l = associated (varv) -+end subroutine baz -+subroutine foo (vary, varw) -+ real :: vary (:, :) -+ real :: varw (:, :, :) -+ vary(:, :) = 4 ! vary-passed -+ vary(1, 1) = 8 -+ vary(2, 2) = 9 -+ vary(1, 3) = 10 -+ varw(:, :, :) = 5 ! vary-filled -+ varw(1, 1, 1) = 6 -+ varw(2, 2, 2) = 7 ! varw-almostfilled -+end subroutine foo -+subroutine bar (varz, vart) -+ real :: varz (*) -+ real :: vart (2:11, 7:*) -+ varz(1:3) = 4 -+ varz(2) = 5 ! varz-almostfilled -+ vart(2,7) = vart(2,7) -+end subroutine bar -+program test -+ interface -+ subroutine foo (vary, varw) -+ real :: vary (:, :) -+ real :: varw (:, :, :) -+ end subroutine -+ end interface -+ interface -+ subroutine bar (varz, vart) -+ real :: varz (*) -+ real :: vart (2:11, 7:*) -+ end subroutine -+ end interface -+ real :: x (10, 10), y (5), z(8, 8, 8) -+ x(:,:) = 1 -+ y(:) = 2 -+ z(:,:,:) = 3 -+ call baz -+ call foo (x, z(2:6, 4:7, 6:8)) -+ call bar (y, x) -+ if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort -+ if (x (1, 3) .ne. 10) call abort -+ if (z (2, 4, 6) .ne. 6 .or. z (3, 5, 7) .ne. 7 .or. z (2, 4, 7) .ne. 5) call abort -+ if (any (y .ne. (/4, 5, 4, 2, 2/))) call abort -+ call foo (transpose (x), z) -+ if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort -+ if (x (3, 1) .ne. 10) call abort -+end -diff --git a/gdb/testsuite/gdb.fortran/string.exp b/gdb/testsuite/gdb.fortran/string.exp -new file mode 100644 -index 0000000..ab72206 ---- /dev/null -+++ b/gdb/testsuite/gdb.fortran/string.exp -@@ -0,0 +1,72 @@ -+# Copyright 2008 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. -+ -+# This file was written by Jan Kratochvil . -+ -+# This file is part of the gdb testsuite. It contains tests for Fortran -+# strings with dynamic length. -+ -+set testfile "string" -+set srcfile ${testfile}.f90 -+set binfile ${objdir}/${subdir}/${testfile} -+ -+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { -+ untested "Couldn't compile ${srcfile}" -+ return -1 -+} -+ -+gdb_exit -+gdb_start -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+if ![runto MAIN__] then { -+ perror "couldn't run to breakpoint MAIN__" -+ continue -+} -+ -+gdb_breakpoint [gdb_get_line_number "var-init"] -+gdb_continue_to_breakpoint "var-init" -+gdb_test "ptype c" "type = character(\\(kind=1\\)|\\*1)" -+gdb_test "ptype d" "type = character(\\(kind=8\\)|\\*8)" -+gdb_test "ptype e" "type = character(\\(kind=4\\)|\\*4)" -+gdb_test "ptype f" "type = character(\\(kind=4\\)|\\*4) \\(7,8:10\\)" -+gdb_test "ptype *e" "Attempt to take contents of a non-pointer value." -+gdb_test "ptype *f" "type = character(\\(kind=4\\)|\\*4) \\(7\\)" -+gdb_test "p c" "\\$\[0-9\]* = 'c'" -+gdb_test "p d" "\\$\[0-9\]* = 'd '" -+gdb_test "p e" "\\$\[0-9\]* = 'g '" -+gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\)" -+gdb_test "p *e" "Attempt to take contents of a non-pointer value." -+gdb_test "p *f" "Attempt to take contents of a non-pointer value." -+ -+gdb_breakpoint [gdb_get_line_number "var-finish"] -+gdb_continue_to_breakpoint "var-finish" -+gdb_test "p e" "\\$\[0-9\]* = 'e '" "p e re-set" -+gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'f ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\( 'f2 ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\( 'f ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\)" "p *f re-set" -+ -+set test "quit #1" -+gdb_test_multiple "quit" $test { -+ -re "The program is running. Quit anyway \\(and kill it\\)\\? \\(y or n\\) " { -+ pass $test -+ } -+} -+set test "quit #2" -+gdb_test_multiple "y" $test { -+ eof { -+ pass $test -+ } -+} -diff --git a/gdb/testsuite/gdb.fortran/string.f90 b/gdb/testsuite/gdb.fortran/string.f90 -new file mode 100644 -index 0000000..226dc5d ---- /dev/null -+++ b/gdb/testsuite/gdb.fortran/string.f90 -@@ -0,0 +1,37 @@ -+! Copyright 2008 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. -+! -+! Ihis file is the Fortran source file for dynamic.exp. -+! Original file written by Jakub Jelinek . -+! Modified for the GDB testcase by Jan Kratochvil . -+ -+subroutine foo (e, f) -+ character (len=1) :: c -+ character (len=8) :: d -+ character (len=*) :: e -+ character (len=*) :: f (1:7, 8:10) -+ c = 'c' -+ d = 'd' -+ e = 'e' ! var-init -+ f = 'f' -+ f(1,9) = 'f2' -+ c = 'c' ! var-finish -+end subroutine foo -+ character (len=4) :: g, h (1:7, 8:10) -+ g = 'g' -+ h = 'h' -+ call foo (g, h) -+end -diff --git a/gdb/top.c b/gdb/top.c -index d5ef706..6045e21 100644 ---- a/gdb/top.c -+++ b/gdb/top.c -@@ -377,6 +377,7 @@ execute_command (char *p, int from_tty) - } - - free_all_values (); -+ free_all_types (); - - /* Force cleanup of any alloca areas if using C alloca instead of - a builtin alloca. */ -diff --git a/gdb/typeprint.c b/gdb/typeprint.c -index 1f824fa..60a4c5b 100644 ---- a/gdb/typeprint.c -+++ b/gdb/typeprint.c -@@ -35,6 +35,7 @@ - #include "gdb_string.h" - #include "exceptions.h" - #include "valprint.h" -+#include "dwarf2loc.h" - #include - - extern void _initialize_typeprint (void); -@@ -76,6 +77,9 @@ void - type_print (struct type *type, char *varstring, struct ui_file *stream, - int show) - { -+ if (show >= 0) -+ type = check_typedef (type); -+ - LA_PRINT_TYPE (type, varstring, stream, show, 0); - } - -@@ -115,7 +119,8 @@ whatis_exp (char *exp, int show) - { - struct expression *expr; - struct value *val; -- struct cleanup *old_chain = NULL; -+ /* Required at least for the object_address_set call. */ -+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); - struct type *real_type = NULL; - struct type *type; - int full = 0; -@@ -126,12 +131,13 @@ whatis_exp (char *exp, int show) - if (exp) - { - expr = parse_expression (exp); -- old_chain = make_cleanup (free_current_contents, &expr); -+ make_cleanup (free_current_contents, &expr); - val = evaluate_type (expr); - } - else - val = access_value_history (0); - -+ object_address_set (VALUE_ADDRESS (val)); - type = value_type (val); - - get_user_print_options (&opts); -@@ -168,8 +174,7 @@ whatis_exp (char *exp, int show) - type_print (type, "", gdb_stdout, show); - printf_filtered ("\n"); - -- if (exp) -- do_cleanups (old_chain); -+ do_cleanups (old_chain); - } - - static void -diff --git a/gdb/valarith.c b/gdb/valarith.c -index f38cdb8..8e103cf 100644 ---- a/gdb/valarith.c -+++ b/gdb/valarith.c -@@ -164,9 +164,9 @@ an integer nor a pointer of the same type.")); - struct value * - value_subscript (struct value *array, struct value *idx) - { -- struct value *bound; - int c_style = current_language->c_style_arrays; - struct type *tarray; -+ LONGEST index = value_as_long (idx); - - array = coerce_ref (array); - tarray = check_typedef (value_type (array)); -@@ -179,13 +179,26 @@ value_subscript (struct value *array, struct value *idx) - get_discrete_bounds (range_type, &lowerbound, &upperbound); - - if (VALUE_LVAL (array) != lval_memory) -- return value_subscripted_rvalue (array, idx, lowerbound); -+ { -+ if (index >= lowerbound && index <= upperbound) -+ { -+ CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray)); -+ CORE_ADDR offset = (index - lowerbound) * element_size; -+ -+ return value_subscripted_rvalue (array, offset); -+ } -+ error (_("array or string index out of range")); -+ } - - if (c_style == 0) - { -- LONGEST index = value_as_long (idx); - if (index >= lowerbound && index <= upperbound) -- return value_subscripted_rvalue (array, idx, lowerbound); -+ { -+ CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray)); -+ CORE_ADDR offset = (index - lowerbound) * element_size; -+ -+ return value_subscripted_rvalue (array, offset); -+ } - /* Emit warning unless we have an array of unknown size. - An array of unknown size has lowerbound 0 and upperbound -1. */ - if (upperbound > -1) -@@ -194,49 +207,52 @@ value_subscript (struct value *array, struct value *idx) - c_style = 1; - } - -- if (lowerbound != 0) -- { -- bound = value_from_longest (value_type (idx), (LONGEST) lowerbound); -- idx = value_binop (idx, bound, BINOP_SUB); -- } -- -+ index -= lowerbound; - array = value_coerce_array (array); - } - - if (c_style) -- return value_ind (value_ptradd (array, idx)); -+ { -+ struct value *idx; -+ -+ idx = value_from_longest (builtin_type_int32, index); -+ return value_ind (value_ptradd (array, idx)); -+ } - else - error (_("not an array or string")); - } - --/* Return the value of EXPR[IDX], expr an aggregate rvalue -- (eg, a vector register). This routine used to promote floats -- to doubles, but no longer does. */ -+/* Return the value of *((void *) ARRAY + ELEMENT), ARRAY an aggregate rvalue -+ (eg, a vector register). This routine used to promote floats to doubles, -+ but no longer does. OFFSET is zero-based with 0 for the lowermost existing -+ element, it must be expressed in bytes (therefore multiplied by -+ check_typedef (TYPE_TARGET_TYPE (array_type)). */ - - struct value * --value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound) -+value_subscripted_rvalue (struct value *array, CORE_ADDR offset) - { - struct type *array_type = check_typedef (value_type (array)); - struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type)); -- unsigned int elt_size = TYPE_LENGTH (elt_type); -- LONGEST index = value_as_long (idx); -- unsigned int elt_offs = elt_size * longest_to_int (index - lowerbound); - struct value *v; - -- if (index < lowerbound || elt_offs >= TYPE_LENGTH (array_type)) -- error (_("no such vector element")); -+ /* Do not check TYPE_LENGTH (array_type) as we may have been given the -+ innermost dimension of a multi-dimensional Fortran array where its length -+ is shorter than the possibly accessed element offset. */ - - v = allocate_value (elt_type); - if (VALUE_LVAL (array) == lval_memory && value_lazy (array)) - set_value_lazy (v, 1); - else -- memcpy (value_contents_writeable (v), -- value_contents (array) + elt_offs, elt_size); -+ { -+ unsigned int elt_size = TYPE_LENGTH (elt_type); -+ memcpy (value_contents_writeable (v), -+ value_contents (array) + offset, elt_size); -+ } - - set_value_component_location (v, array); - VALUE_REGNUM (v) = VALUE_REGNUM (array); - VALUE_FRAME_ID (v) = VALUE_FRAME_ID (array); -- set_value_offset (v, value_offset (array) + elt_offs); -+ set_value_offset (v, value_offset (array) + offset); - return v; - } - -diff --git a/gdb/valops.c b/gdb/valops.c -index 9810f2b..c3a48b4 100644 ---- a/gdb/valops.c -+++ b/gdb/valops.c -@@ -38,6 +38,7 @@ - #include "cp-support.h" - #include "dfp.h" - #include "user-regs.h" -+#include "dwarf2loc.h" - - #include - #include "gdb_string.h" -@@ -371,8 +372,6 @@ value_cast (struct type *type, struct value *arg2) - new_length = val_length / element_length; - if (val_length % element_length != 0) - warning (_("array element type size does not divide object size in cast")); -- /* FIXME-type-allocation: need a way to free this type when -- we are done with it. */ - range_type = create_range_type ((struct type *) NULL, - TYPE_TARGET_TYPE (range_type), - low_bound, -@@ -568,6 +567,64 @@ value_one (struct type *type, enum lval_type lv) - return val; - } - -+/* object_address_set must be already called before this function. */ -+ -+const char * -+object_address_data_not_valid (struct type *type) -+{ -+ /* Attributes are present only at the target type of a typedef. Make the -+ call conditional as it would otherwise loop through type_length_get. */ -+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) -+ CHECK_TYPEDEF (type); -+ -+ /* DW_AT_associated has a preference over DW_AT_allocated. */ -+ if (TYPE_NOT_ASSOCIATED (type) -+ || (TYPE_ASSOCIATED (type) != NULL -+ && 0 == dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (type)))) -+ return N_("object is not associated"); -+ -+ if (TYPE_NOT_ALLOCATED (type) -+ || (TYPE_ALLOCATED (type) != NULL -+ && 0 == dwarf_locexpr_baton_eval (TYPE_ALLOCATED (type)))) -+ return N_("object is not allocated"); -+ -+ return NULL; -+} -+ -+/* Return non-zero if the variable is valid. If it is valid the function -+ may store the data address (DW_AT_DATA_LOCATION) of TYPE at *ADDRESS_RETURN. -+ You must set *ADDRESS_RETURN as VALUE_ADDRESS (VAL) before calling this -+ function. If no DW_AT_DATA_LOCATION is present for TYPE the address at -+ *ADDRESS_RETURN is left unchanged. ADDRESS_RETURN must not be NULL, use -+ object_address_data_not_valid () for just the data validity check. */ -+ -+int -+object_address_get_data (struct type *type, CORE_ADDR *address_return) -+{ -+ gdb_assert (address_return != NULL); -+ -+ object_address_set (*address_return); -+ -+ /* TYPE_DATA_LOCATION_DWARF_BLOCK / TYPE_DATA_LOCATION_ADDR are present only -+ at the target type of a typedef. */ -+ CHECK_TYPEDEF (type); -+ -+ if (object_address_data_not_valid (type) != NULL) -+ { -+ /* Do not try to evaluate DW_AT_data_location as it may even crash -+ (it would just return the value zero in the gfortran case). */ -+ return 0; -+ } -+ -+ if (TYPE_DATA_LOCATION_IS_ADDR (type)) -+ *address_return = TYPE_DATA_LOCATION_ADDR (type); -+ else if (TYPE_DATA_LOCATION_DWARF_BLOCK (type) != NULL) -+ *address_return -+ = dwarf_locexpr_baton_eval (TYPE_DATA_LOCATION_DWARF_BLOCK (type)); -+ -+ return 1; -+} -+ - /* Return a value with type TYPE located at ADDR. - - Call value_at only if the data needs to be fetched immediately; -@@ -637,11 +694,19 @@ value_fetch_lazy (struct value *val) - allocate_value_contents (val); - if (VALUE_LVAL (val) == lval_memory) - { -- CORE_ADDR addr = VALUE_ADDRESS (val) + value_offset (val); -- int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val))); -+ CORE_ADDR addr = VALUE_ADDRESS (val); - -- if (length) -- read_memory (addr, value_contents_all_raw (val), length); -+ if (object_address_get_data (value_type (val), &addr)) -+ { -+ struct type *type = value_enclosing_type (val); -+ int length = TYPE_LENGTH (check_typedef (type)); -+ -+ if (length) -+ { -+ addr += value_offset (val); -+ read_memory (addr, value_contents_all_raw (val), length); -+ } -+ } - } - else if (VALUE_LVAL (val) == lval_register) - { -@@ -1036,7 +1101,8 @@ address_of_variable (struct symbol *var, struct block *b) - - val = value_of_variable (var, b); - -- if ((VALUE_LVAL (val) == lval_memory && value_lazy (val)) -+ if ((VALUE_LVAL (val) == lval_memory && value_lazy (val) -+ && object_address_get_data (type, &VALUE_ADDRESS (val))) - || TYPE_CODE (type) == TYPE_CODE_FUNC) - { - CORE_ADDR addr = VALUE_ADDRESS (val); -@@ -1145,6 +1211,7 @@ struct value * - value_coerce_array (struct value *arg1) - { - struct type *type = check_typedef (value_type (arg1)); -+ CORE_ADDR address; - - /* If the user tries to do something requiring a pointer with an - array that has not yet been pushed to the target, then this would -@@ -1154,8 +1221,12 @@ value_coerce_array (struct value *arg1) - if (VALUE_LVAL (arg1) != lval_memory) - error (_("Attempt to take address of value not located in memory.")); - -+ address = VALUE_ADDRESS (arg1); -+ if (!object_address_get_data (type, &address)) -+ error (_("Attempt to take address of non-valid value.")); -+ - return value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), -- (VALUE_ADDRESS (arg1) + value_offset (arg1))); -+ address + value_offset (arg1)); - } - - /* Given a value which is a function, return a value which is a pointer -@@ -2989,8 +3060,6 @@ value_slice (struct value *array, int lowbound, int length) - || lowbound + length - 1 > upperbound) - error (_("slice out of range")); - -- /* FIXME-type-allocation: need a way to free this type when we are -- done with it. */ - slice_range_type = create_range_type ((struct type *) NULL, - TYPE_TARGET_TYPE (range_type), - lowbound, -diff --git a/gdb/value.c b/gdb/value.c -index 4d4329e..47739c9 100644 ---- a/gdb/value.c -+++ b/gdb/value.c -@@ -225,7 +225,9 @@ allocate_value_lazy (struct type *type) - val->next = all_values; - all_values = val; - val->type = type; -+ type_incref (type); - val->enclosing_type = type; -+ type_incref (type); - VALUE_LVAL (val) = not_lval; - VALUE_ADDRESS (val) = 0; - VALUE_FRAME_ID (val) = null_frame_id; -@@ -269,13 +271,9 @@ struct value * - allocate_repeat_value (struct type *type, int count) - { - int low_bound = current_language->string_lower_bound; /* ??? */ -- /* FIXME-type-allocation: need a way to free this type when we are -- done with it. */ - struct type *range_type - = create_range_type ((struct type *) NULL, builtin_type_int32, - low_bound, count + low_bound - 1); -- /* FIXME-type-allocation: need a way to free this type when we are -- done with it. */ - return allocate_value (create_array_type ((struct type *) NULL, - type, range_type)); - } -@@ -335,6 +333,8 @@ value_type (struct value *value) - void - deprecated_set_value_type (struct value *value, struct type *type) - { -+ type_incref (type); -+ type_decref (value->type); - value->type = type; - } - -@@ -552,6 +552,9 @@ value_free (struct value *val) - { - if (val) - { -+ type_decref (val->type); -+ type_decref (val->enclosing_type); -+ - if (VALUE_LVAL (val) == lval_computed) - { - struct lval_funcs *funcs = val->location.computed.funcs; -@@ -655,6 +658,8 @@ value_copy (struct value *arg) - val = allocate_value_lazy (encl_type); - else - val = allocate_value (encl_type); -+ type_incref (arg->type); -+ type_decref (val->type); - val->type = arg->type; - VALUE_LVAL (val) = VALUE_LVAL (arg); - val->location = arg->location; -@@ -693,6 +698,7 @@ set_value_component_location (struct value *component, struct value *whole) - VALUE_LVAL (component) = VALUE_LVAL (whole); - - component->location = whole->location; -+ - if (VALUE_LVAL (whole) == lval_computed) - { - struct lval_funcs *funcs = whole->location.computed.funcs; -@@ -700,6 +706,8 @@ set_value_component_location (struct value *component, struct value *whole) - if (funcs->copy_closure) - component->location.computed.closure = funcs->copy_closure (whole); - } -+ -+ object_address_get_data (value_type (whole), &VALUE_ADDRESS (component)); - } - - -@@ -830,6 +838,25 @@ show_values (char *num_exp, int from_tty) - num_exp[1] = '\0'; - } - } -+ -+/* Sanity check for memory leaks and proper types reference counting. */ -+ -+static void -+value_history_cleanup (void *unused) -+{ -+ while (value_history_chain) -+ { -+ struct value_history_chunk *chunk = value_history_chain; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE (chunk->values); i++) -+ value_free (chunk->values[i]); -+ -+ value_history_chain = chunk->next; -+ xfree (chunk); -+ } -+ value_history_count = 0; -+} - - /* Internal variables. These are variables within the debugger - that hold values assigned by debugger commands. -@@ -1067,12 +1094,21 @@ preserve_one_value (struct value *value, struct objfile *objfile, - htab_t copied_types) - { - if (TYPE_OBJFILE (value->type) == objfile) -- value->type = copy_type_recursive (objfile, value->type, copied_types); -+ { -+ /* No need to decref the old type here, since we know it has no -+ reference count. */ -+ value->type = copy_type_recursive (value->type, copied_types); -+ type_incref (value->type); -+ } - - if (TYPE_OBJFILE (value->enclosing_type) == objfile) -- value->enclosing_type = copy_type_recursive (objfile, -- value->enclosing_type, -- copied_types); -+ { -+ /* No need to decref the old type here, since we know it has no -+ reference count. */ -+ value->enclosing_type = copy_type_recursive (value->enclosing_type, -+ copied_types); -+ type_incref (value->enclosing_type); -+ } - } - - /* Update the internal variables and value history when OBJFILE is -@@ -1461,6 +1497,8 @@ value_static_field (struct type *type, int fieldno) - struct value * - value_change_enclosing_type (struct value *val, struct type *new_encl_type) - { -+ type_incref (new_encl_type); -+ type_decref (val->enclosing_type); - if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) - val->contents = - (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type)); -@@ -1516,6 +1554,8 @@ value_primitive_field (struct value *arg1, int offset, - memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1), - TYPE_LENGTH (value_enclosing_type (arg1))); - } -+ type_incref (type); -+ type_decref (v->type); - v->type = type; - v->offset = value_offset (arg1); - v->embedded_offset = (offset + value_embedded_offset (arg1) -@@ -1944,4 +1984,6 @@ init-if-undefined VARIABLE = EXPRESSION\n\ - Set an internal VARIABLE to the result of the EXPRESSION if it does not\n\ - exist or does not contain a value. The EXPRESSION is not evaluated if the\n\ - VARIABLE is already initialized.")); -+ -+ make_final_cleanup (value_history_cleanup, NULL); - } -diff --git a/gdb/value.h b/gdb/value.h -index aa43365..ad5306a 100644 ---- a/gdb/value.h -+++ b/gdb/value.h -@@ -348,6 +348,10 @@ extern struct value *value_from_decfloat (struct type *type, - const gdb_byte *decbytes); - extern struct value *value_from_string (char *string); - -+extern const char *object_address_data_not_valid (struct type *type); -+extern int object_address_get_data (struct type *type, -+ CORE_ADDR *address_return); -+ - extern struct value *value_at (struct type *type, CORE_ADDR addr); - extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr); - -@@ -658,5 +662,7 @@ extern struct value *value_allocate_space_in_inferior (int); - - extern struct value *value_of_local (const char *name, int complain); - --extern struct value * value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound); -+extern struct value *value_subscripted_rvalue (struct value *array, -+ CORE_ADDR offset); -+ - #endif /* !defined (VALUE_H) */ diff --git a/gdb-6.8-bz436037-reg-no-longer-active.patch b/gdb-6.8-bz436037-reg-no-longer-active.patch new file mode 100644 index 0000000..1337300 --- /dev/null +++ b/gdb-6.8-bz436037-reg-no-longer-active.patch @@ -0,0 +1,24 @@ +diff -d -urpN src.0/gdb/valops.c src.1/gdb/valops.c +--- src.0/gdb/valops.c 2008-07-27 04:00:03.000000000 +0200 ++++ src.1/gdb/valops.c 2008-07-31 15:17:42.000000000 +0200 +@@ -813,10 +813,18 @@ value_assign (struct value *toval, struc + struct frame_info *frame; + int value_reg; + +- /* Figure out which frame this is in currently. */ +- frame = frame_find_by_id (VALUE_FRAME_ID (toval)); + value_reg = VALUE_REGNUM (toval); + ++ /* Figure out which frame this is in currently. */ ++ frame = frame_find_by_id (VALUE_FRAME_ID (toval)); ++ /* "set $reg+=1" should work on programs with no debug info, ++ but frame_find_by_id returns NULL here (RH bug 436037). ++ Use current frame, it represents CPU state in this case. ++ If frame_find_by_id is changed to do it internally ++ (it is contemplated there), remove this. */ ++ if (!frame) ++ frame = get_current_frame (); ++ /* Probably never happens. */ + if (!frame) + error (_("Value being assigned to is no longer active.")); + diff --git a/gdb-6.8-bz442765-threaded-exec-test.patch b/gdb-6.8-bz442765-threaded-exec-test.patch new file mode 100644 index 0000000..c149b03 --- /dev/null +++ b/gdb-6.8-bz442765-threaded-exec-test.patch @@ -0,0 +1,173 @@ +Test various forms of threads tracking across exec(2). + +diff -up -u -X /root/jkratoch/.diffi.list -rup gdb-6.8/gdb/testsuite/gdb.threads/threaded-exec.c gdb-6.8-patched/gdb/testsuite/gdb.threads/threaded-exec.c +--- gdb-6.8/gdb/testsuite/gdb.threads/threaded-exec.c 2008-04-16 17:05:19.000000000 -0400 ++++ gdb-6.8-patched/gdb/testsuite/gdb.threads/threaded-exec.c 2008-04-16 14:43:50.000000000 -0400 +@@ -18,21 +18,95 @@ + Boston, MA 02111-1307, USA. */ + + #include +-#include + #include + #include + #include ++#include + ++#ifdef THREADS ++ ++# include + + static void * + threader (void *arg) + { +- return NULL; ++ return NULL; + } + ++#endif ++ + int +-main (void) ++main (int argc, char **argv) + { ++ char *exec_nothreads, *exec_threads, *cmd; ++ int phase; ++ char phase_s[8]; ++ ++ setbuf (stdout, NULL); ++ ++ if (argc != 4) ++ { ++ fprintf (stderr, "%s \n", argv[0]); ++ return 1; ++ } ++ ++#ifdef THREADS ++ puts ("THREADS: Y"); ++#else ++ puts ("THREADS: N"); ++#endif ++ exec_nothreads = argv[1]; ++ printf ("exec_nothreads: %s\n", exec_nothreads); ++ exec_threads = argv[2]; ++ printf ("exec_threads: %s\n", exec_threads); ++ phase = atoi (argv[3]); ++ printf ("phase: %d\n", phase); ++ ++ /* Phases: threading ++ 0: N -> N ++ 1: N -> Y ++ 2: Y -> Y ++ 3: Y -> N ++ 4: N -> exit */ ++ ++ cmd = NULL; ++ ++#ifndef THREADS ++ switch (phase) ++ { ++ case 0: ++ cmd = exec_nothreads; ++ break; ++ case 1: ++ cmd = exec_threads; ++ break; ++ case 2: ++ fprintf (stderr, "%s: We should have threads for phase %d!\n", argv[0], ++ phase); ++ return 1; ++ case 3: ++ fprintf (stderr, "%s: We should have threads for phase %d!\n", argv[0], ++ phase); ++ return 1; ++ case 4: ++ return 0; ++ default: ++ assert (0); ++ } ++#else /* THREADS */ ++ switch (phase) ++ { ++ case 0: ++ fprintf (stderr, "%s: We should not have threads for phase %d!\n", ++ argv[0], phase); ++ return 1; ++ case 1: ++ fprintf (stderr, "%s: We should not have threads for phase %d!\n", ++ argv[0], phase); ++ return 1; ++ case 2: ++ cmd = exec_threads; ++ { + pthread_t t1; + int i; + +@@ -40,7 +114,34 @@ main (void) + assert (i == 0); + i = pthread_join (t1, NULL); + assert (i == 0); ++ } ++ break; ++ case 3: ++ cmd = exec_nothreads; ++ { ++ pthread_t t1; ++ int i; ++ ++ i = pthread_create (&t1, NULL, threader, (void *) NULL); ++ assert (i == 0); ++ i = pthread_join (t1, NULL); ++ assert (i == 0); ++ } ++ break; ++ case 4: ++ fprintf (stderr, "%s: We should not have threads for phase %d!\n", ++ argv[0], phase); ++ return 1; ++ default: ++ assert (0); ++ } ++#endif /* THREADS */ ++ ++ assert (cmd != NULL); ++ ++ phase++; ++ snprintf (phase_s, sizeof phase_s, "%d", phase); + +- execl ("/bin/true", "/bin/true", NULL); +- abort (); ++ execl (cmd, cmd, exec_nothreads, exec_threads, phase_s, NULL); ++ assert (0); + } +diff -up -u -X /root/jkratoch/.diffi.list -rup gdb-6.8/gdb/testsuite/gdb.threads/threaded-exec.exp gdb-6.8-patched/gdb/testsuite/gdb.threads/threaded-exec.exp +--- gdb-6.8/gdb/testsuite/gdb.threads/threaded-exec.exp 2008-04-16 17:05:19.000000000 -0400 ++++ gdb-6.8-patched/gdb/testsuite/gdb.threads/threaded-exec.exp 2008-04-16 14:42:49.000000000 -0400 +@@ -20,9 +20,14 @@ + + set testfile threaded-exec + set srcfile ${testfile}.c +-set binfile ${objdir}/${subdir}/${testfile} ++set binfile_nothreads ${objdir}/${subdir}/${testfile}N ++set binfile_threads ${objdir}/${subdir}/${testfile}Y + +-if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable []] != "" } { ++if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile_nothreads}" executable {additional_flags=-UTHREADS}] != "" } { ++ return -1 ++} ++ ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile_threads}" executable {additional_flags=-DTHREADS}] != "" } { + return -1 + } + +@@ -30,9 +35,9 @@ gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + +-gdb_load ${binfile} ++gdb_load ${binfile_nothreads} + +-gdb_run_cmd ++gdb_run_cmd ${binfile_nothreads} ${binfile_threads} 0 + + gdb_test_multiple {} "Program exited" { + -re "\r\nProgram exited normally.\r\n$gdb_prompt $" { diff --git a/gdb-6.8-bz457187-largefile.patch b/gdb-6.8-bz457187-largefile.patch new file mode 100644 index 0000000..673817f --- /dev/null +++ b/gdb-6.8-bz457187-largefile.patch @@ -0,0 +1,423 @@ +gdb/ +2009-03-02 Jan Kratochvil + + * configure.ac: Call AC_SYS_LARGEFILE. + * config.in: Regenerate. + * configure: Regenerate. + +diff -up -rup gdb-orig/configure.ac gdb/configure.ac +--- ./gdb-orig/configure.ac 2009-03-02 23:39:01.000000000 +0100 ++++ ./gdb/configure.ac 2009-03-02 23:40:46.000000000 +0100 +@@ -30,6 +30,7 @@ AC_GNU_SOURCE + AC_AIX + AC_ISC_POSIX + gl_EARLY ++AC_SYS_LARGEFILE + AM_PROG_CC_STDC + + AC_CONFIG_AUX_DIR(..) +diff -up -rup gdb-orig/config.in gdb/config.in +--- ./gdb-orig/config.in 2009-03-02 23:39:01.000000000 +0100 ++++ ./gdb/config.in 2009-03-02 23:40:53.000000000 +0100 +@@ -725,6 +725,9 @@ + # undef _ALL_SOURCE + #endif + ++/* Number of bits in a file offset, on hosts where this is settable. */ ++#undef _FILE_OFFSET_BITS ++ + /* Enable GNU extensions on systems that have them. */ + #ifndef _GNU_SOURCE + # undef _GNU_SOURCE +@@ -734,6 +737,9 @@ + problem on IRIX 5. */ + #undef _KMEMUSER + ++/* Define for large files, on AIX-style hosts. */ ++#undef _LARGE_FILES ++ + /* Define to 1 if on MINIX. */ + #undef _MINIX + +diff -up -rup gdb-orig/configure gdb/configure +--- ./gdb-orig/configure 2009-03-02 23:39:01.000000000 +0100 ++++ ./gdb/configure 2009-03-02 23:40:49.000000000 +0100 +@@ -862,6 +862,7 @@ Optional Features: + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer ++ --disable-largefile omit support for large files + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-targets alternative target configurations +@@ -3313,6 +3314,370 @@ _ACEOF + + + ++# Check whether --enable-largefile or --disable-largefile was given. ++if test "${enable_largefile+set}" = set; then ++ enableval="$enable_largefile" ++ ++fi; ++if test "$enable_largefile" != no; then ++ ++ echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 ++echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6 ++if test "${ac_cv_sys_largefile_CC+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ ac_cv_sys_largefile_CC=no ++ if test "$GCC" != yes; then ++ ac_save_CC=$CC ++ while :; do ++ # IRIX 6.2 and later do not support large files by default, ++ # so use the C compiler's -n32 option if that helps. ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++ /* Check that off_t can represent 2**63 - 1 correctly. ++ We can't simply define LARGE_OFF_T to be 9223372036854775807, ++ since some C++ compilers masquerading as C compilers ++ incorrectly reject 9223372036854775807. */ ++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) ++ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 ++ && LARGE_OFF_T % 2147483647 == 1) ++ ? 1 : -1]; ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++ rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ break ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext ++ CC="$CC -n32" ++ rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ac_cv_sys_largefile_CC=' -n32'; break ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext ++ break ++ done ++ CC=$ac_save_CC ++ rm -f conftest.$ac_ext ++ fi ++fi ++echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 ++echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6 ++ if test "$ac_cv_sys_largefile_CC" != no; then ++ CC=$CC$ac_cv_sys_largefile_CC ++ fi ++ ++ echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 ++echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6 ++if test "${ac_cv_sys_file_offset_bits+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ while :; do ++ ac_cv_sys_file_offset_bits=no ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++ /* Check that off_t can represent 2**63 - 1 correctly. ++ We can't simply define LARGE_OFF_T to be 9223372036854775807, ++ since some C++ compilers masquerading as C compilers ++ incorrectly reject 9223372036854775807. */ ++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) ++ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 ++ && LARGE_OFF_T % 2147483647 == 1) ++ ? 1 : -1]; ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ break ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#define _FILE_OFFSET_BITS 64 ++#include ++ /* Check that off_t can represent 2**63 - 1 correctly. ++ We can't simply define LARGE_OFF_T to be 9223372036854775807, ++ since some C++ compilers masquerading as C compilers ++ incorrectly reject 9223372036854775807. */ ++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) ++ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 ++ && LARGE_OFF_T % 2147483647 == 1) ++ ? 1 : -1]; ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ac_cv_sys_file_offset_bits=64; break ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++ break ++done ++fi ++echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 ++echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6 ++if test "$ac_cv_sys_file_offset_bits" != no; then ++ ++cat >>confdefs.h <<_ACEOF ++#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits ++_ACEOF ++ ++fi ++rm -f conftest* ++ echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 ++echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6 ++if test "${ac_cv_sys_large_files+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ while :; do ++ ac_cv_sys_large_files=no ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++ /* Check that off_t can represent 2**63 - 1 correctly. ++ We can't simply define LARGE_OFF_T to be 9223372036854775807, ++ since some C++ compilers masquerading as C compilers ++ incorrectly reject 9223372036854775807. */ ++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) ++ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 ++ && LARGE_OFF_T % 2147483647 == 1) ++ ? 1 : -1]; ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ break ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#define _LARGE_FILES 1 ++#include ++ /* Check that off_t can represent 2**63 - 1 correctly. ++ We can't simply define LARGE_OFF_T to be 9223372036854775807, ++ since some C++ compilers masquerading as C compilers ++ incorrectly reject 9223372036854775807. */ ++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) ++ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 ++ && LARGE_OFF_T % 2147483647 == 1) ++ ? 1 : -1]; ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ac_cv_sys_large_files=1; break ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++ break ++done ++fi ++echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 ++echo "${ECHO_T}$ac_cv_sys_large_files" >&6 ++if test "$ac_cv_sys_large_files" != no; then ++ ++cat >>confdefs.h <<_ACEOF ++#define _LARGE_FILES $ac_cv_sys_large_files ++_ACEOF ++ ++fi ++rm -f conftest* ++fi ++ + + + diff --git a/gdb-6.8-bz466901-backtrace-full-prelinked.patch b/gdb-6.8-bz466901-backtrace-full-prelinked.patch new file mode 100644 index 0000000..4a1d1ff --- /dev/null +++ b/gdb-6.8-bz466901-backtrace-full-prelinked.patch @@ -0,0 +1,488 @@ +Fix resolving of variables at locations lists in prelinked libs (BZ 466901). + +Index: gdb-6.8.50.20081128/gdb/dwarf2loc.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/dwarf2loc.c 2008-12-08 11:00:45.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/dwarf2loc.c 2008-12-08 18:02:49.000000000 +0100 +@@ -55,7 +55,9 @@ find_location_expression (struct dwarf2_ + CORE_ADDR low, high; + gdb_byte *loc_ptr, *buf_end; + int length; +- struct objfile *objfile = dwarf2_per_cu_objfile (baton->per_cu); ++ struct objfile *objfile1 = dwarf2_per_cu_objfile (baton->per_cu); ++ struct objfile *objfile = objfile1->separate_debug_objfile ++ ? objfile1->separate_debug_objfile : objfile1; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + unsigned int addr_size = dwarf2_per_cu_addr_size (baton->per_cu); + CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.dwarf2/dw2-loclist-prelinked.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.dwarf2/dw2-loclist-prelinked.exp 2008-12-08 18:00:43.000000000 +0100 +@@ -0,0 +1,102 @@ ++# Copyright 2008 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. ++ ++# Minimal DWARF-2 unit test ++ ++# This test can only be run on i386/x86_64 targets which support DWARF-2. ++# For now pick a sampling of likely targets. ++if {(![istarget *-*-linux*] ++ && ![istarget *-*-gnu*] ++ && ![istarget *-*-elf*] ++ && ![istarget *-*-openbsd*]) ++ || (![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"])} { ++ return 0 ++} ++ ++set testfile "dw2-loclist-prelinked" ++set srcfuncfile ${testfile}-func.S ++set binsharedfuncfile ${objdir}/${subdir}/${testfile}.so ++set srcmainfile ${testfile}-main.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++remote_exec build "rm -f ${binfile}" ++ ++# get the value of gcc_compiled ++if [get_compiler_info ${binfile}] { ++ return -1 ++} ++ ++# This test can only be run on gcc as we use additional_flags=FIXME ++if {$gcc_compiled == 0} { ++ return 0 ++} ++ ++if { [gdb_compile_shlib "${srcdir}/${subdir}/${srcfuncfile}" "${binsharedfuncfile}" {debug additional_flags=-m32}] != "" } { ++ untested "Couldn't compile test library" ++ return -1 ++} ++ ++# The new separate debug info file will be stored in the .debug subdirectory. ++ ++if [gdb_gnu_strip_debug ${binsharedfuncfile}] { ++ # check that you have a recent version of strip and objcopy installed ++ unsupported "cannot produce separate debug info files" ++ return -1 ++} ++ ++if {[catch "system \"/usr/sbin/prelink -qNR --no-exec-shield ${binsharedfuncfile}\""] != 0} { ++ # Maybe we don't have prelink. ++ return -1 ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcmainfile}" \ ++ "${binfile}" executable [list debug additional_flags=-m32 shlib=${binsharedfuncfile}]] != "" } { ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_run_cmd ++ ++gdb_test "" "Program received signal SIGABRT, Aborted..*" "Enter abort()" ++ ++# Incorrect: ++# #0 0x00110430 in __kernel_vsyscall () ++# No symbol table info available. ++# #1 0x003d44c0 in raise () from /lib/libc.so.6 ++# No symbol table info available. ++# #2 0x003d5e88 in abort () from /lib/libc.so.6 ++# No symbol table info available. ++# #3 0x44f10437 in func () at dw2-loclist-prelinked.c:8 ++# i = Could not find the frame base for "func". ++ ++# Correct: ++# #0 0x00110430 in __kernel_vsyscall () ++# No symbol table info available. ++# #1 0x003d44c0 in raise () from /lib/libc.so.6 ++# No symbol table info available. ++# #2 0x003d5e88 in abort () from /lib/libc.so.6 ++# No symbol table info available. ++# #3 0x4ae36437 in func () at dw2-loclist-prelinked.c:8 ++# i = 3827288 ++# #4 0x0804851a in main () at ../../../gdb/testsuite/gdb.dwarf2/dw2-loclist-prelinked-main.c:24 ++# No locals. ++ ++# `abort' can get expressed as `*__GI_abort'. ++gdb_test "bt full" "in \[^ \]*abort \\(.*in func \\(.*\r\n\[\t \]+i = -?\[0-9\].*in main \\(.*" "Backtrace after abort()" +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.dwarf2/dw2-loclist-prelinked-main.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.dwarf2/dw2-loclist-prelinked-main.c 2008-12-08 18:00:43.000000000 +0100 +@@ -0,0 +1,26 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . */ ++ ++/* dw2-loclist-prelinked-func.S */ ++extern void func (void); ++ ++int ++main (void) ++{ ++ func (); ++ return 0; ++} +Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.dwarf2/dw2-loclist-prelinked-func.S +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-6.8.50.20081128/gdb/testsuite/gdb.dwarf2/dw2-loclist-prelinked-func.S 2008-12-08 18:00:43.000000000 +0100 +@@ -0,0 +1,328 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . */ ++ ++/* ++#include ++ ++void ++func (void) ++{ ++ int i; ++ ++ abort (); ++} ++*/ ++ .file "dw2-loclist-prelinked.c" ++ .section .debug_abbrev,"",@progbits ++.Ldebug_abbrev0: ++ .section .debug_info,"",@progbits ++.Ldebug_info0: ++ .section .debug_line,"",@progbits ++.Ldebug_line0: ++ .text ++.Ltext0: ++.globl func ++ .type func, @function ++func: ++.LFB2: ++ .file 1 "dw2-loclist-prelinked.c" ++ .loc 1 5 0 ++ pushl %ebp ++.LCFI0: ++ movl %esp, %ebp ++.LCFI1: ++ subl $24, %esp ++.LCFI2: ++ .loc 1 8 0 ++ call abort ++.LFE2: ++ .size func, .-func ++ .section .debug_frame,"",@progbits ++.Lframe0: ++ .long .LECIE0-.LSCIE0 ++.LSCIE0: ++ .long 0xffffffff ++ .byte 0x1 ++ .string "" ++ .uleb128 0x1 ++ .sleb128 -4 ++ .byte 0x8 ++ .byte 0xc ++ .uleb128 0x4 ++ .uleb128 0x4 ++ .byte 0x88 ++ .uleb128 0x1 ++ .align 4 ++.LECIE0: ++.LSFDE0: ++ .long .LEFDE0-.LASFDE0 ++.LASFDE0: ++ .long .Lframe0 ++ .long .LFB2 ++ .long .LFE2-.LFB2 ++ .byte 0x4 ++ .long .LCFI0-.LFB2 ++ .byte 0xe ++ .uleb128 0x8 ++ .byte 0x85 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x5 ++ .align 4 ++.LEFDE0: ++ .text ++.Letext0: ++ .section .debug_loc,"",@progbits ++.Ldebug_loc0: ++.LLST0: ++ .long .LFB2-.Ltext0 ++ .long .LCFI0-.Ltext0 ++ .value 0x2 ++ .byte 0x74 ++ .sleb128 4 ++ .long .LCFI0-.Ltext0 ++ .long .LCFI1-.Ltext0 ++ .value 0x2 ++ .byte 0x74 ++ .sleb128 8 ++ .long .LCFI1-.Ltext0 ++ .long .LFE2-.Ltext0 ++ .value 0x2 ++ .byte 0x75 ++ .sleb128 8 ++ .long 0x0 ++ .long 0x0 ++ .section .debug_info ++ .long 0x94 ++ .value 0x2 ++ .long .Ldebug_abbrev0 ++ .byte 0x4 ++ .uleb128 0x1 ++ .long .LASF10 ++ .byte 0x1 ++ .long .LASF11 ++ .long .LASF12 ++ .long .Ltext0 ++ .long .Letext0 ++ .long .Ldebug_line0 ++ .uleb128 0x2 ++ .byte 0x4 ++ .byte 0x7 ++ .long .LASF0 ++ .uleb128 0x3 ++ .byte 0x4 ++ .byte 0x5 ++ .string "int" ++ .uleb128 0x2 ++ .byte 0x4 ++ .byte 0x5 ++ .long .LASF1 ++ .uleb128 0x2 ++ .byte 0x1 ++ .byte 0x8 ++ .long .LASF2 ++ .uleb128 0x2 ++ .byte 0x2 ++ .byte 0x7 ++ .long .LASF3 ++ .uleb128 0x2 ++ .byte 0x4 ++ .byte 0x7 ++ .long .LASF4 ++ .uleb128 0x2 ++ .byte 0x1 ++ .byte 0x6 ++ .long .LASF5 ++ .uleb128 0x2 ++ .byte 0x2 ++ .byte 0x5 ++ .long .LASF6 ++ .uleb128 0x2 ++ .byte 0x8 ++ .byte 0x5 ++ .long .LASF7 ++ .uleb128 0x2 ++ .byte 0x8 ++ .byte 0x7 ++ .long .LASF8 ++ .uleb128 0x4 ++ .byte 0x4 ++ .byte 0x7 ++ .uleb128 0x2 ++ .byte 0x1 ++ .byte 0x6 ++ .long .LASF9 ++ .uleb128 0x5 ++ .byte 0x1 ++ .long .LASF13 ++ .byte 0x1 ++ .byte 0x5 ++ .byte 0x1 ++ .long .LFB2 ++ .long .LFE2 ++ .long .LLST0 ++ .uleb128 0x6 ++ .string "i" ++ .byte 0x1 ++ .byte 0x6 ++ .long 0x2c ++ .byte 0x2 ++ .byte 0x91 ++ .sleb128 -12 ++ .byte 0x0 ++ .byte 0x0 ++ .section .debug_abbrev ++ .uleb128 0x1 ++ .uleb128 0x11 ++ .byte 0x1 ++ .uleb128 0x25 ++ .uleb128 0xe ++ .uleb128 0x13 ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x1b ++ .uleb128 0xe ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x10 ++ .uleb128 0x6 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x2 ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0xe ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x4 ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x5 ++ .uleb128 0x2e ++ .byte 0x1 ++ .uleb128 0x3f ++ .uleb128 0xc ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x27 ++ .uleb128 0xc ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x40 ++ .uleb128 0x6 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x6 ++ .uleb128 0x34 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .byte 0x0 ++ .section .debug_pubnames,"",@progbits ++ .long 0x17 ++ .value 0x2 ++ .long .Ldebug_info0 ++ .long 0x98 ++ .long 0x75 ++ .string "func" ++ .long 0x0 ++ .section .debug_aranges,"",@progbits ++ .long 0x1c ++ .value 0x2 ++ .long .Ldebug_info0 ++ .byte 0x4 ++ .byte 0x0 ++ .value 0x0 ++ .value 0x0 ++ .long .Ltext0 ++ .long .Letext0-.Ltext0 ++ .long 0x0 ++ .long 0x0 ++ .section .debug_str,"MS",@progbits,1 ++.LASF7: ++ .string "long long int" ++.LASF0: ++ .string "unsigned int" ++.LASF11: ++ .string "dw2-loclist-prelinked.c" ++.LASF12: ++ .string "gdb-6.8/gdb/testsuite/gdb.dwarf2" ++.LASF4: ++ .string "long unsigned int" ++.LASF8: ++ .string "long long unsigned int" ++.LASF2: ++ .string "unsigned char" ++.LASF9: ++ .string "char" ++.LASF1: ++ .string "long int" ++.LASF3: ++ .string "short unsigned int" ++.LASF5: ++ .string "signed char" ++.LASF10: ++ .string "GNU C 4.3.2 20081007 (Red Hat 4.3.2-6)" ++.LASF13: ++ .string "func" ++.LASF6: ++ .string "short int" ++ .ident "GCC: (GNU) 4.3.2 20081007 (Red Hat 4.3.2-6)" ++ .section .note.GNU-stack,"",@progbits diff --git a/gdb-6.8-constant-watchpoints.patch b/gdb-6.8-constant-watchpoints.patch new file mode 100644 index 0000000..b2f3045 --- /dev/null +++ b/gdb-6.8-constant-watchpoints.patch @@ -0,0 +1,236 @@ +2008-07-10 Jan Kratochvil + + * breakpoint.c (fetch_watchpoint_value): New comment on unreachable + values. + (watch_command_1): New variable VAL_CHAIN. Refuse constant watchpoints. + * gdbtypes.h (TYPE_CODE_FUNC): New comment regarding pointers to it. + +2008-07-10 Jan Kratochvil + + * gdb.texinfo (Set Watchpoints): Document constant value watchpoints. + +2008-07-10 Jan Kratochvil + + * gdb.base/watchpoint.exp: Call TEST_CONSTANT_WATCHPOINT. + (test_constant_watchpoint): New function. + (test_inaccessible_watchpoint): Cleanup (delete) the watchpoint. + Test also a double-indirection watchpoint. + gdb.base/watchpoint.c (global_ptr_ptr): New variable. + (func4): New testing code for GLOBAL_PTR_PTR. + +Index: gdb-6.8.50.20090209/gdb/breakpoint.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/breakpoint.c 2009-02-09 15:39:01.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/breakpoint.c 2009-02-09 16:04:10.000000000 +0100 +@@ -769,7 +769,15 @@ is_hardware_watchpoint (struct breakpoin + If VAL_CHAIN is non-NULL, *VAL_CHAIN will be released from the + value chain. The caller must free the values individually. If + VAL_CHAIN is NULL, all generated values will be left on the value +- chain. */ ++ chain. ++ ++ Inferior unreachable values return: ++ Inferior `int *intp = NULL;' with `watch *intp': ++ *VALP is NULL, *RESULTP contains lazy LVAL_MEMORY address 0, *VAL_CHAIN ++ contains the *RESULTP element and also INTP as LVAL_MEMORY. ++ Inferior `int **intpp = NULL;' with `watch **intpp': ++ *VALP is NULL, *RESULTP is NULL, *VAL_CHAIN contains lazy LVAL_MEMORY ++ address 0 and also INTPP as LVAL_MEMORY. */ + + static void + fetch_watchpoint_value (struct expression *exp, struct value **valp, +@@ -5862,7 +5870,7 @@ watch_command_1 (char *arg, int accessfl + struct symtab_and_line sal; + struct expression *exp; + struct block *exp_valid_block; +- struct value *val, *mark; ++ struct value *val, *mark, *val_chain; + struct frame_info *frame; + struct frame_info *prev_frame = NULL; + char *exp_start = NULL; +@@ -5954,6 +5962,27 @@ watch_command_1 (char *arg, int accessfl + exp_valid_block = innermost_block; + mark = value_mark (); + fetch_watchpoint_value (exp, &val, NULL, NULL); ++ ++ /* VALUE_MARK gets us the same value as FETCH_WATCHPOINT_VALUE's VAL_CHAIN ++ parameter. Just this way we do not have to VALUE_FREE the chained VALUEs ++ ourselves. */ ++ for (val_chain = value_mark (); ++ val_chain != mark; ++ val_chain = value_next (val_chain)) ++ if ((VALUE_LVAL (val_chain) == lval_memory ++ && TYPE_CODE (value_type (val_chain)) != TYPE_CODE_FUNC) ++ || VALUE_LVAL (val_chain) == lval_register) ++ break; ++ if (val_chain == mark) ++ { ++ int len; ++ ++ len = exp_end - exp_start; ++ while (len > 0 && isspace (exp_start[len - 1])) ++ len--; ++ error (_("Cannot watch constant value %.*s."), len, exp_start); ++ } ++ /* Break the values chain only after its check above. */ + if (val != NULL) + release_value (val); + +Index: gdb-6.8.50.20090209/gdb/gdbtypes.h +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/gdbtypes.h 2009-02-09 15:51:57.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/gdbtypes.h 2009-02-09 16:04:10.000000000 +0100 +@@ -70,7 +70,22 @@ enum type_code + TYPE_CODE_UNION, /* C union or Pascal variant part */ + TYPE_CODE_ENUM, /* Enumeration type */ + TYPE_CODE_FLAGS, /* Bit flags type */ +- TYPE_CODE_FUNC, /* Function type */ ++ ++ /* Function type. It is not a pointer to a function. Function reference ++ by its name (such as `printf') has this type. C automatically converts ++ this function type to a pointer to function for any operation except ++ `sizeof (function_type)' or `&function_type' (unary &). ++ `sizeof (function_type)' is undefined in C. But GCC provides extension ++ (info '(gcc)Pointer Arith') defining its size as 1 byte. DWARF does not ++ define its size but GDB defines the size the GCC compatible way - GDB ++ function MAKE_FUNCTION_TYPE. The address itself is not modifiable. ++ As the function type has size 1 but its real value has `sizeof ++ (CORE_ADDR)' we cannot use NOT_LVAL category because the address would ++ not fit in the VALUE_CONTENTS_RAW container of its VALUE. We use ++ LVAL_MEMORY (and its VALUE_ADDRESS field) for it but we must be careful ++ it is not lvalue, it is the only non-modifiable LVAL_MEMORY. */ ++ TYPE_CODE_FUNC, ++ + TYPE_CODE_INT, /* Integer type */ + + /* Floating type. This is *NOT* a complex type. Beware, there are parts +Index: gdb-6.8.50.20090209/gdb/doc/gdb.texinfo +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/doc/gdb.texinfo 2009-02-09 16:02:42.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/doc/gdb.texinfo 2009-02-09 16:04:10.000000000 +0100 +@@ -3480,6 +3480,18 @@ This command prints a list of watchpoint + it is the same as @code{info break} (@pxref{Set Breaks}). + @end table + ++If you watch for a change in a numerically entered address you need to ++dereference it as the address itself is just a constant number which will never ++change. @value{GDBN} refuses to create a watchpoint that watches ++a never-changing value: ++ ++@smallexample ++(@value{GDBP}) watch 0x600850 ++Cannot watch constant value 0x600850. ++(@value{GDBP}) watch *(int *) 0x600850 ++Watchpoint 1: *(int *) 6293584 ++@end smallexample ++ + @value{GDBN} sets a @dfn{hardware watchpoint} if possible. Hardware + watchpoints execute very quickly, and the debugger reports a change in + value at the exact instruction where the change occurs. If @value{GDBN} +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.base/watchpoint.c +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/testsuite/gdb.base/watchpoint.c 2008-03-03 14:24:12.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.base/watchpoint.c 2009-02-09 16:04:10.000000000 +0100 +@@ -40,6 +40,7 @@ struct foo struct1, struct2, *ptr1, *ptr + int doread = 0; + + char *global_ptr; ++char **global_ptr_ptr; + + void marker1 () + { +@@ -118,6 +119,10 @@ func4 () + buf[0] = 3; + global_ptr = buf; + buf[0] = 7; ++ buf[1] = 5; ++ global_ptr_ptr = &global_ptr; ++ buf[0] = 9; ++ global_ptr++; + } + + int main () +Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.base/watchpoint.exp +=================================================================== +--- gdb-6.8.50.20090209.orig/gdb/testsuite/gdb.base/watchpoint.exp 2009-01-03 06:58:03.000000000 +0100 ++++ gdb-6.8.50.20090209/gdb/testsuite/gdb.base/watchpoint.exp 2009-02-09 16:05:03.000000000 +0100 +@@ -641,7 +641,21 @@ proc test_watchpoint_and_breakpoint {} { + } + } + } +- ++ ++proc test_constant_watchpoint {} { ++ global gdb_prompt ++ ++ gdb_test "watch 5" "Cannot watch constant value 5." "number is constant" ++ gdb_test "watch marker1" "Cannot watch constant value marker1." \ ++ "marker1 is constant" ++ gdb_test "watch count + 6" ".*atchpoint \[0-9\]+: count \\+ 6" ++ gdb_test "set \$expr_breakpoint_number = \$bpnum" "" ++ gdb_test "delete \$expr_breakpoint_number" "" ++ gdb_test "watch 7 + count" ".*atchpoint \[0-9\]+: 7 \\+ count" ++ gdb_test "set \$expr_breakpoint_number = \$bpnum" "" ++ gdb_test "delete \$expr_breakpoint_number" "" ++} ++ + proc test_inaccessible_watchpoint {} { + global gdb_prompt + +@@ -662,7 +676,8 @@ proc test_inaccessible_watchpoint {} { + } + + gdb_test "watch *global_ptr" ".*atchpoint \[0-9\]+: \\*global_ptr" +- gdb_test "next" ".*global_ptr = buf.*" ++ gdb_test "set \$global_ptr_breakpoint_number = \$bpnum" "" ++ gdb_test "next" ".*global_ptr = buf.*" "global_ptr next" + gdb_test_multiple "next" "next over ptr init" { + -re ".*atchpoint \[0-9\]+: \\*global_ptr\r\n\r\nOld value = .*\r\nNew value = 3 .*\r\n.*$gdb_prompt $" { + # We can not test for here because NULL may be readable. +@@ -675,6 +690,28 @@ proc test_inaccessible_watchpoint {} { + pass "next over buffer set" + } + } ++ gdb_test "delete \$global_ptr_breakpoint_number" "" ++ gdb_test "watch **global_ptr_ptr" ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr" ++ gdb_test "set \$global_ptr_ptr_breakpoint_number = \$bpnum" "" ++ gdb_test "next" ".*global_ptr_ptr = &global_ptr.*" "gloabl_ptr_ptr next" ++ gdb_test_multiple "next" "next over global_ptr_ptr init" { ++ -re ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr\r\n\r\nOld value = .*\r\nNew value = 7 .*\r\n.*$gdb_prompt $" { ++ # We can not test for here because NULL may be readable. ++ # This test does rely on *NULL != 7. ++ pass "next over global_ptr_ptr init" ++ } ++ } ++ gdb_test_multiple "next" "next over global_ptr_ptr buffer set" { ++ -re ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr\r\n\r\nOld value = 7 .*\r\nNew value = 9 .*\r\n.*$gdb_prompt $" { ++ pass "next over global_ptr_ptr buffer set" ++ } ++ } ++ gdb_test_multiple "next" "next over global_ptr_ptr pointer advance" { ++ -re ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr\r\n\r\nOld value = 9 .*\r\nNew value = 5 .*\r\n.*$gdb_prompt $" { ++ pass "next over global_ptr_ptr pointer advance" ++ } ++ } ++ gdb_test "delete \$global_ptr_ptr_breakpoint_number" "" + } + } + +@@ -842,6 +879,17 @@ if [initialize] then { + } + + test_watchpoint_and_breakpoint ++ ++ # See above. ++ if [istarget "mips-idt-*"] then { ++ gdb_exit ++ gdb_start ++ gdb_reinitialize_dir $srcdir/$subdir ++ gdb_load $binfile ++ initialize ++ } ++ ++ test_constant_watchpoint + } + + # Restore old timeout diff --git a/gdb-6.8-ctors-dtors-unique.patch b/gdb-6.8-ctors-dtors-unique.patch new file mode 100644 index 0000000..3cbc8e0 --- /dev/null +++ b/gdb-6.8-ctors-dtors-unique.patch @@ -0,0 +1,73 @@ +--- ./gdb/linespec.c 2008-08-27 00:27:33.000000000 +0200 ++++ ./gdb/linespec.c 2008-08-27 00:53:16.000000000 +0200 +@@ -284,6 +284,15 @@ find_methods (struct type *t, char *name + } + + static int ++add_minsym_members_compar (const void *ap, const void *bp) ++{ ++ const char *a = *(const char **) ap; ++ const char *b = *(const char **) bp; ++ ++ return strcmp (a, b); ++} ++ ++static int + add_minsym_members (const char *class_name, + const char *member_name, + struct minimal_symbol **msym_arr) +@@ -293,6 +302,7 @@ add_minsym_members (const char *class_na + int i; + int comp_len; + int counter = 0; ++ int src_i, dst_i; + + /* To find the member, we first cheat and use symbol completion. + This will give us a list of all the member names including +@@ -307,6 +317,28 @@ add_minsym_members (const char *class_na + strcat (completion_name, "("); + list = make_symbol_completion_list (completion_name, + completion_name+1); ++ if (list == NULL || list[0] == NULL) ++ { ++ xfree (completion_name); ++ return 0; ++ } ++ ++ /* Make the list entries unique - Multi-PC breakpoints are already resolved ++ by GDB-6.8+. */ ++ counter = 0; ++ while (list && list[counter] != NULL) ++ counter++; ++ qsort (list, counter, sizeof (*list), add_minsym_members_compar); ++ src_i = dst_i = 0; ++ while (src_i + 1 < counter) ++ { ++ if (strcmp (list[src_i], list[src_i + 1]) != 0) ++ list[dst_i++] = list[src_i]; ++ src_i++; ++ } ++ list[dst_i++] = list[src_i++]; ++ gdb_assert (list[src_i] == NULL); ++ list[dst_i] = 0; + + /* Now that we have the list, we generate an array of their + corresponding minimal symbols. */ +@@ -319,6 +351,8 @@ add_minsym_members (const char *class_na + + xfree (list); + ++#if 0 /* Multi-PC breakpoints are already resolved by GDB-6.8+. */ ++ + /* In the case of constructors, there may be in-charge vs not-in-charge + constructors. Check for names with $base which indicates not-in-charge + constructors. */ +@@ -353,6 +387,8 @@ add_minsym_members (const char *class_na + } + xfree (list); + ++#endif /* Multi-PC breakpoints are already resolved by GDB-6.8+. */ ++ + xfree (completion_name); + + return counter; diff --git a/gdb-6.8-fortran-tag-constant.patch b/gdb-6.8-fortran-tag-constant.patch new file mode 100644 index 0000000..7bfe237 --- /dev/null +++ b/gdb-6.8-fortran-tag-constant.patch @@ -0,0 +1,76 @@ +Index: gdb-6.8.50.20090228/gdb/dwarf2read.c +=================================================================== +--- gdb-6.8.50.20090228.orig/gdb/dwarf2read.c 2009-03-02 01:07:36.000000000 +0100 ++++ gdb-6.8.50.20090228/gdb/dwarf2read.c 2009-03-02 01:07:50.000000000 +0100 +@@ -1996,6 +1996,7 @@ scan_partial_symbols (struct partial_die + add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu); + break; + case DW_TAG_variable: ++ case DW_TAG_constant: + case DW_TAG_typedef: + case DW_TAG_union_type: + if (!pdi->is_declaration) +@@ -2211,6 +2212,7 @@ add_partial_symbol (struct partial_die_i + } + break; + case DW_TAG_variable: ++ case DW_TAG_constant: + if (pdi->is_external) + { + /* Global Variable. +@@ -4213,7 +4215,8 @@ dwarf2_add_field (struct field_info *fip + fip->non_public_fields = 1; + } + } +- else if (die->tag == DW_TAG_member || die->tag == DW_TAG_variable) ++ else if (die->tag == DW_TAG_member || die->tag == DW_TAG_variable ++ || die->tag == DW_TAG_constant) + { + /* C++ static member. */ + +@@ -4703,7 +4706,8 @@ read_structure_type (struct die_info *di + while (child_die && child_die->tag) + { + if (child_die->tag == DW_TAG_member +- || child_die->tag == DW_TAG_variable) ++ || child_die->tag == DW_TAG_variable ++ || child_die->tag == DW_TAG_constant) + { + /* NOTE: carlton/2002-11-05: A C++ static data member + should be a DW_TAG_member that is a declaration, but +@@ -4822,6 +4826,7 @@ process_structure_scope (struct die_info + { + if (child_die->tag == DW_TAG_member + || child_die->tag == DW_TAG_variable ++ || child_die->tag == DW_TAG_constant + || child_die->tag == DW_TAG_inheritance) + { + /* Do nothing. */ +@@ -6455,6 +6460,7 @@ load_partial_dies (bfd *abfd, gdb_byte * + && abbrev->tag != DW_TAG_subprogram + && abbrev->tag != DW_TAG_lexical_block + && abbrev->tag != DW_TAG_variable ++ && abbrev->tag != DW_TAG_constant + && abbrev->tag != DW_TAG_namespace + && abbrev->tag != DW_TAG_member) + { +@@ -6562,6 +6568,7 @@ load_partial_dies (bfd *abfd, gdb_byte * + if (load_all + || abbrev->tag == DW_TAG_subprogram + || abbrev->tag == DW_TAG_variable ++ || abbrev->tag == DW_TAG_constant + || abbrev->tag == DW_TAG_namespace + || part_die->is_declaration) + { +@@ -8341,6 +8348,11 @@ new_symbol (struct die_info *die, struct + /* Do not add the symbol to any lists. It will be found via + BLOCK_FUNCTION from the blockvector. */ + break; ++ case DW_TAG_constant: ++ SYMBOL_TYPE (sym) = make_cv_type (1, ++ TYPE_VOLATILE (SYMBOL_TYPE (sym)), ++ SYMBOL_TYPE (sym), NULL); ++ /* PASSTHRU */ + case DW_TAG_variable: + /* Compilation with minimal debug info may result in variables + with missing type entries. Change the misleading `void' type diff --git a/gdb-6.8-gcc35998-ada-memory-trash.patch b/gdb-6.8-gcc35998-ada-memory-trash.patch new file mode 100644 index 0000000..7a35438 --- /dev/null +++ b/gdb-6.8-gcc35998-ada-memory-trash.patch @@ -0,0 +1,18 @@ +--- ./gdb/dwarf2read.c 4 May 2008 17:27:01 -0000 1.260 ++++ ./gdb/dwarf2read.c 4 May 2008 18:26:20 -0000 +@@ -6754,7 +6754,14 @@ dwarf2_attr (struct die_info *die, unsig + for (i = 0; i < die->num_attrs; ++i) + { + if (die->attrs[i].name == name) +- return &die->attrs[i]; ++ { ++ /* GCC PR ada/35998 workaround. */ ++ if (name == DW_AT_byte_size ++ && DW_UNSND (&die->attrs[i]) == 0xffffffff) ++ return NULL; ++ ++ return &die->attrs[i]; ++ } + if (die->attrs[i].name == DW_AT_specification + || die->attrs[i].name == DW_AT_abstract_origin) + spec = &die->attrs[i]; diff --git a/gdb-6.8-glibc-headers-compat.patch b/gdb-6.8-glibc-headers-compat.patch new file mode 100644 index 0000000..2149c1a --- /dev/null +++ b/gdb-6.8-glibc-headers-compat.patch @@ -0,0 +1,14 @@ +../../libiberty/strsignal.c:552: error: conflicting types for 'psignal' +/usr/include/signal.h:141: error: previous declaration of 'psignal' was here + +--- gdb-6.8/libiberty/strsignal.c-orig 2007-01-31 00:13:04.000000000 +0100 ++++ gdb-6.8/libiberty/strsignal.c 2008-06-17 16:30:13.000000000 +0200 +@@ -549,7 +549,7 @@ followed by a newline. + #ifndef HAVE_PSIGNAL + + void +-psignal (int signo, char *message) ++psignal (int signo, const char *message) + { + if (signal_names == NULL) + { diff --git a/gdb-6.8-inlining-addon.patch b/gdb-6.8-inlining-addon.patch index ebceae0..ee8d07e 100644 --- a/gdb-6.8-inlining-addon.patch +++ b/gdb-6.8-inlining-addon.patch @@ -5,10 +5,10 @@ causing: FAIL: gdb.base/unwindonsignal.exp: unwindonsignal, stack unwound resume() -> target_resume() move of clear_inline_frame_state() is for: gdb.mi/mi-nsmoribund.exp -Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-bt.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.c 2009-02-09 13:28:49.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-25 22:34:02.000000000 +0100 @@ -13,10 +13,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -28,10 +28,10 @@ Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.c inline int func1(void) { -Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-bt.exp 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.exp 2009-02-09 13:28:49.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-25 22:34:02.000000000 +0100 @@ -41,18 +41,19 @@ if { [skip_inline_frame_tests] } { return } @@ -60,10 +60,10 @@ Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.exp gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (3)" gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ -Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-cmds.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.c 2009-02-09 13:28:49.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-25 22:34:02.000000000 +0100 @@ -13,13 +13,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -86,10 +86,10 @@ Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.c inline int func1(void) { bar (); -Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-02-09 13:30:16.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-25 22:34:02.000000000 +0100 @@ -45,28 +45,28 @@ if { [skip_inline_frame_tests] } { # First, check that the things we expected to be inlined really were, @@ -180,10 +180,10 @@ Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.exp +gdb_test "info frame" "inlined into frame.*" "outer_inline2 inlined" +gdb_test "fini" "" "up from outer_inline2" +gdb_test "info frame" " in main \[^\n\]*\n source language.*" "main not inlined" -Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-locals.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.c 2009-02-09 13:28:49.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-25 22:34:02.000000000 +0100 @@ -13,11 +13,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -203,10 +203,10 @@ Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.c inline int func1(int arg1) { -Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-locals.exp 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.exp 2009-02-09 13:28:49.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-25 22:34:02.000000000 +0100 @@ -43,8 +43,8 @@ if { [skip_inline_var_tests] } { set no_frames [skip_inline_frame_tests] @@ -236,10 +236,10 @@ Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.exp + setup_kfail *-*-* "gcc/debug.optimization" +} gdb_test "print array\[0\]" "\\\$$decimal = 184" "print local (3)" -Index: gdb-6.8.50.20081214/gdb/frame.c +Index: gdb-6.8.50.20090302/gdb/frame.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/frame.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/frame.c 2009-02-09 13:30:16.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/frame.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/frame.c 2009-03-25 22:34:02.000000000 +0100 @@ -269,7 +269,7 @@ fprint_frame (struct ui_file *file, stru static struct frame_info * skip_inlined_frames (struct frame_info *frame) @@ -249,7 +249,7 @@ Index: gdb-6.8.50.20081214/gdb/frame.c frame = get_prev_frame (frame); return frame; -@@ -1697,6 +1697,7 @@ get_frame_address_in_block (struct frame +@@ -1670,6 +1670,7 @@ get_frame_address_in_block (struct frame { /* A draft address. */ CORE_ADDR pc = get_frame_pc (this_frame); @@ -257,7 +257,7 @@ Index: gdb-6.8.50.20081214/gdb/frame.c struct frame_info *next_frame = this_frame->next; -@@ -1739,6 +1740,9 @@ get_frame_address_in_block (struct frame +@@ -1712,6 +1713,9 @@ get_frame_address_in_block (struct frame while in an inlined function, then the code address of the "calling" normal function should not be adjusted either. */ @@ -267,7 +267,7 @@ Index: gdb-6.8.50.20081214/gdb/frame.c while (get_frame_type (next_frame) == INLINE_FRAME) next_frame = next_frame->next; -@@ -1770,7 +1774,7 @@ find_frame_sal (struct frame_info *frame +@@ -1743,7 +1747,7 @@ find_frame_sal (struct frame_info *frame sym = inline_skipped_symbol (inferior_ptid); init_sal (sal); @@ -276,10 +276,10 @@ Index: gdb-6.8.50.20081214/gdb/frame.c { sal->symtab = SYMBOL_SYMTAB (sym); sal->line = SYMBOL_LINE (sym); -Index: gdb-6.8.50.20081214/gdb/breakpoint.c +Index: gdb-6.8.50.20090302/gdb/breakpoint.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/breakpoint.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/breakpoint.c 2009-02-09 13:30:16.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/breakpoint.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/breakpoint.c 2009-03-25 22:34:02.000000000 +0100 @@ -57,6 +57,7 @@ #include "top.h" #include "wrapper.h" @@ -288,7 +288,7 @@ Index: gdb-6.8.50.20081214/gdb/breakpoint.c #include "mi/mi-common.h" -@@ -2833,10 +2834,24 @@ bpstat_check_breakpoint_conditions (bpst +@@ -2902,10 +2903,24 @@ bpstat_check_breakpoint_conditions (bpst const struct bp_location *bl = bs->breakpoint_at; struct breakpoint *b = bl->owner; @@ -317,7 +317,7 @@ Index: gdb-6.8.50.20081214/gdb/breakpoint.c { int value_is_zero = 0; -@@ -2975,6 +2990,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p +@@ -3044,6 +3059,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p bs->print = 0; } bs->commands = copy_command_lines (bs->commands); @@ -330,7 +330,7 @@ Index: gdb-6.8.50.20081214/gdb/breakpoint.c } /* Print nothing for this entry if we dont stop or if we dont print. */ -@@ -4826,9 +4847,9 @@ set_momentary_breakpoint (struct symtab_ +@@ -5169,9 +5190,9 @@ set_momentary_breakpoint (struct symtab_ { struct breakpoint *b; @@ -343,10 +343,10 @@ Index: gdb-6.8.50.20081214/gdb/breakpoint.c b = set_raw_breakpoint (sal, type); b->enable_state = bp_enabled; -Index: gdb-6.8.50.20081214/gdb/inline-frame.c +Index: gdb-6.8.50.20090302/gdb/inline-frame.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/inline-frame.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/inline-frame.c 2009-02-09 13:30:16.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/inline-frame.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/inline-frame.c 2009-03-25 22:34:02.000000000 +0100 @@ -183,6 +183,12 @@ inline_frame_sniffer (const struct frame if (frame_block == NULL) return 0; @@ -423,10 +423,10 @@ Index: gdb-6.8.50.20081214/gdb/inline-frame.c /* Return the number of hidden functions inlined into the current frame. */ -Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-markers.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-markers.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-markers.c 2009-02-09 13:28:49.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-25 22:34:02.000000000 +0100 @@ -15,11 +15,6 @@ extern int x, y; @@ -439,10 +439,10 @@ Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-markers.c void marker(void) { x += y; /* set breakpoint 2 here */ -Index: gdb-6.8.50.20081214/gdb/gdbthread.h +Index: gdb-6.8.50.20090302/gdb/gdbthread.h =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/gdbthread.h 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/gdbthread.h 2009-02-09 13:30:16.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/gdbthread.h 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/gdbthread.h 2009-03-25 22:34:02.000000000 +0100 @@ -180,6 +180,12 @@ struct thread_info /* Private data used by the target vector implementation. */ @@ -456,11 +456,11 @@ Index: gdb-6.8.50.20081214/gdb/gdbthread.h }; /* Create an empty thread list, or empty the existing one. */ -Index: gdb-6.8.50.20081214/gdb/infcmd.c +Index: gdb-6.8.50.20090302/gdb/infcmd.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/infcmd.c 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/infcmd.c 2009-02-09 13:30:16.000000000 +0100 -@@ -1373,11 +1373,11 @@ finish_command_continuation (void *arg) +--- gdb-6.8.50.20090302.orig/gdb/infcmd.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/infcmd.c 2009-03-25 22:34:02.000000000 +0100 +@@ -1391,11 +1391,11 @@ finish_command_continuation (void *arg) struct type *value_type; value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function)); @@ -474,7 +474,7 @@ Index: gdb-6.8.50.20081214/gdb/infcmd.c print_return_value (SYMBOL_TYPE (a->function), value_type); } -@@ -1481,6 +1481,16 @@ finish_forward (struct symbol *function, +@@ -1499,6 +1499,16 @@ finish_forward (struct symbol *function, old_chain = make_cleanup_delete_breakpoint (breakpoint); @@ -491,7 +491,7 @@ Index: gdb-6.8.50.20081214/gdb/infcmd.c tp->proceed_to_finish = 1; /* We want stop_registers, please... */ make_cleanup_restore_integer (&suppress_stop_observer); suppress_stop_observer = 1; -@@ -1504,7 +1514,9 @@ finish_forward (struct symbol *function, +@@ -1522,7 +1532,9 @@ finish_forward (struct symbol *function, static void finish_command (char *arg, int from_tty) { @@ -502,7 +502,7 @@ Index: gdb-6.8.50.20081214/gdb/infcmd.c struct symbol *function; int async_exec = 0; -@@ -1535,46 +1547,63 @@ finish_command (char *arg, int from_tty) +@@ -1553,46 +1565,63 @@ finish_command (char *arg, int from_tty) if (!target_has_execution) error (_("The program is not running.")); @@ -584,7 +584,7 @@ Index: gdb-6.8.50.20081214/gdb/infcmd.c /* Print info on the selected frame, including level number but not source. */ -@@ -1588,10 +1617,14 @@ finish_command (char *arg, int from_tty) +@@ -1606,10 +1635,14 @@ finish_command (char *arg, int from_tty) print_stack_frame (get_selected_frame (NULL), 1, LOCATION); } @@ -600,11 +600,11 @@ Index: gdb-6.8.50.20081214/gdb/infcmd.c } -Index: gdb-6.8.50.20081214/gdb/infrun.c +Index: gdb-6.8.50.20090302/gdb/infrun.c =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/infrun.c 2009-02-09 13:29:51.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/infrun.c 2009-02-09 13:30:16.000000000 +0100 -@@ -1147,8 +1150,6 @@ a command like `return' or `jump' to con +--- gdb-6.8.50.20090302.orig/gdb/infrun.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/infrun.c 2009-03-25 22:34:02.000000000 +0100 +@@ -1152,8 +1152,6 @@ a command like `return' or `jump' to con step = 0; } @@ -613,7 +613,7 @@ Index: gdb-6.8.50.20081214/gdb/infrun.c if (debug_displaced && use_displaced_stepping (gdbarch) && tp->trap_expected) -@@ -1201,6 +1201,8 @@ clear_proceed_status_thread (struct thre +@@ -1205,6 +1203,8 @@ clear_proceed_status_thread (struct thre /* Discard any remaining commands or status from previous stop. */ bpstat_clear (&tp->stop_bpstat); @@ -622,8 +622,10 @@ Index: gdb-6.8.50.20081214/gdb/infrun.c } static int ---- ./gdb/target.c 2009-02-10 23:45:59.000000000 +0100 -+++ ./gdb/target.c 2009-02-10 23:43:29.000000000 +0100 +Index: gdb-6.8.50.20090302/gdb/target.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/target.c 2009-03-25 22:26:51.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/target.c 2009-03-25 22:34:02.000000000 +0100 @@ -41,6 +41,7 @@ #include "target-descriptions.h" #include "gdbthread.h" @@ -632,18 +634,18 @@ Index: gdb-6.8.50.20081214/gdb/infrun.c static void target_info (char *, int); -@@ -1938,6 +1939,7 @@ target_pid_to_str (ptid_t ptid) - void - target_resume (ptid_t ptid, int step, enum target_signal signal) +@@ -1925,6 +1926,7 @@ target_resume (ptid_t ptid, int step, en { + struct target_ops *t; + + clear_inline_frame_state (ptid); dcache_invalidate (target_dcache); - (*current_target.to_resume) (ptid, step, signal); - set_executing (ptid, 1); -Index: gdb-6.8.50.20081214/gdb/inline-frame.h + + for (t = current_target.beneath; t != NULL; t = t->beneath) +Index: gdb-6.8.50.20090302/gdb/inline-frame.h =================================================================== ---- gdb-6.8.50.20081214.orig/gdb/inline-frame.h 2009-02-09 13:28:48.000000000 +0100 -+++ gdb-6.8.50.20081214/gdb/inline-frame.h 2009-02-09 13:30:16.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/inline-frame.h 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/inline-frame.h 2009-03-25 22:34:02.000000000 +0100 @@ -43,6 +43,10 @@ void clear_inline_frame_state (ptid_t pt void step_into_inline_frame (ptid_t ptid); @@ -655,9 +657,11 @@ Index: gdb-6.8.50.20081214/gdb/inline-frame.h /* Return the number of hidden functions inlined into the current frame. */ ---- gdb-6.8.50.20090209/gdb/infcall.c 2009-02-10 00:16:10.000000000 +0100 -+++ gdb-6.8.50.20090209/gdb/infcall.c-removed 2009-02-10 00:15:58.000000000 +0100 -@@ -841,8 +841,15 @@ When the function is done executing, GDB +Index: gdb-6.8.50.20090302/gdb/infcall.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/infcall.c 2009-03-25 22:33:02.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/infcall.c 2009-03-25 22:34:02.000000000 +0100 +@@ -898,8 +898,15 @@ The program being debugged exited while if (unwind_on_signal_p) { @@ -675,3 +679,35 @@ Index: gdb-6.8.50.20081214/gdb/inline-frame.h /* FIXME: Insert a bunch of wrap_here; name can be very long if it's a C++ name with arguments and stuff. */ +Index: gdb-6.8.50.20090302/gdb/dwarf2read.c +=================================================================== +--- gdb-6.8.50.20090302.orig/gdb/dwarf2read.c 2009-03-25 22:33:44.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/dwarf2read.c 2009-03-25 22:34:11.000000000 +0100 +@@ -3471,6 +3471,7 @@ read_func_scope (struct die_info *die, s + unsigned die_children; + struct attribute *call_line, *call_file; + int inlined_func = (die->tag == DW_TAG_inlined_subroutine); ++ struct type *type; + + if (inlined_func) + { +@@ -3513,7 +3514,10 @@ read_func_scope (struct die_info *die, s + add_to_cu_func_list (name, lowpc, highpc, cu); + + new = push_context (0, lowpc); +- new->name = new_symbol (die, read_type_die (die, cu), cu); ++ type = read_type_die (die, cu); ++ gdb_assert (type != NULL); ++ new->name = new_symbol (die, type, cu); ++ gdb_assert (TYPE_CODE (SYMBOL_TYPE (new->name)) == TYPE_CODE_FUNC); + + /* If there is a location expression for DW_AT_frame_base, record + it. */ +@@ -8751,6 +8755,7 @@ read_type_die (struct die_info *die, str + break; + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: ++ case DW_TAG_inlined_subroutine: + this_type = read_subroutine_type (die, cu); + break; + case DW_TAG_array_type: diff --git a/gdb-6.8-inlining.patch b/gdb-6.8-inlining.patch index 7ef8b1c..42e69d7 100644 --- a/gdb-6.8-inlining.patch +++ b/gdb-6.8-inlining.patch @@ -5,10 +5,10 @@ http://sourceware.org/ml/gdb-patches/2008-07/msg00317.html Removed dwarf_expr_frame_base NULL check duplicity with *-vla.patch. -Index: gdb-6.8.50.20090216-cvs/gdb/NEWS +Index: gdb-6.8.50.20090302/gdb/NEWS =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/NEWS 2009-02-09 10:56:02.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/NEWS 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/NEWS 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/NEWS 2009-04-13 22:22:01.000000000 +0200 @@ -1,6 +1,11 @@ What has changed in GDB? (Organized release by release) @@ -20,11 +20,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/NEWS + *** Changes since GDB 6.8 - * GDB now supports automatic retrieval of shared library files from -Index: gdb-6.8.50.20090216-cvs/gdb/block.c + * GDB now has support for multi-byte and wide character sets on the +Index: gdb-6.8.50.20090302/gdb/block.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/block.c 2009-01-07 09:44:56.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/block.c 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/block.c 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/block.c 2009-04-13 22:22:01.000000000 +0200 @@ -47,8 +47,16 @@ contained_in (const struct block *a, con { if (!a || !b) @@ -67,10 +67,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/block.c /* Return the blockvector immediately containing the innermost lexical block containing the specified pc value and section, or 0 if there is none. PBLOCK is a pointer to the block. If PBLOCK is NULL, we -Index: gdb-6.8.50.20090216-cvs/gdb/block.h +Index: gdb-6.8.50.20090302/gdb/block.h =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/block.h 2009-01-07 09:44:56.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/block.h 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/block.h 2009-01-03 06:57:50.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/block.h 2009-04-13 22:22:01.000000000 +0200 @@ -65,7 +65,7 @@ struct block CORE_ADDR endaddr; @@ -80,7 +80,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/block.h struct symbol *function; -@@ -134,6 +134,8 @@ enum { GLOBAL_BLOCK = 0, STATIC_BLOCK = +@@ -134,6 +134,8 @@ enum { GLOBAL_BLOCK = 0, STATIC_BLOCK = extern struct symbol *block_linkage_function (const struct block *); @@ -89,10 +89,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/block.h extern int contained_in (const struct block *, const struct block *); extern struct blockvector *blockvector_for_pc (CORE_ADDR, struct block **); -Index: gdb-6.8.50.20090216-cvs/gdb/blockframe.c +Index: gdb-6.8.50.20090302/gdb/blockframe.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/blockframe.c 2009-01-07 09:44:56.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/blockframe.c 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/blockframe.c 2009-01-03 06:57:50.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/blockframe.c 2009-04-13 22:22:01.000000000 +0200 @@ -36,6 +36,7 @@ #include "command.h" #include "gdbcmd.h" @@ -161,11 +161,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/blockframe.c return frame; frame = get_prev_frame (frame); -Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c +Index: gdb-6.8.50.20090302/gdb/breakpoint.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/breakpoint.c 2009-03-02 11:37:58.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/breakpoint.c 2009-03-02 11:38:29.000000000 +0100 -@@ -2622,19 +2622,21 @@ watchpoint_check (void *p) +--- gdb-6.8.50.20090302.orig/gdb/breakpoint.c 2009-04-13 22:19:50.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/breakpoint.c 2009-04-13 22:22:01.000000000 +0200 +@@ -2641,19 +2641,21 @@ watchpoint_check (void *p) within_current_scope = 1; else { @@ -195,7 +195,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c /* in_function_epilogue_p() returns a non-zero value if we're still in the function but the stack frame has already been invalidated. -@@ -2646,10 +2648,9 @@ watchpoint_check (void *p) +@@ -2665,10 +2667,9 @@ watchpoint_check (void *p) that the watchpoint frame couldn't be found by frame_find_by_id() because the current PC is currently in an epilogue. Calling gdbarch_in_function_epilogue_p() also when fr == NULL fixes that. */ @@ -208,7 +208,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c /* If we end up stopping, the current frame will get selected in normal_stop. So this call to select_frame won't affect the user. */ -@@ -2883,7 +2884,7 @@ bpstat_check_breakpoint_conditions (bpst +@@ -2902,7 +2903,7 @@ bpstat_check_breakpoint_conditions (bpst struct breakpoint *b = bl->owner; if (frame_id_p (b->frame_id) @@ -217,7 +217,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c bs->stop = 0; else if (bs->stop) { -@@ -2898,8 +2899,12 @@ bpstat_check_breakpoint_conditions (bpst +@@ -2917,8 +2918,12 @@ bpstat_check_breakpoint_conditions (bpst if (bl->cond && bl->owner->disposition != disp_del_at_next_stop) { @@ -232,7 +232,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c select_frame (get_current_frame ()); value_is_zero = catch_errors (breakpoint_cond_eval, (bl->cond), -@@ -4926,6 +4931,11 @@ set_momentary_breakpoint (struct symtab_ +@@ -5163,6 +5168,11 @@ set_momentary_breakpoint (struct symtab_ enum bptype type) { struct breakpoint *b; @@ -244,15 +244,15 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c b = set_raw_breakpoint (sal, type); b->enable_state = bp_enabled; b->disposition = disp_donttouch; -@@ -5924,7 +5934,6 @@ watch_command_1 (char *arg, int accessfl +@@ -6208,7 +6218,6 @@ watch_command_1 (char *arg, int accessfl struct block *exp_valid_block; - struct value *val, *mark; + struct value *val, *mark, *val_chain; struct frame_info *frame; - struct frame_info *prev_frame = NULL; char *exp_start = NULL; char *exp_end = NULL; char *tok, *id_tok_start, *end_tok; -@@ -6064,34 +6073,34 @@ watch_command_1 (char *arg, int accessfl +@@ -6369,34 +6378,34 @@ watch_command_1 (char *arg, int accessfl bp_type = bp_watchpoint; frame = block_innermost_frame (exp_valid_block); @@ -305,7 +305,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c } /* Now set up the breakpoint. */ -@@ -6272,7 +6281,6 @@ until_break_command (char *arg, int from +@@ -6577,7 +6586,6 @@ until_break_command (char *arg, int from struct symtabs_and_lines sals; struct symtab_and_line sal; struct frame_info *frame = get_selected_frame (NULL); @@ -313,7 +313,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c struct breakpoint *breakpoint; struct breakpoint *breakpoint2 = NULL; struct cleanup *old_chain; -@@ -6305,20 +6313,22 @@ until_break_command (char *arg, int from +@@ -6610,20 +6618,22 @@ until_break_command (char *arg, int from we don't specify a frame at which we need to stop. */ breakpoint = set_momentary_breakpoint (sal, null_frame_id, bp_until); else @@ -342,11 +342,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/breakpoint.c bp_until); make_cleanup_delete_breakpoint (breakpoint2); } -Index: gdb-6.8.50.20090216-cvs/gdb/buildsym.c +Index: gdb-6.8.50.20090302/gdb/buildsym.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/buildsym.c 2009-01-07 09:44:56.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/buildsym.c 2009-03-02 11:38:29.000000000 +0100 -@@ -1159,6 +1159,12 @@ end_symtab (CORE_ADDR end_addr, struct o +--- gdb-6.8.50.20090302.orig/gdb/buildsym.c 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/buildsym.c 2009-04-13 22:22:01.000000000 +0200 +@@ -1155,6 +1155,12 @@ end_symtab (CORE_ADDR end_addr, struct o struct symbol *sym; struct dict_iterator iter; @@ -359,10 +359,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/buildsym.c for (sym = dict_iterator_first (BLOCK_DICT (block), &iter); sym != NULL; sym = dict_iterator_next (&iter)) -Index: gdb-6.8.50.20090216-cvs/gdb/doc/gdb.texinfo +Index: gdb-6.8.50.20090302/gdb/doc/gdb.texinfo =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/doc/gdb.texinfo 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/doc/gdb.texinfo 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/doc/gdb.texinfo 2009-04-13 22:19:50.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/doc/gdb.texinfo 2009-04-13 22:22:01.000000000 +0200 @@ -137,6 +137,7 @@ software in general. We will miss him. * Stack:: Examining the stack * Source:: Examining source files @@ -371,7 +371,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/doc/gdb.texinfo * Macros:: Preprocessor Macros * Tracepoints:: Debugging remote targets non-intrusively * Overlays:: Debugging programs that use overlays -@@ -1806,7 +1807,7 @@ To request debugging information, specif +@@ -1824,7 +1825,7 @@ To request debugging information, specif the compiler. Programs that are to be shipped to your customers are compiled with @@ -380,7 +380,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/doc/gdb.texinfo compilers are unable to handle the @samp{-g} and @samp{-O} options together. Using those compilers, you cannot generate optimized executables containing debugging information. -@@ -1815,22 +1816,7 @@ executables containing debugging informa +@@ -1833,22 +1834,7 @@ executables containing debugging informa without @samp{-O}, making it possible to debug optimized code. We recommend that you @emph{always} use @samp{-g} whenever you compile a program. You may think your program is correct, but there is no sense @@ -404,7 +404,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/doc/gdb.texinfo Older versions of the @sc{gnu} C compiler permitted a variant option @w{@samp{-gg}} for debugging information. @value{GDBN} no longer supports this -@@ -8271,6 +8257,107 @@ $1 = 1 +@@ -8406,6 +8392,107 @@ $1 = 1 $2 = (void *) 0x8049560 @end smallexample @@ -512,10 +512,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/doc/gdb.texinfo @node Macros @chapter C Preprocessor Macros -Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2loc.c +Index: gdb-6.8.50.20090302/gdb/dwarf2loc.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/dwarf2loc.c 2009-01-14 10:23:13.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/dwarf2loc.c 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/dwarf2loc.c 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/dwarf2loc.c 2009-04-13 22:22:01.000000000 +0200 @@ -31,6 +31,7 @@ #include "regcache.h" #include "objfiles.h" @@ -524,7 +524,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2loc.c #include "elf/dwarf2.h" #include "dwarf2expr.h" -@@ -147,7 +148,10 @@ dwarf_expr_frame_base (void *baton, gdb_ +@@ -150,7 +151,10 @@ dwarf_expr_frame_base (void *baton, gdb_ struct symbol *framefunc; struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; @@ -536,19 +536,19 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2loc.c /* If we found a frame-relative symbol then it was certainly within some function associated with a frame. If we can't find the frame, -Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c +Index: gdb-6.8.50.20090302/gdb/dwarf2read.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/dwarf2read.c 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c 2009-03-02 11:38:29.000000000 +0100 -@@ -46,6 +46,7 @@ - #include "hashtab.h" - #include "command.h" - #include "gdbcmd.h" -+#include "block.h" - #include "addrmap.h" +--- gdb-6.8.50.20090302.orig/gdb/dwarf2read.c 2009-04-13 22:19:50.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/dwarf2read.c 2009-04-13 22:22:41.000000000 +0200 +@@ -50,6 +50,7 @@ + #include "c-lang.h" + #include "typeprint.h" #include "top.h" ++#include "block.h" -@@ -2818,12 +2819,8 @@ process_die (struct die_info *die, struc + #include + #include "gdb_string.h" +@@ -2992,12 +2993,8 @@ process_die (struct die_info *die, struc read_file_scope (die, cu); break; case DW_TAG_subprogram: @@ -562,15 +562,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c break; case DW_TAG_lexical_block: case DW_TAG_try_block: -@@ -3089,10 +3086,25 @@ read_func_scope (struct die_info *die, s - CORE_ADDR lowpc; - CORE_ADDR highpc; - struct die_info *child_die; -- struct attribute *attr; -+ struct attribute *attr, *call_line, *call_file; - char *name; +@@ -3472,6 +3469,22 @@ read_func_scope (struct die_info *die, s CORE_ADDR baseaddr; struct block *block; + unsigned die_children; ++ struct attribute *call_line, *call_file; + int inlined_func = (die->tag == DW_TAG_inlined_subroutine); + + if (inlined_func) @@ -589,7 +585,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); -@@ -6858,6 +6870,9 @@ die_specification (struct die_info *die, +@@ -7531,6 +7544,9 @@ die_specification (struct die_info *die, *spec_cu); if (spec_attr == NULL) @@ -599,7 +595,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c return NULL; else return follow_die_ref (die, spec_attr, spec_cu); -@@ -7539,6 +7554,7 @@ new_symbol (struct die_info *die, struct +@@ -8214,6 +8230,7 @@ new_symbol (struct die_info *die, struct struct attribute *attr = NULL; struct attribute *attr2 = NULL; CORE_ADDR baseaddr; @@ -607,7 +603,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); -@@ -7566,13 +7582,17 @@ new_symbol (struct die_info *die, struct +@@ -8264,13 +8281,17 @@ new_symbol (struct die_info *die, struct SYMBOL_TYPE (sym) = type; else SYMBOL_TYPE (sym) = die_type (die, cu); @@ -627,7 +623,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c if (attr) { int file_index = DW_UNSND (attr); -@@ -7619,6 +7639,14 @@ new_symbol (struct die_info *die, struct +@@ -8317,6 +8338,14 @@ new_symbol (struct die_info *die, struct add_symbol_to_list (sym, cu->list_in_scope); } break; @@ -642,7 +638,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c case DW_TAG_variable: /* Compilation with minimal debug info may result in variables with missing type entries. Change the misleading `void' type -@@ -7666,7 +7694,14 @@ new_symbol (struct die_info *die, struct +@@ -8372,7 +8401,14 @@ new_symbol (struct die_info *die, struct } break; case DW_TAG_formal_parameter: @@ -658,10 +654,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/dwarf2read.c attr = dwarf2_attr (die, DW_AT_location, cu); if (attr) { -Index: gdb-6.8.50.20090216-cvs/gdb/frame-unwind.c +Index: gdb-6.8.50.20090302/gdb/frame-unwind.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/frame-unwind.c 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/frame-unwind.c 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/frame-unwind.c 2009-01-03 06:57:51.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/frame-unwind.c 2009-04-13 22:22:01.000000000 +0200 @@ -21,6 +21,7 @@ #include "frame.h" #include "frame-unwind.h" @@ -682,14 +678,14 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame-unwind.c return table; } -Index: gdb-6.8.50.20090216-cvs/gdb/frame.c +Index: gdb-6.8.50.20090302/gdb/frame.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/frame.c 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/frame.c 2009-03-02 11:39:34.000000000 +0100 -@@ -42,8 +42,14 @@ +--- gdb-6.8.50.20090302.orig/gdb/frame.c 2009-04-13 22:19:48.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/frame.c 2009-04-13 22:22:01.000000000 +0200 +@@ -41,8 +41,14 @@ + #include "objfiles.h" #include "exceptions.h" #include "gdbthread.h" - #include "arch-utils.h" +#include "block.h" +#include "inline-frame.h" @@ -701,7 +697,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c /* We keep a cache of stack frames, each of which is a "struct frame_info". The innermost one gets allocated (in -@@ -181,6 +187,8 @@ fprint_frame_id (struct ui_file *file, s +@@ -183,6 +189,8 @@ fprint_frame_id (struct ui_file *file, s fprint_field (file, "code", id.code_addr_p, id.code_addr); fprintf_unfiltered (file, ","); fprint_field (file, "special", id.special_addr_p, id.special_addr); @@ -710,7 +706,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c fprintf_unfiltered (file, "}"); } -@@ -195,6 +203,12 @@ fprint_frame_type (struct ui_file *file, +@@ -197,6 +205,12 @@ fprint_frame_type (struct ui_file *file, case DUMMY_FRAME: fprintf_unfiltered (file, "DUMMY_FRAME"); return; @@ -723,7 +719,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c case SIGTRAMP_FRAME: fprintf_unfiltered (file, "SIGTRAMP_FRAME"); return; -@@ -250,6 +264,18 @@ fprint_frame (struct ui_file *file, stru +@@ -249,6 +263,18 @@ fprint_frame (struct ui_file *file, stru fprintf_unfiltered (file, "}"); } @@ -742,7 +738,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c /* Return a frame uniq ID that can be used to, later, re-find the frame. */ -@@ -287,13 +313,21 @@ get_frame_id (struct frame_info *fi) +@@ -281,13 +307,21 @@ get_frame_id (struct frame_info *fi) } struct frame_id @@ -765,7 +761,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c } const struct frame_id null_frame_id; /* All zeros. */ -@@ -348,6 +382,15 @@ frame_id_p (struct frame_id l) +@@ -342,6 +376,15 @@ frame_id_p (struct frame_id l) } int @@ -781,7 +777,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c frame_id_eq (struct frame_id l, struct frame_id r) { int eq; -@@ -358,21 +401,22 @@ frame_id_eq (struct frame_id l, struct f +@@ -352,21 +395,22 @@ frame_id_eq (struct frame_id l, struct f else if (l.stack_addr != r.stack_addr) /* If .stack addresses are different, the frames are different. */ eq = 0; @@ -816,7 +812,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c if (frame_debug) { fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l="); -@@ -417,6 +461,29 @@ frame_id_inner (struct gdbarch *gdbarch, +@@ -411,6 +455,29 @@ frame_id_inner (struct gdbarch *gdbarch, if (!l.stack_addr_p || !r.stack_addr_p) /* Like NaN, any operation involving an invalid ID always fails. */ inner = 0; @@ -846,7 +842,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c else /* Only return non-zero when strictly inner than. Note that, per comment in "frame.h", there is some fuzz here. Frameless -@@ -469,8 +536,8 @@ frame_find_by_id (struct frame_id id) +@@ -463,8 +530,8 @@ frame_find_by_id (struct frame_id id) return NULL; } @@ -857,7 +853,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c { if (!this_frame->prev_pc.p) { -@@ -509,6 +576,12 @@ frame_pc_unwind (struct frame_info *this +@@ -503,6 +570,12 @@ frame_pc_unwind (struct frame_info *this } CORE_ADDR @@ -870,7 +866,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c get_frame_func (struct frame_info *this_frame) { struct frame_info *next_frame = this_frame->next; -@@ -1240,7 +1313,6 @@ frame_register_unwind_location (struct f +@@ -1226,7 +1299,6 @@ frame_register_unwind_location (struct f static struct frame_info * get_prev_frame_1 (struct frame_info *this_frame) { @@ -878,7 +874,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c struct frame_id this_id; struct gdbarch *gdbarch; -@@ -1280,6 +1352,14 @@ get_prev_frame_1 (struct frame_info *thi +@@ -1266,6 +1338,14 @@ get_prev_frame_1 (struct frame_info *thi this_frame->prev_p = 1; this_frame->stop_reason = UNWIND_NO_REASON; @@ -893,7 +889,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c /* Check that this frame's ID was valid. If it wasn't, don't try to unwind to the prev frame. Be careful to not apply this test to the sentinel frame. */ -@@ -1347,7 +1427,8 @@ get_prev_frame_1 (struct frame_info *thi +@@ -1333,7 +1413,8 @@ get_prev_frame_1 (struct frame_info *thi if (this_frame->level > 0 && gdbarch_pc_regnum (gdbarch) >= 0 && get_frame_type (this_frame) == NORMAL_FRAME @@ -903,7 +899,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c { int optimized, realnum, nrealnum; enum lval_type lval, nlval; -@@ -1376,6 +1457,17 @@ get_prev_frame_1 (struct frame_info *thi +@@ -1362,6 +1443,17 @@ get_prev_frame_1 (struct frame_info *thi } } @@ -921,7 +917,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c /* Allocate the new frame but do not wire it in to the frame chain. Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along frame->next to pull some fancy tricks (of course such code is, by -@@ -1498,7 +1590,7 @@ get_prev_frame (struct frame_info *this_ +@@ -1484,7 +1576,7 @@ get_prev_frame (struct frame_info *this_ the main function when we created the dummy frame, the dummy frame will point inside the main function. */ if (this_frame->level >= 0 @@ -930,7 +926,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c && !backtrace_past_main && inside_main_func (this_frame)) /* Don't unwind past main(). Note, this is done _before_ the -@@ -1543,8 +1635,9 @@ get_prev_frame (struct frame_info *this_ +@@ -1529,8 +1621,9 @@ get_prev_frame (struct frame_info *this_ from main returns directly to the caller of main. Since we don't stop at main, we should at least stop at the entry point of the application. */ @@ -942,7 +938,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c && inside_entry_func (this_frame)) { frame_debug_got_null_frame (this_frame, "inside entry func"); -@@ -1555,7 +1648,8 @@ get_prev_frame (struct frame_info *this_ +@@ -1541,7 +1634,8 @@ get_prev_frame (struct frame_info *this_ like a SIGSEGV or a dummy frame, and hence that NORMAL frames will never unwind a zero PC. */ if (this_frame->level > 0 @@ -952,7 +948,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME && get_frame_pc (this_frame) == 0) { -@@ -1570,7 +1664,7 @@ CORE_ADDR +@@ -1566,7 +1660,7 @@ CORE_ADDR get_frame_pc (struct frame_info *frame) { gdb_assert (frame->next != NULL); @@ -961,7 +957,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c } /* Return an address that falls within THIS_FRAME's code block. */ -@@ -1615,17 +1709,58 @@ get_frame_address_in_block (struct frame +@@ -1611,17 +1705,58 @@ get_frame_address_in_block (struct frame We check the type of NEXT_FRAME first, since it is already known; frame type is determined by the unwinder, and since we have THIS_FRAME we've already selected an unwinder for @@ -1024,7 +1020,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c /* If FRAME is not the innermost frame, that normally means that FRAME->pc points at the return instruction (which is *after* the call instruction), and we want to get the line containing the -@@ -1635,15 +1770,8 @@ pc_notcurrent (struct frame_info *frame) +@@ -1631,15 +1766,8 @@ pc_notcurrent (struct frame_info *frame) PC and such a PC indicates the current (rather than next) instruction/line, consequently, for such cases, want to get the line containing fi->pc. */ @@ -1042,10 +1038,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.c } /* Per "frame.h", return the ``address'' of the frame. Code should -Index: gdb-6.8.50.20090216-cvs/gdb/frame.h +Index: gdb-6.8.50.20090302/gdb/frame.h =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/frame.h 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/frame.h 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/frame.h 2009-02-05 18:28:20.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/frame.h 2009-04-13 22:22:01.000000000 +0200 @@ -34,6 +34,9 @@ frame_unwind_WHAT...(): Unwind THIS frame's WHAT from the NEXT frame. @@ -1099,7 +1095,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.h /* In a signal handler, various OSs handle this in various ways. The main thing is that the frame may be far from normal. */ SIGTRAMP_FRAME, -@@ -347,6 +365,7 @@ extern CORE_ADDR get_frame_base (struct +@@ -345,6 +363,7 @@ extern CORE_ADDR get_frame_base (struct instead, since that avoids the bug. */ extern struct frame_id get_frame_id (struct frame_info *fi); @@ -1107,10 +1103,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/frame.h extern struct frame_id frame_unwind_id (struct frame_info *next_frame); /* Assuming that a frame is `normal', return its base-address, or 0 if -Index: gdb-6.8.50.20090216-cvs/gdb/gdbthread.h +Index: gdb-6.8.50.20090302/gdb/gdbthread.h =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/gdbthread.h 2009-01-19 10:30:36.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/gdbthread.h 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/gdbthread.h 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/gdbthread.h 2009-04-13 22:22:01.000000000 +0200 @@ -83,6 +83,13 @@ struct thread_info This is how we know when we step into a subroutine call, and how to set the frame for the breakpoint used to step out. */ @@ -1125,11 +1121,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/gdbthread.h int current_line; struct symtab *current_symtab; -Index: gdb-6.8.50.20090216-cvs/gdb/infcall.c +Index: gdb-6.8.50.20090302/gdb/infcall.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/infcall.c 2009-02-16 11:31:31.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/infcall.c 2009-03-02 11:38:29.000000000 +0100 -@@ -841,15 +841,8 @@ When the function is done executing, GDB +--- gdb-6.8.50.20090302.orig/gdb/infcall.c 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/infcall.c 2009-04-13 22:22:01.000000000 +0200 +@@ -898,15 +898,8 @@ The program being debugged exited while if (unwind_on_signal_p) { @@ -1147,10 +1143,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infcall.c /* FIXME: Insert a bunch of wrap_here; name can be very long if it's a C++ name with arguments and stuff. */ -Index: gdb-6.8.50.20090216-cvs/gdb/infcmd.c +Index: gdb-6.8.50.20090302/gdb/infcmd.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/infcmd.c 2009-02-16 11:04:44.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/infcmd.c 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/infcmd.c 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/infcmd.c 2009-04-13 22:22:01.000000000 +0200 @@ -52,6 +52,7 @@ #include "cli/cli-decode.h" #include "gdbthread.h" @@ -1159,7 +1155,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infcmd.c /* Functions exported for general use, in inferior.h: */ -@@ -739,6 +740,17 @@ Can't resume all threads and specify pro +@@ -744,6 +745,17 @@ Can't resume all threads and specify pro continue_1 (all_threads); } @@ -1177,7 +1173,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infcmd.c /* Step until outside of current statement. */ static void -@@ -916,6 +928,20 @@ step_once (int skip_subroutines, int sin +@@ -921,6 +933,20 @@ step_once (int skip_subroutines, int sin THREAD is set. */ struct thread_info *tp = inferior_thread (); clear_proceed_status (); @@ -1198,7 +1194,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infcmd.c frame = get_current_frame (); tp->step_frame_id = get_frame_id (frame); -@@ -1168,6 +1194,7 @@ until_next_command (int from_tty) +@@ -1173,6 +1199,7 @@ until_next_command (int from_tty) clear_proceed_status (); frame = get_current_frame (); @@ -1206,7 +1202,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infcmd.c /* Step until either exited from this function or greater than the current line (if in symbolic section) or pc (if -@@ -1195,7 +1222,6 @@ until_next_command (int from_tty) +@@ -1200,7 +1227,6 @@ until_next_command (int from_tty) } tp->step_over_calls = STEP_OVER_ALL; @@ -1214,7 +1210,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infcmd.c tp->step_multi = 0; /* Only one call to proceed */ -@@ -1528,6 +1554,37 @@ finish_command (char *arg, int from_tty) +@@ -1533,6 +1559,37 @@ finish_command (char *arg, int from_tty) clear_proceed_status (); @@ -1252,11 +1248,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infcmd.c /* Find the function we will return from. */ function = find_pc_function (get_frame_pc (get_selected_frame (NULL))); -Index: gdb-6.8.50.20090216-cvs/gdb/inferior.h +Index: gdb-6.8.50.20090302/gdb/inferior.h =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/inferior.h 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/inferior.h 2009-03-02 11:38:29.000000000 +0100 -@@ -255,6 +255,9 @@ extern void error_is_running (void); +--- gdb-6.8.50.20090302.orig/gdb/inferior.h 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/inferior.h 2009-04-13 22:22:01.000000000 +0200 +@@ -259,6 +259,9 @@ extern void error_is_running (void); /* Calls error_is_running if the current thread is running. */ extern void ensure_not_running (void); @@ -1266,10 +1262,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/inferior.h /* From infcmd.c */ extern void tty_command (char *, int); -Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c +Index: gdb-6.8.50.20090302/gdb/infrun.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/infrun.c 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/infrun.c 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/infrun.c 2009-04-13 22:19:49.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/infrun.c 2009-04-13 22:22:01.000000000 +0200 @@ -48,6 +48,7 @@ #include "gdb_assert.h" #include "mi/mi-common.h" @@ -1287,7 +1283,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c /* Command list pointer for the "stop" placeholder. */ -@@ -1143,6 +1144,8 @@ a command like `return' or `jump' to con +@@ -1151,6 +1152,8 @@ a command like `return' or `jump' to con step = 0; } @@ -1296,7 +1292,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c if (debug_displaced && use_displaced_stepping (gdbarch) && tp->trap_expected) -@@ -1184,6 +1187,7 @@ clear_proceed_status_thread (struct thre +@@ -1192,6 +1195,7 @@ clear_proceed_status_thread (struct thre tp->step_range_start = 0; tp->step_range_end = 0; tp->step_frame_id = null_frame_id; @@ -1304,7 +1300,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c tp->step_over_calls = STEP_OVER_UNDEBUGGABLE; tp->stop_requested = 0; -@@ -1523,6 +1527,9 @@ init_wait_for_inferior (void) +@@ -1536,6 +1540,9 @@ init_wait_for_inferior (void) init_infwait_state (); displaced_step_clear (); @@ -1314,7 +1310,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c } -@@ -1578,7 +1585,7 @@ struct execution_control_state +@@ -1591,7 +1598,7 @@ struct execution_control_state int wait_some_more; }; @@ -1323,7 +1319,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c void handle_inferior_event (struct execution_control_state *ecs); -@@ -1936,10 +1943,21 @@ fetch_inferior_event (void *client_data) +@@ -1975,10 +1982,21 @@ fetch_inferior_event (void *client_data) display_gdb_prompt (0); } @@ -1346,7 +1342,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c init_execution_control_state (struct execution_control_state *ecs) { ecs->random_signal = 0; -@@ -1950,16 +1968,10 @@ init_execution_control_state (struct exe +@@ -1989,16 +2007,10 @@ init_execution_control_state (struct exe void init_thread_stepping_state (struct thread_info *tss) { @@ -1363,8 +1359,8 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c } /* Return the cached copy of the last pid/waitstatus returned by -@@ -2129,6 +2141,22 @@ ensure_not_running (void) - error_is_running (); +@@ -2212,6 +2224,22 @@ deal_with_syscall_event (struct executio + } } +static int @@ -1386,7 +1382,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c /* Given an execution control state that has been freshly filled in by an event from the inferior, figure out what it means and take appropriate action. */ -@@ -2825,6 +2853,12 @@ targets should add new threads to the th +@@ -2906,6 +2934,12 @@ targets should add new threads to the th ecs->random_signal = 0; stopped_by_random_signal = 0; @@ -1399,7 +1395,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP && ecs->event_thread->trap_expected && gdbarch_single_step_through_delay_p (current_gdbarch) -@@ -3057,8 +3091,8 @@ process_event_stop_test: +@@ -3138,8 +3172,8 @@ process_event_stop_test: && ecs->event_thread->stop_signal != TARGET_SIGNAL_0 && (ecs->event_thread->step_range_start <= stop_pc && stop_pc < ecs->event_thread->step_range_end) @@ -1410,7 +1406,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c && ecs->event_thread->step_resume_breakpoint == NULL) { /* The inferior is about to take a signal that will take it -@@ -3449,10 +3483,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( +@@ -3525,10 +3559,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( NOTE: frame_id_eq will never report two invalid frame IDs as being equal, so to get into this block, both the current and previous frame must have valid frame IDs. */ @@ -1424,7 +1420,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c || execution_direction == EXEC_REVERSE)) { CORE_ADDR real_stop_pc; -@@ -3695,6 +3729,82 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( +@@ -3771,6 +3805,82 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( return; } @@ -1507,7 +1503,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c if ((stop_pc == stop_pc_sal.pc) && (ecs->event_thread->current_line != stop_pc_sal.line || ecs->event_thread->current_symtab != stop_pc_sal.symtab)) -@@ -3720,9 +3830,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( +@@ -3796,9 +3906,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( ecs->event_thread->step_range_start = stop_pc_sal.pc; ecs->event_thread->step_range_end = stop_pc_sal.end; @@ -1518,7 +1514,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n"); -@@ -4968,6 +5076,7 @@ struct inferior_status +@@ -5050,6 +5158,7 @@ struct inferior_status CORE_ADDR step_range_start; CORE_ADDR step_range_end; struct frame_id step_frame_id; @@ -1526,7 +1522,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c enum step_over_calls_kind step_over_calls; CORE_ADDR step_resume_break_address; int stop_after_trap; -@@ -4997,6 +5106,7 @@ save_inferior_status (void) +@@ -5079,6 +5188,7 @@ save_inferior_status (void) inf_status->step_range_start = tp->step_range_start; inf_status->step_range_end = tp->step_range_end; inf_status->step_frame_id = tp->step_frame_id; @@ -1534,7 +1530,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c inf_status->step_over_calls = tp->step_over_calls; inf_status->stop_after_trap = stop_after_trap; inf_status->stop_soon = inf->stop_soon; -@@ -5050,6 +5160,7 @@ restore_inferior_status (struct inferior +@@ -5132,6 +5242,7 @@ restore_inferior_status (struct inferior tp->step_range_start = inf_status->step_range_start; tp->step_range_end = inf_status->step_range_end; tp->step_frame_id = inf_status->step_frame_id; @@ -1542,10 +1538,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/infrun.c tp->step_over_calls = inf_status->step_over_calls; stop_after_trap = inf_status->stop_after_trap; inf->stop_soon = inf_status->stop_soon; -Index: gdb-6.8.50.20090216-cvs/gdb/inline-frame.c +Index: gdb-6.8.50.20090302/gdb/inline-frame.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/inline-frame.c 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/inline-frame.c 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,382 @@ +/* Inline frame unwinder for GDB. + @@ -1929,10 +1925,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/inline-frame.c + + return inline_count; +} -Index: gdb-6.8.50.20090216-cvs/gdb/inline-frame.h +Index: gdb-6.8.50.20090302/gdb/inline-frame.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/inline-frame.h 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/inline-frame.h 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,62 @@ +/* Definitions for inline frame support. + @@ -1996,11 +1992,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/inline-frame.h +int frame_inlined_callees (struct frame_info *this_frame); + +#endif /* !defined (INLINE_FRAME_H) */ -Index: gdb-6.8.50.20090216-cvs/gdb/minsyms.c +Index: gdb-6.8.50.20090302/gdb/minsyms.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/minsyms.c 2009-02-16 11:31:31.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/minsyms.c 2009-03-02 11:38:29.000000000 +0100 -@@ -762,7 +762,7 @@ prim_record_minimal_symbol_and_info (con +--- gdb-6.8.50.20090302.orig/gdb/minsyms.c 2009-04-13 22:19:49.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/minsyms.c 2009-04-13 22:22:01.000000000 +0200 +@@ -795,7 +795,7 @@ prim_record_minimal_symbol_and_info (con if (msym_bunch_index == BUNCH_SIZE) { @@ -2009,10 +2005,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/minsyms.c msym_bunch_index = 0; new->next = msym_bunch; msym_bunch = new; -Index: gdb-6.8.50.20090216-cvs/gdb/s390-tdep.c +Index: gdb-6.8.50.20090302/gdb/s390-tdep.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/s390-tdep.c 2009-01-07 09:45:04.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/s390-tdep.c 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/s390-tdep.c 2009-02-22 02:02:19.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/s390-tdep.c 2009-04-13 22:22:01.000000000 +0200 @@ -1182,6 +1182,7 @@ s390_prologue_frame_unwind_cache (struct CORE_ADDR prev_sp; int frame_pointer; @@ -2046,19 +2042,19 @@ Index: gdb-6.8.50.20090216-cvs/gdb/s390-tdep.c || get_frame_type (get_next_frame (this_frame)) != NORMAL_FRAME)) { /* See the comment in s390_in_function_epilogue_p on why this is -Index: gdb-6.8.50.20090216-cvs/gdb/stack.c +Index: gdb-6.8.50.20090302/gdb/stack.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/stack.c 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/stack.c 2009-03-02 11:40:00.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/stack.c 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/stack.c 2009-04-13 22:22:01.000000000 +0200 @@ -45,6 +45,7 @@ #include "valprint.h" #include "gdbthread.h" #include "cp-support.h" +#include "inline-frame.h" - #include "arch-utils.h" #include "gdb_assert.h" -@@ -99,6 +100,30 @@ print_stack_frame_stub (void *args) + #include +@@ -98,6 +99,30 @@ print_stack_frame_stub (void *args) return 0; } @@ -2089,7 +2085,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c /* Show or print a stack frame FRAME briefly. The output is format according to PRINT_LEVEL and PRINT_WHAT printing the frame's relative level, function name, argument list, and file name and -@@ -554,7 +579,7 @@ print_frame_info (struct frame_info *fra +@@ -538,7 +563,7 @@ print_frame_info (struct frame_info *fra { int done = 0; int mid_statement = ((print_what == SRC_LINE) @@ -2098,16 +2094,16 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c if (annotation_level) done = identify_source_line (sal.symtab, sal.line, mid_statement, -@@ -612,7 +637,7 @@ print_frame (struct frame_info *frame, i - stb = ui_out_stream_new (uiout); - old_chain = make_cleanup_ui_out_stream_delete (stb); +@@ -591,7 +616,7 @@ find_frame_funname (struct frame_info *f + *funname = NULL; + *funlang = language_unknown; - func = find_pc_function (get_frame_address_in_block (frame)); + func = get_frame_function (frame); if (func) { /* In certain pathological cases, the symtabs give the wrong -@@ -633,8 +658,13 @@ print_frame (struct frame_info *frame, i +@@ -612,8 +637,13 @@ find_frame_funname (struct frame_info *f changed (and we'll create a find_pc_minimal_function or some such). */ @@ -2123,7 +2119,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c if (msymbol != NULL && (SYMBOL_VALUE_ADDRESS (msymbol) -@@ -691,7 +721,7 @@ print_frame (struct frame_info *frame, i +@@ -687,7 +717,7 @@ print_frame (struct frame_info *frame, i } get_user_print_options (&opts); if (opts.addressprint) @@ -2132,7 +2128,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c || print_what == LOC_AND_ADDRESS) { annotate_frame_address (); -@@ -871,8 +901,16 @@ parse_frame_specification_1 (const char +@@ -867,8 +897,16 @@ parse_frame_specification_1 (const char { if (frame_id_eq (id, get_frame_id (fid))) { @@ -2151,7 +2147,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c return fid; } } -@@ -1006,8 +1044,10 @@ frame_info (char *addr_exp, int from_tty +@@ -1002,8 +1040,10 @@ frame_info (char *addr_exp, int from_tty printf_filtered (_(" Outermost frame: %s\n"), frame_stop_reason_string (reason)); } @@ -2164,7 +2160,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c { printf_filtered (" called by frame at "); fputs_filtered (paddress (get_frame_base (calling_frame_info)), -@@ -1471,7 +1511,9 @@ print_frame_local_vars (struct frame_inf +@@ -1465,7 +1505,9 @@ print_frame_local_vars (struct frame_inf if (print_block_frame_locals (block, frame, num_tabs, stream)) values_printed = 1; /* After handling the function's top-level block, stop. Don't @@ -2175,7 +2171,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c if (BLOCK_FUNCTION (block)) break; block = BLOCK_SUPERBLOCK (block); -@@ -1544,7 +1586,9 @@ print_frame_label_vars (struct frame_inf +@@ -1536,7 +1578,9 @@ print_frame_label_vars (struct frame_inf return; /* After handling the function's top-level block, stop. Don't @@ -2186,7 +2182,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c if (BLOCK_FUNCTION (block)) break; block = BLOCK_SUPERBLOCK (block); -@@ -1814,6 +1858,9 @@ return_command (char *retval_exp, int fr +@@ -1806,6 +1850,9 @@ return_command (char *retval_exp, int fr thisframe = get_selected_frame ("No selected frame."); thisfun = get_frame_function (thisframe); @@ -2196,26 +2192,27 @@ Index: gdb-6.8.50.20090216-cvs/gdb/stack.c /* Compute the return value. If the computation triggers an error, let it bail. If the return type can't be handled, set RETURN_VALUE to NULL, and QUERY_PREFIX to an informational -Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c +Index: gdb-6.8.50.20090302/gdb/symtab.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/symtab.c 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/symtab.c 2009-03-02 11:38:29.000000000 +0100 -@@ -1373,10 +1373,13 @@ lookup_symbol_aux_local (const char *nam - sym = lookup_symbol_aux_block (name, linkage_name, block, domain); +--- gdb-6.8.50.20090302.orig/gdb/symtab.c 2009-04-13 22:19:49.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/symtab.c 2009-04-13 22:22:01.000000000 +0200 +@@ -1417,11 +1417,14 @@ lookup_symbol_aux_local (const char *nam + sym = lookup_symbol_aux_block (name, linkage_name, block_iterator, domain); if (sym != NULL) return sym; + + if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block)) + break; - block = BLOCK_SUPERBLOCK (block); + + block_iterator = BLOCK_SUPERBLOCK (block_iterator); } -- /* We've reached the static block without finding a result. */ +- /* We've reached the global block without finding a result. */ + /* We've reached the edge of the function without finding a result. */ return NULL; } -@@ -2605,6 +2608,7 @@ find_function_start_sal (struct symbol * +@@ -2678,6 +2681,7 @@ find_function_start_sal (struct symbol * CORE_ADDR pc; struct symtab_and_line sal; @@ -2223,7 +2220,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c pc = BLOCK_START (block); fixup_symbol_section (sym, objfile); -@@ -2643,6 +2647,25 @@ find_function_start_sal (struct symbol * +@@ -2716,6 +2720,25 @@ find_function_start_sal (struct symbol * sal.pc = pc; @@ -2249,7 +2246,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c return sal; } -@@ -3665,6 +3688,24 @@ add_macro_name (const char *name, const +@@ -3738,6 +3761,24 @@ add_macro_name (const char *name, const datum->text, datum->word); } @@ -2274,7 +2271,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c char ** default_make_symbol_completion_list (char *text, char *word) { -@@ -3677,9 +3718,9 @@ default_make_symbol_completion_list (cha +@@ -3750,9 +3791,9 @@ default_make_symbol_completion_list (cha struct partial_symtab *ps; struct minimal_symbol *msymbol; struct objfile *objfile; @@ -2286,7 +2283,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c struct partial_symbol **psym; /* The symbol we are completing on. Points in same buffer as text. */ char *sym_text; -@@ -3789,41 +3830,43 @@ default_make_symbol_completion_list (cha +@@ -3862,41 +3903,43 @@ default_make_symbol_completion_list (cha } /* Search upwards from currently selected frame (so that we can @@ -2361,7 +2358,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c /* Go through the symtabs and check the externs and statics for symbols which match. */ -@@ -3842,9 +3885,6 @@ default_make_symbol_completion_list (cha +@@ -3915,9 +3958,6 @@ default_make_symbol_completion_list (cha { QUIT; b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); @@ -2371,7 +2368,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c ALL_BLOCK_SYMBOLS (b, iter, sym) { COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); -@@ -4311,6 +4351,25 @@ skip_prologue_using_sal (CORE_ADDR func_ +@@ -4384,6 +4424,25 @@ skip_prologue_using_sal (CORE_ADDR func_ line mark the prologue -> body transition. */ if (sal.line >= prologue_sal.line) break; @@ -2397,11 +2394,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.c /* The case in which compiler's optimizer/scheduler has moved instructions into the prologue. We look ahead in the function looking for address ranges whose -Index: gdb-6.8.50.20090216-cvs/gdb/symtab.h +Index: gdb-6.8.50.20090302/gdb/symtab.h =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/symtab.h 2009-02-09 10:56:03.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/symtab.h 2009-03-02 11:38:29.000000000 +0100 -@@ -556,9 +556,18 @@ struct symbol +--- gdb-6.8.50.20090302.orig/gdb/symtab.h 2009-04-13 22:19:47.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/symtab.h 2009-04-13 22:22:01.000000000 +0200 +@@ -562,9 +562,18 @@ struct symbol unsigned is_argument : 1; @@ -2423,7 +2420,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.h unsigned short line; -@@ -589,6 +598,7 @@ struct symbol +@@ -595,6 +604,7 @@ struct symbol #define SYMBOL_DOMAIN(symbol) (symbol)->domain #define SYMBOL_CLASS(symbol) (symbol)->aclass #define SYMBOL_IS_ARGUMENT(symbol) (symbol)->is_argument @@ -2431,10 +2428,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/symtab.h #define SYMBOL_TYPE(symbol) (symbol)->type #define SYMBOL_LINE(symbol) (symbol)->line #define SYMBOL_SYMTAB(symbol) (symbol)->symtab -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.base/break.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.base/break.exp =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/testsuite/gdb.base/break.exp 2009-01-20 10:17:27.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.base/break.exp 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.base/break.exp 2009-01-19 20:05:01.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.base/break.exp 2009-04-13 22:22:01.000000000 +0200 @@ -880,6 +880,13 @@ gdb_expect { # marker4() is defined at line 46 when compiled with -DPROTOTYPES pass "run until breakpoint set at small function, optimized file (line bp_location14)" @@ -2449,10 +2446,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.base/break.exp -re ".*$gdb_prompt " { fail "run until breakpoint set at small function, optimized file" } -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.cp/annota2.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.cp/annota2.exp =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/testsuite/gdb.cp/annota2.exp 2009-01-07 09:45:17.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.cp/annota2.exp 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.cp/annota2.exp 2009-01-03 06:58:04.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.cp/annota2.exp 2009-04-13 22:22:01.000000000 +0200 @@ -119,10 +119,11 @@ gdb_expect { # continue until exit # this will test: @@ -2466,10 +2463,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.cp/annota2.exp { pass "continue until exit" } -re ".*$gdb_prompt$" { fail "continue to exit" } timeout { fail "continue to exit (timeout)" } -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-bt.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,47 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + @@ -2518,10 +2515,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-bt.c + + return 0; +} -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-bt.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,63 @@ +# Copyright 2008 Free Software Foundation, Inc. + @@ -2586,10 +2583,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-bt.exp +gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (3)" +gdb_test "up" "#2 .*func2.*" "up from func1 (3)" +gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (3)" -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-cmds.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,85 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + @@ -2676,10 +2673,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-cmds.c + + return 0; +} -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-cmds.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,279 @@ +# Copyright 2008 Free Software Foundation, Inc. + @@ -2960,10 +2957,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-cmds.exp +gdb_test "info frame" ".*inlined into frame.*" "outer_inline2 inlined" +gdb_test "up" "#4 main.*" "up from outer_inline2" +gdb_test "info frame" ".*\n caller of frame.*" "main not inlined" -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-locals.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,52 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + @@ -3017,10 +3014,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-locals.c + + return 0; +} -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-locals.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,118 @@ +# Copyright 2008 Free Software Foundation, Inc. + @@ -3140,10 +3137,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-locals.exp +} + +gdb_test "print array\[0\]" "\\\$$decimal = 184" "print local (3)" -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-markers.c +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-02 11:38:29.000000000 +0100 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c 2009-04-13 22:22:01.000000000 +0200 @@ -0,0 +1,36 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + @@ -3181,11 +3178,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/inline-markers.c +{ + inlined_fn (); /* inlined */ +} -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/lib/gdb.exp +Index: gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/testsuite/lib/gdb.exp 2009-02-16 11:04:46.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/lib/gdb.exp 2009-03-02 11:38:29.000000000 +0100 -@@ -1452,6 +1452,37 @@ proc skip_hp_tests {} { +--- gdb-6.8.50.20090302.orig/gdb/testsuite/lib/gdb.exp 2009-04-13 22:19:50.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp 2009-04-13 22:22:01.000000000 +0200 +@@ -1474,6 +1474,37 @@ proc skip_hp_tests {} { return $skip_hp } @@ -3223,11 +3220,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/lib/gdb.exp set compiler_info "unknown" set gcc_compiled 0 set hp_cc_compiler 0 -Index: gdb-6.8.50.20090216-cvs/gdb/valops.c +Index: gdb-6.8.50.20090302/gdb/valops.c =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/valops.c 2009-02-09 10:56:04.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/valops.c 2009-03-02 11:38:29.000000000 +0100 -@@ -1009,7 +1009,7 @@ value_of_variable (struct symbol *var, s +--- gdb-6.8.50.20090302.orig/gdb/valops.c 2009-04-13 22:19:48.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/valops.c 2009-04-13 22:22:01.000000000 +0200 +@@ -1072,7 +1072,7 @@ value_of_variable (struct symbol *var, s frame = block_innermost_frame (b); if (!frame) { @@ -3236,11 +3233,11 @@ Index: gdb-6.8.50.20090216-cvs/gdb/valops.c && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))) error (_("No frame is currently executing in block %s."), SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))); -Index: gdb-6.8.50.20090216-cvs/gdb/Makefile.in +Index: gdb-6.8.50.20090302/gdb/Makefile.in =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/Makefile.in 2009-03-02 11:37:57.000000000 +0100 -+++ gdb-6.8.50.20090216-cvs/gdb/Makefile.in 2009-03-02 11:38:29.000000000 +0100 -@@ -634,6 +634,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr +--- gdb-6.8.50.20090302.orig/gdb/Makefile.in 2009-04-13 22:19:49.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/Makefile.in 2009-04-13 22:22:01.000000000 +0200 +@@ -667,6 +667,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr inf-loop.c \ infcall.c \ infcmd.c inflow.c infrun.c \ @@ -3248,7 +3245,7 @@ Index: gdb-6.8.50.20090216-cvs/gdb/Makefile.in interps.c \ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ language.c linespec.c \ -@@ -804,6 +805,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $ +@@ -839,6 +840,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $ user-regs.o \ frame.o frame-unwind.o doublest.o \ frame-base.o \ @@ -3256,10 +3253,10 @@ Index: gdb-6.8.50.20090216-cvs/gdb/Makefile.in gnu-v2-abi.o gnu-v3-abi.o cp-abi.o cp-support.o \ cp-namespace.o \ reggroups.o regset.o \ -Index: gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/Makefile.in +Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/Makefile.in =================================================================== ---- gdb-6.8.50.20090216-cvs.orig/gdb/testsuite/gdb.opt/Makefile.in 2008-04-18 11:24:27.000000000 +0200 -+++ gdb-6.8.50.20090216-cvs/gdb/testsuite/gdb.opt/Makefile.in 2009-03-02 11:38:29.000000000 +0100 +--- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/Makefile.in 2008-04-18 01:06:54.000000000 +0200 ++++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/Makefile.in 2009-04-13 22:22:01.000000000 +0200 @@ -1,7 +1,7 @@ VPATH = @srcdir@ srcdir = @srcdir@ diff --git a/gdb-6.8-quit-never-aborts.patch b/gdb-6.8-quit-never-aborts.patch new file mode 100644 index 0000000..f3214cc --- /dev/null +++ b/gdb-6.8-quit-never-aborts.patch @@ -0,0 +1,72 @@ +We may abort the process of detaching threads with multiple SIGINTs - which are +being sent during a testcase terminating its child GDB. + +Some of the threads may not be properly PTRACE_DETACHed which hurts if they +should have been detached with SIGSTOP (as they are accidentally left running +on the debugger termination). + +Index: gdb-6.8.50.20081128/gdb/defs.h +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/defs.h 2008-11-27 10:23:01.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/defs.h 2008-12-06 21:49:32.000000000 +0100 +@@ -155,6 +155,7 @@ extern char *gdb_sysroot; + extern char *debug_file_directory; + + extern int quit_flag; ++extern int quit_flag_cleanup; + extern int immediate_quit; + extern int sevenbit_strings; + +@@ -168,7 +169,7 @@ extern void quit (void); + needed. */ + + #define QUIT { \ +- if (quit_flag) quit (); \ ++ if (quit_flag && !quit_flag_cleanup) quit (); \ + if (deprecated_interactive_hook) deprecated_interactive_hook (); \ + } + +Index: gdb-6.8.50.20081128/gdb/event-top.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/event-top.c 2008-12-04 10:34:31.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/event-top.c 2008-12-06 21:49:07.000000000 +0100 +@@ -939,7 +939,7 @@ async_request_quit (gdb_client_data arg) + is no reason to call quit again here, unless immediate_quit is + set.*/ + +- if (quit_flag || immediate_quit) ++ if ((quit_flag || immediate_quit) && !quit_flag_cleanup) + quit (); + } + +Index: gdb-6.8.50.20081128/gdb/top.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/top.c 2008-12-04 10:23:12.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/top.c 2008-12-06 21:49:07.000000000 +0100 +@@ -1299,7 +1299,9 @@ quit_force (char *args, int from_tty) + qt.args = args; + qt.from_tty = from_tty; + +- /* We want to handle any quit errors and exit regardless. */ ++ /* We want to handle any quit errors and exit regardless but we should never ++ get user-interrupted to properly detach the inferior. */ ++ quit_flag_cleanup = 1; + catch_errors (quit_target, &qt, + "Quitting: ", RETURN_MASK_ALL); + +Index: gdb-6.8.50.20081128/gdb/utils.c +=================================================================== +--- gdb-6.8.50.20081128.orig/gdb/utils.c 2008-12-04 10:31:00.000000000 +0100 ++++ gdb-6.8.50.20081128/gdb/utils.c 2008-12-06 21:49:07.000000000 +0100 +@@ -114,6 +114,11 @@ int job_control; + + int quit_flag; + ++/* Nonzero means we are already processing the quitting cleanups and we should ++ no longer get aborted. */ ++ ++int quit_flag_cleanup; ++ + /* Nonzero means quit immediately if Control-C is typed now, rather + than waiting until QUIT is executed. Be careful in setting this; + code which executes with immediate_quit set has to be very careful diff --git a/gdb-6.8-sparc64-silence-memcpy-check.patch b/gdb-6.8-sparc64-silence-memcpy-check.patch new file mode 100644 index 0000000..cf97c2f --- /dev/null +++ b/gdb-6.8-sparc64-silence-memcpy-check.patch @@ -0,0 +1,11 @@ +diff -up gdb-6.8/gdb/sparc-tdep.c.BAD gdb-6.8/gdb/sparc-tdep.c +--- gdb-6.8/gdb/sparc-tdep.c.BAD 2008-05-15 16:12:58.000000000 -0500 ++++ gdb-6.8/gdb/sparc-tdep.c 2008-05-15 16:13:41.000000000 -0500 +@@ -1122,6 +1122,7 @@ sparc32_store_return_value (struct type + if (sparc_floating_p (type)) + { + /* Floating return values. */ ++ len = (len <= 8) ? len : 8; + memcpy (buf, valbuf, len); + regcache_cooked_write (regcache, SPARC_F0_REGNUM, buf); + if (len > 4) diff --git a/gdb-6.8-tui-singlebinary.patch b/gdb-6.8-tui-singlebinary.patch new file mode 100644 index 0000000..f3f457c --- /dev/null +++ b/gdb-6.8-tui-singlebinary.patch @@ -0,0 +1,24 @@ +Provide `gdb --tui' functionality for the hardlink `gdbtui'. + +--- ./gdb/gdb.c 1 Jan 2008 22:53:09 -0000 1.6 ++++ ./gdb/gdb.c 20 Jun 2008 08:02:57 -0000 +@@ -30,5 +30,19 @@ main (int argc, char **argv) + args.argv = argv; + args.use_windows = 0; + args.interpreter_p = INTERP_CONSOLE; ++ ++ if (argv[0]) ++ { ++ char *s; ++ ++ s = strrchr (argv[0], '/'); ++ if (s) ++ s++; ++ else ++ s = argv[0]; ++ if (strcmp (s, "gdbtui") == 0) ++ args.interpreter_p = INTERP_TUI; ++ } ++ + return gdb_main (&args); + } diff --git a/gdb-6.8-watchpoint-conditionals-test.patch b/gdb-6.8-watchpoint-conditionals-test.patch new file mode 100644 index 0000000..f21d797 --- /dev/null +++ b/gdb-6.8-watchpoint-conditionals-test.patch @@ -0,0 +1,78 @@ +For: +http://sourceware.org/ml/gdb-patches/2008-04/msg00379.html +http://sourceware.org/ml/gdb-cvs/2008-04/msg00104.html + +--- /dev/null 2008-11-04 06:31:10.599601840 +0100 ++++ gdb-6.8/gdb/testsuite/gdb.base/watchpoint-cond.exp 2008-11-04 06:43:29.000000000 +0100 +@@ -0,0 +1,37 @@ ++# Copyright 2008 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 3 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, see . ++ ++set testfile watchpoint-cond ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if { [runto_main] < 0 } { ++ untested watchpoint-cond ++ return -1 ++} ++ ++gdb_test "watch i if i < 20" "atchpoint \[0-9\]+: i" ++gdb_test "cont" "atchpoint \[0-9\]+: i.*Old value = 20.*New value = 19.*" +--- /dev/null 2008-11-04 06:31:10.599601840 +0100 ++++ gdb-6.8/gdb/testsuite/gdb.base/watchpoint-cond.c 2008-11-04 06:42:48.000000000 +0100 +@@ -0,0 +1,31 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . ++ ++ Please email any bugs, comments, and/or additions to this file to: ++ bug-gdb@prep.ai.mit.edu */ ++ ++int ++main (int argc, char **argv) ++{ ++ static int i = 0; /* `static' to start initialized. */ ++ int j = 2; ++ ++ for (j = 0; j < 30; j++) ++ i = 30 - j; ++ ++ return 0; ++} diff --git a/gdb-6.8.50.20090216-cvs.tar.bz2 b/gdb-6.8.50.20090216-cvs.tar.bz2 deleted file mode 100644 index 42192ec..0000000 --- a/gdb-6.8.50.20090216-cvs.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6c93d11f9695a67fb9b0c26a3fef5afeafdd4b9a4863b0d08514c2548b47fee7 -size 15831628 diff --git a/gdb-6.8.50.20090302.tar.bz2 b/gdb-6.8.50.20090302.tar.bz2 new file mode 100644 index 0000000..da968c5 --- /dev/null +++ b/gdb-6.8.50.20090302.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72ff388b7cf0122c076d2bad4314dcedf289c32935e20ee13d9f16cb85a6a05f +size 17361503 diff --git a/gdb-archer.patch b/gdb-archer.patch new file mode 100644 index 0000000..408bead --- /dev/null +++ b/gdb-archer.patch @@ -0,0 +1,47439 @@ +http://sourceware.org/gdb/wiki/ProjectArcher +http://sourceware.org/gdb/wiki/ArcherBranchManagement + +GIT snapshot: +commit d1fee5066408a09423621d1ebc64e6d3e248ed08 + +branch `archer' - the merge of branches: +archer-jankratochvil-merge-expr + archer-keiths-expr-cumulative + (archer-swagiaal-using-directive) +archer-jankratochvil-misc +archer-jankratochvil-python + archer-jankratochvil-type-refcount + archer-tromey-python +archer-jankratochvil-vla + archer-jankratochvil-type-refcount +archer-pmuldoon-exception-rewind-master +archer-sergio-catch-syscall +archer-tromey-charset +archer-tromey-delayed-symfile + + +diff --git a/bfd/po/es.po b/bfd/po/es.po +index 9f2ec21..e4410d7 100644 +--- a/bfd/po/es.po ++++ b/bfd/po/es.po +@@ -1,13 +1,14 @@ +-# Mensajes en español para bfd 2.17.90. +-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +-# Cristian Othón Martínez Vera , 2002, 2003, 2004, 2005, 2006, 2007 ++# Mensajes en español para bfd 2.18.90. ++# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ++# This file is distributed under the same license as the binutils package. ++# Cristian Othón Martínez Vera , 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + # + msgid "" + msgstr "" +-"Project-Id-Version: bfd 2.17.90\n" +-"Report-Msgid-Bugs-To: \n" +-"POT-Creation-Date: 2007-08-06 16:21-0400\n" +-"PO-Revision-Date: 2007-09-08 08:57-0500\n" ++"Project-Id-Version: bfd 2.18.90\n" ++"Report-Msgid-Bugs-To: bug-binutils@gnu.org\n" ++"POT-Creation-Date: 2008-09-09 15:56+0930\n" ++"PO-Revision-Date: 2009-03-03 22:20-0600\n" + "Last-Translator: Cristian Othón Martínez Vera \n" + "Language-Team: Spanish \n" + "MIME-Version: 1.0\n" +@@ -31,143 +32,143 @@ msgstr "%B: Tipo de reubicaci + msgid "%B: Bad relocation record imported: %d" + msgstr "%B: Registro de reubicación importado erróneo: %d" + +-#: aoutx.h:1268 aoutx.h:1602 ++#: aoutx.h:1268 aoutx.h:1604 + #, c-format + msgid "%s: can not represent section `%s' in a.out object file format" + msgstr "%s: no se puede representar la sección `%s' en el fichero objeto de formato a.out" + +-#: aoutx.h:1568 ++#: aoutx.h:1570 + #, c-format + msgid "%s: can not represent section for symbol `%s' in a.out object file format" + msgstr "%s: no se puede representar la sección para el símbolo `%s' en el fichero objeto de formato a.out" + +-#: aoutx.h:1570 ++#: aoutx.h:1572 + msgid "*unknown*" + msgstr "*desconocido*" + +-#: aoutx.h:3987 aoutx.h:4313 ++#: aoutx.h:3989 aoutx.h:4315 + msgid "%P: %B: unexpected relocation type\n" + msgstr "%P: %B: tipo de reubicación inesperado\n" + +-#: aoutx.h:5347 ++#: aoutx.h:5349 + #, c-format + msgid "%s: relocatable link from %s to %s not supported" + msgstr "%s: no se admite el enlace reubicable de %s a %s" + +-#: archive.c:1766 ++#: archive.c:2046 + msgid "Warning: writing archive was slow: rewriting timestamp\n" + msgstr "Aviso: la escritura del fichero fue lenta: se reescribe la marca de tiempo\n" + + # ¡Uff! Si utilizáramos file=archivo, esta traducción sería imposible. cfuga +-#: archive.c:2029 ++#: archive.c:2309 + msgid "Reading archive file mod timestamp" + msgstr "Se lee el archivo de la modificación de marca de tiempo del fichero" + +-#: archive.c:2053 ++#: archive.c:2333 + msgid "Writing updated armap timestamp" + msgstr "Se escribe la marca de tiempo actualizada de armap" + +-#: bfd.c:289 ++#: bfd.c:368 + msgid "No error" + msgstr "No hay error" + +-#: bfd.c:290 ++#: bfd.c:369 + msgid "System call error" + msgstr "Error en la llamada al sistema" + +-#: bfd.c:291 ++#: bfd.c:370 + msgid "Invalid bfd target" + msgstr "Objetivo bfd inválido" + +-#: bfd.c:292 ++#: bfd.c:371 + msgid "File in wrong format" + msgstr "Fichero en formato erróneo" + +-#: bfd.c:293 ++#: bfd.c:372 + msgid "Archive object file in wrong format" + msgstr "Archivo de ficheros objeto en formato erróneo" + +-#: bfd.c:294 ++#: bfd.c:373 + msgid "Invalid operation" + msgstr "Operación inválida" + +-#: bfd.c:295 ++#: bfd.c:374 + msgid "Memory exhausted" + msgstr "Memoria agotada" + +-#: bfd.c:296 ++#: bfd.c:375 + msgid "No symbols" + msgstr "No hay símbolos" + +-#: bfd.c:297 ++#: bfd.c:376 + msgid "Archive has no index; run ranlib to add one" + msgstr "El archivo no tiene índice; ejecute ranlib para agregar uno" + +-#: bfd.c:298 ++#: bfd.c:377 + msgid "No more archived files" + msgstr "No hay más ficheros archivados" + +-#: bfd.c:299 ++#: bfd.c:378 + msgid "Malformed archive" + msgstr "Archivo malformado" + +-#: bfd.c:300 ++#: bfd.c:379 + msgid "File format not recognized" + msgstr "No se reconoce el formato del fichero" + +-#: bfd.c:301 ++#: bfd.c:380 + msgid "File format is ambiguous" + msgstr "El formato del fichero es ambiguo" + +-#: bfd.c:302 ++#: bfd.c:381 + msgid "Section has no contents" + msgstr "La sección no tiene contenidos" + +-#: bfd.c:303 ++#: bfd.c:382 + msgid "Nonrepresentable section on output" + msgstr "Sección no representable en la salida" + +-#: bfd.c:304 ++#: bfd.c:383 + msgid "Symbol needs debug section which does not exist" + msgstr "Un símbolo requiere de una sección de depuración, la cual no existe" + +-#: bfd.c:305 ++#: bfd.c:384 + msgid "Bad value" + msgstr "Valor erróneo" + +-#: bfd.c:306 ++#: bfd.c:385 + msgid "File truncated" + msgstr "Fichero truncado" + +-#: bfd.c:307 ++#: bfd.c:386 + msgid "File too big" + msgstr "Fichero demasiado grande" + +-#: bfd.c:308 ++#: bfd.c:387 + #, c-format + msgid "Error reading %s: %s" + msgstr "Error al leer %s: %s" + +-#: bfd.c:309 ++#: bfd.c:388 + msgid "#" + msgstr "#" + +-#: bfd.c:830 ++#: bfd.c:912 + #, c-format + msgid "BFD %s assertion fail %s:%d" + msgstr "falló la aseveración BFD %s %s:%d" + +-#: bfd.c:842 ++#: bfd.c:924 + #, c-format + msgid "BFD %s internal error, aborting at %s line %d in %s\n" + msgstr "error interno de BFD %s, se aborta en %s línea %d en %s\n" + +-#: bfd.c:846 ++#: bfd.c:928 + #, c-format + msgid "BFD %s internal error, aborting at %s line %d\n" + msgstr "error interno de BFD %s, se aborta en %s línea %d\n" + +-#: bfd.c:848 ++#: bfd.c:930 + msgid "Please report this bug.\n" + msgstr "Por favor reporte este bicho.\n" + +@@ -186,14 +187,10 @@ msgstr "no se mapea: no se estableci + msgid "Warning: Writing section `%s' to huge (ie negative) file offset 0x%lx." + msgstr "Aviso: Se escribe la sección `%s' a un desplazamiento de fichero grande (pe negativo) 0x%lx." + +-#: cache.c:238 ++#: cache.c:222 + msgid "reopening %B: %s\n" + msgstr "se reabre %B: %s\n" + +-#: coff64-rs6000.c:2126 coff-rs6000.c:3624 +-msgid "%B: symbol `%s' has unrecognized smclas %d" +-msgstr "%B: el símbolo `%s' tiene smclas %d que no se reconoce" +- + #: coff-alpha.c:490 + msgid "" + "%B: Cannot handle compressed Alpha binaries.\n" +@@ -206,7 +203,7 @@ msgstr "" + msgid "%B: unknown/unsupported relocation type %d" + msgstr "%B: tipo de reubicación %d desconocida/no admitida" + +-#: coff-alpha.c:899 coff-alpha.c:936 coff-alpha.c:2024 coff-mips.c:1002 ++#: coff-alpha.c:899 coff-alpha.c:936 coff-alpha.c:2024 coff-mips.c:1003 + msgid "GP relative relocation used when GP not defined" + msgstr "se usó una reubicación GP relativa cuando GP no estaba definido" + +@@ -222,22 +219,22 @@ msgstr "%B: tipo de reubicaci + msgid "%B: unsupported relocation: ALPHA_R_GPRELLOW" + msgstr "%B: tipo de reubicación no admitida: ALPHA_R_GPRELLOW" + +-#: coff-alpha.c:1574 elf32-m32r.c:2487 elf64-alpha.c:3953 elf64-alpha.c:4106 +-#: elf32-ia64.c:4675 elf64-ia64.c:4675 ++#: coff-alpha.c:1574 elf32-m32r.c:2487 elf64-alpha.c:3970 elf64-alpha.c:4125 ++#: elf32-ia64.c:4465 elf64-ia64.c:4465 + msgid "%B: unknown relocation type %d" + msgstr "%B: tipo de reubicación %d desconocido" + +-#: coff-arm.c:1036 ++#: coff-arm.c:1039 + #, c-format + msgid "%B: unable to find THUMB glue '%s' for `%s'" + msgstr "%B: no se puede encontrar el pegamento THUMB '%s' para `%s'" + +-#: coff-arm.c:1065 ++#: coff-arm.c:1068 + #, c-format + msgid "%B: unable to find ARM glue '%s' for `%s'" + msgstr "%B: no se puede encontrar el pegamento ARM '%s' para `%s'" + +-#: coff-arm.c:1367 elf32-arm.c:4167 ++#: coff-arm.c:1370 elf32-arm.c:5453 + #, c-format + msgid "" + "%B(%s): warning: interworking not enabled.\n" +@@ -246,7 +243,7 @@ msgstr "" + "%B(%s): aviso: no se activó la interoperabilidad.\n" + " primer suceso: %B: llamada arm a thumb" + +-#: coff-arm.c:1457 ++#: coff-arm.c:1460 + #, c-format + msgid "" + "%B(%s): warning: interworking not enabled.\n" +@@ -257,188 +254,118 @@ msgstr "" + " primer suceso: %B: llamada arm a thumb\n" + " considere reenlazar con --support-old-code activado" + +-#: coff-arm.c:1750 cofflink.c:3018 coff-tic80.c:695 ++#: coff-arm.c:1755 coff-tic80.c:695 cofflink.c:3018 + msgid "%B: bad reloc address 0x%lx in section `%A'" + msgstr "%B: dirección de reubicación 0x%lx errónea en la sección `%A'" + +-#: coff-arm.c:2075 ++#: coff-arm.c:2080 + msgid "%B: illegal symbol index in reloc: %d" + msgstr "%B: índice de símbolos ilegal en la reubicación: %d" + +-#: coff-arm.c:2206 ++#: coff-arm.c:2211 + #, c-format + msgid "ERROR: %B is compiled for APCS-%d, whereas %B is compiled for APCS-%d" + msgstr "ERROR: %B está compilado para APCS-%d, mientras que %B está compilado para APCS-%d" + +-#: coff-arm.c:2222 elf32-arm.c:7072 ++#: coff-arm.c:2227 elf32-arm.c:8563 + #, c-format + msgid "ERROR: %B passes floats in float registers, whereas %B passes them in integer registers" + msgstr "ERROR: %B pasa números de coma flotante en registros de coma flotante, mientras que %B los pasa en registros enteros" + +-#: coff-arm.c:2225 elf32-arm.c:7076 ++#: coff-arm.c:2230 elf32-arm.c:8567 + #, c-format + msgid "ERROR: %B passes floats in integer registers, whereas %B passes them in float registers" + msgstr "ERROR: %B pasa números de coma flotante en registros enteros, mientras que %B los pasa en registros de coma flotante" + +-#: coff-arm.c:2239 ++#: coff-arm.c:2244 + #, c-format + msgid "ERROR: %B is compiled as position independent code, whereas target %B is absolute position" + msgstr "ERROR: %B está compilado como código independiente de posición, mientras que el objetivo %B es de posición absoluta" + +-#: coff-arm.c:2242 ++#: coff-arm.c:2247 + #, c-format + msgid "ERROR: %B is compiled as absolute position code, whereas target %B is position independent" + msgstr "ERROR: %B está compilado como código de posición absoluta, mientras que el objetivo %B es independiente de posición" + +-#: coff-arm.c:2270 elf32-arm.c:7141 ++#: coff-arm.c:2275 elf32-arm.c:8632 + #, c-format + msgid "Warning: %B supports interworking, whereas %B does not" + msgstr "Aviso: %B admite interoperabilidad, mientras que %B no" + +-#: coff-arm.c:2273 elf32-arm.c:7147 ++#: coff-arm.c:2278 elf32-arm.c:8638 + #, c-format + msgid "Warning: %B does not support interworking, whereas %B does" + msgstr "Aviso: %B no admite interoperabilidad, mientras que %B sí" + +-#: coff-arm.c:2297 ++#: coff-arm.c:2302 + #, c-format + msgid "private flags = %x:" + msgstr "opciones privadas = %x:" + +-#: coff-arm.c:2305 elf32-arm.c:7198 ++#: coff-arm.c:2310 elf32-arm.c:8689 + #, c-format + msgid " [floats passed in float registers]" + msgstr "[números de coma flotante pasados en registros de coma flotante]" + +-#: coff-arm.c:2307 ++#: coff-arm.c:2312 + #, c-format + msgid " [floats passed in integer registers]" + msgstr "[números de coma flotante pasados en registros enteros]" + +-#: coff-arm.c:2310 elf32-arm.c:7201 ++#: coff-arm.c:2315 elf32-arm.c:8692 + #, c-format + msgid " [position independent]" + msgstr "[independiente de posición]" + +-#: coff-arm.c:2312 ++#: coff-arm.c:2317 + #, c-format + msgid " [absolute position]" + msgstr "[posición absoluta]" + +-#: coff-arm.c:2316 ++#: coff-arm.c:2321 + #, c-format + msgid " [interworking flag not initialised]" + msgstr "[no se inicializó la opción de interoperabilidad]" + +-#: coff-arm.c:2318 ++#: coff-arm.c:2323 + #, c-format + msgid " [interworking supported]" + msgstr "[admite interoperabilidad]" + +-#: coff-arm.c:2320 ++#: coff-arm.c:2325 + #, c-format + msgid " [interworking not supported]" + msgstr "[no admite interoperabilidad]" + +-#: coff-arm.c:2366 elf32-arm.c:6578 ++#: coff-arm.c:2371 elf32-arm.c:8050 + #, c-format + msgid "Warning: Not setting interworking flag of %B since it has already been specified as non-interworking" + msgstr "Aviso: No se establece la opción de interoperabilidad de %B ya que se había especificado con anterioridad como no interoperable" + +-#: coff-arm.c:2370 elf32-arm.c:6582 ++#: coff-arm.c:2375 elf32-arm.c:8054 + #, c-format + msgid "Warning: Clearing the interworking flag of %B due to outside request" + msgstr "Aviso: Se limpia la opción de interoperabilidad de %B debido a una petición externa" + +-#: coffcode.h:850 +-msgid "%B: warning: COMDAT symbol '%s' does not match section name '%s'" +-msgstr "%B: aviso: el símbolo COMDAT '%s' no coincide con el nombre de sección '%s'" +- +-#. Generate a warning message rather using the 'unhandled' +-#. variable as this will allow some .sys files generate by +-#. other toolchains to be processed. See bugzilla issue 196. +-#: coffcode.h:1062 +-msgid "%B: Warning: Ignoring section flag IMAGE_SCN_MEM_NOT_PAGED in section %s" +-msgstr "%B: Aviso: Se descarta la opción de sección IMAGE_SCN_MEM_NOT_PAGED en la sección %s" +- +-#: coffcode.h:1117 +-msgid "%B (%s): Section flag %s (0x%x) ignored" +-msgstr "%B (%s): Se descarta la opción de sección %s (0x%x)" +- +-#: coffcode.h:2236 +-#, c-format +-msgid "Unrecognized TI COFF target id '0x%x'" +-msgstr "No se reconoce el id de objetivo TI COFF '0x%x'" +- +-#: coffcode.h:2551 +-msgid "%B: reloc against a non-existant symbol index: %ld" +-msgstr "%B: reubicación contra un índice símbolo que no existe: %ld" +- +-#: coffcode.h:4296 +-msgid "%B: warning: line number table read failed" +-msgstr "%B: aviso: falló la lectura de tabla de números de línea" +- +-#: coffcode.h:4329 +-msgid "%B: warning: illegal symbol index %ld in line numbers" +-msgstr "%B: aviso: índice de símbolos %ld ilegal en los números de línea" +- +-#: coffcode.h:4343 +-msgid "%B: warning: duplicate line number information for `%s'" +-msgstr "%B: aviso: información duplicada de números de línea para `%s'" +- +-#: coffcode.h:4735 +-msgid "%B: Unrecognized storage class %d for %s symbol `%s'" +-msgstr "%B: Clase de almacenamiento %d no reconocida para %s símbolo `%s'" +- +-#: coffcode.h:4861 +-msgid "warning: %B: local symbol `%s' has no section" +-msgstr "aviso: %B: el símbolo local `%s' no tiene sección" +- +-#: coffcode.h:4966 coff-i860.c:601 coff-tic54x.c:393 +-msgid "%B: warning: illegal symbol index %ld in relocs" +-msgstr "%B: aviso: índice de símbolos %ld ilegal en reubicaciones" +- +-#: coffcode.h:5004 +-msgid "%B: illegal relocation type %d at address 0x%lx" +-msgstr "%B: tipo de reubicación %d ilegal en la dirección 0x%lx" +- +-#: coffgen.c:1518 +-msgid "%B: bad string table size %lu" +-msgstr "%B: tamaño de tabla de cadenas %lu erróneo" +- + #: coff-h8300.c:1122 + #, c-format + msgid "cannot handle R_MEM_INDIRECT reloc when using %s output" + msgstr "no se puede manejar la reubicación R_MEM_INDIRECT cuando se utiliza la salida %s" + +-#: coff-i860.c:143 ++#: coff-i860.c:147 + #, c-format + msgid "Relocation `%s' not yet implemented\n" + msgstr "La reubicación `%s' aún no está implementada\n" + +-#: coff-i960.c:138 coff-i960.c:501 ++#: coff-i860.c:605 coff-tic54x.c:398 coffcode.h:4975 ++msgid "%B: warning: illegal symbol index %ld in relocs" ++msgstr "%B: aviso: índice de símbolos %ld ilegal en reubicaciones" ++ ++#: coff-i960.c:143 coff-i960.c:506 + msgid "uncertain calling convention for non-COFF symbol" + msgstr "convención de llamada incierta para un símbolo que no es COFF" + +-#: cofflink.c:513 elflink.c:4175 +-msgid "Warning: type of symbol `%s' changed from %d to %d in %B" +-msgstr "Aviso: el tipo del símbolo `%s' cambió de %d a %d en %B" +- +-#: cofflink.c:2296 +-msgid "%B: relocs in section `%A', but it has no contents" +-msgstr "%B: reubicaciones en la sección `%A', pero no tiene contenido" +- +-#: cofflink.c:2627 coffswap.h:824 +-#, c-format +-msgid "%s: %s: reloc overflow: 0x%lx > 0xffff" +-msgstr "%s: %s: desbordamiento de reubicación: 0x%lx > 0xffff" +- +-#: cofflink.c:2636 coffswap.h:810 +-#, c-format +-msgid "%s: warning: %s: line number overflow: 0x%lx > 0xffff" +-msgstr "%s: aviso: %s: desbordamiento de número de línea: 0x%lx > 0xffff" +- +-#: coff-m68k.c:506 elf32-bfin.c:5434 elf32-m68k.c:2393 ++#: coff-m68k.c:506 elf32-bfin.c:5510 elf32-m68k.c:3938 + msgid "unsupported reloc type" + msgstr "no se admite el tipo de reubicación" + +@@ -462,31 +389,35 @@ msgstr "La direcci + msgid "Unrecognized Reloc Type" + msgstr "Tipo de Reubicación no Reconocida" + +-#: coff-mips.c:687 elf32-mips.c:958 elf32-score.c:345 elf64-mips.c:1911 +-#: elfn32-mips.c:1752 ++#: coff-mips.c:688 elf32-mips.c:1014 elf32-score.c:345 elf64-mips.c:1991 ++#: elfn32-mips.c:1832 + msgid "GP relative relocation when _gp not defined" + msgstr "reubicación GP relativa cuando _gp no está definido" + +-#: coff-or32.c:228 ++#: coff-or32.c:229 + msgid "Unrecognized reloc" + msgstr "Reubicación no reconocida" + +-#: coff-rs6000.c:2799 ++#: coff-rs6000.c:2803 + #, c-format + msgid "%s: unsupported relocation type 0x%02x" + msgstr "%s: no se admite el tipo de reubicación 0x%02x" + +-#: coff-rs6000.c:2892 ++#: coff-rs6000.c:2896 + #, c-format + msgid "%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry" + msgstr "%s: reubicación de TOC en 0x%x al símbolo `%s' sin entrada TOC" + +-#: coff-tic4x.c:191 coff-tic54x.c:299 coff-tic80.c:458 ++#: coff-rs6000.c:3628 coff64-rs6000.c:2130 ++msgid "%B: symbol `%s' has unrecognized smclas %d" ++msgstr "%B: el símbolo `%s' tiene smclas %d que no se reconoce" ++ ++#: coff-tic4x.c:195 coff-tic54x.c:299 coff-tic80.c:458 + #, c-format + msgid "Unrecognized reloc type 0x%x" + msgstr "Tipo de reubicación 0x%x no reconocida" + +-#: coff-tic4x.c:236 ++#: coff-tic4x.c:240 + #, c-format + msgid "%s: warning: illegal symbol index %ld in relocs" + msgstr "%s: aviso: íncide de símbolos %ld ilegal en reubicaciones" +@@ -496,6 +427,76 @@ msgstr "%s: aviso: + msgid "ignoring reloc %s\n" + msgstr "se descarta la reubicación %s\n" + ++#: coffcode.h:850 ++msgid "%B: warning: COMDAT symbol '%s' does not match section name '%s'" ++msgstr "%B: aviso: el símbolo COMDAT '%s' no coincide con el nombre de sección '%s'" ++ ++#. Generate a warning message rather using the 'unhandled' ++#. variable as this will allow some .sys files generate by ++#. other toolchains to be processed. See bugzilla issue 196. ++#: coffcode.h:1062 ++msgid "%B: Warning: Ignoring section flag IMAGE_SCN_MEM_NOT_PAGED in section %s" ++msgstr "%B: Aviso: Se descarta la opción de sección IMAGE_SCN_MEM_NOT_PAGED en la sección %s" ++ ++#: coffcode.h:1117 ++msgid "%B (%s): Section flag %s (0x%x) ignored" ++msgstr "%B (%s): Se descarta la opción de sección %s (0x%x)" ++ ++#: coffcode.h:2244 ++#, c-format ++msgid "Unrecognized TI COFF target id '0x%x'" ++msgstr "No se reconoce el id de objetivo TI COFF '0x%x'" ++ ++#: coffcode.h:2559 ++msgid "%B: reloc against a non-existant symbol index: %ld" ++msgstr "%B: reubicación contra un índice símbolo que no existe: %ld" ++ ++#: coffcode.h:4309 ++msgid "%B: warning: line number table read failed" ++msgstr "%B: aviso: falló la lectura de tabla de números de línea" ++ ++#: coffcode.h:4339 ++msgid "%B: warning: illegal symbol index %ld in line numbers" ++msgstr "%B: aviso: índice de símbolos %ld ilegal en los números de línea" ++ ++#: coffcode.h:4353 ++msgid "%B: warning: duplicate line number information for `%s'" ++msgstr "%B: aviso: información duplicada de números de línea para `%s'" ++ ++#: coffcode.h:4744 ++msgid "%B: Unrecognized storage class %d for %s symbol `%s'" ++msgstr "%B: Clase de almacenamiento %d no reconocida para %s símbolo `%s'" ++ ++#: coffcode.h:4870 ++msgid "warning: %B: local symbol `%s' has no section" ++msgstr "aviso: %B: el símbolo local `%s' no tiene sección" ++ ++#: coffcode.h:5013 ++msgid "%B: illegal relocation type %d at address 0x%lx" ++msgstr "%B: tipo de reubicación %d ilegal en la dirección 0x%lx" ++ ++#: coffgen.c:1518 ++msgid "%B: bad string table size %lu" ++msgstr "%B: tamaño de tabla de cadenas %lu erróneo" ++ ++#: cofflink.c:513 elflink.c:4218 ++msgid "Warning: type of symbol `%s' changed from %d to %d in %B" ++msgstr "Aviso: el tipo del símbolo `%s' cambió de %d a %d en %B" ++ ++#: cofflink.c:2296 ++msgid "%B: relocs in section `%A', but it has no contents" ++msgstr "%B: reubicaciones en la sección `%A', pero no tiene contenido" ++ ++#: cofflink.c:2627 coffswap.h:824 ++#, c-format ++msgid "%s: %s: reloc overflow: 0x%lx > 0xffff" ++msgstr "%s: %s: desbordamiento de reubicación: 0x%lx > 0xffff" ++ ++#: cofflink.c:2636 coffswap.h:810 ++#, c-format ++msgid "%s: warning: %s: line number overflow: 0x%lx > 0xffff" ++msgstr "%s: aviso: %s: desbordamiento de número de línea: 0x%lx > 0xffff" ++ + #: cpu-arm.c:189 cpu-arm.c:200 + msgid "ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale" + msgstr "ERROR: %B está compilado para el EP9312, mientras que %B está compilado para XScale" +@@ -505,66 +506,50 @@ msgstr "ERROR: %B est + msgid "warning: unable to update contents of %s section in %s" + msgstr "aviso: no se puede actualizar el contenido de la sección %s en %s" + +-#: dwarf2.c:481 +-msgid "Dwarf Error: Can't find .debug_str section." +-msgstr "Error de Dwarf: No se puede encontrar la sección .debug_str." +- +-#: dwarf2.c:499 ++#: dwarf2.c:424 + #, c-format +-msgid "Dwarf Error: DW_FORM_strp offset (%lu) greater than or equal to .debug_str size (%lu)." +-msgstr "Error de Dwarf: El desplazamiento DW_FROM_strp (%lu) es más grande o igual que el tamaño de .debug_str (%lu)." ++msgid "Dwarf Error: Can't find %s section." ++msgstr "Error de Dwarf: No se puede encontrar la sección %s." + +-#: dwarf2.c:592 +-msgid "Dwarf Error: Can't find .debug_abbrev section." +-msgstr "Error de Dwarf: No se puede encontrar la sección .debug_abbrev." ++#: dwarf2.c:452 ++#, c-format ++msgid "Dwarf Error: unable to decompress %s section." ++msgstr "Error de Dwarf: no se puede descomprimir la sección %s." + +-#: dwarf2.c:607 ++#: dwarf2.c:462 + #, c-format +-msgid "Dwarf Error: Abbrev offset (%lu) greater than or equal to .debug_abbrev size (%lu)." +-msgstr "Error de Dwarf: El desplazamiento de abreviatura (%lu) es más grande o igual que el tamaño de .debug_abbrev (%lu)." ++msgid "Dwarf Error: Offset (%lu) greater than or equal to %s size (%lu)." ++msgstr "Error de Dwarf: El desplazamiento (%lu) es mayor que o igual que el tamaño de %s (%lu)." + +-#: dwarf2.c:822 ++#: dwarf2.c:849 + #, c-format + msgid "Dwarf Error: Invalid or unhandled FORM value: %u." + msgstr "Error de Dwarf: Valor de FORM inválido o no manejado: %u." + +-#: dwarf2.c:1025 ++#: dwarf2.c:1063 + msgid "Dwarf Error: mangled line number section (bad file number)." + msgstr "Error de Dwarf: sección de números de línea revuelta (número erróneo de fichero)." + +-#: dwarf2.c:1137 +-msgid "Dwarf Error: Can't find .debug_line section." +-msgstr "Error de Dwarf: No se puede encontrar lan sección .debug_line." +- +-#: dwarf2.c:1154 +-#, c-format +-msgid "Dwarf Error: Line offset (%lu) greater than or equal to .debug_line size (%lu)." +-msgstr "Error de Dwarf: El desplazamiento de línea (%lu) es más grande o igual que el tamaño de .debug_line (%lu)." +- +-#: dwarf2.c:1380 ++#: dwarf2.c:1393 + msgid "Dwarf Error: mangled line number section." + msgstr "Error de Dwarf: sección de números de línea revuelta." + +-#: dwarf2.c:1568 +-msgid "Dwarf Error: Can't find .debug_ranges section." +-msgstr "Error de Dwarf: No se puede encontrar lan sección .debug_ranges." +- +-#: dwarf2.c:1731 dwarf2.c:1847 dwarf2.c:2119 ++#: dwarf2.c:1726 dwarf2.c:1842 dwarf2.c:2114 + #, c-format + msgid "Dwarf Error: Could not find abbrev number %u." + msgstr "Error de Dwarf: No se puede encontrar el número de abreviatura %u." + +-#: dwarf2.c:2080 ++#: dwarf2.c:2075 + #, c-format + msgid "Dwarf Error: found dwarf version '%u', this reader only handles version 2 information." + msgstr "Error de Dwarf: se encontró la versión de dwarf '%u', este lector solamente maneja información de la versión 2." + +-#: dwarf2.c:2087 ++#: dwarf2.c:2082 + #, c-format + msgid "Dwarf Error: found address size '%u', this reader can not handle sizes greater than '%u'." + msgstr "Error de Dwarf: se encontró el tamaño de dirección '%u', este lector no puede manejar tamaños más grandes que '%u'." + +-#: dwarf2.c:2110 ++#: dwarf2.c:2105 + #, c-format + msgid "Dwarf Error: Bad abbrev number: %u." + msgstr "Error de Dwarf: Número de abreviación erróneo: %u." +@@ -646,35 +631,271 @@ msgstr "" + "\n" + " Tipo: %s" + +-#: elf32-arm.c:2524 ++#: elf-attrs.c:582 ++msgid "ERROR: %B: Must be processed by '%s' toolchain" ++msgstr "ERROR: %B: Se debe procesar por la cadena de compilación '%s'" ++ ++#: elf-attrs.c:602 elf-attrs.c:621 ++msgid "ERROR: %B: Incompatible object tag '%s':%d" ++msgstr "ERROR: %B: Etiqueta de objeto '%s' incompatible:%d" ++ ++#: elf-eh-frame.c:866 ++msgid "%P: error in %B(%A); no .eh_frame_hdr table will be created.\n" ++msgstr "%P: error en %B(%A); no se creará la tabla .eh_frame_hdr.\n" ++ ++#: elf-eh-frame.c:1102 ++msgid "%P: fde encoding in %B(%A) prevents .eh_frame_hdr table being created.\n" ++msgstr "%P: la codificación fde en %B(%A) previene la creación de la tabla .eh_frame_hdr.\n" ++ ++#: elf-hppa.h:2241 elf-m10300.c:1546 elf32-arm.c:7954 elf32-i386.c:3582 ++#: elf32-m32r.c:2598 elf32-m68k.c:3516 elf32-ppc.c:7223 elf32-s390.c:3058 ++#: elf32-sh.c:3438 elf32-xtensa.c:3021 elf64-ppc.c:11528 elf64-s390.c:3019 ++#: elf64-sh64.c:1648 elf64-x86-64.c:3239 elfxx-sparc.c:3336 ++msgid "%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'" ++msgstr "%B(%A+0x%lx): reubicación %s sin resolución contra el símbolo `%s'" ++ ++#: elf-hppa.h:2266 elf-hppa.h:2280 ++msgid "%B(%A): warning: unresolvable relocation against symbol `%s'" ++msgstr "%B(%A): aviso: reubicación sin resolución contra el símbolo `%s'" ++ ++#: elf-m10200.c:456 elf-m10300.c:1609 elf32-avr.c:1250 elf32-bfin.c:3214 ++#: elf32-cr16.c:959 elf32-cr16c.c:790 elf32-cris.c:1538 elf32-crx.c:933 ++#: elf32-d10v.c:516 elf32-fr30.c:616 elf32-frv.c:4114 elf32-h8300.c:516 ++#: elf32-i860.c:1218 elf32-ip2k.c:1499 elf32-iq2000.c:691 elf32-m32c.c:560 ++#: elf32-m32r.c:3124 elf32-m68hc1x.c:1135 elf32-mep.c:541 elf32-msp430.c:493 ++#: elf32-mt.c:402 elf32-openrisc.c:411 elf32-score.c:2451 elf32-spu.c:4132 ++#: elf32-v850.c:1703 elf32-xstormy16.c:948 elf64-mmix.c:1533 ++msgid "internal error: out of range error" ++msgstr "error interno: error fuera de rango" ++ ++#: elf-m10200.c:460 elf-m10300.c:1613 elf32-avr.c:1254 elf32-bfin.c:3218 ++#: elf32-cr16.c:963 elf32-cr16c.c:794 elf32-cris.c:1542 elf32-crx.c:937 ++#: elf32-d10v.c:520 elf32-fr30.c:620 elf32-frv.c:4118 elf32-h8300.c:520 ++#: elf32-i860.c:1222 elf32-iq2000.c:695 elf32-m32c.c:564 elf32-m32r.c:3128 ++#: elf32-m68hc1x.c:1139 elf32-mep.c:545 elf32-msp430.c:497 ++#: elf32-openrisc.c:415 elf32-score.c:2455 elf32-spu.c:4136 elf32-v850.c:1707 ++#: elf32-xstormy16.c:952 elf64-mmix.c:1537 elfxx-mips.c:9065 ++msgid "internal error: unsupported relocation error" ++msgstr "error interno: error de reubicación no admitida" ++ ++#: elf-m10200.c:464 elf32-cr16.c:967 elf32-cr16c.c:798 elf32-crx.c:941 ++#: elf32-d10v.c:524 elf32-h8300.c:524 elf32-m32r.c:3132 elf32-m68hc1x.c:1143 ++#: elf32-score.c:2459 elf32-spu.c:4140 ++msgid "internal error: dangerous error" ++msgstr "error interno: error peligroso" ++ ++#: elf-m10200.c:468 elf-m10300.c:1626 elf32-avr.c:1262 elf32-bfin.c:3226 ++#: elf32-cr16.c:971 elf32-cr16c.c:802 elf32-cris.c:1550 elf32-crx.c:945 ++#: elf32-d10v.c:528 elf32-fr30.c:628 elf32-frv.c:4126 elf32-h8300.c:528 ++#: elf32-i860.c:1230 elf32-ip2k.c:1514 elf32-iq2000.c:703 elf32-m32c.c:572 ++#: elf32-m32r.c:3136 elf32-m68hc1x.c:1147 elf32-mep.c:553 elf32-msp430.c:505 ++#: elf32-mt.c:410 elf32-openrisc.c:423 elf32-score.c:2463 elf32-spu.c:4144 ++#: elf32-v850.c:1727 elf32-xstormy16.c:960 elf64-mmix.c:1545 ++msgid "internal error: unknown error" ++msgstr "error interno: error desconocido" ++ ++#: elf-m10300.c:1618 ++msgid "error: inappropriate relocation type for shared library (did you forget -fpic?)" ++msgstr "error: tipo de reubicación inapropiada para la biblioteca compartida (¿olvidó -fpic?)" ++ ++#: elf-m10300.c:1621 ++msgid "internal error: suspicious relocation type used in shared library" ++msgstr "error interno: se usó un tipo de reubicación sospechosa en una biblioteca compartida" ++ ++#: elf-m10300.c:4397 elf32-arm.c:9578 elf32-cris.c:2403 elf32-hppa.c:1921 ++#: elf32-i370.c:506 elf32-i386.c:1807 elf32-m32r.c:1931 elf32-m68k.c:2787 ++#: elf32-ppc.c:4693 elf32-s390.c:1687 elf32-sh.c:2583 elf32-vax.c:1055 ++#: elf64-ppc.c:6075 elf64-s390.c:1662 elf64-sh64.c:3432 elf64-x86-64.c:1641 ++#: elfxx-sparc.c:1828 ++#, c-format ++msgid "dynamic variable `%s' is zero size" ++msgstr "la variable dinámica `%s' es de tamaño cero" ++ ++#: elf.c:328 ++msgid "%B: invalid string offset %u >= %lu for section `%s'" ++msgstr "%B: desplazamiento de cadena inválido %u >= %lu para la sección `%s'" ++ ++#: elf.c:438 ++msgid "%B symbol number %lu references nonexistent SHT_SYMTAB_SHNDX section" ++msgstr "%B el número de símbolo %lu hace referencia a la sección inexistente SHT_SYMTAB_SHNDX" ++ ++#: elf.c:594 ++msgid "%B: Corrupt size field in group section header: 0x%lx" ++msgstr "%B: Tamaño de campo corrupto en el encabezado de la sección de grupo: 0x%lx" ++ ++#: elf.c:630 ++msgid "%B: invalid SHT_GROUP entry" ++msgstr "%B: entrada SHT_GROUP inválida" ++ ++#: elf.c:700 ++msgid "%B: no group info for section %A" ++msgstr "%B: no hay información de grupo para la sección %A" ++ ++#: elf.c:729 elf.c:2976 elflink.c:9746 ++msgid "%B: warning: sh_link not set for section `%A'" ++msgstr "%B: aviso: no se estableción sh_link para la sección `%A'" ++ ++#: elf.c:748 ++msgid "%B: sh_link [%d] in section `%A' is incorrect" ++msgstr "%B: sh_link [%d] en la sección `%A', es incorrecto" ++ ++#: elf.c:783 ++msgid "%B: unknown [%d] section `%s' in group [%s]" ++msgstr "%B: sección [%d] desconocida `%s' en el grupo [%s]" ++ ++#: elf.c:1159 ++#, c-format ++msgid "" ++"\n" ++"Program Header:\n" ++msgstr "" ++"\n" ++"Encabezado del Programa:\n" ++ ++#: elf.c:1201 ++#, c-format ++msgid "" ++"\n" ++"Dynamic Section:\n" ++msgstr "" ++"\n" ++"Sección Dinámica:\n" ++ ++#: elf.c:1337 ++#, c-format ++msgid "" ++"\n" ++"Version definitions:\n" ++msgstr "" ++"\n" ++"Definiciones de versión:\n" ++ ++#: elf.c:1362 ++#, c-format ++msgid "" ++"\n" ++"Version References:\n" ++msgstr "" ++"\n" ++"Referencias de Versión:\n" ++ ++#: elf.c:1367 ++#, c-format ++msgid " required from %s:\n" ++msgstr " requerido desde %s:\n" ++ ++#: elf.c:1755 ++msgid "%B: invalid link %lu for reloc section %s (index %u)" ++msgstr "%B: enlace %lu inválido para la sección de reubicación %s (índice %u)" ++ ++#: elf.c:1924 ++msgid "%B: don't know how to handle allocated, application specific section `%s' [0x%8x]" ++msgstr "%B: no se sabe cómo manejar lo reservado, aplicación específica de la sección `%s' [0x%8x]" ++ ++#: elf.c:1936 ++msgid "%B: don't know how to handle processor specific section `%s' [0x%8x]" ++msgstr "%B: no se sabe cómo manejar la sección específica de procesador `%s' [0x%8x]" ++ ++#: elf.c:1947 ++msgid "%B: don't know how to handle OS specific section `%s' [0x%8x]" ++msgstr "%B: no se sabe cómo manejar la sección específica de SO `%s' [0x%8x]" ++ ++#: elf.c:1957 ++msgid "%B: don't know how to handle section `%s' [0x%8x]" ++msgstr "%B: no se sabe cómo manejar la sección `%s' [0x%8x]" ++ ++#: elf.c:2555 ++#, c-format ++msgid "warning: section `%A' type changed to PROGBITS" ++msgstr "aviso: el tipo de la sección `%A' cambió a PROGBITS" ++ ++#: elf.c:2933 ++msgid "%B: sh_link of section `%A' points to discarded section `%A' of `%B'" ++msgstr "%B: sh_link de la sección `%A' apunta a la sección descartada `%A' de `%B'" ++ ++#: elf.c:2956 ++msgid "%B: sh_link of section `%A' points to removed section `%A' of `%B'" ++msgstr "%B: sh_link de la sección `%A' apunta a la sección descartada `%A' de `%B'" ++ ++#: elf.c:4300 ++msgid "%B: The first section in the PT_DYNAMIC segment is not the .dynamic section" ++msgstr "%B: La primera sección en el segmento PT_DYNAMIC no es la sección .dynamic" ++ ++#: elf.c:4327 ++msgid "%B: Not enough room for program headers, try linking with -N" ++msgstr "%B: No hay suficiente espacio para los encabezados del programa, pruebe enlazar con -N" ++ ++#: elf.c:4404 ++msgid "%B: section %A vma 0x%lx overlaps previous sections" ++msgstr "%B: la sección %A vma 0x%lx traslapa las secciones anteriores" ++ ++#: elf.c:4499 ++msgid "%B: section `%A' can't be allocated in segment %d" ++msgstr "%B: la sección `%A' no se puede asignar en el segmento %d" ++ ++#: elf.c:4549 ++msgid "%B: warning: allocated section `%s' not in segment" ++msgstr "%B: aviso: la sección asignada `%s' no está en el segmento" ++ ++#: elf.c:5064 ++msgid "%B: symbol `%s' required but not present" ++msgstr "%B: se requiere el símbolo `%s' pero no está presente" ++ ++#: elf.c:5403 ++msgid "%B: warning: Empty loadable segment detected, is this intentional ?\n" ++msgstr "%B: aviso: Se detectó un segmento cargable vacío, ¿ esto es intencional ?\n" ++ ++#: elf.c:6366 ++#, c-format ++msgid "Unable to find equivalent output section for symbol '%s' from section '%s'" ++msgstr "No se puede encontrar la sección de salida equivalente para el símbolo '%s' de la sección '%s'" ++ ++#: elf.c:7346 ++msgid "%B: unsupported relocation type %s" ++msgstr "%B: no se admite el tipo de reubicación %s" ++ ++#: elf32-arm.c:2846 elf32-arm.c:2878 ++msgid "" ++"%B(%s): warning: interworking not enabled.\n" ++" first occurrence: %B: Thumb call to ARM" ++msgstr "" ++"%B(%s): aviso: no se activó la interoperabilidad.\n" ++" primer suceso: %B: llamada Thumb para ARM" ++ ++#: elf32-arm.c:3041 ++#, c-format ++msgid "%s: cannot create stub entry %s" ++msgstr "%s: no se puede crear la entrada de cabo %s" ++ ++#: elf32-arm.c:3825 + #, c-format + msgid "unable to find THUMB glue '%s' for '%s'" + msgstr "no se puede encontrar el pegamento THUMB '%s' para `%s'" + +-#: elf32-arm.c:2557 ++#: elf32-arm.c:3859 + #, c-format + msgid "unable to find ARM glue '%s' for '%s'" + msgstr "no se puede encontrar el pegamento ARM '%s' para `%s'" + +-#: elf32-arm.c:3127 ++#: elf32-arm.c:4463 + msgid "%B: BE8 images only valid in big-endian mode." + msgstr "%B: las imágenes BE8 sólo son válidas en modo big-endian." + + #. Give a warning, but do as the user requests anyway. +-#: elf32-arm.c:3331 ++#: elf32-arm.c:4678 + msgid "%B: warning: selected VFP11 erratum workaround is not necessary for target architecture" + msgstr "%B: aviso: no se necesita la alternativa para evita la errata del VFP11 seleccionado para la arquitectura objetivo" + +-#: elf32-arm.c:3865 elf32-arm.c:3885 ++#: elf32-arm.c:5212 elf32-arm.c:5232 + msgid "%B: unable to find VFP11 veneer `%s'" + msgstr "%B: no se puede encontrar la chapa de VFP11 `%s'" + +-#: elf32-arm.c:3930 ++#: elf32-arm.c:5278 + #, c-format + msgid "Invalid TARGET2 relocation type '%s'." + msgstr "Tipo de reubicación TARGET2 '%s' inválido." + +-#: elf32-arm.c:4071 ++#: elf32-arm.c:5362 + msgid "" + "%B(%s): warning: interworking not enabled.\n" + " first occurrence: %B: thumb call to arm" +@@ -682,374 +903,326 @@ msgstr "" + "%s(%s): aviso: no se activó la interoperabilidad.\n" + " primer suceso: %B: llamada thumb para arm" + +-#: elf32-arm.c:4759 ++#: elf32-arm.c:6094 + msgid "\\%B: Warning: Arm BLX instruction targets Arm function '%s'." + msgstr "\\%B: Aviso: La instrucción Arm BLX apunta a la función Arm '%s'." + +-#: elf32-arm.c:5059 ++#: elf32-arm.c:6418 + msgid "%B: Warning: Thumb BLX instruction targets thumb function '%s'." + msgstr "%B: Aviso: La instrucción Thumb BLX apunta a la función thumb '%s'." + +-#: elf32-arm.c:5689 ++#: elf32-arm.c:7095 + msgid "%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object" + msgstr "%B(%A+0x%lx): la reubicación R_ARM_TLS_LE32 no se permite en objetos compartidos" + +-#: elf32-arm.c:5890 ++#: elf32-arm.c:7310 + msgid "%B(%A+0x%lx): Only ADD or SUB instructions are allowed for ALU group relocations" + msgstr "%B(%A+0x%lx): Sólo se permiten las instrucciones ADD o SUB para la reubicación de grupo ALU" + +-#: elf32-arm.c:5930 elf32-arm.c:6017 elf32-arm.c:6100 elf32-arm.c:6185 ++#: elf32-arm.c:7350 elf32-arm.c:7437 elf32-arm.c:7520 elf32-arm.c:7605 + msgid "%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s" + msgstr "%B(%A+0x%lx): Desborde al dividirse 0x%lx para la reubicación de grupo %s" + +-#: elf32-arm.c:6369 elf32-sh.c:3304 elf64-sh64.c:1556 ++#: elf32-arm.c:7812 elf32-sh.c:3334 elf64-sh64.c:1556 + msgid "%B(%A+0x%lx): %s relocation against SEC_MERGE section" + msgstr "%B(%A+0x%lx): reubicación %s contra la sección SEC_MERGE" + +-#: elf32-arm.c:6458 elf64-ppc.c:9973 ++#: elf32-arm.c:7930 elf32-xtensa.c:2759 elf64-ppc.c:10374 + msgid "%B(%A+0x%lx): %s used with TLS symbol %s" + msgstr "%B(%A+0x%lx): se usó %s con el símbolo TLS %s" + +-#: elf32-arm.c:6459 elf64-ppc.c:9974 ++#: elf32-arm.c:7931 elf32-xtensa.c:2760 elf64-ppc.c:10375 + msgid "%B(%A+0x%lx): %s used with non-TLS symbol %s" + msgstr "%B(%A+0x%lx): se usó %s con el símbolo %s que no es TLS" + +-#: elf32-arm.c:6482 elf32-i386.c:3310 elf32-m32r.c:2598 elf32-m68k.c:1982 +-#: elf32-ppc.c:6796 elf32-s390.c:3048 elf32-sh.c:3408 elf32-xtensa.c:2290 +-#: elf64-ppc.c:11138 elf64-s390.c:3009 elf64-sh64.c:1648 elf64-x86-64.c:3002 +-#: elf-hppa.h:2194 elf-m10300.c:1460 elfxx-sparc.c:3256 +-msgid "%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'" +-msgstr "%B(%A+0x%lx): reubicación %s sin resolución contra el símbolo `%s'" +- +-#: elf32-arm.c:6516 ++#: elf32-arm.c:7988 + msgid "out of range" + msgstr "fuera de rango" + +-#: elf32-arm.c:6520 ++#: elf32-arm.c:7992 + msgid "unsupported relocation" + msgstr "no se admite la reubicación" + +-#: elf32-arm.c:6528 ++#: elf32-arm.c:8000 + msgid "unknown error" + msgstr "error desconocido" + +-#: elf32-arm.c:6628 ++#: elf32-arm.c:8099 + msgid "Warning: Clearing the interworking flag of %B because non-interworking code in %B has been linked with it" + msgstr "Aviso: Se limpia la opción de interoperación en %B porque se ha enlazado con él código no interoperable en %B" + +-#: elf32-arm.c:6730 ++#: elf32-arm.c:8205 + msgid "ERROR: %B uses VFP register arguments, %B does not" + msgstr "ERROR: %B utiliza argumentos de registro VFP, mientras que %B no" + +-#: elf32-arm.c:6780 ++#: elf32-arm.c:8254 + msgid "ERROR: %B: Conflicting architecture profiles %c/%c" + msgstr "ERROR: %B: Perfiles de arquitecturas en conflicto %c/%c" + +-#: elf32-arm.c:6795 ++#: elf32-arm.c:8274 + msgid "Warning: %B: Conflicting platform configuration" + msgstr "Aviso: %B: Configuración de plataformas en conflicto" + +-#: elf32-arm.c:6804 ++#: elf32-arm.c:8283 + msgid "ERROR: %B: Conflicting use of R9" + msgstr "ERROR: %B: Uso en conflicto de R9" + +-#: elf32-arm.c:6816 ++#: elf32-arm.c:8295 + msgid "ERROR: %B: SB relative addressing conflicts with use of R9" + msgstr "ERROR: %B: El direccionamiento relativo a SB tiene conflictos con el uso de R9" + +-#: elf32-arm.c:6838 +-msgid "ERROR: %B: Conflicting definitions of wchar_t" +-msgstr "ERROR: %B: Definiciones en conflicto de wchar_t" ++#: elf32-arm.c:8318 ++msgid "warning: %B uses %u-byte wchar_t yet the output is to use %u-byte wchar_t; use of wchar_t values across objects may fail" ++msgstr "aviso: %B usa wchar_t de %u bytes aunque la salida usa wchar_t de %u bytes; el uso de valores wchar_t entre objetos puede fallar" + +-#: elf32-arm.c:6867 ++#: elf32-arm.c:8347 + msgid "warning: %B uses %s enums yet the output is to use %s enums; use of enum values across objects may fail" + msgstr "aviso: %B usa %s enums aunque la salida usa %s enums; el uso de valores enum entre objetos puede fallar" + +-#: elf32-arm.c:6880 ++#: elf32-arm.c:8360 + msgid "ERROR: %B uses iWMMXt register arguments, %B does not" + msgstr "ERROR: %B utiliza argumentos de registro iWMMXt, mientras que %B no" + +-#: elf32-arm.c:6920 ++#: elf32-arm.c:8400 + msgid "Warning: %B: Unknown EABI object attribute %d" + msgstr "Aviso: %B: Atributo de objeto EABI %d desconocido" + +-#: elf32-arm.c:7045 ++#: elf32-arm.c:8460 ++msgid "ERROR: %B is already in final BE8 format" ++msgstr "ERROR: %B ya está en el formato BE8 final" ++ ++#: elf32-arm.c:8536 + msgid "ERROR: Source object %B has EABI version %d, but target %B has EABI version %d" + msgstr "ERROR: El objeto fuente %B tiene EABI versión %d, pero el objetivo %B tiene EABI versión %d" + +-#: elf32-arm.c:7061 ++#: elf32-arm.c:8552 + msgid "ERROR: %B is compiled for APCS-%d, whereas target %B uses APCS-%d" + msgstr "ERROR: %B está compilado para APCS-%d mientras que el objetivo %B usa APCS-%d" + +-#: elf32-arm.c:7086 ++#: elf32-arm.c:8577 + msgid "ERROR: %B uses VFP instructions, whereas %B does not" + msgstr "ERROR: %B utiliza instrucciones VFP, mientras que %B no" + +-#: elf32-arm.c:7090 ++#: elf32-arm.c:8581 + msgid "ERROR: %B uses FPA instructions, whereas %B does not" + msgstr "ERROR: %B utiliza instrucciones FPA, mientras que %B no" + +-#: elf32-arm.c:7100 ++#: elf32-arm.c:8591 + msgid "ERROR: %B uses Maverick instructions, whereas %B does not" + msgstr "ERROR: %B utiliza instrucciones Maverick, mientras que %B no" + +-#: elf32-arm.c:7104 ++#: elf32-arm.c:8595 + msgid "ERROR: %B does not use Maverick instructions, whereas %B does" + msgstr "ERROR: %B no utiliza instrucciones Maverick, mientras que %B sí" + +-#: elf32-arm.c:7123 ++#: elf32-arm.c:8614 + msgid "ERROR: %B uses software FP, whereas %B uses hardware FP" + msgstr "ERROR: %B utiliza FP de software, mientras que %B utiliza FP de hardware" + +-#: elf32-arm.c:7127 ++#: elf32-arm.c:8618 + msgid "ERROR: %B uses hardware FP, whereas %B uses software FP" + msgstr "ERROR: %B utiliza FP de hardware, mientras que %B utiliza FP de software" + + #. Ignore init flag - it may not be set, despite the flags field + #. containing valid data. + #. Ignore init flag - it may not be set, despite the flags field containing valid data. +-#: elf32-arm.c:7174 elf32-bfin.c:4795 elf32-cris.c:3234 elf32-m68hc1x.c:1277 +-#: elf32-m68k.c:620 elf32-score.c:3753 elf32-vax.c:538 elfxx-mips.c:11331 ++#: elf32-arm.c:8665 elf32-bfin.c:4899 elf32-cris.c:3235 elf32-m68hc1x.c:1279 ++#: elf32-m68k.c:774 elf32-score.c:3750 elf32-vax.c:538 elfxx-mips.c:12699 + #, c-format + msgid "private flags = %lx:" + msgstr "opciones privadas = %lx:" + +-#: elf32-arm.c:7183 ++#: elf32-arm.c:8674 + #, c-format + msgid " [interworking enabled]" + msgstr " [interoperabilidad activada]" + +-#: elf32-arm.c:7191 ++#: elf32-arm.c:8682 + #, c-format + msgid " [VFP float format]" + msgstr " [formato de coma flotante VFP]" + +-#: elf32-arm.c:7193 ++#: elf32-arm.c:8684 + #, c-format + msgid " [Maverick float format]" + msgstr " [formato de coma flotante Maverick]" + +-#: elf32-arm.c:7195 ++#: elf32-arm.c:8686 + #, c-format + msgid " [FPA float format]" + msgstr " [formato de coma flotante FPA]" + +-#: elf32-arm.c:7204 ++#: elf32-arm.c:8695 + #, c-format + msgid " [new ABI]" + msgstr " [ABI nuevo]" + +-#: elf32-arm.c:7207 ++#: elf32-arm.c:8698 + #, c-format + msgid " [old ABI]" + msgstr " [ABI antiguo]" + +-#: elf32-arm.c:7210 ++#: elf32-arm.c:8701 + #, c-format + msgid " [software FP]" + msgstr " [FP por software]" + +-#: elf32-arm.c:7219 ++#: elf32-arm.c:8710 + #, c-format + msgid " [Version1 EABI]" + msgstr " [EABI Version1]" + +-#: elf32-arm.c:7222 elf32-arm.c:7233 ++#: elf32-arm.c:8713 elf32-arm.c:8724 + #, c-format + msgid " [sorted symbol table]" + msgstr " [tabla de símbolos ordenados]" + +-#: elf32-arm.c:7224 elf32-arm.c:7235 ++#: elf32-arm.c:8715 elf32-arm.c:8726 + #, c-format + msgid " [unsorted symbol table]" + msgstr " [tabla de símbolos sin ordenar]" + +-#: elf32-arm.c:7230 ++#: elf32-arm.c:8721 + #, c-format + msgid " [Version2 EABI]" + msgstr " [EABI Version2]" + +-#: elf32-arm.c:7238 ++#: elf32-arm.c:8729 + #, c-format + msgid " [dynamic symbols use segment index]" + msgstr " [los símbolos dinámicos utilizan índices de segmento]" + +-#: elf32-arm.c:7241 ++#: elf32-arm.c:8732 + #, c-format + msgid " [mapping symbols precede others]" + msgstr " [el mapeo de símbolos precede a otros]" + +-#: elf32-arm.c:7248 ++#: elf32-arm.c:8739 + #, c-format + msgid " [Version3 EABI]" + msgstr " [EABI Version3]" + +-#: elf32-arm.c:7252 ++#: elf32-arm.c:8743 + #, c-format + msgid " [Version4 EABI]" + msgstr " [EABI Version4]" + +-#: elf32-arm.c:7256 ++#: elf32-arm.c:8747 + #, c-format + msgid " [Version5 EABI]" + msgstr " [EABI Version5]" + +-#: elf32-arm.c:7259 ++#: elf32-arm.c:8750 + #, c-format + msgid " [BE8]" + msgstr " [BE8]" + +-#: elf32-arm.c:7262 ++#: elf32-arm.c:8753 + #, c-format + msgid " [LE8]" + msgstr " [LE8]" + +-#: elf32-arm.c:7268 ++#: elf32-arm.c:8759 + #, c-format + msgid " " + msgstr " " + +-#: elf32-arm.c:7275 ++#: elf32-arm.c:8766 + #, c-format + msgid " [relocatable executable]" + msgstr " [ejecutable reubicable]" + +-#: elf32-arm.c:7278 ++#: elf32-arm.c:8769 + #, c-format + msgid " [has entry point]" + msgstr " [tiene punto de entrada]" + +-#: elf32-arm.c:7283 ++#: elf32-arm.c:8774 + #, c-format + msgid "" + msgstr "" + +-#: elf32-arm.c:7522 elf32-i386.c:961 elf32-s390.c:1003 elf32-xtensa.c:814 +-#: elf64-s390.c:958 elf64-x86-64.c:773 elfxx-sparc.c:1115 ++#: elf32-arm.c:9013 elf32-i386.c:1236 elf32-s390.c:1006 elf32-xtensa.c:999 ++#: elf64-s390.c:961 elf64-x86-64.c:1016 elfxx-sparc.c:1127 + msgid "%B: bad symbol index: %d" + msgstr "%B: índice de símbolos erróneo: %d" + +-#: elf32-arm.c:8080 elf32-cris.c:2400 elf32-hppa.c:1906 elf32-i370.c:506 +-#: elf32-i386.c:1522 elf32-m32r.c:1931 elf32-m68k.c:1331 elf32-ppc.c:4314 +-#: elf32-s390.c:1679 elf32-sh.c:2584 elf32-vax.c:1050 elf64-ppc.c:5898 +-#: elf64-s390.c:1654 elf64-sh64.c:3438 elf64-x86-64.c:1382 elf-m10300.c:4207 +-#: elfxx-sparc.c:1797 +-#, c-format +-msgid "dynamic variable `%s' is zero size" +-msgstr "la variable dinámica `%s' es de tamaño cero" +- +-#: elf32-arm.c:8603 ++#: elf32-arm.c:10125 + #, c-format + msgid "Errors encountered processing file %s" + msgstr "Se encontraron errores al procesar el fichero %s" + +-#: elf32-arm.c:9839 elf32-arm.c:9861 ++#: elf32-arm.c:11526 elf32-arm.c:11548 + msgid "%B: error: VFP11 veneer out of range" + msgstr "%B: error: la chapa VFP11 está fuera de rango" + +-#: elf32-avr.c:1253 elf32-bfin.c:2795 elf32-cr16.c:887 elf32-cr16c.c:790 +-#: elf32-cris.c:1538 elf32-crx.c:933 elf32-d10v.c:517 elf32-fr30.c:616 +-#: elf32-frv.c:4129 elf32-h8300.c:516 elf32-i860.c:1218 elf32-ip2k.c:1499 +-#: elf32-iq2000.c:647 elf32-m32c.c:560 elf32-m32r.c:3124 elf32-m68hc1x.c:1133 +-#: elf32-mep.c:642 elf32-msp430.c:497 elf32-mt.c:402 elf32-openrisc.c:411 +-#: elf32-score.c:2456 elf32-spu.c:2813 elf32-v850.c:1701 elf32-xstormy16.c:946 +-#: elf64-mmix.c:1533 elf-m10200.c:456 elf-m10300.c:1523 +-msgid "internal error: out of range error" +-msgstr "error interno: error fuera de rango" +- +-#: elf32-avr.c:1257 elf32-bfin.c:2799 elf32-cr16.c:891 elf32-cr16c.c:794 +-#: elf32-cris.c:1542 elf32-crx.c:937 elf32-d10v.c:521 elf32-fr30.c:620 +-#: elf32-frv.c:4133 elf32-h8300.c:520 elf32-i860.c:1222 elf32-iq2000.c:651 +-#: elf32-m32c.c:564 elf32-m32r.c:3128 elf32-m68hc1x.c:1137 elf32-mep.c:646 +-#: elf32-msp430.c:501 elf32-openrisc.c:415 elf32-score.c:2460 elf32-spu.c:2817 +-#: elf32-v850.c:1705 elf32-xstormy16.c:950 elf64-mmix.c:1537 elf-m10200.c:460 +-#: elf-m10300.c:1527 elfxx-mips.c:8025 +-msgid "internal error: unsupported relocation error" +-msgstr "error interno: error de reubicación no admitida" +- +-#: elf32-avr.c:1261 elf32-bfin.c:2803 elf32-cris.c:1546 elf32-fr30.c:624 +-#: elf32-frv.c:4137 elf32-i860.c:1226 elf32-ip2k.c:1510 elf32-iq2000.c:655 +-#: elf32-m32c.c:568 elf32-mep.c:650 elf32-msp430.c:505 elf32-mt.c:406 +-#: elf32-openrisc.c:419 elf32-v850.c:1709 elf32-xstormy16.c:954 ++#: elf32-avr.c:1258 elf32-bfin.c:3222 elf32-cris.c:1546 elf32-fr30.c:624 ++#: elf32-frv.c:4122 elf32-i860.c:1226 elf32-ip2k.c:1510 elf32-iq2000.c:699 ++#: elf32-m32c.c:568 elf32-mep.c:549 elf32-msp430.c:501 elf32-mt.c:406 ++#: elf32-openrisc.c:419 elf32-v850.c:1711 elf32-xstormy16.c:956 + #: elf64-mmix.c:1541 + msgid "internal error: dangerous relocation" + msgstr "error interno: reubicación peligrosa" + +-#: elf32-avr.c:1265 elf32-bfin.c:2807 elf32-cr16.c:899 elf32-cr16c.c:802 +-#: elf32-cris.c:1550 elf32-crx.c:945 elf32-d10v.c:529 elf32-fr30.c:628 +-#: elf32-frv.c:4141 elf32-h8300.c:528 elf32-i860.c:1230 elf32-ip2k.c:1514 +-#: elf32-iq2000.c:659 elf32-m32c.c:572 elf32-m32r.c:3136 elf32-m68hc1x.c:1145 +-#: elf32-mep.c:654 elf32-msp430.c:509 elf32-mt.c:410 elf32-openrisc.c:423 +-#: elf32-score.c:2468 elf32-spu.c:2825 elf32-v850.c:1725 elf32-xstormy16.c:958 +-#: elf64-mmix.c:1545 elf-m10200.c:468 elf-m10300.c:1540 +-msgid "internal error: unknown error" +-msgstr "error interno: error desconocido" +- +-#: elf32-avr.c:2369 elf32-hppa.c:595 elf32-m68hc1x.c:164 elf64-ppc.c:3802 ++#: elf32-avr.c:2396 elf32-hppa.c:605 elf32-m68hc1x.c:164 elf64-ppc.c:3983 + msgid "%B: cannot create stub entry %s" + msgstr "%B: no se puede crear la entrada de cabo %s" + +-#: elf32-bfin.c:2274 ++#: elf32-bfin.c:1585 ++msgid "%B(%A+0x%lx): unresolvable relocation against symbol `%s'" ++msgstr "%B(%A+0x%lx): reubicación sin resolución contra el símbolo `%s'" ++ ++#: elf32-bfin.c:1618 elf32-i386.c:3623 elf32-m68k.c:3557 elf32-s390.c:3110 ++#: elf64-s390.c:3071 elf64-x86-64.c:3278 ++msgid "%B(%A+0x%lx): reloc against `%s': error %d" ++msgstr "%B(%A+0x%lx): reubicación contra `%s': error %d" ++ ++#: elf32-bfin.c:2711 + msgid "%B: relocation at `%A+0x%x' references symbol `%s' with nonzero addend" + msgstr "%B: la reubicación en `%A+0x%x' referencía al símbolo `%s' con adición que no es cero" + +-#: elf32-bfin.c:2288 elf32-frv.c:2919 ++#: elf32-bfin.c:2725 elf32-frv.c:2904 + msgid "relocation references symbol not defined in the module" + msgstr "la reubicación referencía un símbolo que no está definido en el módulo" + +-#: elf32-bfin.c:2385 ++#: elf32-bfin.c:2822 + msgid "R_BFIN_FUNCDESC references dynamic symbol with nonzero addend" + msgstr "R_BFIN_FUNCDESC referencía un símbolo dinámico con adición que no es cero" + +-#: elf32-bfin.c:2424 elf32-bfin.c:2547 elf32-frv.c:3656 elf32-frv.c:3777 ++#: elf32-bfin.c:2861 elf32-bfin.c:2987 elf32-frv.c:3641 elf32-frv.c:3762 + msgid "cannot emit fixups in read-only section" + msgstr "no se pueden emitir composturas en la sección de sólo lectura" + +-#: elf32-bfin.c:2452 elf32-bfin.c:2587 elf32-frv.c:3687 elf32-frv.c:3821 ++#: elf32-bfin.c:2889 elf32-bfin.c:3036 elf32-frv.c:3672 elf32-frv.c:3806 + msgid "cannot emit dynamic relocations in read-only section" +-msgstr "no se pueden emitri reubicaciones dinámicas en la sección de sólo lectura" ++msgstr "no se pueden emitir reubicaciones dinámicas en la sección de sólo lectura" + +-#: elf32-bfin.c:2505 ++#: elf32-bfin.c:2945 + msgid "R_BFIN_FUNCDESC_VALUE references dynamic symbol with nonzero addend" + msgstr "R_BFIN_FUNCDESC_VALUE referencía un símbolo dinámico con adición que no es cero" + +-#: elf32-bfin.c:2673 ++#: elf32-bfin.c:3126 + msgid "relocations between different segments are not supported" + msgstr "no se admiten las reubicaciones entre segmentos diferentes" + +-#: elf32-bfin.c:2674 ++#: elf32-bfin.c:3127 + msgid "warning: relocation references a different segment" + msgstr "aviso: la reubicación referencía un segmento diferente" + +-#: elf32-bfin.c:3083 +-msgid "%B(%A+0x%lx): unresolvable relocation against symbol `%s'" +-msgstr "%B(%A+0x%lx): reubicación sin resolución contra el símbolo `%s'" +- +-#: elf32-bfin.c:3116 elf32-i386.c:3351 elf32-m68k.c:2023 elf32-s390.c:3100 +-#: elf64-s390.c:3061 elf64-x86-64.c:3041 +-msgid "%B(%A+0x%lx): reloc against `%s': error %d" +-msgstr "%B(%A+0x%lx): reubicación contra `%s': error %d" +- +-#: elf32-bfin.c:4687 elf32-frv.c:6423 ++#: elf32-bfin.c:4791 elf32-frv.c:6404 + msgid "%B: unsupported relocation type %i" + msgstr "%B: no se admite el tipo de reubicación %i" + +-#: elf32-bfin.c:4868 elf32-frv.c:6831 ++#: elf32-bfin.c:4944 elf32-frv.c:6812 + #, c-format + msgid "%s: cannot link non-fdpic object file into fdpic executable" + msgstr "%s: no se puede enlazar el fichero objeto que no es fdpic en un ejecutable fdpic" + +-#: elf32-bfin.c:4872 elf32-frv.c:6835 ++#: elf32-bfin.c:4948 elf32-frv.c:6816 + #, c-format + msgid "%s: cannot link fdpic object file into non-fdpic executable" + msgstr "%s: no se puede enlazar el fichero objeto fdpic en un ejecutable que no es fdpic" + +-#: elf32-cr16.c:895 elf32-cr16c.c:798 elf32-crx.c:941 elf32-d10v.c:525 +-#: elf32-h8300.c:524 elf32-m32r.c:3132 elf32-m68hc1x.c:1141 elf32-score.c:2464 +-#: elf32-spu.c:2821 elf-m10200.c:464 +-msgid "internal error: dangerous error" +-msgstr "error interno: error peligroso" +- + #: elf32-cris.c:1060 + msgid "%B, section %A: unresolvable relocation %s against symbol `%s'" + msgstr "%B, sección %A: reubicación %s sin resolución contra el símbolo `%s'" +@@ -1086,7 +1259,7 @@ msgstr "%B, secci + msgid "%B: Internal inconsistency; no relocation section %s" + msgstr "%B: Inconsistencia interna; no se encuentra la sección de reubicación %s" + +-#: elf32-cris.c:2511 ++#: elf32-cris.c:2510 + msgid "" + "%B, section %A:\n" + " v10/v32 compatible object %s must not contain a PIC relocation" +@@ -1094,7 +1267,7 @@ msgstr "" + "%B, sección %A:\n" + " el objeto %s compatible con v10/v32 no debe contener una reubicación PIC" + +-#: elf32-cris.c:2698 elf32-cris.c:2766 ++#: elf32-cris.c:2697 elf32-cris.c:2765 + msgid "" + "%B, section %A:\n" + " relocation %s should not be used in a shared object; recompile with -fPIC" +@@ -1102,129 +1275,129 @@ msgstr "" + "%B, sección %A:\n" + " la reubicación %s no se debe usar en un objeto compartido; recompile con -fPIC" + +-#: elf32-cris.c:3183 ++#: elf32-cris.c:3184 + msgid "Unexpected machine number" + msgstr "Número de máquina inesperado" + +-#: elf32-cris.c:3237 ++#: elf32-cris.c:3238 + #, c-format + msgid " [symbols have a _ prefix]" + msgstr " [los símbolos tiene un prefijo _]" + +-#: elf32-cris.c:3240 ++#: elf32-cris.c:3241 + #, c-format + msgid " [v10 and v32]" + msgstr " [v10 y v32]" + +-#: elf32-cris.c:3243 ++#: elf32-cris.c:3244 + #, c-format + msgid " [v32]" + msgstr " [v32]" + +-#: elf32-cris.c:3288 ++#: elf32-cris.c:3289 + msgid "%B: uses _-prefixed symbols, but writing file with non-prefixed symbols" + msgstr "%B: utiliza símbolos con prefijo _, pero escribe el fichero con símbolos sin prefijo" + +-#: elf32-cris.c:3289 ++#: elf32-cris.c:3290 + msgid "%B: uses non-prefixed symbols, but writing file with _-prefixed symbols" + msgstr "%B: utiliza símbolos sin prefijo, pero escribe el fichero con símbolos con prefijo _" + +-#: elf32-cris.c:3308 ++#: elf32-cris.c:3309 + msgid "%B contains CRIS v32 code, incompatible with previous objects" + msgstr "%B contiene código CRIS v32, incompatible con objetos previos" + +-#: elf32-cris.c:3310 ++#: elf32-cris.c:3311 + msgid "%B contains non-CRIS-v32 code, incompatible with previous objects" + msgstr "%B contiene código que no es CRIS v32, incompatible con objetos previos" + +-#: elf32-frv.c:1523 elf32-frv.c:1672 ++#: elf32-frv.c:1507 elf32-frv.c:1656 + msgid "relocation requires zero addend" + msgstr "la reubicación requiere una adición cero" + +-#: elf32-frv.c:2906 ++#: elf32-frv.c:2891 + msgid "%B(%A+0x%x): relocation to `%s+%x' may have caused the error above" + msgstr "%B(%A+0x%x): la reubicación a `%s+%x' tal vez causó el error anterior" + +-#: elf32-frv.c:2995 ++#: elf32-frv.c:2980 + msgid "R_FRV_GETTLSOFF not applied to a call instruction" + msgstr "no se aplicó R_FRV_GETTLSOFF a una instrucción call" + +-#: elf32-frv.c:3037 ++#: elf32-frv.c:3022 + msgid "R_FRV_GOTTLSDESC12 not applied to an lddi instruction" + msgstr "no se aplicó R_FRV_GOTTLSDESC12 a una instrucción lddi" + +-#: elf32-frv.c:3108 ++#: elf32-frv.c:3093 + msgid "R_FRV_GOTTLSDESCHI not applied to a sethi instruction" + msgstr "no se aplicó R_FRV_GOTTLSDESCHI a una instrucción sethi" + +-#: elf32-frv.c:3145 ++#: elf32-frv.c:3130 + msgid "R_FRV_GOTTLSDESCLO not applied to a setlo or setlos instruction" + msgstr "no se aplicó R_FRV_GOTTLSDESCLO a una instrucción setlo o setlos" + +-#: elf32-frv.c:3193 ++#: elf32-frv.c:3178 + msgid "R_FRV_TLSDESC_RELAX not applied to an ldd instruction" + msgstr "no se aplicó R_FRV_GOTTLSDESC_RELAX a una instrucción ldd" + +-#: elf32-frv.c:3277 ++#: elf32-frv.c:3262 + msgid "R_FRV_GETTLSOFF_RELAX not applied to a calll instruction" + msgstr "no se aplicó R_FRV_GETTLSOFF_RELAX a una instrucción calll" + +-#: elf32-frv.c:3332 ++#: elf32-frv.c:3317 + msgid "R_FRV_GOTTLSOFF12 not applied to an ldi instruction" + msgstr "no se aplicó R_FRV_GOTTLSOFF12 a una instrucción ldi" + +-#: elf32-frv.c:3362 ++#: elf32-frv.c:3347 + msgid "R_FRV_GOTTLSOFFHI not applied to a sethi instruction" + msgstr "no se aplicó R_FRV_GOTTLSOFFHI a una instrucción sethi" + +-#: elf32-frv.c:3391 ++#: elf32-frv.c:3376 + msgid "R_FRV_GOTTLSOFFLO not applied to a setlo or setlos instruction" + msgstr "no se aplicó R_FRV_GOTTLSOFFLO a una instrucción setlo o setlos" + +-#: elf32-frv.c:3422 ++#: elf32-frv.c:3407 + msgid "R_FRV_TLSOFF_RELAX not applied to an ld instruction" + msgstr "no se aplicó R_FRV_TLSOFF_RELAX a una instrucción ld" + +-#: elf32-frv.c:3467 ++#: elf32-frv.c:3452 + msgid "R_FRV_TLSMOFFHI not applied to a sethi instruction" + msgstr "no se aplicó R_FRV_TLSMOFFHI a una instrucción sethi" + +-#: elf32-frv.c:3494 ++#: elf32-frv.c:3479 + msgid "R_FRV_TLSMOFFLO not applied to a setlo or setlos instruction" + msgstr "no se aplicó R_FRV_TLSMOFFLO a una instrucción setlo o setlos" + +-#: elf32-frv.c:3615 ++#: elf32-frv.c:3600 + msgid "R_FRV_FUNCDESC references dynamic symbol with nonzero addend" + msgstr "R_FRV_FUNCDESC referencía un símbolo dinámico con adición que no es cero" + +-#: elf32-frv.c:3735 ++#: elf32-frv.c:3720 + msgid "R_FRV_FUNCDESC_VALUE references dynamic symbol with nonzero addend" + msgstr "R_FRV_FUNCDESC_VALUE referencía un símbolo dinámico con adición que no es cero" + +-#: elf32-frv.c:3992 elf32-frv.c:4148 ++#: elf32-frv.c:3977 elf32-frv.c:4133 + msgid "%B(%A+0x%lx): reloc against `%s': %s" + msgstr "%B(%A+0x%lx): reubicación contra `%s': %s" + +-#: elf32-frv.c:3994 elf32-frv.c:3998 ++#: elf32-frv.c:3979 elf32-frv.c:3983 + msgid "relocation references a different segment" + msgstr "la reubicación referencía un segmento diferente" + +-#: elf32-frv.c:6745 ++#: elf32-frv.c:6726 + #, c-format + msgid "%s: compiled with %s and linked with modules that use non-pic relocations" + msgstr "%s: compilado con %s y enlazado con módulos que usan reubicaciones que no son pic" + +-#: elf32-frv.c:6798 elf32-iq2000.c:808 elf32-m32c.c:819 ++#: elf32-frv.c:6779 elf32-iq2000.c:852 elf32-m32c.c:814 + #, c-format + msgid "%s: compiled with %s and linked with modules compiled with %s" + msgstr "%s: compilado con %s y enlazado con módulos compilados con %s" + +-#: elf32-frv.c:6810 ++#: elf32-frv.c:6791 + #, c-format + msgid "%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)" + msgstr "%s: usa campos e_flags desconocidos (0x%lx) diferentes a aquéllos de los módulos previos (0x%lx)" + +-#: elf32-frv.c:6860 elf32-iq2000.c:845 elf32-m32c.c:855 elf32-mt.c:587 ++#: elf32-frv.c:6841 elf32-iq2000.c:889 elf32-m32c.c:850 elf32-mt.c:583 + #, c-format + msgid "private flags = 0x%lx:" + msgstr "opciones privadas = 0x%lx:" +@@ -1233,55 +1406,79 @@ msgstr "opciones privadas = 0x%lx:" + msgid "%B: Relocations in generic ELF (EM: %d)" + msgstr "%B: Reubicaciones en ELF genérico (EM: %d)" + +-#: elf32-hppa.c:844 elf32-hppa.c:3577 ++#: elf32-hppa.c:854 elf32-hppa.c:3600 + msgid "%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections" + msgstr "%B(%A+0x%lx): no se puede alcanzar %s, recompile con -ffuntion-sections" + +-#: elf32-hppa.c:1253 ++#: elf32-hppa.c:1263 + msgid "%B: relocation %s can not be used when making a shared object; recompile with -fPIC" + msgstr "%B: no se puede usar la reubicación %s cuando se hace un objeto compartido; recompile con -fPIC" + +-#: elf32-hppa.c:1506 ++#: elf32-hppa.c:1518 + #, c-format + msgid "Could not find relocation section for %s" + msgstr "No se puede encontrar la sección de reubicación para %s" + +-#: elf32-hppa.c:2795 ++#: elf32-hppa.c:2810 + msgid "%B: duplicate export stub %s" + msgstr "%B: cabo de exportación %s duplicado" + +-#: elf32-hppa.c:3413 ++#: elf32-hppa.c:3436 + msgid "%B(%A+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link" + msgstr "%B(%A+0x%lx): la compostura %s para la insn 0x%x no se admite en un enlazado que no es compartido" + +-#: elf32-hppa.c:4267 ++#: elf32-hppa.c:4290 + msgid "%B(%A+0x%lx): cannot handle %s for %s" + msgstr "%B(%A+0x%lx): no se puede manejar %s para %s" + +-#: elf32-hppa.c:4574 ++#: elf32-hppa.c:4597 + msgid ".got section not immediately after .plt section" + msgstr "la sección .got no está inmediatamente después de la sección .plt" + +-#: elf32-i386.c:364 elf32-ppc.c:1616 elf32-s390.c:379 elf64-ppc.c:2148 +-#: elf64-s390.c:403 elf64-x86-64.c:221 ++#: elf32-i386.c:362 elf32-ppc.c:1616 elf32-s390.c:379 elf64-ppc.c:2153 ++#: elf64-s390.c:403 elf64-x86-64.c:222 + msgid "%B: invalid relocation type %d" + msgstr "%B: tipo de reubicación %d inválido" + +-#: elf32-i386.c:1085 elf32-s390.c:1185 elf32-sh.c:5063 elf64-s390.c:1149 +-#: elfxx-sparc.c:1243 ++#: elf32-i386.c:1183 elf64-x86-64.c:964 ++msgid "%B: TLS transition from %s to %s against `%s' at 0x%lx in section `%A' failed" ++msgstr "%B: falló la transición TLS de %s para %s contra `%s' en 0x%lx en la sección `%A'" ++ ++#: elf32-i386.c:1364 elf32-s390.c:1188 elf32-sh.c:5098 elf32-xtensa.c:1162 ++#: elf64-s390.c:1152 elfxx-sparc.c:1263 + msgid "%B: `%s' accessed both as normal and thread local symbol" + msgstr "%B: se accesó `%s' como un símbolo normal y un símbolo local de hilo" + +-#: elf32-i386.c:1200 elf32-s390.c:1294 elf64-ppc.c:4864 elf64-s390.c:1261 +-#: elf64-x86-64.c:1051 ++#: elf32-i386.c:1479 elf32-s390.c:1297 elf64-ppc.c:5046 elf64-s390.c:1264 ++#: elf64-x86-64.c:1299 + msgid "%B: bad relocation section name `%s'" + msgstr "%B: nombre de sección de reubicación `%s' erróneo" + +-#: elf32-i386.c:2257 ++#: elf32-i386.c:2598 + msgid "%B: unrecognized relocation (0x%x) in section `%A'" + msgstr "%B: no se reconoce la dirección de reubicación (0x%lx) en la sección `%A'" + +-#: elf32-i386.c:2479 ++#: elf32-i386.c:2822 elf64-x86-64.c:2660 ++msgid "hidden symbol" ++msgstr "símbolo oculto" ++ ++#: elf32-i386.c:2825 elf64-x86-64.c:2663 ++msgid "internal symbol" ++msgstr "símbolo interno" ++ ++#: elf32-i386.c:2828 elf64-x86-64.c:2666 ++msgid "protected symbol" ++msgstr "símbolos protegido" ++ ++#: elf32-i386.c:2831 elf64-x86-64.c:2669 ++msgid "symbol" ++msgstr "símbolo" ++ ++#: elf32-i386.c:2836 ++msgid "%B: relocation R_386_GOTOFF against undefined %s `%s' can not be used when making a shared object" ++msgstr "%B: no se puede usar la reubicación R_386_GOTOFF contra %s indefinida `%s' cuando se hace un objeto compartido" ++ ++#: elf32-i386.c:2846 + msgid "%B: relocation R_386_GOTOFF against protected function `%s' can not be used when making a shared object" + msgstr "%B: no se puede usar la reubicación R_386_GOTOFF contra la función protegida `%s' cuando se hace un objeto compartido" + +@@ -1308,7 +1505,7 @@ msgstr "enlazador ip2k: instrucci + msgid "unsupported relocation between data/insn address spaces" + msgstr "no se admite la reubicación entre espacios de direcciones datos/insn" + +-#: elf32-iq2000.c:821 elf32-m32c.c:831 ++#: elf32-iq2000.c:865 elf32-m32c.c:826 + #, c-format + msgid "%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)" + msgstr "%s: usa campos de e_flags diferentes (0x%lx) que los módulos previos (0x%lx)" +@@ -1345,86 +1542,94 @@ msgstr ": instrucciones m32rx" + msgid ": m32r2 instructions" + msgstr ": instrucciones m32r2" + +-#: elf32-m68hc1x.c:1045 ++#: elf32-m68hc1x.c:1047 + #, c-format + msgid "Reference to the far symbol `%s' using a wrong relocation may result in incorrect execution" + msgstr "El referenciar al símbolo far `%s' usando una reubicación incorrecta puede resultar en una ejecución incorrecta" + +-#: elf32-m68hc1x.c:1068 ++#: elf32-m68hc1x.c:1070 + #, c-format + msgid "banked address [%lx:%04lx] (%lx) is not in the same bank as current banked address [%lx:%04lx] (%lx)" + msgstr "la dirección almacenada [%lx:%04lx] (%lx) no está en el mismo banco que la dirección almacenada actual [%lx:%04lx] (%lx)" + +-#: elf32-m68hc1x.c:1087 ++#: elf32-m68hc1x.c:1089 + #, c-format + msgid "reference to a banked address [%lx:%04lx] in the normal address space at %04lx" + msgstr "referencia a una dirección almacenada [%lx:%04lx] en el espacio normal de direcciones en %04lx" + +-#: elf32-m68hc1x.c:1220 ++#: elf32-m68hc1x.c:1222 + msgid "%B: linking files compiled for 16-bit integers (-mshort) and others for 32-bit integers" + msgstr "%B: se enlazan ficheros compilados con enteros de 16-bit (-mshort) y otros con enteros de 32-bit" + +-#: elf32-m68hc1x.c:1227 ++#: elf32-m68hc1x.c:1229 + msgid "%B: linking files compiled for 32-bit double (-fshort-double) and others for 64-bit double" + msgstr "%B: se enlazan ficheros compilados con dobles de 32-bit (-fshort-double) y otros con dobles de 64-bit" + +-#: elf32-m68hc1x.c:1236 ++#: elf32-m68hc1x.c:1238 + msgid "%B: linking files compiled for HCS12 with others compiled for HC12" + msgstr "%B: se enlazan ficheros compilados para HCS12, con otros compilados para HC12" + +-#: elf32-m68hc1x.c:1252 elf32-ppc.c:3734 elf64-sparc.c:697 elfxx-mips.c:11292 ++#: elf32-m68hc1x.c:1254 elf32-ppc.c:4046 elf64-sparc.c:697 elfxx-mips.c:12561 + msgid "%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)" + msgstr "%B: usa campos de e_flags diferentes (0x%lx) que los módulos previos (0x%lx)" + +-#: elf32-m68hc1x.c:1280 ++#: elf32-m68hc1x.c:1282 + #, c-format + msgid "[abi=32-bit int, " + msgstr "[abi=int de 32-bit, " + +-#: elf32-m68hc1x.c:1282 ++#: elf32-m68hc1x.c:1284 + #, c-format + msgid "[abi=16-bit int, " + msgstr "[abi=int de 16-bit, " + +-#: elf32-m68hc1x.c:1285 ++#: elf32-m68hc1x.c:1287 + #, c-format + msgid "64-bit double, " + msgstr "doble de 64-bit, " + +-#: elf32-m68hc1x.c:1287 ++#: elf32-m68hc1x.c:1289 + #, c-format + msgid "32-bit double, " + msgstr "doble de 32-bit, " + +-#: elf32-m68hc1x.c:1290 ++#: elf32-m68hc1x.c:1292 + #, c-format + msgid "cpu=HC11]" + msgstr "cpu=HC11]" + +-#: elf32-m68hc1x.c:1292 ++#: elf32-m68hc1x.c:1294 + #, c-format + msgid "cpu=HCS12]" + msgstr "cpu=HCS12]" + +-#: elf32-m68hc1x.c:1294 ++#: elf32-m68hc1x.c:1296 + #, c-format + msgid "cpu=HC12]" + msgstr "cpu=HC12]" + +-#: elf32-m68hc1x.c:1297 ++#: elf32-m68hc1x.c:1299 + #, c-format + msgid " [memory=bank-model]" + msgstr " [memoria=modelo de bancos]" + +-#: elf32-m68hc1x.c:1299 ++#: elf32-m68hc1x.c:1301 + #, c-format + msgid " [memory=flat]" + msgstr " [memoria=plana]" + +-#: elf32-m68k.c:635 elf32-m68k.c:636 ++#: elf32-m68k.c:789 elf32-m68k.c:790 + msgid "unknown" + msgstr "desconocido" + ++#: elf32-m68k.c:1216 ++msgid "%B: GOT overflow: Number of R_68K_GOT8O relocations > %d" ++msgstr "%B: desbordamiento de GOT: Número de reubicaciones R_68K_GOT80 > %d" ++ ++#: elf32-m68k.c:1221 ++msgid "%B: GOT overflow: Number of R_68K_GOT8O and R_68K_GOT16O relocations > %d" ++msgstr "%B desbordamiento de GOT: Número de reubicaciones R_68K_GOT80 Y R_68K_GOT160 > %d" ++ + #: elf32-mcore.c:99 elf32-mcore.c:442 + msgid "%B: Relocation %s (%d) is not currently supported.\n" + msgstr "%B: La reubicación %s (%d) actualmente no se admite.\n" +@@ -1433,24 +1638,24 @@ msgstr "%B: La reubicaci + msgid "%B: Unknown relocation type %d\n" + msgstr "%B: Tipo de reubicación %d desconocido\n" + +-#: elf32-mep.c:812 ++#: elf32-mep.c:654 + msgid "%B and %B are for different cores" + msgstr "%B y %B son para núcleos diferentes" + +-#: elf32-mep.c:829 ++#: elf32-mep.c:671 + msgid "%B and %B are for different configurations" + msgstr "%B y %B son para configuraciones diferentes" + +-#: elf32-mep.c:867 ++#: elf32-mep.c:709 + #, c-format + msgid "private flags = 0x%lx" + msgstr "opciones privadas = 0x%lx" + +-#: elf32-mips.c:989 elf64-mips.c:1976 elfn32-mips.c:1808 ++#: elf32-mips.c:1045 elf64-mips.c:2056 elfn32-mips.c:1888 + msgid "literal relocation occurs for an external symbol" + msgstr "la reubicación literal sucede para un símbolo externo" + +-#: elf32-mips.c:1029 elf32-score.c:484 elf64-mips.c:2019 elfn32-mips.c:1849 ++#: elf32-mips.c:1085 elf32-score.c:484 elf64-mips.c:2099 elfn32-mips.c:1929 + msgid "32bits gp relative relocation occurs for an external symbol" + msgstr "la reubicación gp relativa de 32bits sucede para un símbolo externo" + +@@ -1459,162 +1664,143 @@ msgstr "la reubicaci + msgid "generic linker can't handle %s" + msgstr "el enlazador genérico no puede manejar %s" + +-#: elf32-ppc.c:2163 ++#: elf32-ppc.c:2161 + msgid "corrupt or empty %s section in %B" + msgstr "sección %s corrupta o vacía en %B" + +-#: elf32-ppc.c:2170 ++#: elf32-ppc.c:2168 + msgid "unable to read in %s section from %B" + msgstr "no se puede leer en la sección %s desde %B" + +-#: elf32-ppc.c:2176 ++#: elf32-ppc.c:2174 + msgid "corrupt %s section in %B" + msgstr "sección %s corrupta en %B" + +-#: elf32-ppc.c:2219 ++#: elf32-ppc.c:2217 + msgid "warning: unable to set size of %s section in %B" + msgstr "aviso: no se puede establecer el tamaño de la sección %s en %B" + +-#: elf32-ppc.c:2267 ++#: elf32-ppc.c:2265 + msgid "failed to allocate space for new APUinfo section." + msgstr "no se puede reservar espacio para la nueva sección APUinfo." + +-#: elf32-ppc.c:2286 ++#: elf32-ppc.c:2284 + msgid "failed to compute new APUinfo section." + msgstr "no se puede calcular la nueva sección APUinfo." + +-#: elf32-ppc.c:2289 ++#: elf32-ppc.c:2287 + msgid "failed to install new APUinfo section." + msgstr "no se puede instalar la nueva sección APUinfo." + +-#: elf32-ppc.c:3022 ++#: elf32-ppc.c:3263 + msgid "%B: relocation %s cannot be used when making a shared object" + msgstr "%B: no se puede usar la reubicación %s cuando se hace un objeto compartido" + + #. It does not make sense to have a procedure linkage + #. table entry for a local symbol. +-#: elf32-ppc.c:3292 ++#: elf32-ppc.c:3534 + msgid "%B(%A+0x%lx): %s reloc against local symbol" + msgstr "%B(%A+0x%lx): reubicación %s contra un símbolo local" + +-#: elf32-ppc.c:3633 elf32-ppc.c:3637 elfxx-mips.c:11036 elfxx-mips.c:11055 +-#: elfxx-mips.c:11070 ++#: elf32-ppc.c:3885 elf32-ppc.c:3900 elfxx-mips.c:12268 elfxx-mips.c:12294 ++#: elfxx-mips.c:12316 elfxx-mips.c:12342 + msgid "Warning: %B uses hard float, %B uses soft float" + msgstr "Aviso: %B usa coma flotante hard, %B usa coma flotante soft" + +-#: elf32-ppc.c:3640 elf32-ppc.c:3644 elfxx-mips.c:11017 elfxx-mips.c:11021 ++#: elf32-ppc.c:3888 elf32-ppc.c:3892 ++msgid "Warning: %B uses double-precision hard float, %B uses single-precision hard float" ++msgstr "Aviso: %B usa coma flotante hard de doble precisión, %B usa coma flotante hard de precisión simple" ++ ++#: elf32-ppc.c:3896 ++msgid "Warning: %B uses soft float, %B uses single-precision hard float" ++msgstr "Aviso: %B usa coma flotante soft, %B usa coma flotante hard de precisión simple" ++ ++#: elf32-ppc.c:3903 elf32-ppc.c:3907 elfxx-mips.c:12248 elfxx-mips.c:12252 + msgid "Warning: %B uses unknown floating point ABI %d" + msgstr "Aviso: %B usa la ABI de coma flotante desconocida %d" + +-#: elf32-ppc.c:3699 ++#: elf32-ppc.c:3949 elf32-ppc.c:3953 ++msgid "Warning: %B uses unknown vector ABI %d" ++msgstr "Aviso: %B usa la ABI de vector desconocida %d" ++ ++#: elf32-ppc.c:3957 ++msgid "Warning: %B uses vector ABI \"%s\", %B uses \"%s\"" ++msgstr "Aviso: %B usa la ABI de vector \"%s\", %B usa \"%s\"" ++ ++#: elf32-ppc.c:4011 + msgid "%B: compiled with -mrelocatable and linked with modules compiled normally" + msgstr "%B: compilado con -mrelocatable y enlazado con módulos compilados de forma normal" + +-#: elf32-ppc.c:3707 ++#: elf32-ppc.c:4019 + msgid "%B: compiled normally and linked with modules compiled with -mrelocatable" + msgstr "%B: compilado de forma normal y enlazado con módulos compilados con -mrelocatable" + +-#: elf32-ppc.c:3793 ++#: elf32-ppc.c:4105 + msgid "Using bss-plt due to %B" + msgstr "Se usa bss-plt debido a %B" + +-#: elf32-ppc.c:6002 elf64-ppc.c:10490 ++#: elf32-ppc.c:6418 elf64-ppc.c:10881 + msgid "%B: unknown relocation type %d for symbol %s" + msgstr "%B: tipo de reubicación %d desconocido para el símbolo %s" + +-#: elf32-ppc.c:6252 ++#: elf32-ppc.c:6668 + msgid "%B(%A+0x%lx): non-zero addend on %s reloc against `%s'" + msgstr "%B(%A+0x%lx): adición que no es cero en la reubicación %s contra `%s'" + +-#: elf32-ppc.c:6597 elf32-ppc.c:6623 elf32-ppc.c:6682 ++#: elf32-ppc.c:7024 elf32-ppc.c:7050 elf32-ppc.c:7109 + msgid "%B: the target (%s) of a %s relocation is in the wrong output section (%s)" + msgstr "%B: el objetivo (%s) de una reubicación %s está en la sección de salida errónea (%s)" + +-#: elf32-ppc.c:6737 ++#: elf32-ppc.c:7164 + msgid "%B: relocation %s is not yet supported for symbol %s." + msgstr "%B: la reubicación %s aún no se admite para el símbolo %s." + +-#: elf32-ppc.c:6845 elf64-ppc.c:11185 ++#: elf32-ppc.c:7272 elf64-ppc.c:11575 + msgid "%B(%A+0x%lx): %s reloc against `%s': error %d" + msgstr "%B(%A+0x%lx): reubicación %s contra `%s': error %d" + +-#: elf32-s390.c:2238 elf64-s390.c:2212 ++#: elf32-s390.c:2246 elf64-s390.c:2220 + msgid "%B(%A+0x%lx): invalid instruction for TLS relocation %s" + msgstr "%B(%A+0x%lx): instrucción inválida para la reubicación TLS %s" + +-#: elf32-score.c:1418 elfxx-mips.c:2699 ++#: elf32-score.c:1415 elfxx-mips.c:3273 + msgid "not enough GOT space for local GOT entries" + msgstr "no hay suficiente espacio GOT para entradas GOT locales" + +-#: elf32-score.c:2550 ++#: elf32-score.c:2545 + #, c-format + msgid "%s: Malformed reloc detected for section %s" + msgstr "%s: Se detectó una reubicación malformada para la sección %s" + +-#: elf32-score.c:2601 ++#: elf32-score.c:2596 + msgid "%B: CALL15 reloc at 0x%lx not against global symbol" + msgstr "%B: la reubicación CALL15 en 0x%lx no es contra un símbolo global" + +-#: elf32-score.c:3756 ++#: elf32-score.c:3753 + #, c-format + msgid " [pic]" + msgstr " [pic]" + +-#: elf32-score.c:3760 ++#: elf32-score.c:3757 + #, c-format + msgid " [fix dep]" + msgstr " [fix dep]" + +-#: elf32-score.c:3802 elfxx-mips.c:11201 ++#: elf32-score.c:3799 + msgid "%B: warning: linking PIC files with non-PIC files" + msgstr "%B: aviso: se enlazan ficheros PIC con ficheros que no son PIC" + +-#: elf32-sh64.c:222 elf64-sh64.c:2350 +-#, c-format +-msgid "%s: compiled as 32-bit object and %s is 64-bit" +-msgstr "%s: compilado como un objeto de 32-bit y %s es de 64-bit" +- +-#: elf32-sh64.c:225 elf64-sh64.c:2353 +-#, c-format +-msgid "%s: compiled as 64-bit object and %s is 32-bit" +-msgstr "%s: compilado como un objeto de 64-bit y %s es de 32-bit" +- +-#: elf32-sh64.c:227 elf64-sh64.c:2355 +-#, c-format +-msgid "%s: object size does not match that of target %s" +-msgstr "%s: el tamaño del objeto no coincide con el tamaño del objetivo %s" +- +-#: elf32-sh64.c:450 elf64-sh64.c:2894 +-#, c-format +-msgid "%s: encountered datalabel symbol in input" +-msgstr "%s: se encontró un símbolo datalabel en la entrada" +- +-#: elf32-sh64.c:527 +-msgid "PTB mismatch: a SHmedia address (bit 0 == 1)" +-msgstr "No coincide PTB: una dirección SHmedia (bit 0 == 1)" +- +-#: elf32-sh64.c:530 +-msgid "PTA mismatch: a SHcompact address (bit 0 == 0)" +-msgstr "No coincide PTA: una dirección SHcompact (bit 0 == 0)" +- +-#: elf32-sh64.c:548 +-#, c-format +-msgid "%s: GAS error: unexpected PTB insn with R_SH_PT_16" +-msgstr "%s: error de GAS: instrucción PTB inesperada con R_SH_PT_16" +- +-#: elf32-sh64.c:597 +-msgid "%B: error: unaligned relocation type %d at %08x reloc %p\n" +-msgstr "%B: error: tipo de reubicación %d sin alinear en %08x reubicación %p\n" ++#: elf32-sh-symbian.c:130 ++msgid "%B: IMPORT AS directive for %s conceals previous IMPORT AS" ++msgstr "%B: la directiva IMPORT AS para %s oculta un IMPORT AS previo" + +-#: elf32-sh64.c:673 +-#, c-format +-msgid "%s: could not write out added .cranges entries" +-msgstr "%s: no se pueden escribir las entradas .cranges agregadas" ++#: elf32-sh-symbian.c:383 ++msgid "%B: Unrecognised .directive command: %s" ++msgstr "%B: Orden .directive no reconocida: %s" + +-#: elf32-sh64.c:733 +-#, c-format +-msgid "%s: could not write out sorted .cranges entries" +-msgstr "%s: no se pueden escribir las entradas .cranges ordenadas" ++#: elf32-sh-symbian.c:504 ++msgid "%B: Failed to add renamed symbol %s" ++msgstr "%B: Falló al agregar el símbolo renombrado %s" + + #: elf32-sh.c:533 + msgid "%B: 0x%lx: warning: bad R_SH_USES offset" +@@ -1648,41 +1834,76 @@ msgstr "%B: 0x%lx: aviso: cuenta err + msgid "%B: 0x%lx: fatal: reloc overflow while relaxing" + msgstr "%B: 0x%lx: fatal: desbordamiento de reubicación durante la relajación" + +-#: elf32-sh.c:3249 elf64-sh64.c:1526 ++#: elf32-sh.c:3279 elf64-sh64.c:1526 + msgid "Unexpected STO_SH5_ISA32 on local symbol is not handled" + msgstr "No se maneja un STO_SH5_ISA32 inesperado en un símbolo local" + +-#: elf32-sh.c:3486 ++#: elf32-sh.c:3516 + msgid "%B: 0x%lx: fatal: unaligned branch target for relax-support relocation" + msgstr "%B: 0x%lx: fatal: objetivo de ramificación sin alineación para la reubicación de soporte de relajamiento" + +-#: elf32-sh.c:3519 elf32-sh.c:3534 ++#: elf32-sh.c:3549 elf32-sh.c:3564 + msgid "%B: 0x%lx: fatal: unaligned %s relocation 0x%lx" + msgstr "%B: 0x%lx: fatal: reubicación %s sin alineación 0x%lx" + +-#: elf32-sh.c:3548 ++#: elf32-sh.c:3578 + msgid "%B: 0x%lx: fatal: R_SH_PSHA relocation %d not in range -32..32" + msgstr "%B: 0x%lx: fatal: la reubicación R_SH_PSHA %d no está en el rango -32..32" + +-#: elf32-sh.c:3562 ++#: elf32-sh.c:3592 + msgid "%B: 0x%lx: fatal: R_SH_PSHL relocation %d not in range -32..32" + msgstr "%B: 0x%lx: fatal: la reubicación R_SH_PSHL %d no está en el rango -32..32" + +-#: elf32-sh.c:5275 elf64-alpha.c:4533 ++#: elf32-sh.c:5310 elf64-alpha.c:4552 + msgid "%B: TLS local exec code cannot be linked into shared objects" + msgstr "%B: el código de ejecución local TLS no se puede enlazar en objetos compartidos" + +-#: elf32-sh-symbian.c:130 +-msgid "%B: IMPORT AS directive for %s conceals previous IMPORT AS" +-msgstr "%B: la directiva IMPORT AS para %s oculta un IMPORT AS previo" ++#: elf32-sh64.c:222 elf64-sh64.c:2345 ++#, c-format ++msgid "%s: compiled as 32-bit object and %s is 64-bit" ++msgstr "%s: compilado como un objeto de 32-bit y %s es de 64-bit" + +-#: elf32-sh-symbian.c:383 +-msgid "%B: Unrecognised .directive command: %s" +-msgstr "%B: Orden .directive no reconocida: %s" ++#: elf32-sh64.c:225 elf64-sh64.c:2348 ++#, c-format ++msgid "%s: compiled as 64-bit object and %s is 32-bit" ++msgstr "%s: compilado como un objeto de 64-bit y %s es de 32-bit" + +-#: elf32-sh-symbian.c:504 +-msgid "%B: Failed to add renamed symbol %s" +-msgstr "%B: Falló al agregar el símbolo renombrado %s" ++#: elf32-sh64.c:227 elf64-sh64.c:2350 ++#, c-format ++msgid "%s: object size does not match that of target %s" ++msgstr "%s: el tamaño del objeto no coincide con el tamaño del objetivo %s" ++ ++#: elf32-sh64.c:450 elf64-sh64.c:2888 ++#, c-format ++msgid "%s: encountered datalabel symbol in input" ++msgstr "%s: se encontró un símbolo datalabel en la entrada" ++ ++#: elf32-sh64.c:527 ++msgid "PTB mismatch: a SHmedia address (bit 0 == 1)" ++msgstr "No coincide PTB: una dirección SHmedia (bit 0 == 1)" ++ ++#: elf32-sh64.c:530 ++msgid "PTA mismatch: a SHcompact address (bit 0 == 0)" ++msgstr "No coincide PTA: una dirección SHcompact (bit 0 == 0)" ++ ++#: elf32-sh64.c:548 ++#, c-format ++msgid "%s: GAS error: unexpected PTB insn with R_SH_PT_16" ++msgstr "%s: error de GAS: instrucción PTB inesperada con R_SH_PT_16" ++ ++#: elf32-sh64.c:597 ++msgid "%B: error: unaligned relocation type %d at %08x reloc %p\n" ++msgstr "%B: error: tipo de reubicación %d sin alinear en %08x reubicación %p\n" ++ ++#: elf32-sh64.c:673 ++#, c-format ++msgid "%s: could not write out added .cranges entries" ++msgstr "%s: no se pueden escribir las entradas .cranges agregadas" ++ ++#: elf32-sh64.c:733 ++#, c-format ++msgid "%s: could not write out sorted .cranges entries" ++msgstr "%s: no se pueden escribir las entradas .cranges ordenadas" + + #: elf32-sparc.c:89 + msgid "%B: compiled for a 64 bit system and target is 32 bit" +@@ -1692,69 +1913,103 @@ msgstr "%B: compilado para un sistema de 64 bit y el objetivo es de 32 bit" + msgid "%B: linking little endian files with big endian files" + msgstr "%B: se enlazan ficheros little endian con ficheros big endian" + +-#: elf32-spu.c:995 ++#: elf32-spu.c:607 ++msgid "%X%P: overlay sections %A and %A do not start at the same address.\n" ++msgstr "%X%P: las secciones de sobreescritura %A y %A no inician en la misma dirección.\n" ++ ++#: elf32-spu.c:805 + msgid "warning: call to non-function symbol %s defined in %B" + msgstr "aviso: se llama al símbolo %s que no es función, definido en %B" + +-#: elf32-spu.c:1315 ++#: elf32-spu.c:1406 + msgid "%B is not allowed to define %s" + msgstr "%B no se permite para definir %s" + +-#: elf32-spu.c:1352 ++#: elf32-spu.c:1453 + #, c-format + msgid "%s in overlay section" + msgstr "%s en la sección de sobreescritura" + +-#: elf32-spu.c:1363 ++#: elf32-spu.c:1469 + msgid "overlay stub relocation overflow" + msgstr "desbordamiento del segmento de reubicación de sobreescritura" + +-#: elf32-spu.c:1820 ++#: elf32-spu.c:1478 elf64-ppc.c:10078 ++msgid "stubs don't match calculated size" ++msgstr "los cabos no coinciden con el tamaño calculado" ++ ++#: elf32-spu.c:1976 + #, c-format + msgid "warning: %s overlaps %s\n" + msgstr "aviso: %s sobreescribe %s\n" + +-#: elf32-spu.c:1836 ++#: elf32-spu.c:1992 + #, c-format + msgid "warning: %s exceeds section size\n" + msgstr "aviso: %s excede el tamaño de la sección\n" + +-#: elf32-spu.c:1867 ++#: elf32-spu.c:2023 + msgid "%A:0x%v not found in function table\n" + msgstr "%A:0x%v no se encuentra en la tabla de función\n" + +-#: elf32-spu.c:1958 +-msgid "%B(%A+0x%v): call to non-code section %B(%A), stack analysis incomplete\n" +-msgstr "%B(%A+0x%v): se llama a la sección %B(%A) que no es de código, análisis de pila incompleto\n" ++#: elf32-spu.c:2165 ++msgid "%B(%A+0x%v): call to non-code section %B(%A), analysis incomplete\n" ++msgstr "%B(%A+0x%v): se llama a la sección %B(%A) que no es de código, análisis incompleto\n" + +-#: elf32-spu.c:2079 ++#: elf32-spu.c:2339 + #, c-format + msgid "%A link_order not found\n" + msgstr "no se encontró link_order %A\n" + +-#: elf32-spu.c:2358 ++#: elf32-spu.c:2706 + #, c-format + msgid "Stack analysis will ignore the call from %s to %s\n" + msgstr "El análisis de pila descartará la llamada de %s a %s\n" + +-#: elf32-spu.c:2513 ++#: elf32-spu.c:3348 ++msgid " %s: 0x%v\n" ++msgstr " %s: 0x%v\n" ++ ++#: elf32-spu.c:3349 + msgid "%s: 0x%v 0x%v\n" + msgstr "%s: 0x%v 0x%v\n" + +-#: elf32-spu.c:2517 ++#: elf32-spu.c:3354 + msgid " calls:\n" + msgstr " llama:\n" + +-#: elf32-spu.c:2524 ++#: elf32-spu.c:3362 + #, c-format + msgid " %s%s %s\n" + msgstr " %s%s %s\n" + +-#: elf32-spu.c:2585 ++#: elf32-spu.c:3564 ++#, c-format ++msgid "%s duplicated in %s\n" ++msgstr "%s duplicado en %s\n" ++ ++#: elf32-spu.c:3568 ++#, c-format ++msgid "%s duplicated\n" ++msgstr "%s duplicado\n" ++ ++#: elf32-spu.c:3575 ++msgid "sorry, no support for duplicate object files in auto-overlay script\n" ++msgstr "perdón, no se admiten ficheros objeto duplicados en el guión de sobreescritura automática\n" ++ ++#: elf32-spu.c:3605 ++msgid "non-overlay size of 0x%v plus maximum overlay size of 0x%v exceeds local store\n" ++msgstr "eltamaño 0x%v que no es de sobreescritura mas el tamaño de sobreescritura máximo de 0x%v excede el almacenamiento local\n" ++ ++#: elf32-spu.c:3741 ++msgid "%B:%A%s exceeds overlay size\n" ++msgstr "%B:%A%s excede el tamaño de sobreescritura\n" ++ ++#: elf32-spu.c:3862 + msgid "Stack size for call graph root nodes.\n" + msgstr "Tamaño de la pila para los nodos raíz del grafo de llamadas.\n" + +-#: elf32-spu.c:2586 ++#: elf32-spu.c:3863 + msgid "" + "\n" + "Stack size for functions. Annotations: '*' max stack, 't' tail call\n" +@@ -1762,80 +2017,76 @@ msgstr "" + "\n" + "Tamaño de la pila para funciones. Anotaciones: '*' max de pila, 't' llamada cola\n" + +-#: elf32-spu.c:2615 +-msgid " %s: 0x%v\n" +-msgstr " %s: 0x%v\n" +- +-#: elf32-spu.c:2625 ++#: elf32-spu.c:3871 + msgid "Maximum stack required is 0x%v\n" + msgstr "La pila máxima requerida es 0x%v\n" + +-#: elf32-spu.c:2751 ++#: elf32-spu.c:4067 + msgid "%B(%s+0x%lx): unresolvable %s relocation against symbol `%s'" + msgstr "%B(%s+0x%lx): reubicación %s sin resolución contra el símbolo `%s'" + +-#: elf32-v850.c:163 ++#: elf32-v850.c:165 + #, c-format + msgid "Variable `%s' cannot occupy in multiple small data regions" + msgstr "La variable `%s' no puede ocupar múltiples regiones de datos small" + +-#: elf32-v850.c:166 ++#: elf32-v850.c:168 + #, c-format + msgid "Variable `%s' can only be in one of the small, zero, and tiny data regions" + msgstr "La variable `%s' solamente puede estar en una de las regiones de datos small, cero, y tiny" + +-#: elf32-v850.c:169 ++#: elf32-v850.c:171 + #, c-format + msgid "Variable `%s' cannot be in both small and zero data regions simultaneously" + msgstr "La variable `%s' no puede estar simultáneamente en las regiones de datos small y cero" + +-#: elf32-v850.c:172 ++#: elf32-v850.c:174 + #, c-format + msgid "Variable `%s' cannot be in both small and tiny data regions simultaneously" + msgstr "La variable `%s' no puede estar simultáneamente en las regiones de datos small y tiny" + +-#: elf32-v850.c:175 ++#: elf32-v850.c:177 + #, c-format + msgid "Variable `%s' cannot be in both zero and tiny data regions simultaneously" + msgstr "La variable `%s' no puede estar simultáneamente en las regiones de datos cero y tiny" + +-#: elf32-v850.c:478 ++#: elf32-v850.c:480 + #, c-format + msgid "FAILED to find previous HI16 reloc\n" + msgstr "FALLO para encontrar la reubicación HI16 previa\n" + +-#: elf32-v850.c:1713 ++#: elf32-v850.c:1715 + msgid "could not locate special linker symbol __gp" + msgstr "no se puede localizar el símbolo especial del enlazador __gp" + +-#: elf32-v850.c:1717 ++#: elf32-v850.c:1719 + msgid "could not locate special linker symbol __ep" + msgstr "no se puede localizar el símbolo especial del enlazador __ep" + +-#: elf32-v850.c:1721 ++#: elf32-v850.c:1723 + msgid "could not locate special linker symbol __ctbp" + msgstr "no se puede localizar el símbolo especial del enlazador __ctbp" + +-#: elf32-v850.c:1871 ++#: elf32-v850.c:1873 + msgid "%B: Architecture mismatch with previous modules" + msgstr "%B: No coincide la arquitectura con los módulos previos" + +-#: elf32-v850.c:1890 ++#: elf32-v850.c:1892 + #, c-format + msgid "private flags = %lx: " + msgstr "opciones privadas = %lx: " + +-#: elf32-v850.c:1895 ++#: elf32-v850.c:1897 + #, c-format + msgid "v850 architecture" + msgstr "arquitectura v850" + +-#: elf32-v850.c:1896 ++#: elf32-v850.c:1898 + #, c-format + msgid "v850e architecture" + msgstr "arquitectura v850e" + +-#: elf32-v850.c:1897 ++#: elf32-v850.c:1899 + #, c-format + msgid "v850e1 architecture" + msgstr "arquitectura v850e1" +@@ -1860,114 +2111,118 @@ msgstr " [flotante-g]" + msgid "%s: warning: GOT addend of %ld to `%s' does not match previous GOT addend of %ld" + msgstr "%s: aviso: la adición GOT de %ld a `%s' no coincide con la adición previa GOT de %ld" + +-#: elf32-vax.c:1584 ++#: elf32-vax.c:1589 + #, c-format + msgid "%s: warning: PLT addend of %d to `%s' from %s section ignored" + msgstr "%s: aviso: se descarta la adición PLT de %d a `%s' de la sección %s" + +-#: elf32-vax.c:1721 ++#: elf32-vax.c:1726 + #, c-format + msgid "%s: warning: %s relocation against symbol `%s' from %s section" + msgstr "%s: aviso: reubicación %s contra el símbolo `%s' de la sección %s" + +-#: elf32-vax.c:1727 ++#: elf32-vax.c:1732 + #, c-format + msgid "%s: warning: %s relocation to 0x%x from %s section" + msgstr "%s: aviso: reubicación %s a 0x%x de la sección %s" + +-#: elf32-xstormy16.c:451 elf32-ia64.c:2962 elf64-ia64.c:2962 ++#: elf32-xstormy16.c:451 elf32-ia64.c:2794 elf64-ia64.c:2794 + msgid "non-zero addend in @fptr reloc" + msgstr "adición que no es cero en la reubicación @fptr" + +-#: elf32-xtensa.c:733 ++#: elf32-xtensa.c:911 + msgid "%B(%A): invalid property table" + msgstr "%B(%A): tabla de propiedades inválida" + +-#: elf32-xtensa.c:2177 ++#: elf32-xtensa.c:2734 + msgid "%B(%A+0x%lx): relocation offset out of range (size=0x%x)" + msgstr "%B(%A+0x%lx): desplazamiento de reubicación fuera de rango (tamaño=0x%x)" + +-#: elf32-xtensa.c:2234 ++#: elf32-xtensa.c:2813 elf32-xtensa.c:2934 + msgid "dynamic relocation in read-only section" + msgstr "reubicación dinámica en la sección de sólo lectura" + +-#: elf32-xtensa.c:2407 ++#: elf32-xtensa.c:2910 ++msgid "TLS relocation invalid without dynamic sections" ++msgstr "reubicación TLS inválida sin secciones dinámicas" ++ ++#: elf32-xtensa.c:3127 + msgid "internal inconsistency in size of .got.loc section" + msgstr "inconsistencia interna en el tamaño de la sección .got.loc" + +-#: elf32-xtensa.c:2714 ++#: elf32-xtensa.c:3437 + msgid "%B: incompatible machine type. Output is 0x%x. Input is 0x%x" + msgstr "%B: tipo de máquina incompatible. La salida es 0x%x. La entrada es 0x%x" + +-#: elf32-xtensa.c:3920 elf32-xtensa.c:3928 ++#: elf32-xtensa.c:4666 elf32-xtensa.c:4674 + msgid "Attempt to convert L32R/CALLX to CALL failed" + msgstr "Falló el intento de convertir L32R/CALLX a CALL" + +-#: elf32-xtensa.c:5522 elf32-xtensa.c:5598 elf32-xtensa.c:6714 ++#: elf32-xtensa.c:6276 elf32-xtensa.c:6352 elf32-xtensa.c:7468 + msgid "%B(%A+0x%lx): could not decode instruction; possible configuration mismatch" + msgstr "%B(%A+0x%lx): no se puede decodificar la instrucción; posible falta de coincidencia de la configuración" + +-#: elf32-xtensa.c:6454 ++#: elf32-xtensa.c:7208 + msgid "%B(%A+0x%lx): could not decode instruction for XTENSA_ASM_SIMPLIFY relocation; possible configuration mismatch" + msgstr "%B(%A+0x%lx): no se puede decodificar la instrucción para la reubicación XTENSA_ASM_SIMPLIFY; posible falta de coincidencia de la configuración" + +-#: elf32-xtensa.c:8166 ++#: elf32-xtensa.c:8969 + msgid "invalid relocation address" + msgstr "dirección de reubicación inválida" + +-#: elf32-xtensa.c:8215 ++#: elf32-xtensa.c:9018 + msgid "overflow after relaxation" + msgstr "desbordamiento después de la relajación" + +-#: elf32-xtensa.c:9341 ++#: elf32-xtensa.c:10154 + msgid "%B(%A+0x%lx): unexpected fix for %s relocation" + msgstr "%B(%A+0x%lx): compostura inesperada para la reubicación %s" + +-#: elf64-alpha.c:453 ++#: elf64-alpha.c:452 + msgid "GPDISP relocation did not find ldah and lda instructions" + msgstr "la reubicación GPDISP no encontró las instrucciones ldah y lda" + +-#: elf64-alpha.c:2404 ++#: elf64-alpha.c:2416 + msgid "%B: .got subsegment exceeds 64K (size %d)" + msgstr "%B: el subsegmento .got excede los 64K (tamaño %d)" + +-#: elf64-alpha.c:4277 elf64-alpha.c:4289 ++#: elf64-alpha.c:4296 elf64-alpha.c:4308 + msgid "%B: gp-relative relocation against dynamic symbol %s" + msgstr "%B: reubicación gp relativa contra el símbolo dinámico %s" + +-#: elf64-alpha.c:4315 elf64-alpha.c:4450 ++#: elf64-alpha.c:4334 elf64-alpha.c:4469 + msgid "%B: pc-relative relocation against dynamic symbol %s" + msgstr "%B: reubicación relativa al pc contra el símbolo dinámico %s" + +-#: elf64-alpha.c:4343 ++#: elf64-alpha.c:4362 + msgid "%B: change in gp: BRSGP %s" + msgstr "%B: cambio en gp: BRSGP %s" + +-#: elf64-alpha.c:4368 ++#: elf64-alpha.c:4387 + msgid "" + msgstr "" + +-#: elf64-alpha.c:4373 ++#: elf64-alpha.c:4392 + msgid "%B: !samegp reloc against symbol without .prologue: %s" + msgstr "%B: reubicación !samegp contra un símbolo sin .prologue: %s" + +-#: elf64-alpha.c:4425 ++#: elf64-alpha.c:4444 + msgid "%B: unhandled dynamic relocation against %s" + msgstr "%B: reubicación dinámica sin manejar contra %s" + +-#: elf64-alpha.c:4457 ++#: elf64-alpha.c:4476 + msgid "%B: pc-relative relocation against undefined weak symbol %s" + msgstr "%B: reubicación relativa al pc contra el símbolo débil sin definir %s" + +-#: elf64-alpha.c:4517 ++#: elf64-alpha.c:4536 + msgid "%B: dtp-relative relocation against dynamic symbol %s" + msgstr "%B: reubicación relativa a dtp contra el símbolo dinámico %s" + +-#: elf64-alpha.c:4540 ++#: elf64-alpha.c:4559 + msgid "%B: tp-relative relocation against dynamic symbol %s" + msgstr "%B: reubicación relativa a tp contra el símbolo dinámico %s" + +-#: elf64-hppa.c:2040 ++#: elf64-hppa.c:2071 + #, c-format + msgid "stub entry for %s cannot load .plt, dp offset = %ld" + msgstr "la entrada de cabo para %s no puede cargar .plt, desplazamiento dp = %ld" +@@ -2011,16 +2266,16 @@ msgstr "%s: la directiva LOCAL s + msgid "%s: LOCAL directive: Register $%ld is not a local register. First global register is $%ld." + msgstr "%s: directiva LOCAL: El registro $%ld no es un registro local. El primer registro global es $%ld." + +-#: elf64-mmix.c:2202 ++#: elf64-mmix.c:2201 + #, c-format + msgid "%s: Error: multiple definition of `%s'; start of %s is set in a earlier linked file\n" + msgstr "%s: Error: definición múltiple de `%s'; el inicio de %s está definido en un fichero enlazado con anterioridad\n" + +-#: elf64-mmix.c:2260 ++#: elf64-mmix.c:2259 + msgid "Register section has contents\n" + msgstr "La sección de registros no tiene contenido\n" + +-#: elf64-mmix.c:2452 ++#: elf64-mmix.c:2451 + #, c-format + msgid "" + "Internal inconsistency: remaining %u != max %u.\n" +@@ -2029,69 +2284,65 @@ msgstr "" + "Inconsistencia interna: %u restante != %u máximo.\n" + " Por favor reporte este bicho." + +-#: elf64-ppc.c:2569 libbfd.c:950 ++#: elf64-ppc.c:2561 libbfd.c:978 + msgid "%B: compiled for a big endian system and target is little endian" + msgstr "%B: compilado para un sistema big endian y el objetivo es little endian" + +-#: elf64-ppc.c:2572 libbfd.c:952 ++#: elf64-ppc.c:2564 libbfd.c:980 + msgid "%B: compiled for a little endian system and target is big endian" + msgstr "%B: compilado para un sistema little endian y el objetivo es big endian" + +-#: elf64-ppc.c:5888 ++#: elf64-ppc.c:6065 + #, c-format + msgid "copy reloc against `%s' requires lazy plt linking; avoid setting LD_BIND_NOW=1 or upgrade gcc" + msgstr "la reubicación de copia contra `%s' requiere de enlazado plt suelto; evite establecer LD_BIND_NOW=1 o actualice gcc" + +-#: elf64-ppc.c:6316 ++#: elf64-ppc.c:6486 + msgid "dynreloc miscount for %B, section %A" + msgstr "cuenta errónea de la reubicación dinámica de %B, sección %A" + +-#: elf64-ppc.c:6420 ++#: elf64-ppc.c:6570 + msgid "%B: .opd is not a regular array of opd entries" + msgstr "%B: .opd no es una matriz regular de entradas opd" + +-#: elf64-ppc.c:6429 ++#: elf64-ppc.c:6579 + msgid "%B: unexpected reloc type %u in .opd section" + msgstr "%B: tipo de reubicación %u inesperado en la sección .opd" + +-#: elf64-ppc.c:6450 ++#: elf64-ppc.c:6600 + msgid "%B: undefined sym `%s' in .opd section" + msgstr "%B: símbolo `%s' indefinido en la sección .opd" + +-#: elf64-ppc.c:7157 elf64-ppc.c:7537 ++#: elf64-ppc.c:7377 elf64-ppc.c:7754 + #, c-format + msgid "%s defined in removed toc entry" + msgstr "se definió %s en la entrada toc eliminada" + +-#: elf64-ppc.c:8272 ++#: elf64-ppc.c:8581 + #, c-format + msgid "long branch stub `%s' offset overflow" + msgstr "desbordamiento del desplazamiento de stub de ramificación long `%s'" + +-#: elf64-ppc.c:8347 ++#: elf64-ppc.c:8640 + #, c-format + msgid "can't find branch stub `%s'" + msgstr "no se puede encontrar la ramificación de cabo `%s'" + +-#: elf64-ppc.c:8413 elf64-ppc.c:8489 ++#: elf64-ppc.c:8702 elf64-ppc.c:8822 + #, c-format + msgid "linkage table error against `%s'" + msgstr "error de la tabla de enlazado contra `%s'" + +-#: elf64-ppc.c:8618 ++#: elf64-ppc.c:8978 + #, c-format + msgid "can't build branch stub `%s'" + msgstr "no se puede construir la ramificación de cabos `%s'" + +-#: elf64-ppc.c:9070 ++#: elf64-ppc.c:9451 + msgid "%B section %A exceeds stub group size" + msgstr "%B sección %A excede el tamaño de grupo de stub" + +-#: elf64-ppc.c:9682 +-msgid "stubs don't match calculated size" +-msgstr "los cabos no coinciden con el tamaño calculado" +- +-#: elf64-ppc.c:9694 ++#: elf64-ppc.c:10090 + #, c-format + msgid "" + "linker stubs in %u group%s\n" +@@ -2108,19 +2359,19 @@ msgstr "" + " ajuste toc long %lu\n" + " llamada plt %lu" + +-#: elf64-ppc.c:10378 ++#: elf64-ppc.c:10769 + msgid "%B(%A+0x%lx): automatic multiple TOCs not supported using your crt files; recompile with -mminimal-toc or upgrade gcc" + msgstr "%B(%A+0x%lx): no se admiten los TOCs múltiples automáticos, utilizando sus ficheros crt; recompile con -mminimal-toc o actualice gcc" + +-#: elf64-ppc.c:10386 ++#: elf64-ppc.c:10777 + msgid "%B(%A+0x%lx): sibling call optimization to `%s' does not allow automatic multiple TOCs; recompile with -mminimal-toc or -fno-optimize-sibling-calls, or make `%s' extern" + msgstr "%B(%A+0x%lx): la optimización de llamada hermana a `%s' no permite TOCs múltiples automáticos; recompile con -mminimal-toc ó -fno-optimize-sibling-calls, o vuelva `%s' externa" + +-#: elf64-ppc.c:11037 ++#: elf64-ppc.c:11427 + msgid "%B: relocation %s is not supported for symbol %s." + msgstr "%B: no se admite la reubicación %s para el símbolo %s." + +-#: elf64-ppc.c:11119 ++#: elf64-ppc.c:11509 + msgid "%B: error: relocation %s not a multiple of %d" + msgstr "%B: error: la reubicación %s no es un múltiplo de %d" + +@@ -2149,194 +2400,48 @@ msgstr "El s + msgid "%B: linking UltraSPARC specific with HAL specific code" + msgstr "%B: se enlaza código específico de UltraSPARC con código específico de HAL" + +-#: elf64-x86-64.c:799 elf64-x86-64.c:959 elf64-x86-64.c:2360 ++#: elf64-x86-64.c:1047 elf64-x86-64.c:1207 elfxx-mips.c:7834 + msgid "%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC" + msgstr "%B: no se puede usar la reubicación %s contra `%s' cuando se hace un objeto compartido; recompile con -fPIC" + +-#: elf64-x86-64.c:890 +-msgid "%B: %s' accessed both as normal and thread local symbol" +-msgstr "%B: se accesó `%s' como un símbolo normal y como un símbolo local de hilo" ++#: elf64-x86-64.c:1138 ++msgid "%B: '%s' accessed both as normal and thread local symbol" ++msgstr "%B: se accedió a '%s' como un símbolo normal y como un símbolo local de hilo" + +-#: elf64-x86-64.c:2272 ++#: elf64-x86-64.c:2559 + msgid "%B: relocation R_X86_64_GOTOFF64 against protected function `%s' can not be used when making a shared object" + msgstr "%B: no se puede usar la reubicación R_X86_64_GOTOFF contra la función protegida `%s' cuando se hace un objeto compartido" + +-#: elf64-x86-64.c:2356 +-msgid "%B: relocation R_X86_64_PC32 against protected function `%s' can not be used when making a shared object" +-msgstr "%B: no se puede usar la reubicación R_X86_64_PC32 contra la función protegida `%' cuando se hace un objeto compartido" ++#: elf64-x86-64.c:2670 ++msgid "; recompile with -fPIC" ++msgstr "; recompile con -fPIC" + +-#: elf-attrs.c:582 +-msgid "ERROR: %B: Must be processed by '%s' toolchain" +-msgstr "ERROR: %B: Se debe procesar por la cadena de compilación '%s'" +- +-#: elf-attrs.c:602 elf-attrs.c:621 +-msgid "ERROR: %B: Incompatible object tag '%s':%d" +-msgstr "ERROR: %B: Etiqueta de objeto '%s' incompatible:%d" +- +-#: elf.c:312 +-msgid "%B: invalid string offset %u >= %lu for section `%s'" +-msgstr "%B: desplazamiento de cadena inválido %u >= %lu para la sección `%s'" +- +-#: elf.c:414 +-msgid "%B symbol number %lu references nonexistent SHT_SYMTAB_SHNDX section" +-msgstr "%B el número de símbolo %lu hace referencia a la sección inexistente SHT_SYMTAB_SHNDX" +- +-#: elf.c:567 +-msgid "%B: Corrupt size field in group section header: 0x%lx" +-msgstr "%B: Tamaño de campo corrupto en el encabezado de la sección de grupo: 0x%lx" ++#: elf64-x86-64.c:2675 ++msgid "%B: relocation %s against %s `%s' can not be used when making a shared object%s" ++msgstr "%B: no se puede usar la reubicación %s contra %s `%s' cuando se hace un objeto compartido%s" + +-#: elf.c:603 +-msgid "%B: invalid SHT_GROUP entry" +-msgstr "%B: entrada SHT_GROUP inválida" +- +-#: elf.c:673 +-msgid "%B: no group info for section %A" +-msgstr "%B: no hay información de grupo para la sección %A" ++#: elf64-x86-64.c:2677 ++msgid "%B: relocation %s against undefined %s `%s' can not be used when making a shared object%s" ++msgstr "%B: no se puede usar la reubicación %s contra %s sin definir `%s' cuando se hace un objeto compartido%s" + +-#: elf.c:703 elf.c:2886 elflink.c:9858 +-msgid "%B: warning: sh_link not set for section `%A'" +-msgstr "%B: aviso: no se estableción sh_link para la sección `%A'" +- +-#: elf.c:719 +-msgid "%B: sh_link [%d] in section `%A' is incorrect" +-msgstr "%B: sh_link [%d] en la sección `%A', es incorrecto" +- +-#: elf.c:754 +-msgid "%B: unknown [%d] section `%s' in group [%s]" +-msgstr "%B: sección [%d] desconocida `%s' en el grupo [%s]" +- +-#: elf.c:1108 +-#, c-format +-msgid "" +-"\n" +-"Program Header:\n" +-msgstr "" +-"\n" +-"Encabezado del Programa:\n" +- +-#: elf.c:1150 +-#, c-format +-msgid "" +-"\n" +-"Dynamic Section:\n" +-msgstr "" +-"\n" +-"Sección Dinámica:\n" +- +-#: elf.c:1276 +-#, c-format +-msgid "" +-"\n" +-"Version definitions:\n" +-msgstr "" +-"\n" +-"Definiciones de versión:\n" +- +-#: elf.c:1301 +-#, c-format +-msgid "" +-"\n" +-"Version References:\n" +-msgstr "" +-"\n" +-"Referencias de Versión:\n" +- +-#: elf.c:1306 +-#, c-format +-msgid " required from %s:\n" +-msgstr " requerido desde %s:\n" +- +-#: elf.c:1690 +-msgid "%B: invalid link %lu for reloc section %s (index %u)" +-msgstr "%B: enlace %lu inválido para la sección de reubicación %s (índice %u)" +- +-#: elf.c:1858 +-msgid "%B: don't know how to handle allocated, application specific section `%s' [0x%8x]" +-msgstr "%B: no se sabe cómo manejar lo reservado, aplicación específica de la sección `%s' [0x%8x]" +- +-#: elf.c:1870 +-msgid "%B: don't know how to handle processor specific section `%s' [0x%8x]" +-msgstr "%B: no se sabe cómo manejar la sección específica de procesador `%s' [0x%8x]" +- +-#: elf.c:1881 +-msgid "%B: don't know how to handle OS specific section `%s' [0x%8x]" +-msgstr "%B: no se sabe cómo manejar la sección específica de SO `%s' [0x%8x]" +- +-#: elf.c:1891 +-msgid "%B: don't know how to handle section `%s' [0x%8x]" +-msgstr "%B: no se sabe cómo manejar la sección `%s' [0x%8x]" +- +-#: elf.c:2843 +-msgid "%B: sh_link of section `%A' points to discarded section `%A' of `%B'" +-msgstr "%B: sh_link de la sección `%A' apunta a la sección descartada `%A' de `%B'" +- +-#: elf.c:2866 +-msgid "%B: sh_link of section `%A' points to removed section `%A' of `%B'" +-msgstr "%B: sh_link de la sección `%A' apunta a la sección descartada `%A' de `%B'" +- +-#: elf.c:4142 +-msgid "%B: The first section in the PT_DYNAMIC segment is not the .dynamic section" +-msgstr "%B: La primera sección en el segmento PT_DYNAMIC no es la sección .dynamic" +- +-#: elf.c:4165 +-msgid "%B: Not enough room for program headers, try linking with -N" +-msgstr "%B: No hay suficiente espacio para los encabezados del programa, pruebe enlazar con -N" +- +-#: elf.c:4243 +-msgid "%B: section %A lma 0x%lx overlaps previous sections" +-msgstr "%B: la sección %A lma 0x%lx traslapa las secciones anteriores" +- +-#: elf.c:4341 +-msgid "%B: section `%A' can't be allocated in segment %d" +-msgstr "%B: la sección `%A' no se puede asignar en el segmento %d" +- +-#: elf.c:4390 +-msgid "%B: warning: allocated section `%s' not in segment" +-msgstr "%B: aviso: la sección asignada `%s' no está en el segmento" +- +-#: elf.c:4886 +-msgid "%B: symbol `%s' required but not present" +-msgstr "%B: se requiere el símbolo `%s' pero no está presente" +- +-#: elf.c:5199 +-msgid "%B: warning: Empty loadable segment detected, is this intentional ?\n" +-msgstr "%B: aviso: Se detectó un segmento cargable vacío, ¿ esto es intencional ?\n" +- +-#: elf.c:6105 +-#, c-format +-msgid "Unable to find equivalent output section for symbol '%s' from section '%s'" +-msgstr "No se puede encontrar la sección de salida equivalente para el símbolo '%s' de la sección '%s'" +- +-#: elf.c:7079 +-msgid "%B: unsupported relocation type %s" +-msgstr "%B: no se admite el tipo de reubicación %s" +- +-#: elfcode.h:813 ++#: elfcode.h:795 + #, c-format + msgid "warning: %s has a corrupt string table index - ignoring" + msgstr "aviso: %s tiene un índice de tablas de cadenas corrupto - se descarta" + +-#: elfcode.h:1226 ++#: elfcode.h:1201 + #, c-format + msgid "%s: version count (%ld) does not match symbol count (%ld)" + msgstr "%s: la cuenta de versión (%ld) no coincide con la cuenta de símbolos (%ld)" + +-#: elfcode.h:1459 ++#: elfcode.h:1435 + #, c-format + msgid "%s(%s): relocation %d has invalid symbol index %ld" + msgstr "%s(%s): la reubicación %d tiene un índice de símbolo %ld inválido" + +-#: elf-eh-frame.c:823 +-msgid "%P: fde encoding in %B(%A) prevents .eh_frame_hdr table being created.\n" +-msgstr "%P: la codificación fde en %B(%A) previene la creación de la tabla .eh_frame_hdr.\n" +- +-#: elf-eh-frame.c:974 +-msgid "%P: error in %B(%A); no .eh_frame_hdr table will be created.\n" +-msgstr "%P: error en %B(%A); no se creará la tabla .eh_frame_hdr.\n" +- +-#: elf-hppa.h:2219 elf-hppa.h:2233 +-msgid "%B(%A): warning: unresolvable relocation against symbol `%s'" +-msgstr "%B(%A): aviso: reubicación sin resolución contra el símbolo `%s'" ++#: elfcore.h:251 ++msgid "Warning: %B is truncated: expected core file size >= %lu, found: %lu." ++msgstr "Aviso: se truncó %B: se esperaba el tamaño de fichero core >= %lu, se encontró: %lu." + + #: elflink.c:1028 + msgid "%s: TLS definition in %B section %A mismatches non-TLS definition in %B section %A" +@@ -2358,282 +2463,295 @@ msgstr "%s: la referencia TLS en %B no coincide con la definici + msgid "%B: unexpected redefinition of indirect versioned symbol `%s'" + msgstr "%B: redefinición inesperada del símbolo con versión indirecta `%s'" + +-#: elflink.c:1974 ++#: elflink.c:1982 + msgid "%B: version node not found for symbol %s" + msgstr "%B: no se encuentra la versión del nodo para el símbolo %s" + +-#: elflink.c:2122 ++#: elflink.c:2130 + msgid "%B: bad reloc symbol index (0x%lx >= 0x%lx) for offset 0x%lx in section `%A'" + msgstr "%B: índice de símbolos de reubicación inválido (0x%lx >= 0x%lx) erróneo para el desplazamiento 0x%lx en la sección `%A'" + +-#: elflink.c:2314 ++#: elflink.c:2327 + msgid "%B: relocation size mismatch in %B section %A" + msgstr "%B: el tamaño de reubicación no coincide en %B sección %A" + +-#: elflink.c:2616 ++#: elflink.c:2629 + #, c-format + msgid "warning: type and size of dynamic symbol `%s' are not defined" + msgstr "aviso: el tipo y tamaño del símbolo dinámico `%s' no están definidos" + +-#: elflink.c:3910 ++#: elflink.c:3953 + msgid "%B: %s: invalid version %u (max %d)" + msgstr "%B: %s: versión %u inválida (máximo %d)" + +-#: elflink.c:3946 ++#: elflink.c:3989 + msgid "%B: %s: invalid needed version %d" + msgstr "%B: %s: versión requerida %d inválida" + +-#: elflink.c:4129 ++#: elflink.c:4172 + msgid "Warning: alignment %u of common symbol `%s' in %B is greater than the alignment (%u) of its section %A" + msgstr "Aviso: la alineación %u del símbolo común `%s' en %B es más grande que la alineación (%u) de su sección %A" + +-#: elflink.c:4135 ++#: elflink.c:4178 + msgid "Warning: alignment %u of symbol `%s' in %B is smaller than %u in %B" + msgstr "Aviso: la alineación %u del símbolo `%s' en %B es más pequeña que %u en %B" + +-#: elflink.c:4150 ++#: elflink.c:4193 + msgid "Warning: size of symbol `%s' changed from %lu in %B to %lu in %B" + msgstr "Aviso: el tamaño del símbolo `%s' cambió de %lu en %B a %lu en %B" + +-#: elflink.c:4326 ++#: elflink.c:4371 + #, c-format + msgid "%s: invalid DSO for symbol `%s' definition" + msgstr "%s: DSO inválido para la definición del símbolo `%s'" + +-#: elflink.c:5552 ++#: elflink.c:5621 + #, c-format + msgid "%s: undefined version: %s" + msgstr "%s: versión sin definir: %s" + +-#: elflink.c:5620 ++#: elflink.c:5689 + msgid "%B: .preinit_array section is not allowed in DSO" + msgstr "%B: no se permite la sección .preinit_array en DSO" + +-#: elflink.c:7359 ++#: elflink.c:7414 + #, c-format + msgid "undefined %s reference in complex symbol: %s" + msgstr "referencia %s indefinida en el símbolo complejo: %s" + +-#: elflink.c:7514 ++#: elflink.c:7568 + #, c-format + msgid "unknown operator '%c' in complex symbol" + msgstr "operador desconocido '%c' en el símbolo complejo" + +-#: elflink.c:8053 elflink.c:8070 elflink.c:8107 elflink.c:8124 ++#: elflink.c:7904 elflink.c:7921 elflink.c:7958 elflink.c:7975 + msgid "%B: Unable to sort relocs - they are in more than one size" + msgstr "%B: No se pueden ordenar las reubicaciones - son de tamaños diferentes" + +-#: elflink.c:8084 elflink.c:8138 ++#: elflink.c:7935 elflink.c:7989 + msgid "%B: Unable to sort relocs - they are of an unknown size" + msgstr "%B: No se pueden ordenar las reubicaciones - son de tamaño desconocido" + +-#: elflink.c:8187 ++#: elflink.c:8038 + msgid "Not enough memory to sort relocations" + msgstr "No hay suficiente memoria para ordenar las reubicaciones" + +-#: elflink.c:8374 ++#: elflink.c:8227 + msgid "%B: Too many sections: %d (>= %d)" + msgstr "%B: Demasiadas secciones: %d (>= %d)" + +-#: elflink.c:8608 ++#: elflink.c:8461 + msgid "%B: %s symbol `%s' in %B is referenced by DSO" + msgstr "%B: el símbolo %s `%s' en %B está referenciado por DSO" + +-#: elflink.c:8691 ++#: elflink.c:8544 + msgid "%B: could not find output section %A for input section %A" + msgstr "%B: no se puede encontrar la sección de salida %A para la sección de entrada %A" + +-#: elflink.c:8788 ++#: elflink.c:8655 + msgid "%B: %s symbol `%s' isn't defined" + msgstr "%B: el símbolo %s `%s' no está definido" + +-#: elflink.c:9284 ++#: elflink.c:9141 + msgid "error: %B contains a reloc (0x%s) for section %A that references a non-existent global symbol" + msgstr "error: %B contiene una reubicación (0x%s) para la sección %A que refiere a un símbolo global que no existe" + +-#: elflink.c:9318 ++#: elflink.c:9205 + msgid "%X`%s' referenced in section `%A' of %B: defined in discarded section `%A' of %B\n" + msgstr "%X`%s' referido en la sección `%A' de %B: se definió en la sección descartada `%A' de %B\n" + +-#: elflink.c:9936 ++#: elflink.c:9825 + msgid "%A has both ordered [`%A' in %B] and unordered [`%A' in %B] sections" + msgstr "%A tiene tanto secciones ordenadas [`%A' en %B] como desordenadas [`%A' en %B]" + +-#: elflink.c:9941 ++#: elflink.c:9830 + #, c-format + msgid "%A has both ordered and unordered sections" + msgstr "%A tiene tanto secciones ordenadas como desordenadas" + +-#: elflink.c:10828 elflink.c:10872 ++#: elflink.c:10715 elflink.c:10759 + msgid "%B: could not find output section %s" + msgstr "%B: no se puede encontrar la sección de salida %s" + +-#: elflink.c:10833 ++#: elflink.c:10720 + #, c-format + msgid "warning: %s section has zero size" + msgstr "aviso: la sección %s es de tamaño cero" + +-#: elflink.c:10937 ++#: elflink.c:10824 + msgid "%P: warning: creating a DT_TEXTREL in a shared object.\n" + msgstr "%P: aviso: se crea un DT_TEXTREL en un objeto compartido.\n" + +-#: elflink.c:11305 ++#: elflink.c:11006 ++msgid "%P%X: can not read symbols: %E\n" ++msgstr "%P%X: no se pueden leer símbolos: %E\n" ++ ++#: elflink.c:11313 + msgid "Removing unused section '%s' in file '%B'" + msgstr "Se elimina la sección sin uso '%s' en el fichero '%B'" + +-#: elflink.c:11496 ++#: elflink.c:11525 + msgid "Warning: gc-sections option ignored" + msgstr "Aviso: se descarta la opción gc-sections" + +-#: elflink.c:11987 +-msgid "%P%X: can not read symbols: %E\n" +-msgstr "%P%X: no se pueden leer símbolos: %E\n" +- +-#: elflink.c:12129 ++#: elflink.c:12056 + msgid "%B: ignoring duplicate section `%A'" + msgstr "%B: se descarta la sección duplicada `%A'" + +-#: elflink.c:12136 elflink.c:12143 ++#: elflink.c:12063 elflink.c:12070 + msgid "%B: duplicate section `%A' has different size" + msgstr "%B: la sección duplicada `%A' tiene tamaño diferente" + +-#: elflink.c:12151 elflink.c:12156 ++#: elflink.c:12078 elflink.c:12083 + msgid "%B: warning: could not read contents of section `%A'" + msgstr "%B: aviso: no se puede leer el contenido de la sección `%A'" + +-#: elflink.c:12160 ++#: elflink.c:12087 + msgid "%B: warning: duplicate section `%A' has different contents" + msgstr "%B: aviso: la sección duplicada `%A' tiene contenido diferente" + +-#: elflink.c:12239 linker.c:3081 ++#: elflink.c:12166 linker.c:3080 + msgid "%F%P: already_linked_table: %E" + msgstr "%F%P: already_linked_table: %E" + +-#: elf-m10300.c:1532 +-msgid "error: inappropriate relocation type for shared library (did you forget -fpic?)" +-msgstr "error: tipo de reubicación inapropiada para la biblioteca compartida (¿olvidó -fpic?)" +- +-#: elf-m10300.c:1535 +-msgid "internal error: suspicious relocation type used in shared library" +-msgstr "error interno: se usó un tipo de reubicación sospechosa en una biblioteca compartida" +- +-#: elfxx-mips.c:990 ++#: elfxx-mips.c:1197 + msgid "static procedure (no name)" + msgstr "procedimiento estático (sin nombre)" + +-#: elfxx-mips.c:4663 ++#: elfxx-mips.c:5562 + msgid "%B: %A+0x%lx: jump to stub routine which is not jal" + msgstr "%B: %A+0x%lx: salto a una rutina cabo la cual no es jal" + +-#: elfxx-mips.c:5326 elfxx-mips.c:5546 ++#: elfxx-mips.c:6206 elfxx-mips.c:6427 + msgid "%B: Warning: bad `%s' option size %u smaller than its header" + msgstr "%B: Aviso: el tamaño de opción `%s' %u erróneo es más pequeño que su encabezado" + +-#: elfxx-mips.c:6405 ++#: elfxx-mips.c:7174 elfxx-mips.c:7299 ++msgid "%B: Warning: cannot determine the target function for stub section `%s'" ++msgstr "%B: Aviso: no se puede determinar la función objetivo para la sección de cabo `%s'" ++ ++#: elfxx-mips.c:7428 + msgid "%B: Malformed reloc detected for section %s" + msgstr "%B: Se detectó una reubicación malformada para la sección %s" + +-#: elfxx-mips.c:6447 ++#: elfxx-mips.c:7468 + msgid "%B: GOT reloc at 0x%lx not expected in executables" + msgstr "%B: no se esperaba la reubicación GOT en 0x%lx en ejecutables" + +-#: elfxx-mips.c:6517 ++#: elfxx-mips.c:7566 + msgid "%B: CALL16 reloc at 0x%lx not against global symbol" + msgstr "%B: la reubicación CALL16 en 0x%lx no es contra un símbolo global" + +-#: elfxx-mips.c:7880 ++#: elfxx-mips.c:8244 ++#, c-format ++msgid "non-dynamic relocations refer to dynamic symbol %s" ++msgstr "reubicaciones que no son dinámicas se refieren al símbolo dinámico %s" ++ ++#: elfxx-mips.c:8947 + msgid "%B: Can't find matching LO16 reloc against `%s' for %s at 0x%lx in section `%A'" + msgstr "%B: No se puede encontrar una reubicación LO16 coincidente contra `%s' para %s en 0x%lx en la sección `%A'" + +-#: elfxx-mips.c:8046 ++#: elfxx-mips.c:9086 + msgid "small-data section exceeds 64KB; lower small-data size limit (see option -G)" + msgstr "la sección small-data excede los 64KB; disminuya el límite de tamaño de small-data (vea la opción -G)" + +-#: elfxx-mips.c:10661 ++#: elfxx-mips.c:11887 + #, c-format + msgid "%s: illegal section name `%s'" + msgstr "%s: nombre de sección `%s' ilegal" + +-#: elfxx-mips.c:11031 elfxx-mips.c:11050 ++#: elfxx-mips.c:12262 elfxx-mips.c:12288 + msgid "Warning: %B uses -msingle-float, %B uses -mdouble-float" + msgstr "Aviso: %B usa -msingle-float, %B usa -mdouble-float" + +-#: elfxx-mips.c:11106 ++#: elfxx-mips.c:12274 elfxx-mips.c:12330 ++msgid "Warning: %B uses -msingle-float, %B uses -mips32r2 -mfp64" ++msgstr "Aviso: %B usa -msingle-float, %B usa -mips32r2 -mfp64" ++ ++#: elfxx-mips.c:12300 elfxx-mips.c:12336 ++msgid "Warning: %B uses -mdouble-float, %B uses -mips32r2 -mfp64" ++msgstr "Aviso: %B usa -mdouble-float, %B usa -mips32r2 -mfp64" ++ ++#: elfxx-mips.c:12378 + msgid "%B: endianness incompatible with that of the selected emulation" + msgstr "%B: la endianez es incompatible con aquella de la emulación seleccionada" + +-#: elfxx-mips.c:11118 ++#: elfxx-mips.c:12389 + msgid "%B: ABI is incompatible with that of the selected emulation" + msgstr "%B: la ABI es incompatible con aquella de la emulación seleccionada" + +-#: elfxx-mips.c:11218 ++#: elfxx-mips.c:12470 ++msgid "%B: warning: linking abicalls files with non-abicalls files" ++msgstr "%B: aviso: se enlazan ficheros de llamadas abi con ficheros que no son de llamadas abi" ++ ++#: elfxx-mips.c:12487 + msgid "%B: linking 32-bit code with 64-bit code" + msgstr "%B: se enlaza código de 32-bit con código de 64-bit" + +-#: elfxx-mips.c:11246 ++#: elfxx-mips.c:12515 + msgid "%B: linking %s module with previous %s modules" + msgstr "%B: se enlaza el módulo %s con módulos %s previos" + +-#: elfxx-mips.c:11269 ++#: elfxx-mips.c:12538 + msgid "%B: ABI mismatch: linking %s module with previous %s modules" + msgstr "%B: no coincide el ABI: se enlaza el módulo %s con módulos %s previos" + +-#: elfxx-mips.c:11334 ++#: elfxx-mips.c:12702 + #, c-format + msgid " [abi=O32]" + msgstr " [abi=O32]" + +-#: elfxx-mips.c:11336 ++#: elfxx-mips.c:12704 + #, c-format + msgid " [abi=O64]" + msgstr " [abi=O64]" + +-#: elfxx-mips.c:11338 ++#: elfxx-mips.c:12706 + #, c-format + msgid " [abi=EABI32]" + msgstr " [abi=EABI32]" + +-#: elfxx-mips.c:11340 ++#: elfxx-mips.c:12708 + #, c-format + msgid " [abi=EABI64]" + msgstr " [abi=EABI64]" + +-#: elfxx-mips.c:11342 ++#: elfxx-mips.c:12710 + #, c-format + msgid " [abi unknown]" + msgstr " [abi desconocido]" + +-#: elfxx-mips.c:11344 ++#: elfxx-mips.c:12712 + #, c-format + msgid " [abi=N32]" + msgstr " [abi=N32]" + +-#: elfxx-mips.c:11346 ++#: elfxx-mips.c:12714 + #, c-format + msgid " [abi=64]" + msgstr " [abi=64]" + +-#: elfxx-mips.c:11348 ++#: elfxx-mips.c:12716 + #, c-format + msgid " [no abi set]" + msgstr " [no hay conjunto abi]" + +-#: elfxx-mips.c:11369 ++#: elfxx-mips.c:12737 + #, c-format + msgid " [unknown ISA]" + msgstr " [ISA desconocido]" + +-#: elfxx-mips.c:11380 ++#: elfxx-mips.c:12748 + #, c-format + msgid " [not 32bitmode]" + msgstr " [no es modo 32bit]" + +-#: elfxx-sparc.c:430 ++#: elfxx-sparc.c:440 + #, c-format + msgid "invalid relocation type %d" + msgstr "tipo de reubicación %d inválido" + +-#: elfxx-sparc.c:2901 ++#: elfxx-sparc.c:2976 + msgid "%B: probably compiled without -fPIC?" + msgstr "%B: ¿Compilado probablemente sin -fPIC?" + +@@ -2720,34 +2838,34 @@ msgstr "%B: longitud de secci + msgid "%s: address 0x%s out of range for Intel Hex file" + msgstr "%s: la dirección 0x%s está fuera de rango en el fichero Hexadecimal de Intel" + +-#: libbfd.c:980 ++#: libbfd.c:1008 + #, c-format + msgid "Deprecated %s called at %s line %d in %s\n" + msgstr "Se llamó a %s que es obsoleto en %s línea %d en %s\n" + +-#: libbfd.c:983 ++#: libbfd.c:1011 + #, c-format + msgid "Deprecated %s called\n" + msgstr "Se llamó a %s que es obsoleto\n" + +-#: linker.c:1875 ++#: linker.c:1874 + msgid "%B: indirect symbol `%s' to `%s' is a loop" + msgstr "%B: el símbolo indirecto `%s' para `%s' es un ciclo" + +-#: linker.c:2741 ++#: linker.c:2740 + #, c-format + msgid "Attempt to do relocatable link with %s input and %s output" + msgstr "Se intentó hacer un enlace reubicable con entrada %s y salida %s" + +-#: linker.c:3048 ++#: linker.c:3047 + msgid "%B: warning: ignoring duplicate section `%A'\n" + msgstr "%B: aviso: se descarta la sección duplicada `%A'\n" + +-#: linker.c:3062 ++#: linker.c:3061 + msgid "%B: warning: duplicate section `%A' has different size\n" + msgstr "%B: aviso: la sección duplicada `%A' es de tamaño diferente\n" + +-#: merge.c:820 ++#: merge.c:828 + #, c-format + msgid "%s: access beyond end of merged section (%ld)" + msgstr "%s: acceso más allá del final de la sección mezclada (%ld)" +@@ -2887,6 +3005,26 @@ msgstr "%s: no se puede representar la secci + msgid "Unhandled OSF/1 core file section type %d\n" + msgstr "Tipo de sección de fichero núcleo OSF/1 %d sin manejar\n" + ++#: pe-mips.c:607 ++msgid "%B: `ld -r' not supported with PE MIPS objects\n" ++msgstr "%B: `ld -r' no se admite con objetos PE MIPS\n" ++ ++#. OK, at this point the following variables are set up: ++#. src = VMA of the memory we're fixing up ++#. mem = pointer to memory we're fixing up ++#. val = VMA of what we need to refer to. ++#: pe-mips.c:723 ++msgid "%B: unimplemented %s\n" ++msgstr "%B: %s sin implementar\n" ++ ++#: pe-mips.c:749 ++msgid "%B: jump too far away\n" ++msgstr "%B: salto demasiado lejos\n" ++ ++#: pe-mips.c:775 ++msgid "%B: bad pair/reflo after refhi\n" ++msgstr "%B: pair/reflo erróneo después de refhi\n" ++ + #. XXX code yet to be written. + #: peicode.h:759 + msgid "%B: Unhandled import type; %x" +@@ -2916,26 +3054,6 @@ msgstr "%B: el tama + msgid "%B: string not null terminated in ILF object file." + msgstr "%B: cadena no terminada en null en el fichero objeto ILF." + +-#: pe-mips.c:606 +-msgid "%B: `ld -r' not supported with PE MIPS objects\n" +-msgstr "%B: `ld -r' no se admite con objetos PE MIPS\n" +- +-#. OK, at this point the following variables are set up: +-#. src = VMA of the memory we're fixing up +-#. mem = pointer to memory we're fixing up +-#. val = VMA of what we need to refer to. +-#: pe-mips.c:722 +-msgid "%B: unimplemented %s\n" +-msgstr "%B: %s sin implementar\n" +- +-#: pe-mips.c:748 +-msgid "%B: jump too far away\n" +-msgstr "%B: salto demasiado lejos\n" +- +-#: pe-mips.c:774 +-msgid "%B: bad pair/reflo after refhi\n" +-msgstr "%B: pair/reflo erróneo después de refhi\n" +- + #: ppcboot.c:414 + #, c-format + msgid "" +@@ -2950,22 +3068,22 @@ msgstr "" + msgid "Entry offset = 0x%.8lx (%ld)\n" + msgstr "Desplazamiento de entrada = 0x%.8lx (%ld)\n" + +-#: ppcboot.c:416 ++#: ppcboot.c:417 + #, c-format + msgid "Length = 0x%.8lx (%ld)\n" + msgstr "Longitud = 0x%.8lx (%ld)\n" + +-#: ppcboot.c:419 ++#: ppcboot.c:421 + #, c-format + msgid "Flag field = 0x%.2x\n" + msgstr "Campo de opciones = 0x%.2x\n" + +-#: ppcboot.c:425 ++#: ppcboot.c:427 + #, c-format + msgid "Partition name = \"%s\"\n" + msgstr "Nombre de la partición = \"%s\"\n" + +-#: ppcboot.c:444 ++#: ppcboot.c:446 + #, c-format + msgid "" + "\n" +@@ -2974,22 +3092,22 @@ msgstr "" + "\n" + "Partición[%d] inicio = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n" + +-#: ppcboot.c:450 ++#: ppcboot.c:452 + #, c-format + msgid "Partition[%d] end = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n" + msgstr "Partición[%d] fin = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n" + +-#: ppcboot.c:456 ++#: ppcboot.c:458 + #, c-format + msgid "Partition[%d] sector = 0x%.8lx (%ld)\n" + msgstr "Partición[%d] sector = 0x%.8lx (%ld)\n" + +-#: ppcboot.c:457 ++#: ppcboot.c:460 + #, c-format + msgid "Partition[%d] length = 0x%.8lx (%ld)\n" + msgstr "Partición[%d] longitud = 0x%.8lx (%ld)\n" + +-#: som.c:5088 ++#: som.c:5137 + #, c-format + msgid "" + "\n" +@@ -2998,7 +3116,7 @@ msgstr "" + "\n" + "Encabezado Auxiliar de Ejecución\n" + +-#: som.c:5349 ++#: som.c:5440 + msgid "som_sizeof_headers unimplemented" + msgstr "som_sizeof_headers sin implementar" + +@@ -3006,11 +3124,15 @@ msgstr "som_sizeof_headers sin implementar" + msgid "%B:%d: Unexpected character `%s' in S-record file\n" + msgstr "%B:%d: Caractér `%s' inesperado en el fichero S-record\n" + ++#: srec.c:567 srec.c:600 ++msgid "%B:%d: Bad checksum in S-record file\n" ++msgstr "%B:%d: Suma de comprobación errónea en el fichero S-record\n" ++ + #: stabs.c:279 + msgid "%B(%A+0x%lx): Stabs entry has invalid string index." + msgstr "%B(%A+0x%lx): La entrada de cabos tiene una cadena índice inválida." + +-#: syms.c:1057 ++#: syms.c:1067 + msgid "Unsupported .stab relocation" + msgstr "No se admite la reubicación .stab" + +@@ -3047,20 +3169,20 @@ msgstr "Desbordamiento de la pila (%d) en _bfd_vms_push" + msgid "Stack underflow in _bfd_vms_pop" + msgstr "Desbordamiento por debajo de la pila en _bfd_vms_pop" + +-#: vms-misc.c:803 ++#: vms-misc.c:808 + msgid "_bfd_vms_output_counted called with zero bytes" + msgstr "se llamó _bfd_vms_output_counted con cero bytes" + +-#: vms-misc.c:808 ++#: vms-misc.c:813 + msgid "_bfd_vms_output_counted called with too many bytes" + msgstr "se llamó _bfd_vms_output_counted con demasiados bytes" + +-#: vms-misc.c:926 ++#: vms-misc.c:931 + #, c-format + msgid "Symbol %s replaced by %s\n" + msgstr "El símbolo %s fue reemplazado por %s\n" + +-#: vms-misc.c:985 ++#: vms-misc.c:990 + #, c-format + msgid "failed to enter %s" + msgstr "falló la introducción de %s" +@@ -3256,73 +3378,77 @@ msgstr "%s: reubicaci + msgid "%s: `%s' in loader reloc but not loader sym" + msgstr "%s: `%s' en la reubicación del cargador pero no es un símbolo del cargador" + +-#: elf32-ia64.c:1169 elf64-ia64.c:1169 ++#: elf32-ia64.c:1037 elf64-ia64.c:1037 + msgid "%B: Can't relax br at 0x%lx in section `%A'. Please use brl or indirect branch." + msgstr "%B: No se puede relajar br en 0x%lx en la sección `%A'. Por favor use brl o ramificación indirecta." + +-#: elf32-ia64.c:2910 elf64-ia64.c:2910 ++#: elf32-ia64.c:2742 elf64-ia64.c:2742 + msgid "@pltoff reloc against local symbol" + msgstr "reubicación @pltoff contra un símbolo local" + +-#: elf32-ia64.c:4523 elf64-ia64.c:4523 ++#: elf32-ia64.c:4317 elf64-ia64.c:4317 + #, c-format + msgid "%s: short data segment overflowed (0x%lx >= 0x400000)" + msgstr "%s: segmento de datos short desbordado (0x%lx >= 0x400000)" + +-#: elf32-ia64.c:4534 elf64-ia64.c:4534 ++#: elf32-ia64.c:4328 elf64-ia64.c:4328 + #, c-format + msgid "%s: __gp does not cover short data segment" + msgstr "%s: __gp no cubre el segmento de datos short" + +-#: elf32-ia64.c:4808 elf64-ia64.c:4808 ++#: elf32-ia64.c:4598 elf64-ia64.c:4598 + msgid "%B: non-pic code with imm relocation against dynamic symbol `%s'" + msgstr "%B: código que no es pic con reubicación imm contra el símbolo dinámico %s" + +-#: elf32-ia64.c:4875 elf64-ia64.c:4875 ++#: elf32-ia64.c:4665 elf64-ia64.c:4665 + msgid "%B: @gprel relocation against dynamic symbol %s" + msgstr "%B: reubicación @gprel contra el símbolo dinámico %s" + +-#: elf32-ia64.c:4938 elf64-ia64.c:4938 ++#: elf32-ia64.c:4728 elf64-ia64.c:4728 + msgid "%B: linking non-pic code in a position independent executable" + msgstr "%B: se enlaza código que no es pic en un ejecutable independiente de posición" + +-#: elf32-ia64.c:5075 elf64-ia64.c:5075 ++#: elf32-ia64.c:4865 elf64-ia64.c:4865 + msgid "%B: @internal branch to dynamic symbol %s" + msgstr "%B: ramificación @internal al símbolo dinámico %s" + +-#: elf32-ia64.c:5077 elf64-ia64.c:5077 ++#: elf32-ia64.c:4867 elf64-ia64.c:4867 + msgid "%B: speculation fixup to dynamic symbol %s" + msgstr "%B: compostura de especulación al símbolo dinámico %s" + +-#: elf32-ia64.c:5079 elf64-ia64.c:5079 ++#: elf32-ia64.c:4869 elf64-ia64.c:4869 + msgid "%B: @pcrel relocation against dynamic symbol %s" + msgstr "%B: reubicación @pcrel contra el símbolo dinámico %s" + +-#: elf32-ia64.c:5279 elf64-ia64.c:5279 ++#: elf32-ia64.c:5066 elf64-ia64.c:5066 + msgid "unsupported reloc" + msgstr "no se admite la reubicación" + +-#: elf32-ia64.c:5312 elf64-ia64.c:5312 ++#: elf32-ia64.c:5104 elf64-ia64.c:5104 ++msgid "%B: missing TLS section for relocation %s against `%s' at 0x%lx in section `%A'." ++msgstr "%B: falta la sección TLS para la reubicación %s contra `%s' en 0x%lx en la sección `%A'." ++ ++#: elf32-ia64.c:5119 elf64-ia64.c:5119 + msgid "%B: Can't relax br (%s) to `%s' at 0x%lx in section `%A' with size 0x%lx (> 0x1000000)." + msgstr "%B: No se puede relajar br (%s) a `%s' en 0x%lx en la sección `%A' con tamaño 0x%lx (> 0x1000000)." + +-#: elf32-ia64.c:5573 elf64-ia64.c:5573 ++#: elf32-ia64.c:5375 elf64-ia64.c:5375 + msgid "%B: linking trap-on-NULL-dereference with non-trapping files" + msgstr "%B: se enlaza deferencias-captura-en-NULL con ficheros que no son de captura" + +-#: elf32-ia64.c:5582 elf64-ia64.c:5582 ++#: elf32-ia64.c:5384 elf64-ia64.c:5384 + msgid "%B: linking big-endian files with little-endian files" + msgstr "%B: se enlazan ficheros big-endian con ficheros little-endian" + +-#: elf32-ia64.c:5591 elf64-ia64.c:5591 ++#: elf32-ia64.c:5393 elf64-ia64.c:5393 + msgid "%B: linking 64-bit files with 32-bit files" + msgstr "%B: se enlazan ficheros de 64-bit con ficheros de 32-bit" + +-#: elf32-ia64.c:5600 elf64-ia64.c:5600 ++#: elf32-ia64.c:5402 elf64-ia64.c:5402 + msgid "%B: linking constant-gp files with non-constant-gp files" + msgstr "%B: se enlazan ficheros de gp constante con ficheros con gp no constante" + +-#: elf32-ia64.c:5610 elf64-ia64.c:5610 ++#: elf32-ia64.c:5412 elf64-ia64.c:5412 + msgid "%B: linking auto-pic files with non-auto-pic files" + msgstr "%B: se enlazan ficheros de pic automático con ficheros sin pic automático" + +@@ -3602,12 +3728,14 @@ msgstr "" + "\n" + "Tabla [Puntero a Ordinal/Nombre]\n" + +-#: peigen.c:1610 pepigen.c:1610 pex64igen.c:1610 ++#: peigen.c:1617 peigen.c:1796 pepigen.c:1617 pepigen.c:1796 pex64igen.c:1617 ++#: pex64igen.c:1796 + #, c-format + msgid "Warning, .pdata section size (%ld) is not a multiple of %d\n" + msgstr "Aviso, el tamaño de la sección .pdata (%ld) no es un múltiplo de %d\n" + +-#: peigen.c:1614 pepigen.c:1614 pex64igen.c:1614 ++#: peigen.c:1621 peigen.c:1800 pepigen.c:1621 pepigen.c:1800 pex64igen.c:1621 ++#: pex64igen.c:1800 + #, c-format + msgid "" + "\n" +@@ -3616,12 +3744,12 @@ msgstr "" + "\n" + "La Tabla de Funciones (se interpretaron los contenidos de la sección .pdata)\n" + +-#: peigen.c:1617 pepigen.c:1617 pex64igen.c:1617 ++#: peigen.c:1624 pepigen.c:1624 pex64igen.c:1624 + #, c-format + msgid " vma:\t\t\tBegin Address End Address Unwind Info\n" + msgstr " vma:\t\t\tDirección Inicio Dirección Fin Información Desenvuelta\n" + +-#: peigen.c:1619 pepigen.c:1619 pex64igen.c:1619 ++#: peigen.c:1626 pepigen.c:1626 pex64igen.c:1626 + #, c-format + msgid "" + " vma:\t\tBegin End EH EH PrologEnd Exception\n" +@@ -3630,22 +3758,31 @@ msgstr "" + " vma:\t\tInicio Fin EH EH FinPrólogo Excepción\n" + " \t\tDirecc Direcc Asa Datos Dirección Máscara\n" + +-#: peigen.c:1689 pepigen.c:1689 pex64igen.c:1689 ++#: peigen.c:1696 pepigen.c:1696 pex64igen.c:1696 + #, c-format + msgid " Register save millicode" + msgstr " Registro para guardar milicódigo" + +-#: peigen.c:1692 pepigen.c:1692 pex64igen.c:1692 ++#: peigen.c:1699 pepigen.c:1699 pex64igen.c:1699 + #, c-format + msgid " Register restore millicode" + msgstr " Registro para restaurar milicódigo" + +-#: peigen.c:1695 pepigen.c:1695 pex64igen.c:1695 ++#: peigen.c:1702 pepigen.c:1702 pex64igen.c:1702 + #, c-format + msgid " Glue code sequence" + msgstr " Secuencia de código pegamento" + +-#: peigen.c:1745 pepigen.c:1745 pex64igen.c:1745 ++#: peigen.c:1802 pepigen.c:1802 pex64igen.c:1802 ++#, c-format ++msgid "" ++" vma:\t\tBegin Prolog Function Flags Exception EH\n" ++" \t\tAddress Length Length 32b exc Handler Data\n" ++msgstr "" ++" vma:\t\tInicio Prólogo Función Opciones Excepción EH\n" ++" \t\tDirecc Longitud Longitud 32b exc Manejador Datos\n" ++ ++#: peigen.c:1933 pepigen.c:1933 pex64igen.c:1933 + #, c-format + msgid "" + "\n" +@@ -3656,7 +3793,7 @@ msgstr "" + "\n" + "Reubicaciones de Fichero Base PE (se interpretaron los contenidos de la sección .reloc)\n" + +-#: peigen.c:1775 pepigen.c:1775 pex64igen.c:1775 ++#: peigen.c:1963 pepigen.c:1963 pex64igen.c:1963 + #, c-format + msgid "" + "\n" +@@ -3665,7 +3802,7 @@ msgstr "" + "\n" + "Dirección Virtual: %08lx Tamaño del trozo %ld (0x%lx) Número de composturas %ld\n" + +-#: peigen.c:1788 pepigen.c:1788 pex64igen.c:1788 ++#: peigen.c:1976 pepigen.c:1976 pex64igen.c:1976 + #, c-format + msgid "\treloc %4d offset %4x [%4lx] %s" + msgstr "\treubicación %4d desplazamiento %4x [%4lx] %s" +@@ -3673,7 +3810,7 @@ msgstr "\treubicaci + #. The MS dumpbin program reportedly ands with 0xff0f before + #. printing the characteristics field. Not sure why. No reason to + #. emulate it here. +-#: peigen.c:1827 pepigen.c:1827 pex64igen.c:1827 ++#: peigen.c:2015 pepigen.c:2015 pex64igen.c:2015 + #, c-format + msgid "" + "\n" +@@ -3682,26 +3819,47 @@ msgstr "" + "\n" + "Características 0x%x\n" + +-#: peigen.c:2088 pepigen.c:2088 pex64igen.c:2088 ++#: peigen.c:2289 pepigen.c:2289 pex64igen.c:2289 + msgid "%B: unable to fill in DataDictionary[1] because .idata$2 is missing" + msgstr "%B: no se puede llenar DataDictionary[1] porque falta .idata$2" + +-#: peigen.c:2106 pepigen.c:2106 pex64igen.c:2106 ++#: peigen.c:2307 pepigen.c:2307 pex64igen.c:2307 + msgid "%B: unable to fill in DataDictionary[1] because .idata$4 is missing" + msgstr "%B: no se puede llenar DataDictionary[1] porque falta .idata$4" + +-#: peigen.c:2125 pepigen.c:2125 pex64igen.c:2125 ++#: peigen.c:2326 pepigen.c:2326 pex64igen.c:2326 + msgid "%B: unable to fill in DataDictionary[12] because .idata$5 is missing" + msgstr "%B: no se puede llenar DataDictionary[12] porque falta .idata$5" + +-#: peigen.c:2143 pepigen.c:2143 pex64igen.c:2143 ++#: peigen.c:2344 pepigen.c:2344 pex64igen.c:2344 + msgid "%B: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE (12)] because .idata$6 is missing" + msgstr "%B: no se puede llenar DataDictionary[PE_IMPORT_ADDRESS_TABLE (12)] porque falta .idata$6" + +-#: peigen.c:2163 pepigen.c:2163 pex64igen.c:2163 ++#: peigen.c:2364 pepigen.c:2364 pex64igen.c:2364 + msgid "%B: unable to fill in DataDictionary[9] because __tls_used is missing" + msgstr "%B: no se puede llenar DataDictionary[9] porque falta __tls_used" + ++#~ msgid "Dwarf Error: DW_FORM_strp offset (%lu) greater than or equal to .debug_str size (%lu)." ++#~ msgstr "Error de Dwarf: El desplazamiento DW_FROM_strp (%lu) es más grande o igual que el tamaño de .debug_str (%lu)." ++ ++#~ msgid "Dwarf Error: Can't find .debug_abbrev section." ++#~ msgstr "Error de Dwarf: No se puede encontrar la sección .debug_abbrev." ++ ++#~ msgid "Dwarf Error: Abbrev offset (%lu) greater than or equal to .debug_abbrev size (%lu)." ++#~ msgstr "Error de Dwarf: El desplazamiento de abreviatura (%lu) es más grande o igual que el tamaño de .debug_abbrev (%lu)." ++ ++#~ msgid "Dwarf Error: Can't find .debug_line section." ++#~ msgstr "Error de Dwarf: No se puede encontrar lan sección .debug_line." ++ ++#~ msgid "Dwarf Error: Can't find .debug_ranges section." ++#~ msgstr "Error de Dwarf: No se puede encontrar lan sección .debug_ranges." ++ ++#~ msgid "ERROR: %B: Conflicting definitions of wchar_t" ++#~ msgstr "ERROR: %B: Definiciones en conflicto de wchar_t" ++ ++#~ msgid "%B: relocation R_X86_64_PC32 against protected function `%s' can not be used when making a shared object" ++#~ msgstr "%B: no se puede usar la reubicación R_X86_64_PC32 contra la función protegida `%' cuando se hace un objeto compartido" ++ + #~ msgid "ERROR: %B: Conflicting enum sizes" + #~ msgstr "ERROR: %B: Tamaños de enum en conflicto" + +@@ -3846,9 +4004,6 @@ msgstr "%B: no se puede llenar DataDictionary[9] porque falta __tls_used" + #~ msgid "local symbols in discarded section %s" + #~ msgstr "símbolos locales en la sección descartada %s" + +-#~ msgid "%s: linking abicalls files with non-abicalls files" +-#~ msgstr "%s: se enlazan ficheros de llamadas abi con ficheros que no son de llamadas abi" +- + #~ msgid "%s: ISA mismatch (-mips%d) with previous modules (-mips%d)" + #~ msgstr "%s: no coincide el ISA (-mips%d) con módulos previos (-mips%d)" + +diff --git a/gdb/Makefile.in b/gdb/Makefile.in +index 74aa72e..c84a4ac 100644 +--- a/gdb/Makefile.in ++++ b/gdb/Makefile.in +@@ -167,11 +167,20 @@ INTL_CFLAGS = @INCINTL@ + + # Where is the ICONV library? This can be empty if libc has iconv. + LIBICONV = @LIBICONV@ ++LIBICONV_INCLUDE = @LIBICONV_INCLUDE@ ++LIBICONV_LIBDIR = @LIBICONV_LIBDIR@ + + # Did the user give us a --with-sysroot option? + TARGET_SYSTEM_ROOT = @TARGET_SYSTEM_ROOT@ + TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@ + ++# Did the user give us a --with-gdb-datadir option? ++GDB_DATADIR_PATH = @GDB_DATADIR_PATH@ ++ ++# The argument to --with-pythondir. If not given, this is ++# GDB_DATADIR_PATH/python. ++pythondir = @pythondir@ ++ + # Helper code from gnulib. + LIBGNU = gnulib/libgnu.a + INCGNU = -I$(srcdir)/gnulib -Ignulib +@@ -270,12 +279,34 @@ SUBDIR_TUI_CFLAGS= \ + # + SUBDIR_PYTHON_OBS = \ + python.o \ ++ python-block.o \ ++ python-breakpoint.o \ + python-cmd.o \ ++ python-frame.o \ ++ python-function.o \ ++ python-hooks.o \ ++ python-membuf.o \ ++ python-objfile.o \ ++ python-param.o \ ++ python-symbol.o \ ++ python-symtab.o \ ++ python-type.o \ + python-utils.o \ + python-value.o + SUBDIR_PYTHON_SRCS = \ + python/python.c \ ++ python/python-block.c \ ++ python/python-breakpoint.c \ + python/python-cmd.c \ ++ python/python-frame.c \ ++ python/python-function.c \ ++ python/python-hooks.c \ ++ python/python-membuf.c \ ++ python/python-objfile.c \ ++ python/python-param.c \ ++ python/python-symbol.c \ ++ python/python-symtab.c \ ++ python/python-type.c \ + python/python-utils.c \ + python/python-value.c + SUBDIR_PYTHON_DEPS = +@@ -390,7 +421,8 @@ INTERNAL_CFLAGS_BASE = \ + $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \ + $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \ + $(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \ +- $(INTL_CFLAGS) $(INCGNU) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS) ++ $(INTL_CFLAGS) $(INCGNU) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS) \ ++ $(LIBICONV_INCLUDE) + INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS) + INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS) + +@@ -402,7 +434,7 @@ LDFLAGS = @LDFLAGS@ + # I think it's perfectly reasonable for a user to set -pg in CFLAGS + # and have it work; that's why CFLAGS is here. + # PROFILE_CFLAGS is _not_ included, however, because we use monstartup. +-INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(MH_LDFLAGS) $(LDFLAGS) $(CONFIG_LDFLAGS) ++INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(MH_LDFLAGS) $(LDFLAGS) $(CONFIG_LDFLAGS) $(LIBICONV_LIBDIR) + + # If your system is missing alloca(), or, more likely, it's there but + # it doesn't work, then refer to libiberty. +@@ -663,6 +695,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ + valarith.c valops.c valprint.c value.c varobj.c vec.c \ + wrapper.c \ + xml-tdesc.c xml-support.c \ ++ xml-syscall.c \ + inferior.c + + LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c +@@ -733,7 +766,8 @@ config/sparc/nm-sol2.h config/nm-linux.h config/mips/nm-irix5.h \ + config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \ + annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ + remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \ +-sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h ++sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h xml-syscall.h \ ++python/python.h python/python-internal.h + + # Header files that already have srcdir in them, or which are in objdir. + +@@ -812,10 +846,16 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ + trad-frame.o \ + tramp-frame.o \ + solib.o solib-null.o \ +- prologue-value.o memory-map.o xml-support.o \ ++ prologue-value.o memory-map.o xml-support.o xml-syscall.o \ + target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ + inferior.o osdata.o + ++# Definitions for the syscall's XML files and dir ++XML_SYSCALLS_DIR = syscalls/ ++XML_SYSCALLS_FILES = gdb-syscalls.dtd \ ++ ppc-linux.xml ppc64-linux.xml \ ++ i386-linux.xml amd64-linux.xml ++ + TSOBS = inflow.o + + SUBDIRS = @subdirs@ +@@ -849,11 +889,38 @@ generated_files = config.h observer.h observer.inc ada-lex.c \ + $(COMPILE) $< + $(POSTCOMPILE) + +-all: gdb$(EXEEXT) $(CONFIG_ALL) ++all: gdb$(EXEEXT) $(CONFIG_ALL) .gdbinit xml-syscall-copy + @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do + .PHONY: all-tui + all-tui: $(TUI)$(EXEEXT) + ++xml-syscall-copy: ++ if [ "`cd $(srcdir) && pwd`" != "`pwd`" ] ; then \ ++ mkdir -p ./$(XML_SYSCALLS_DIR) ; \ ++ list='$(XML_SYSCALLS_FILES)' ; \ ++ for file in $$list ; do \ ++ f=$(srcdir)/$(XML_SYSCALLS_DIR)/$$file ; \ ++ if test -f $$f ; then \ ++ $(INSTALL_DATA) $$f \ ++ ./$(XML_SYSCALLS_DIR) ; \ ++ fi ; \ ++ done ; \ ++ fi ; ++ ++# This target is responsible for properly installing the syscalls' ++# XML files in the system. ++xml-syscall-install: ++ $(SHELL) $(srcdir)/../mkinstalldirs \ ++ $(DESTDIR)$(GDB_DATADIR_PATH)/$(XML_SYSCALLS_DIR) ; \ ++ list='$(XML_SYSCALLS_FILES)' ; \ ++ for file in $$list ; do \ ++ f=$(srcdir)/$(XML_SYSCALLS_DIR)/$$file ; \ ++ if test -f $$f ; then \ ++ $(INSTALL_DATA) $$f \ ++ $(DESTDIR)$(GDB_DATADIR_PATH)/$(XML_SYSCALLS_DIR) ; \ ++ fi ; \ ++ done ; ++ + installcheck: + + # The check target can not use subdir_do, because subdir_do does not +@@ -907,8 +974,11 @@ gdb.z:gdb.1 + # source file and doesn't care about rebuilding or just wants to save the + # time it takes for make to check that all is up to date. + # install-only is intended to address that need. +-install: all install-only +-install-only: $(CONFIG_INSTALL) ++install: all install-only ++ ++# The "install-only" target also installs the syscalls' XML files in ++# the system. ++install-only: $(CONFIG_INSTALL) xml-syscall-install + transformed_name=`t='$(program_transform_name)'; \ + echo gdb | sed -e "$$t"` ; \ + if test "x$$transformed_name" = x; then \ +@@ -1202,6 +1272,12 @@ stamp-h: config.in config.status + CONFIG_LINKS= \ + $(SHELL) config.status + ++.gdbinit: gdbinit.in config.status ++ CONFIG_FILES=".gdbinit:gdbinit.in" \ ++ CONFIG_COMMANDS= \ ++ CONFIG_HEADERS= \ ++ $(SHELL) config.status ++ + config.status: configure configure.tgt configure.host + $(SHELL) config.status --recheck + +@@ -1845,10 +1921,54 @@ python.o: $(srcdir)/python/python.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python.c + $(POSTCOMPILE) + ++python-block.o: $(srcdir)/python/python-block.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-block.c ++ $(POSTCOMPILE) ++ ++python-breakpoint.o: $(srcdir)/python/python-breakpoint.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-breakpoint.c ++ $(POSTCOMPILE) ++ + python-cmd.o: $(srcdir)/python/python-cmd.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-cmd.c + $(POSTCOMPILE) + ++python-frame.o: $(srcdir)/python/python-frame.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-frame.c ++ $(POSTCOMPILE) ++ ++python-function.o: $(srcdir)/python/python-function.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-function.c ++ $(POSTCOMPILE) ++ ++python-hooks.o: $(srcdir)/python/python-hooks.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-hooks.c ++ $(POSTCOMPILE) ++ ++python-membuf.o: $(srcdir)/python/python-membuf.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-membuf.c ++ $(POSTCOMPILE) ++ ++python-objfile.o: $(srcdir)/python/python-objfile.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-objfile.c ++ $(POSTCOMPILE) ++ ++python-param.o: $(srcdir)/python/python-param.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-param.c ++ $(POSTCOMPILE) ++ ++python-symbol.o: $(srcdir)/python/python-symbol.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-symbol.c ++ $(POSTCOMPILE) ++ ++python-symtab.o: $(srcdir)/python/python-symtab.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-symtab.c ++ $(POSTCOMPILE) ++ ++python-type.o: $(srcdir)/python/python-type.c ++ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-type.c ++ $(POSTCOMPILE) ++ + python-utils.o: $(srcdir)/python/python-utils.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c + $(POSTCOMPILE) +@@ -1857,6 +1977,38 @@ python-value.o: $(srcdir)/python/python-value.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-value.c + $(POSTCOMPILE) + ++# All python library files, with the "python/lib" stripped off. ++# Note that we should only install files in the "gdb" module. ++PY_FILES = gdb/FrameIterator.py gdb/command/alias.py \ ++ gdb/command/backtrace.py gdb/command/require.py \ ++ gdb/command/pahole.py gdb/command/__init__.py \ ++ gdb/command/ignore_errors.py gdb/command/save_breakpoints.py \ ++ gdb/libstdcxx/v6/printers.py gdb/libstdcxx/v6/__init__.py \ ++ gdb/libstdcxx/__init__.py gdb/function/caller_is.py \ ++ gdb/function/in_scope.py gdb/function/__init__.py gdb/backtrace.py \ ++ gdb/__init__.py ++ ++# Install the Python library. Python library files go under ++# $(pythondir). ++install-python: ++ files='$(PY_FILES)'; for file in $$files; do \ ++ dir=`echo "$$file" | sed 's,/[^/]*$$,,'`; \ ++ $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(pythondir)/$$dir; \ ++ $(INSTALL_DATA) $(srcdir)/python/lib/$$file $(DESTDIR)$(pythondir)/$$file; \ ++ done ++ ++# Other packages may have their files installed in $(pythondir). ++uninstall-python: ++ files='$(PY_FILES)'; for file in $$files; do \ ++ slashdir=`echo "/$$file" | sed 's,/[^/]*$$,,'`; \ ++ rm -f $(DESTDIR)$(pythondir)/$$file; \ ++ while test "x$$file" != "x$$slashdir"; do \ ++ rmdir 2>/dev/null "$(DESTDIR)$(pythondir)$$slashdir"; \ ++ file="$$slashdir"; \ ++ slashdir=`echo "$$file" | sed 's,/[^/]*$$,,'`; \ ++ done \ ++ done ++ + # + # Dependency tracking. Most of this is conditional on GNU Make being + # found by configure; if GNU Make is not found, we fall back to a +diff --git a/gdb/NEWS b/gdb/NEWS +index 9078412..3f084e7 100644 +--- a/gdb/NEWS ++++ b/gdb/NEWS +@@ -3,6 +3,13 @@ + + *** Changes since GDB 6.8 + ++* GDB now has support for multi-byte and wide character sets on the ++target. Strings whose character type is wchar_t, char16_t, or ++char32_t are now correctly printed. GDB supports wide- and unicode- ++literals in C, that is, L'x', L"string", u'x', u"string", U'x', and ++U"string" syntax. And, GDB allows the "%ls" and "%lc" formats in ++`printf'. ++ + * GDB now supports automatic retrieval of shared library files from + remote targets. To use this feature, specify a system root that begins + with the `remote:' prefix, either via the `set sysroot' command or via +@@ -182,6 +189,11 @@ set target-async + with GDB while the target is running. "show target-async" displays the + current state of asynchronous execution of the target. + ++set target-wide-charset ++show target-wide-charset ++ The target-wide-charset is the name of the character set that GDB ++ uses when printing characters whose type is wchar_t. ++ + set tcp auto-retry (on|off) + show tcp auto-retry + set tcp connect-timeout +diff --git a/gdb/acinclude.m4 b/gdb/acinclude.m4 +index 81b5d47..c2bd043 100644 +--- a/gdb/acinclude.m4 ++++ b/gdb/acinclude.m4 +@@ -29,6 +29,9 @@ sinclude([../config/depstand.m4]) + dnl For AM_LC_MESSAGES + sinclude([../config/lcmessage.m4]) + ++dnl For AM_LANGINFO_CODESET. ++sinclude([../config/codeset.m4]) ++ + # + # Sometimes the native compiler is a bogus stub for gcc or /usr/ucb/cc. This + # makes configure think it's cross compiling. If --target wasn't used, then +@@ -174,8 +177,8 @@ AC_DEFUN([AM_ICONV], + AC_ARG_WITH([libiconv-prefix], + [ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [ + for dir in `echo "$withval" | tr : ' '`; do +- if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi +- if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi ++ if test -d $dir/include; then LIBICONV_INCLUDE="-I$dir/include"; CPPFLAGS="$CPPFLAGS -I$dir/include"; fi ++ if test -d $dir/lib; then LIBICONV_LIBDIR="-L$dir/lib"; LDFLAGS="$LDFLAGS -L$dir/lib"; fi + done + ]) + +@@ -230,6 +233,8 @@ size_t iconv(); + LIBICONV="-liconv" + fi + AC_SUBST(LIBICONV) ++ AC_SUBST(LIBICONV_INCLUDE) ++ AC_SUBST(LIBICONV_LIBDIR) + ]) + + dnl written by Guido Draheim , original by Alexandre Oliva +diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c +index 671cb35..edcee3f 100644 +--- a/gdb/ada-lang.c ++++ b/gdb/ada-lang.c +@@ -486,7 +486,7 @@ coerce_unspec_val_to_type (struct value *val, struct type *type) + set_value_component_location (result, val); + set_value_bitsize (result, value_bitsize (val)); + set_value_bitpos (result, value_bitpos (val)); +- VALUE_ADDRESS (result) += value_offset (val); ++ set_value_address (result, value_address (val)); + if (value_lazy (val) + || TYPE_LENGTH (type) > TYPE_LENGTH (value_type (val))) + set_value_lazy (result, 1); +@@ -1328,7 +1328,7 @@ thin_data_pntr (struct value *val) + value_copy (val)); + else + return value_from_longest (desc_data_type (thin_descriptor_type (type)), +- VALUE_ADDRESS (val) + value_offset (val)); ++ value_address (val)); + } + + /* True iff TYPE indicates a "thick" array pointer type. */ +@@ -1393,7 +1393,7 @@ desc_bounds (struct value *arr) + if (TYPE_CODE (type) == TYPE_CODE_PTR) + addr = value_as_long (arr); + else +- addr = VALUE_ADDRESS (arr) + value_offset (arr); ++ addr = value_address (arr); + + return + value_from_longest (lookup_pointer_type (bounds_type), +@@ -1666,8 +1666,8 @@ ada_type_of_array (struct value *arr, int bounds) + return NULL; + while (arity > 0) + { +- struct type *range_type = alloc_type (objf); +- struct type *array_type = alloc_type (objf); ++ struct type *range_type = alloc_type (objf, NULL); ++ struct type *array_type = alloc_type (objf, NULL); + struct value *low = desc_one_bound (descriptor, arity, 0); + struct value *high = desc_one_bound (descriptor, arity, 1); + arity -= 1; +@@ -1774,9 +1774,9 @@ packed_array_type (struct type *type, long *elt_bits) + if (TYPE_CODE (type) != TYPE_CODE_ARRAY) + return type; + +- new_type = alloc_type (TYPE_OBJFILE (type)); + new_elt_type = packed_array_type (ada_check_typedef (TYPE_TARGET_TYPE (type)), + elt_bits); ++ new_type = alloc_type (TYPE_OBJFILE (type), new_elt_type); + create_array_type (new_type, new_elt_type, TYPE_INDEX_TYPE (type)); + TYPE_FIELD_BITSIZE (new_type, 0) = *elt_bits; + TYPE_NAME (new_type) = ada_type_name (type); +@@ -1831,6 +1831,7 @@ decode_packed_array_type (struct type *type) + return NULL; + } + shadow_type = SYMBOL_TYPE (sym); ++ CHECK_TYPEDEF (shadow_type); + + if (TYPE_CODE (shadow_type) != TYPE_CODE_ARRAY) + { +@@ -2005,10 +2006,9 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, + } + else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj)) + { +- v = value_at (type, +- VALUE_ADDRESS (obj) + value_offset (obj) + offset); ++ v = value_at (type, value_address (obj) + offset); + bytes = (unsigned char *) alloca (len); +- read_memory (VALUE_ADDRESS (v), bytes, len); ++ read_memory (value_address (v), bytes, len); + } + else + { +@@ -2018,15 +2018,18 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, + + if (obj != NULL) + { ++ CORE_ADDR new_addr; ++ + set_value_component_location (v, obj); +- VALUE_ADDRESS (v) += value_offset (obj) + offset; ++ new_addr = value_address (obj) + offset; + set_value_bitpos (v, bit_offset + value_bitpos (obj)); + set_value_bitsize (v, bit_size); + if (value_bitpos (v) >= HOST_CHAR_BIT) + { +- VALUE_ADDRESS (v) += 1; ++ new_addr++; + set_value_bitpos (v, value_bitpos (v) - HOST_CHAR_BIT); + } ++ set_value_address (v, new_addr); + } + else + set_value_bitsize (v, bit_size); +@@ -2218,7 +2221,7 @@ ada_value_assign (struct value *toval, struct value *fromval) + int from_size; + char *buffer = (char *) alloca (len); + struct value *val; +- CORE_ADDR to_addr = VALUE_ADDRESS (toval) + value_offset (toval); ++ CORE_ADDR to_addr = value_address (toval); + + if (TYPE_CODE (type) == TYPE_CODE_FLT) + fromval = value_cast (type, fromval); +@@ -2259,8 +2262,7 @@ value_assign_to_component (struct value *container, struct value *component, + struct value *val) + { + LONGEST offset_in_container = +- (LONGEST) (VALUE_ADDRESS (component) + value_offset (component) +- - VALUE_ADDRESS (container) - value_offset (container)); ++ (LONGEST) (value_address (component) - value_address (container)); + int bit_offset_in_container = + value_bitpos (component) - value_bitpos (container); + int bits; +@@ -3788,7 +3790,7 @@ parse_old_style_renaming (struct type *type, + /* Return an lvalue containing the value VAL. This is the identity on + lvalues, and otherwise has the side-effect of pushing a copy of VAL + on the stack, using and updating *SP as the stack pointer, and +- returning an lvalue whose VALUE_ADDRESS points to the copy. */ ++ returning an lvalue whose value_address points to the copy. */ + + static struct value * + ensure_lval (struct value *val, CORE_ADDR *sp) +@@ -3802,12 +3804,12 @@ ensure_lval (struct value *val, CORE_ADDR *sp) + indicated. */ + if (gdbarch_inner_than (current_gdbarch, 1, 2)) + { +- /* Stack grows downward. Align SP and VALUE_ADDRESS (val) after ++ /* Stack grows downward. Align SP and value_address (val) after + reserving sufficient space. */ + *sp -= len; + if (gdbarch_frame_align_p (current_gdbarch)) + *sp = gdbarch_frame_align (current_gdbarch, *sp); +- VALUE_ADDRESS (val) = *sp; ++ set_value_address (val, *sp); + } + else + { +@@ -3815,14 +3817,14 @@ ensure_lval (struct value *val, CORE_ADDR *sp) + then again, re-align the frame. */ + if (gdbarch_frame_align_p (current_gdbarch)) + *sp = gdbarch_frame_align (current_gdbarch, *sp); +- VALUE_ADDRESS (val) = *sp; ++ set_value_address (val, *sp); + *sp += len; + if (gdbarch_frame_align_p (current_gdbarch)) + *sp = gdbarch_frame_align (current_gdbarch, *sp); + } + VALUE_LVAL (val) = lval_memory; + +- write_memory (VALUE_ADDRESS (val), value_contents_raw (val), len); ++ write_memory (value_address (val), value_contents_raw (val), len); + } + + return val; +@@ -3911,12 +3913,12 @@ make_array_descriptor (struct type *type, struct value *arr, CORE_ADDR *sp) + bounds = ensure_lval (bounds, sp); + + modify_general_field (value_contents_writeable (descriptor), +- VALUE_ADDRESS (ensure_lval (arr, sp)), ++ value_address (ensure_lval (arr, sp)), + fat_pntr_data_bitpos (desc_type), + fat_pntr_data_bitsize (desc_type)); + + modify_general_field (value_contents_writeable (descriptor), +- VALUE_ADDRESS (bounds), ++ value_address (bounds), + fat_pntr_bounds_bitpos (desc_type), + fat_pntr_bounds_bitsize (desc_type)); + +@@ -6790,7 +6792,7 @@ variant_field_index (struct type *type) + static struct type * + empty_record (struct objfile *objfile) + { +- struct type *type = alloc_type (objfile); ++ struct type *type = alloc_type (objfile, NULL); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_NFIELDS (type) = 0; + TYPE_FIELDS (type) = NULL; +@@ -6847,7 +6849,7 @@ ada_template_to_fixed_record_type_1 (struct type *type, + nfields++; + } + +- rtype = alloc_type (TYPE_OBJFILE (type)); ++ rtype = alloc_type (TYPE_OBJFILE (type), NULL); + TYPE_CODE (rtype) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (rtype); + TYPE_NFIELDS (rtype) = nfields; +@@ -7034,7 +7036,8 @@ template_to_static_fixed_type (struct type *type0) + new_type = static_unwrap_type (field_type); + if (type == type0 && new_type != field_type) + { +- TYPE_TARGET_TYPE (type0) = type = alloc_type (TYPE_OBJFILE (type0)); ++ TYPE_TARGET_TYPE (type0) = type = alloc_type (TYPE_OBJFILE (type0), ++ NULL); + TYPE_CODE (type) = TYPE_CODE (type0); + INIT_CPLUS_SPECIFIC (type); + TYPE_NFIELDS (type) = nfields; +@@ -7079,7 +7082,7 @@ to_record_with_fixed_variant_part (struct type *type, const gdb_byte *valaddr, + else + dval = dval0; + +- rtype = alloc_type (TYPE_OBJFILE (type)); ++ rtype = alloc_type (TYPE_OBJFILE (type), NULL); + TYPE_CODE (rtype) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (rtype); + TYPE_NFIELDS (rtype) = nfields; +@@ -7251,7 +7254,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, + if (elt_type0 == elt_type) + result = type0; + else +- result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), ++ result = create_array_type (alloc_type (TYPE_OBJFILE (type0), NULL), + elt_type, TYPE_INDEX_TYPE (type0)); + } + else +@@ -7281,7 +7284,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, + struct type *range_type = + to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i), + dval, TYPE_OBJFILE (type0)); +- result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), ++ result = create_array_type (alloc_type (TYPE_OBJFILE (type0), NULL), + result, range_type); + } + if (!ignore_too_big && TYPE_LENGTH (result) > varsize_limit) +@@ -7523,7 +7526,7 @@ static struct value * + ada_to_fixed_value (struct value *val) + { + return ada_to_fixed_value_create (value_type (val), +- VALUE_ADDRESS (val) + value_offset (val), ++ value_address (val), + val); + } + +@@ -7869,7 +7872,7 @@ unwrap_value (struct value *val) + return + coerce_unspec_val_to_type + (val, ada_to_fixed_type (raw_real_type, 0, +- VALUE_ADDRESS (val) + value_offset (val), ++ value_address (val), + NULL, 1)); + } + } +@@ -9546,7 +9549,7 @@ to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile) + if (L < INT_MIN || U > INT_MAX) + return raw_type; + else +- return create_range_type (alloc_type (objfile), raw_type, ++ return create_range_type (alloc_type (objfile, NULL), raw_type, + discrete_type_low_bound (raw_type), + discrete_type_high_bound (raw_type)); + } +@@ -9611,7 +9614,7 @@ to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile) + + if (objfile == NULL) + objfile = TYPE_OBJFILE (base_type); +- type = create_range_type (alloc_type (objfile), base_type, L, U); ++ type = create_range_type (alloc_type (objfile, NULL), base_type, L, U); + TYPE_NAME (type) = name; + return type; + } +@@ -11009,9 +11012,9 @@ ada_language_arch_info (struct gdbarch *gdbarch, + /* Not really used, but needed in the ada_language_defn. */ + + static void +-emit_char (int c, struct ui_file *stream, int quoter) ++emit_char (int c, struct type *type, struct ui_file *stream, int quoter) + { +- ada_emit_char (c, stream, quoter, 1); ++ ada_emit_char (c, type, stream, quoter, 1); + } + + static int +diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h +index c7cc62a..fac027b 100644 +--- a/gdb/ada-lang.h ++++ b/gdb/ada-lang.h +@@ -257,12 +257,12 @@ extern int ada_value_print (struct value *, struct ui_file *, + + /* Defined in ada-lang.c */ + +-extern void ada_emit_char (int, struct ui_file *, int, int); ++extern void ada_emit_char (int, struct type *, struct ui_file *, int, int); + +-extern void ada_printchar (int, struct ui_file *); ++extern void ada_printchar (int, struct type *, struct ui_file *); + +-extern void ada_printstr (struct ui_file *, const gdb_byte *, +- unsigned int, int, int, ++extern void ada_printstr (struct ui_file *, struct type *, const gdb_byte *, ++ unsigned int, int, + const struct value_print_options *); + + struct value *ada_convert_actual (struct value *actual, +diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c +index 61ed06e..8b1639e 100644 +--- a/gdb/ada-tasks.c ++++ b/gdb/ada-tasks.c +@@ -293,7 +293,7 @@ read_fat_string_value (char *dest, struct value *val, int max_len) + + /* Extract LEN characters from the fat string. */ + array_val = value_ind (value_field (val, array_fieldno)); +- read_memory (VALUE_ADDRESS (array_val), dest, len); ++ read_memory (value_address (array_val), dest, len); + + /* Add the NUL character to close the string. */ + dest[len] = '\0'; +diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c +index f00824a..ef665c4 100644 +--- a/gdb/ada-typeprint.c ++++ b/gdb/ada-typeprint.c +@@ -357,16 +357,17 @@ print_array_type (struct type *type, struct ui_file *stream, int show, + bitsize = 0; + fprintf_filtered (stream, "array ("); + ++ if (type == NULL) ++ { ++ fprintf_filtered (stream, _("")); ++ return; ++ } ++ + n_indices = -1; + if (show < 0) + fprintf_filtered (stream, "..."); + else + { +- if (type == NULL) +- { +- fprintf_filtered (stream, _("")); +- return; +- } + if (ada_is_simple_array_type (type)) + { + struct type *range_desc_type = +diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c +index 9647971..cfa94a2 100644 +--- a/gdb/ada-valprint.c ++++ b/gdb/ada-valprint.c +@@ -269,7 +269,8 @@ printable_val_type (struct type *type, const gdb_byte *valaddr) + (1 or 2) of the character. */ + + void +-ada_emit_char (int c, struct ui_file *stream, int quoter, int type_len) ++ada_emit_char (int c, struct type *type, struct ui_file *stream, ++ int quoter, int type_len) + { + if (type_len != 2) + type_len = 1; +@@ -366,10 +367,10 @@ ada_print_floating (const gdb_byte *valaddr, struct type *type, + } + + void +-ada_printchar (int c, struct ui_file *stream) ++ada_printchar (int c, struct type *type, struct ui_file *stream) + { + fputs_filtered ("'", stream); +- ada_emit_char (c, stream, '\'', 1); ++ ada_emit_char (c, type, stream, '\'', 1); + fputs_filtered ("'", stream); + } + +@@ -411,7 +412,7 @@ ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream) + break; + + case TYPE_CODE_CHAR: +- LA_PRINT_CHAR ((unsigned char) val, stream); ++ LA_PRINT_CHAR ((unsigned char) val, type, stream); + break; + + case TYPE_CODE_BOOL: +@@ -454,7 +455,7 @@ ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream) + */ + + static void +-printstr (struct ui_file *stream, const gdb_byte *string, ++printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string, + unsigned int length, int force_ellipses, int type_len, + const struct value_print_options *options) + { +@@ -506,7 +507,7 @@ printstr (struct ui_file *stream, const gdb_byte *string, + in_quotes = 0; + } + fputs_filtered ("'", stream); +- ada_emit_char (char_at (string, i, type_len), stream, '\'', ++ ada_emit_char (char_at (string, i, type_len), elttype, stream, '\'', + type_len); + fputs_filtered ("'", stream); + fprintf_filtered (stream, _(" "), reps); +@@ -524,7 +525,7 @@ printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("\"", stream); + in_quotes = 1; + } +- ada_emit_char (char_at (string, i, type_len), stream, '"', ++ ada_emit_char (char_at (string, i, type_len), elttype, stream, '"', + type_len); + things_printed += 1; + } +@@ -544,11 +545,12 @@ printstr (struct ui_file *stream, const gdb_byte *string, + } + + void +-ada_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++ada_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, ++ unsigned int length, int force_ellipses, + const struct value_print_options *options) + { +- printstr (stream, string, length, force_ellipses, width, options); ++ printstr (stream, type, string, length, force_ellipses, TYPE_LENGTH (type), ++ options); + } + + +@@ -637,7 +639,7 @@ ada_val_print_array (struct type *type, const gdb_byte *valaddr, + len = temp_len; + } + +- printstr (stream, valaddr, len, 0, eltlen, options); ++ printstr (stream, elttype, valaddr, len, 0, eltlen, options); + result = len; + } + else +@@ -688,7 +690,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, + } + else + retn = ada_val_print_1 (value_type (val), value_contents (val), 0, +- VALUE_ADDRESS (val), stream, recurse, options); ++ value_address (val), stream, recurse, options); + value_free_to_mark (mark); + return retn; + } +@@ -817,7 +819,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, + { + fputs_filtered (" ", stream); + ada_printchar ((unsigned char) unpack_long (type, valaddr), +- stream); ++ type, stream); + } + } + return 0; +@@ -904,7 +906,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, + deref_val_int)); + val_print (value_type (deref_val), + value_contents (deref_val), 0, +- VALUE_ADDRESS (deref_val), stream, recurse + 1, ++ value_address (deref_val), stream, recurse + 1, + options, current_language); + } + else +@@ -944,7 +946,7 @@ ada_value_print (struct value *val0, struct ui_file *stream, + const struct value_print_options *options) + { + const gdb_byte *valaddr = value_contents (val0); +- CORE_ADDR address = VALUE_ADDRESS (val0) + value_offset (val0); ++ CORE_ADDR address = value_address (val0); + struct type *type = + ada_to_fixed_type (value_type (val0), valaddr, address, NULL, 1); + struct value *val = +diff --git a/gdb/auxv.c b/gdb/auxv.c +index 5007cd0..3a51ec5 100644 +--- a/gdb/auxv.c ++++ b/gdb/auxv.c +@@ -205,6 +205,7 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) + TAG (AT_UCACHEBSIZE, _("Unified cache block size"), dec); + TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec); + TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str); ++ TAG (AT_RANDOM, _("Address of 16 random bytes"), hex); + TAG (AT_EXECFN, _("File name of executable"), str); + TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec); + TAG (AT_SYSINFO, _("Special system info/entry points"), hex); +@@ -247,7 +248,8 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) + get_user_print_options (&opts); + if (opts.addressprint) + fprintf_filtered (file, "0x%s", paddr_nz (val)); +- val_print_string (val, -1, 1, file, &opts); ++ val_print_string (builtin_type (target_gdbarch)->builtin_char, ++ val, -1, file, &opts); + fprintf_filtered (file, "\n"); + } + break; +diff --git a/gdb/block.c b/gdb/block.c +index 8f0140c..d451769 100644 +--- a/gdb/block.c ++++ b/gdb/block.c +@@ -207,24 +207,16 @@ block_set_scope (struct block *block, const char *scope, + } + + /* This returns the first using directives associated to BLOCK, if +- any. */ +- +-/* FIXME: carlton/2003-04-23: This uses the fact that we currently +- only have using directives in static blocks, because we only +- generate using directives from anonymous namespaces. Eventually, +- when we support using directives everywhere, we'll want to replace +- this by some iterator functions. */ ++ any. Each BLOCK_NAMESPACE()->USING already contains all the namespaces ++ imported at that code point - even those from its parent blocks. */ + + struct using_direct * + block_using (const struct block *block) + { +- const struct block *static_block = block_static_block (block); +- +- if (static_block == NULL +- || BLOCK_NAMESPACE (static_block) == NULL) ++ if (block == NULL || BLOCK_NAMESPACE (block) == NULL) + return NULL; + else +- return BLOCK_NAMESPACE (static_block)->using; ++ return BLOCK_NAMESPACE (block)->using; + } + + /* Set BLOCK's using member to USING; if needed, allocate memory via +diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c +index b23b294..567f574 100644 +--- a/gdb/breakpoint.c ++++ b/gdb/breakpoint.c +@@ -191,6 +191,8 @@ static int is_hardware_watchpoint (struct breakpoint *bpt); + + static void insert_breakpoint_locations (void); + ++static int syscall_catchpoint_p (struct breakpoint *b); ++ + static const char * + bpdisp_text (enum bpdisp disp) + { +@@ -341,6 +343,18 @@ set_breakpoint_count (int num) + value_from_longest (builtin_type_int32, (LONGEST) num)); + } + ++/* Used in run_command to reset syscall catchpoints fields. */ ++ ++void ++clear_syscall_catchpoints_info (void) ++{ ++ struct breakpoint *b; ++ ++ ALL_BREAKPOINTS (b) ++ if (syscall_catchpoint_p (b)) ++ b->syscall_number = UNKNOWN_SYSCALL; ++} ++ + /* Used in run_command to zero the hit count when a new run starts. */ + + void +@@ -523,6 +537,53 @@ get_number_or_range (char **pp) + + + ++/* Set break condition of breakpoint B to EXP. */ ++ ++void ++set_breakpoint_condition (struct breakpoint *b, char *exp, int from_tty) ++{ ++ struct bp_location *loc = b->loc; ++ ++ for (; loc; loc = loc->next) ++ { ++ if (loc->cond) ++ { ++ xfree (loc->cond); ++ loc->cond = 0; ++ } ++ } ++ ++ if (b->cond_string != NULL) ++ xfree (b->cond_string); ++ ++ if (*exp == 0) ++ { ++ b->cond_string = NULL; ++ if (from_tty) ++ printf_filtered (_("Breakpoint %d now unconditional.\n"), b->number); ++ } ++ else ++ { ++ char *arg = exp; ++ ++ /* I don't know if it matters whether this is the string the user ++ typed in or the decompiled expression. */ ++ b->cond_string = savestring (arg, strlen (arg)); ++ b->condition_not_parsed = 0; ++ for (loc = b->loc; loc; loc = loc->next) ++ { ++ arg = exp; ++ loc->cond = ++ parse_exp_1 (&arg, block_for_pc (loc->address), 0); ++ if (*arg) ++ error (_("Junk at end of expression")); ++ } ++ } ++ ++ breakpoints_changed (); ++ observer_notify_breakpoint_modified (b->number); ++} ++ + /* condition N EXP -- set break condition of breakpoint N to EXP. */ + + static void +@@ -543,42 +604,7 @@ condition_command (char *arg, int from_tty) + ALL_BREAKPOINTS (b) + if (b->number == bnum) + { +- struct bp_location *loc = b->loc; +- for (; loc; loc = loc->next) +- { +- if (loc->cond) +- { +- xfree (loc->cond); +- loc->cond = 0; +- } +- } +- if (b->cond_string != NULL) +- xfree (b->cond_string); +- +- if (*p == 0) +- { +- b->cond_string = NULL; +- if (from_tty) +- printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum); +- } +- else +- { +- arg = p; +- /* I don't know if it matters whether this is the string the user +- typed in or the decompiled expression. */ +- b->cond_string = savestring (arg, strlen (arg)); +- b->condition_not_parsed = 0; +- for (loc = b->loc; loc; loc = loc->next) +- { +- arg = p; +- loc->cond = +- parse_exp_1 (&arg, block_for_pc (loc->address), 0); +- if (*arg) +- error (_("Junk at end of expression")); +- } +- } +- breakpoints_changed (); +- observer_notify_breakpoint_modified (b->number); ++ set_breakpoint_condition (b, p, from_tty); + return; + } + +@@ -961,7 +987,7 @@ update_watchpoint (struct breakpoint *b, int reparse) + int len, type; + struct bp_location *loc, **tmp; + +- addr = VALUE_ADDRESS (v) + value_offset (v); ++ addr = value_address (v); + len = TYPE_LENGTH (value_type (v)); + type = hw_write; + if (b->type == bp_read_watchpoint) +@@ -3948,8 +3974,8 @@ check_duplicates_for (CORE_ADDR address, struct obj_section *section) + } + + /* If we found a permanent breakpoint at this address, go over the +- list again and declare all the other breakpoints there to be the +- duplicates. */ ++ list again and declare all the other breakpoints there (except ++ other permanent breakpoints) to be the duplicates. */ + if (perm_bp) + { + perm_bp->duplicate = 0; +@@ -3963,7 +3989,8 @@ check_duplicates_for (CORE_ADDR address, struct obj_section *section) + ALL_BP_LOCATIONS (b) + if (b != perm_bp) + { +- if (b->owner->enable_state != bp_disabled ++ if (b->owner->enable_state != bp_permanent ++ && b->owner->enable_state != bp_disabled + && b->owner->enable_state != bp_call_disabled + && b->enabled && !b->shlib_disabled + && b->address == address /* address / overlay match */ +@@ -4134,6 +4161,8 @@ set_raw_breakpoint_without_location (enum bptype bptype) + b->frame_id = null_frame_id; + b->forked_inferior_pid = null_ptid; + b->exec_pathname = NULL; ++ b->syscalls_to_be_caught = NULL; ++ b->syscall_number = UNKNOWN_SYSCALL; + b->ops = NULL; + b->condition_not_parsed = 0; + +@@ -4660,7 +4689,241 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops = + print_mention_catch_vfork + }; + +-/* Create a new breakpoint of the bp_catchpoint kind and return it. ++/* We keep a count of the number of times the user has requested a ++ particular syscall to be tracked, and pass this information to the ++ target. This lets capable targets implement filtering directly. */ ++ ++/* Number of times that "any" syscall is requested. */ ++static int any_syscall_count; ++ ++/* Count of each system call. */ ++static int *syscalls_counts; ++ ++/* Number of system entries in SYSCALLS_COUNTS. */ ++static int syscalls_size; ++ ++/* This counts all syscall catch requests, so we can readily determine ++ if any catching is necessary. */ ++static int total_syscalls_count; ++ ++/* Implement the "insert" breakpoint_ops method for syscall ++ catchpoints. */ ++ ++static void ++insert_catch_syscall (struct breakpoint *b) ++{ ++ ++total_syscalls_count; ++ if (!b->syscalls_to_be_caught) ++ ++any_syscall_count; ++ else ++ { ++ struct syscall_filter *iter; ++ for (iter = b->syscalls_to_be_caught; iter; iter = iter->next) ++ { ++ if (iter->syscall >= syscalls_size) ++ { ++ syscalls_counts = xrealloc (syscalls_counts, ++ (iter->syscall + 1) * sizeof (int)); ++ memset (&syscalls_counts[syscalls_size], 0, ++ (iter->syscall + 1 - syscalls_size) * sizeof (int)); ++ } ++ ++syscalls_counts[iter->syscall]; ++ } ++ } ++ ++ target_set_syscall_catchpoint (PIDGET (inferior_ptid), ++ total_syscalls_count != 0, ++ any_syscall_count, ++ syscalls_size, ++ syscalls_counts); ++} ++ ++/* Implement the "remove" breakpoint_ops method for syscall ++ catchpoints. */ ++ ++static int ++remove_catch_syscall (struct breakpoint *b) ++{ ++ --total_syscalls_count; ++ if (!b->syscalls_to_be_caught) ++ --any_syscall_count; ++ else ++ { ++ struct syscall_filter *iter; ++ for (iter = b->syscalls_to_be_caught; iter; iter = iter->next) ++ { ++ if (iter->syscall >= syscalls_size) ++ { ++ /* Shouldn't happen. */ ++ continue; ++ } ++ --syscalls_counts[iter->syscall]; ++ } ++ } ++ ++ return target_set_syscall_catchpoint (PIDGET (inferior_ptid), ++ total_syscalls_count != 0, ++ any_syscall_count, ++ syscalls_size, ++ syscalls_counts); ++} ++ ++/* Implement the "breakpoint_hit" breakpoint_ops method for syscall ++ catchpoints. */ ++ ++static int ++breakpoint_hit_catch_syscall (struct breakpoint *b) ++{ ++ /* We must check if we are catching specific syscalls in this breakpoint. ++ If we are, then we must guarantee that the called syscall is the same ++ syscall we are catching. */ ++ int syscall_number = 0; ++ ++ if (!inferior_has_called_syscall (inferior_ptid, &syscall_number)) ++ return 0; ++ ++ /* Now, checking if the syscall is the same. */ ++ if (b->syscalls_to_be_caught) ++ { ++ struct syscall_filter *iter; ++ for (iter = b->syscalls_to_be_caught; iter; iter = iter->next) ++ if (syscall_number == iter->syscall) ++ break; ++ /* Not the same. */ ++ if (!iter) ++ return 0; ++ } ++ ++ /* It's the same syscall. We can update the breakpoint struct ++ with the correct information. */ ++ b->syscall_number = syscall_number; ++ ++ return 1; ++} ++ ++/* Implement the "print_it" breakpoint_ops method for syscall ++ catchpoints. */ ++ ++static enum print_stop_action ++print_it_catch_syscall (struct breakpoint *b) ++{ ++ /* These are needed because we want to know in which state a ++ syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY ++ or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we ++ must print "called syscall" or "returned from syscall". */ ++ ptid_t ptid; ++ struct target_waitstatus last; ++ struct syscall s; ++ struct cleanup *old_chain; ++ char *syscall_id; ++ ++ gdbarch_get_syscall_by_number (current_gdbarch, b->syscall_number, &s); ++ ++ get_last_target_status (&ptid, &last); ++ ++ annotate_catchpoint (b->number); ++ ++ if (s.name == NULL) ++ syscall_id = xstrprintf ("%d", b->syscall_number); ++ else ++ syscall_id = xstrprintf ("'%s'", s.name); ++ ++ old_chain = make_cleanup (xfree, syscall_id); ++ ++ if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY) ++ printf_filtered (_("\nCatchpoint %d (call to syscall %s), "), ++ b->number, syscall_id); ++ else ++ printf_filtered (_("\nCatchpoint %d (returned from syscall %s), "), ++ b->number, syscall_id); ++ ++ do_cleanups (old_chain); ++ ++ return PRINT_SRC_AND_LOC; ++} ++ ++/* Implement the "print_one" breakpoint_ops method for syscall ++ catchpoints. */ ++ ++static void ++print_one_catch_syscall (struct breakpoint *b, CORE_ADDR *last_addr) ++{ ++ struct value_print_options opts; ++ struct syscall s; ++ ++ gdbarch_get_syscall_by_number (current_gdbarch, b->syscall_number, &s); ++ ++ get_user_print_options (&opts); ++ /* Field 4, the address, is omitted (which makes the columns ++ not line up too nicely with the headers, but the effect ++ is relatively readable). */ ++ if (opts.addressprint) ++ ui_out_field_skip (uiout, "addr"); ++ annotate_field (5); ++ ui_out_text (uiout, "syscall \""); ++ if (b->syscall_number != UNKNOWN_SYSCALL) ++ { ++ if (s.name) ++ ui_out_field_string (uiout, "what", s.name); ++ else ++ ui_out_field_int (uiout, "what", b->syscall_number); ++ } ++ else ++ ui_out_field_string (uiout, "what", ""); ++ ui_out_text (uiout, "\" "); ++} ++ ++/* Implement the "print_mention" breakpoint_ops method for syscall ++ catchpoints. */ ++ ++static void ++print_mention_catch_syscall (struct breakpoint *b) ++{ ++ if (b->syscalls_to_be_caught) ++ { ++ struct syscall_filter *iter; ++ printf_filtered (_("Catchpoint %d (syscall(s)"), b->number); ++ for (iter = b->syscalls_to_be_caught; iter; iter = iter->next) ++ { ++ struct syscall s; ++ gdbarch_get_syscall_by_number (current_gdbarch, iter->syscall, &s); ++ ++ if (s.name) ++ printf_filtered (" '%s'", s.name); ++ else ++ printf_filtered (" %d", iter->syscall); ++ } ++ printf_filtered (")"); ++ } ++ else ++ printf_filtered (_("Catchpoint %d (any syscall)"), ++ b->number); ++} ++ ++/* The breakpoint_ops structure to be used in syscall catchpoints. */ ++ ++static struct breakpoint_ops catch_syscall_breakpoint_ops = ++{ ++ insert_catch_syscall, ++ remove_catch_syscall, ++ breakpoint_hit_catch_syscall, ++ print_it_catch_syscall, ++ print_one_catch_syscall, ++ print_mention_catch_syscall ++}; ++ ++/* Returns non-zero if 'b' is a syscall catchpoint. */ ++ ++static int ++syscall_catchpoint_p (struct breakpoint *b) ++{ ++ return (b->ops == &catch_syscall_breakpoint_ops); ++} ++ ++/* Create a new breakpoint of the bp_catchpoint kind and return it, ++ but does NOT mention it nor update the global location list. ++ This is useful if you need to fill more fields in the ++ struct breakpoint before calling mention. + + If TEMPFLAG is non-zero, then make the breakpoint temporary. + If COND_STRING is not NULL, then store it in the breakpoint. +@@ -4668,16 +4931,13 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops = + to the catchpoint. */ + + static struct breakpoint * +-create_catchpoint (int tempflag, char *cond_string, +- struct breakpoint_ops *ops) ++create_catchpoint_without_mention (int tempflag, char *cond_string, ++ struct breakpoint_ops *ops) + { + struct symtab_and_line sal; + struct breakpoint *b; + + init_sal (&sal); +- sal.pc = 0; +- sal.symtab = NULL; +- sal.line = 0; + + b = set_raw_breakpoint (sal, bp_catchpoint); + set_breakpoint_count (breakpoint_count + 1); +@@ -4691,6 +4951,23 @@ create_catchpoint (int tempflag, char *cond_string, + b->disposition = tempflag ? disp_del : disp_donttouch; + b->ops = ops; + ++ return b; ++} ++ ++/* Create a new breakpoint of the bp_catchpoint kind and return it. ++ ++ If TEMPFLAG is non-zero, then make the breakpoint temporary. ++ If COND_STRING is not NULL, then store it in the breakpoint. ++ OPS, if not NULL, is the breakpoint_ops structure associated ++ to the catchpoint. */ ++ ++static struct breakpoint * ++create_catchpoint (int tempflag, char *cond_string, ++ struct breakpoint_ops *ops) ++{ ++ struct breakpoint *b = ++ create_catchpoint_without_mention (tempflag, cond_string, ops); ++ + mention (b); + update_global_location_list (1); + +@@ -4775,6 +5052,23 @@ static struct breakpoint_ops catch_exec_breakpoint_ops = + print_mention_catch_exec + }; + ++static void ++create_syscall_event_catchpoint (int tempflag, struct syscall_filter *filter, ++ struct breakpoint_ops *ops) ++{ ++ struct breakpoint *b = ++ create_catchpoint_without_mention (tempflag, NULL, ops); ++ ++ b->syscalls_to_be_caught = filter; ++ /* We still don't know the syscall that will be caught :-). */ ++ b->syscall_number = UNKNOWN_SYSCALL; ++ ++ /* Now, we have to mention the breakpoint and update the global ++ location list. */ ++ mention (b); ++ update_global_location_list (1); ++} ++ + static int + hw_breakpoint_used_count (void) + { +@@ -5188,7 +5482,6 @@ expand_line_sal_maybe (struct symtab_and_line sal) + struct symtabs_and_lines expanded; + CORE_ADDR original_pc = sal.pc; + char *original_function = NULL; +- int found; + int i; + + /* If we have explicit pc, don't expand. +@@ -5264,14 +5557,42 @@ expand_line_sal_maybe (struct symtab_and_line sal) + + if (original_pc) + { +- found = 0; ++ /* Find all the other PCs for a line of code with multiple instances ++ (locations). If the instruction is in the middle of an instruction ++ block for source line GDB cannot safely find the same instruction in ++ the other compiled instances of the same source line because the other ++ instances may have been compiled completely differently. ++ ++ The testcase gdb.cp/expand-sals.exp shows that breaking at the return ++ address in a caller of the current frame works for the current ++ instance but the breakpoint cannot catch the point (instruction) where ++ the callee returns in the other compiled instances of this source line. ++ ++ The current implementation will place the breakpoint at the expected ++ returning address of the current instance of the caller. But the ++ other instances will get the breakpoint at the first instruction of ++ the source line - therefore before the call would be made. Another ++ possibility would be to place the breakpoint in the other instances at ++ the start of the next source line. ++ ++ A possible heuristics would compare the instructions length of each of ++ the instances of the current source line and if it matches it would ++ place the breakpoint at the same offset. Unfortunately a mistaken ++ guess would possibly crash the inferior. */ ++ ++ CORE_ADDR best = -1; ++ ++ /* Find the nearest preceding PC and set it to ORIGINAL_PC. */ + for (i = 0; i < expanded.nelts; ++i) +- if (expanded.sals[i].pc == original_pc) +- { +- found = 1; +- break; +- } +- gdb_assert (found); ++ if (expanded.sals[i].pc <= original_pc ++ && (best == -1 || expanded.sals[best].pc < expanded.sals[i].pc)) ++ best = i; ++ ++ if (best == -1) ++ error (_("Cannot find the best address for %s out of the %d locations"), ++ paddr (original_pc), expanded.nelts); ++ ++ expanded.sals[best].pc = original_pc; + } + + return expanded; +@@ -5310,8 +5631,6 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string, + cond_string, type, disposition, + thread, ignore_count, ops, from_tty, enabled); + } +- +- update_global_location_list (1); + } + + /* Parse ARG which is assumed to be a SAL specification possibly +@@ -5637,7 +5956,6 @@ break_command_really (char *arg, char *cond_string, int thread, + b->ops = ops; + b->enable_state = enabled ? bp_enabled : bp_disabled; + +- update_global_location_list (1); + mention (b); + } + +@@ -5649,6 +5967,11 @@ break_command_really (char *arg, char *cond_string, int thread, + discard_cleanups (breakpoint_chain); + /* But cleanup everything else. */ + do_cleanups (old_chain); ++ ++ /* Have already BREAKPOINT_CHAIN discarded as we may get an exception while ++ inserting the breakpoints which would double-free the resources both by ++ BREAKPOINT_CHAIN now and during DELETE_BREAKPOINT in the future. */ ++ update_global_location_list (1); + } + + /* Set a breakpoint. +@@ -5727,7 +6050,12 @@ resolve_sal_pc (struct symtab_and_line *sal) + /* If this SAL corresponds to a breakpoint inserted using + a line number, then skip the function prologue if necessary. */ + if (sal->explicit_line) +- skip_prologue_sal (sal); ++ { ++ /* Preserve the original line number. */ ++ int saved_line = sal->line; ++ skip_prologue_sal (sal); ++ sal->line = saved_line; ++ } + } + + if (sal->section == 0 && sal->symtab != NULL) +@@ -6131,7 +6459,7 @@ can_use_hardware_watchpoint (struct value *v) + || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT + && TYPE_CODE (vtype) != TYPE_CODE_ARRAY)) + { +- CORE_ADDR vaddr = VALUE_ADDRESS (v) + value_offset (v); ++ CORE_ADDR vaddr = value_address (v); + int len = TYPE_LENGTH (value_type (v)); + + if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len)) +@@ -6668,6 +6996,122 @@ catch_ada_exception_command (char *arg, int from_tty, + from_tty); + } + ++/* Cleanup function for a syscall filter list. */ ++static void ++clean_up_filters (void *arg) ++{ ++ struct syscall_filter *iter = *(struct syscall_filter **) arg; ++ while (iter) ++ { ++ struct syscall_filter *next = iter->next; ++ xfree (iter); ++ iter = next; ++ } ++} ++ ++/* Splits the argument using space as delimiter. Returns an xmalloc'd ++ filter list, or NULL if no filtering is required. */ ++static struct syscall_filter * ++catch_syscall_split_args (char *arg) ++{ ++ struct syscall_filter *result = NULL; ++ struct cleanup *cleanup = make_cleanup (clean_up_filters, &result); ++ ++ while (*arg != '\0') ++ { ++ int i, syscall_number; ++ char *endptr; ++ char cur_name[128]; ++ struct syscall_filter *new_filter; ++ struct syscall s; ++ ++ /* Skip whitespace. */ ++ while (isspace (*arg)) ++ arg++; ++ ++ for (i = 0; arg[i] && !isspace (arg[i]); ++i) ++ cur_name[i] = arg[i]; ++ cur_name[i] = '\0'; ++ arg += i; ++ ++ /* Check if the user provided a syscall name or a number. */ ++ syscall_number = (int) strtol (cur_name, &endptr, 10); ++ if (*endptr == '\0') ++ { ++ gdbarch_get_syscall_by_number (current_gdbarch, ++ syscall_number, &s); ++ ++ if (s.name == NULL) ++ /* We can issue just a warning, but still create the catchpoint. ++ This is because, even not knowing the syscall name that ++ this number represents, we can still try to catch the syscall ++ number. */ ++ warning (_("The number '%d' does not represent a known syscall."), ++ syscall_number); ++ } ++ else ++ { ++ /* We have a name. Let's check if it's valid and convert it ++ to a number. */ ++ gdbarch_get_syscall_by_name (current_gdbarch, cur_name, &s); ++ ++ if (s.number == UNKNOWN_SYSCALL) ++ /* Here we have to issue an error instead of a warning, because ++ GDB cannot do anything useful if there's no syscall number to ++ be caught. */ ++ error (_("Unknown syscall name '%s'."), cur_name); ++ } ++ ++ /* Ok, it's valid. */ ++ new_filter = XNEW (struct syscall_filter); ++ new_filter->syscall = s.number; ++ new_filter->next = result; ++ result = new_filter; ++ } ++ ++ discard_cleanups (cleanup); ++ return result; ++} ++ ++/* Implement the "catch syscall" command. */ ++ ++static void ++catch_syscall_command_1 (char *arg, int from_tty, struct cmd_list_element *command) ++{ ++ int tempflag; ++ struct syscall_filter *filter; ++ struct syscall s; ++ ++ /* Checking if the feature if supported. */ ++ if (gdbarch_get_syscall_number_p (current_gdbarch) == 0) ++ error (_("The feature 'catch syscall' is not supported on \ ++this architeture yet.")); ++ ++ tempflag = get_cmd_context (command) == CATCH_TEMPORARY; ++ ++ ep_skip_leading_whitespace (&arg); ++ ++ /* We need to do this first "dummy" translation in order ++ to get the syscall XML file loaded or, most important, ++ to display a warning to the user if there's no XML file ++ for his/her architecture. */ ++ gdbarch_get_syscall_by_number (current_gdbarch, 0, &s); ++ ++ /* The allowed syntax is: ++ catch syscall ++ catch syscall [ ... ] ++ ++ Let's check if there's a syscall name. */ ++ ++ if (arg != NULL) ++ filter = catch_syscall_split_args (arg); ++ else ++ filter = NULL; ++ ++ create_syscall_event_catchpoint (tempflag, filter, ++ &catch_syscall_breakpoint_ops); ++} ++ + /* Implement the "catch assert" command. */ + + static void +@@ -7134,6 +7578,7 @@ delete_breakpoint (struct breakpoint *bpt) + xfree (bpt->source_file); + if (bpt->exec_pathname != NULL) + xfree (bpt->exec_pathname); ++ clean_up_filters (&bpt->syscalls_to_be_caught); + + /* Be sure no bpstat's are pointing at it after it's been freed. */ + /* FIXME, how can we find all bpstat's? +@@ -8041,6 +8486,56 @@ single_step_breakpoint_inserted_here_p (CORE_ADDR pc) + return 0; + } + ++/* Returns 0 if 'bp' is NOT a syscall catchpoint, ++ non-zero otherwise. */ ++static int ++is_syscall_catchpoint_enabled (struct breakpoint *bp) ++{ ++ if (syscall_catchpoint_p (bp) ++ && bp->enable_state != bp_disabled ++ && bp->enable_state != bp_call_disabled) ++ return 1; ++ else ++ return 0; ++} ++ ++int ++catch_syscall_enabled (void) ++{ ++ return total_syscalls_count != 0; ++} ++ ++int ++catching_syscall_number (int syscall_number) ++{ ++ struct breakpoint *bp; ++ ++ ALL_BREAKPOINTS (bp) ++ if (is_syscall_catchpoint_enabled (bp)) ++ { ++ if (bp->syscalls_to_be_caught) ++ { ++ struct syscall_filter *iter; ++ for (iter = bp->syscalls_to_be_caught; iter; iter = iter->next) ++ if (syscall_number == iter->syscall) ++ return 1; ++ } ++ else ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/* Complete syscall names. Used by "catch syscall". */ ++static char ** ++catch_syscall_completer (struct cmd_list_element *self, char *text, char *word) ++{ ++ const char **list = ++ gdbarch_get_syscall_names (current_gdbarch); ++ return (list == NULL) ? NULL : complete_on_enum (list, text, word); ++} ++ + + /* This help string is used for the break, hbreak, tbreak and thbreak commands. + It is defined as a macro to prevent duplication. +@@ -8073,6 +8568,8 @@ static void + add_catch_command (char *name, char *docstring, + void (*sfunc) (char *args, int from_tty, + struct cmd_list_element *command), ++ char **(*completion_function) (struct cmd_list_element *self, ++ char *text, char *word), + void *user_data_catch, + void *user_data_tcatch) + { +@@ -8082,11 +8579,13 @@ add_catch_command (char *name, char *docstring, + &catch_cmdlist); + set_cmd_sfunc (command, sfunc); + set_cmd_context (command, user_data_catch); ++ set_cmd_completer (command, completion_function); + + command = add_cmd (name, class_breakpoint, NULL, docstring, + &tcatch_cmdlist); + set_cmd_sfunc (command, sfunc); + set_cmd_context (command, user_data_tcatch); ++ set_cmd_completer (command, completion_function); + } + + void +@@ -8361,36 +8860,50 @@ Set temporary catchpoints to catch events."), + Catch an exception, when caught.\n\ + With an argument, catch only exceptions with the given name."), + catch_catch_command, ++ NULL, + CATCH_PERMANENT, + CATCH_TEMPORARY); + add_catch_command ("throw", _("\ + Catch an exception, when thrown.\n\ + With an argument, catch only exceptions with the given name."), + catch_throw_command, ++ NULL, + CATCH_PERMANENT, + CATCH_TEMPORARY); + add_catch_command ("fork", _("Catch calls to fork."), + catch_fork_command_1, ++ NULL, + (void *) (uintptr_t) catch_fork_permanent, + (void *) (uintptr_t) catch_fork_temporary); + add_catch_command ("vfork", _("Catch calls to vfork."), + catch_fork_command_1, ++ NULL, + (void *) (uintptr_t) catch_vfork_permanent, + (void *) (uintptr_t) catch_vfork_temporary); + add_catch_command ("exec", _("Catch calls to exec."), + catch_exec_command_1, ++ NULL, + CATCH_PERMANENT, + CATCH_TEMPORARY); ++ add_catch_command ("syscall", _("\ ++Catch system calls.\n\ ++With an argument, catch only that syscall."), ++ catch_syscall_command_1, ++ catch_syscall_completer, ++ CATCH_PERMANENT, ++ CATCH_TEMPORARY); + add_catch_command ("exception", _("\ + Catch Ada exceptions, when raised.\n\ + With an argument, catch only exceptions with the given name."), + catch_ada_exception_command, ++ NULL, + CATCH_PERMANENT, + CATCH_TEMPORARY); + add_catch_command ("assert", _("\ + Catch failed Ada assertions, when raised.\n\ + With an argument, catch only exceptions with the given name."), + catch_assert_command, ++ NULL, + CATCH_PERMANENT, + CATCH_TEMPORARY); + +diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h +index 94287de..8552e1b 100644 +--- a/gdb/breakpoint.h ++++ b/gdb/breakpoint.h +@@ -33,7 +33,8 @@ struct block; + + #define BREAKPOINT_MAX 16 + +-/* Type of breakpoint. */ ++ ++/* Type of breakpoint. */ + /* FIXME In the future, we should fold all other breakpoint-like things into + here. This includes: + +@@ -337,6 +338,17 @@ enum watchpoint_triggered + watch_triggered_yes + }; + ++/* A syscall filter is represented as a linked list of syscall ++ numbers. */ ++struct syscall_filter ++{ ++ /* The system call to accept. */ ++ int syscall; ++ ++ /* The next filter. */ ++ struct syscall_filter *next; ++}; ++ + typedef struct bp_location *bp_location_p; + DEF_VEC_P(bp_location_p); + +@@ -442,6 +454,20 @@ struct breakpoint + triggered. */ + char *exec_pathname; + ++ /* Syscall number used for the 'catch syscall' feature. ++ If no syscall has been called, its value is UNKNOWN_SYSCALL. ++ Otherwise, it holds the system call number in the target. ++ ++ This field is only valid immediately after this catchpoint has ++ triggered. */ ++ int syscall_number; ++ ++ /* Syscall numbers used for the 'catch syscall' feature. ++ If no syscall has been specified for filtering, its value is NULL. ++ Otherwise, it holds a list of all syscalls to be caught. ++ The list elements are allocated with xmalloc. */ ++ struct syscall_filter *syscalls_to_be_caught; ++ + /* Methods associated with this breakpoint. */ + struct breakpoint_ops *ops; + +@@ -783,6 +809,8 @@ extern void enable_watchpoints_after_interactive_call_stop (void); + extern enum command_control_type commands_from_control_command + (char *arg, struct command_line *cmd); + ++extern void clear_syscall_catchpoints_info (void); ++ + extern void clear_breakpoint_hit_counts (void); + + extern int get_number (char **); +@@ -857,7 +885,19 @@ extern int breakpoints_always_inserted_mode (void); + in our opinion won't ever trigger. */ + extern void breakpoint_retire_moribund (void); + ++/* Checks if we are catching syscalls or not. ++ Returns 0 if not, greater than 0 if we are. */ ++extern int catch_syscall_enabled (void); ++ ++/* Checks if we are catching syscalls with the specific ++ syscall_number. Used for "filtering" the catchpoints. ++ Returns 0 if not, greater than 0 if we are. */ ++extern int catching_syscall_number (int syscall_number); ++ + /* Tell a breakpoint to be quiet. */ + extern void make_breakpoint_silent (struct breakpoint *); + ++/* Set break condition of breakpoint B to EXP. */ ++extern void set_breakpoint_condition (struct breakpoint *b, char *exp, int from_tty); ++ + #endif /* !defined (BREAKPOINT_H) */ +diff --git a/gdb/buildsym.c b/gdb/buildsym.c +index 55ace15..2722daa 100644 +--- a/gdb/buildsym.c ++++ b/gdb/buildsym.c +@@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending **listhead, + opblock = pblock; + } + ++ block_set_using (block, using_directives, &objfile->objfile_obstack); ++ + record_pending_block (objfile, block, opblock); + + return block; +@@ -815,10 +817,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr) + /* We shouldn't have any address map at this point. */ + gdb_assert (! pending_addrmap); + +- /* Set up support for C++ namespace support, in case we need it. */ +- +- cp_initialize_namespace (); +- + /* Initialize the list of sub source files with one entry for this + file (the top-level source file). */ + +@@ -1015,8 +1013,6 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) + finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr, + objfile); + blockvector = make_blockvector (objfile); +- cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK), +- &objfile->objfile_obstack); + } + + /* Read the line table if it has to be read separately. */ +@@ -1202,10 +1198,12 @@ push_context (int desc, CORE_ADDR valu) + new->params = param_symbols; + new->old_blocks = pending_blocks; + new->start_addr = valu; ++ new->using_directives = using_directives; + new->name = NULL; + + local_symbols = NULL; + param_symbols = NULL; ++ using_directives = NULL; + + return new; + } +diff --git a/gdb/buildsym.h b/gdb/buildsym.h +index bf23ecc..f542aca 100644 +--- a/gdb/buildsym.h ++++ b/gdb/buildsym.h +@@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols; + + EXTERN struct pending *param_symbols; + ++/* using directives local to lexical context */ ++ ++EXTERN struct using_direct *using_directives; ++ + /* Stack representing unclosed lexical contexts (that will become + blocks, eventually). */ + +@@ -138,6 +142,10 @@ struct context_stack + + struct pending *params; + ++ /* Pending using directives at the time we entered */ ++ ++ struct using_direct *using_directives; ++ + /* Pointer into blocklist as of entry */ + + struct pending_block *old_blocks; +diff --git a/gdb/c-exp.y b/gdb/c-exp.y +index d4bbbcc..107452a 100644 +--- a/gdb/c-exp.y ++++ b/gdb/c-exp.y +@@ -119,6 +119,8 @@ static int yylex (void); + + void yyerror (char *); + ++/* Cleanup for 'nonempty_typelist' */ ++static struct cleanup *typelist_cleanup; + %} + + /* Although the yacc "value" of an expression is not used, +@@ -143,6 +145,7 @@ void yyerror (char *); + struct symbol *sym; + struct type *tval; + struct stoken sval; ++ struct typed_stoken tsval; + struct ttype tsym; + struct symtoken ssym; + int voidval; +@@ -150,6 +153,7 @@ void yyerror (char *); + enum exp_opcode opcode; + struct internalvar *ivar; + ++ struct stoken_vector svec; + struct type **tvec; + int *ivec; + } +@@ -182,11 +186,13 @@ static int parse_number (char *, int, int, YYSTYPE *); + Contexts where this distinction is not important can use the + nonterminal "name", which matches either NAME or TYPENAME. */ + +-%token STRING ++%token STRING ++%token CHAR + %token NAME /* BLOCKNAME defined below to give it higher precedence. */ + %token COMPLETE + %token TYPENAME +-%type name string_exp ++%type name ++%type string_exp + %type name_not_typename + %type typename + +@@ -399,6 +405,38 @@ arglist : arglist ',' exp %prec ABOVE_COMMA + { arglist_len++; } + ; + ++exp : exp '(' nonempty_typelist ')' ++ { int i; ++ /* What to do about freeing memory if ++ there is an error during parsing? */ ++ write_exp_elt_opcode (TYPE_INSTANCE); ++ write_exp_elt_longcst ((LONGEST) $3[0]); ++ for (i = 0; i < $3[0]; ++i) ++ write_exp_elt_type ($3[i + 1]); ++ write_exp_elt_longcst((LONGEST) $3[0]); ++ write_exp_elt_opcode (TYPE_INSTANCE); ++ do_cleanups (typelist_cleanup); ++ } ++ ; ++ ++/* ++exp : BLOCKNAME '(' nonempty_typelist ')' ++ { int i; ++ write_exp_elt_opcode (TYPE_INSTANCE_LOOKUP); ++ write_exp_elt_sym ($1.sym); ++ write_exp_elt_opcode (TYPE_INSTANCE_LOOKUP); ++ ++ write_exp_elt_opcode (TYPE_INSTANCE); ++ write_exp_elt_longcst ((LONGEST) $3[0]); ++ for (i = 0; i < $3[0]; ++i) ++ write_exp_elt_type ($3[i + 1]); ++ write_exp_elt_longcst((LONGEST) $3[0]); ++ write_exp_elt_opcode (TYPE_INSTANCE); ++ do_cleanups (typelist_cleanup); ++ } ++ ; ++*/ ++ + rcurly : '}' + { $$ = end_arglist () - 1; } + ; +@@ -524,6 +562,15 @@ exp : INT + write_exp_elt_opcode (OP_LONG); } + ; + ++exp : CHAR ++ { ++ struct stoken_vector vec; ++ vec.len = 1; ++ vec.tokens = &$1; ++ write_exp_string_vector ($1.type, &vec); ++ } ++ ; ++ + exp : NAME_OR_INT + { YYSTYPE val; + parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val); +@@ -572,48 +619,64 @@ string_exp: + string. Note that we follow the + NUL-termination convention of the + lexer. */ +- $$.length = $1.length; +- $$.ptr = malloc ($1.length + 1); +- memcpy ($$.ptr, $1.ptr, $1.length + 1); ++ struct typed_stoken *vec = XNEW (struct typed_stoken); ++ $$.len = 1; ++ $$.tokens = vec; ++ ++ vec->type = $1.type; ++ vec->length = $1.length; ++ vec->ptr = malloc ($1.length + 1); ++ memcpy (vec->ptr, $1.ptr, $1.length + 1); + } + + | string_exp STRING + { + /* Note that we NUL-terminate here, but just + for convenience. */ +- struct stoken t; +- t.length = $1.length + $2.length; +- t.ptr = malloc (t.length + 1); +- memcpy (t.ptr, $1.ptr, $1.length); +- memcpy (t.ptr + $1.length, $2.ptr, $2.length + 1); +- free ($1.ptr); +- $$ = t; ++ char *p; ++ ++$$.len; ++ $$.tokens = realloc ($$.tokens, ++ $$.len * sizeof (struct typed_stoken)); ++ ++ p = malloc ($2.length + 1); ++ memcpy (p, $2.ptr, $2.length + 1); ++ ++ $$.tokens[$$.len - 1].type = $2.type; ++ $$.tokens[$$.len - 1].length = $2.length; ++ $$.tokens[$$.len - 1].ptr = p; + } + ; + + exp : string_exp +- { /* C strings are converted into array constants with +- an explicit null byte added at the end. Thus +- the array upper bound is the string length. +- There is no such thing in C as a completely empty +- string. */ +- char *sp = $1.ptr; int count = $1.length; +- while (count-- > 0) ++ { ++ int i; ++ enum c_string_type type = C_STRING; ++ ++ for (i = 0; i < $1.len; ++i) + { +- write_exp_elt_opcode (OP_LONG); +- write_exp_elt_type (parse_type->builtin_char); +- write_exp_elt_longcst ((LONGEST)(*sp++)); +- write_exp_elt_opcode (OP_LONG); ++ switch ($1.tokens[i].type) ++ { ++ case C_STRING: ++ break; ++ case C_WIDE_STRING: ++ case C_STRING_16: ++ case C_STRING_32: ++ if (type != C_STRING ++ && type != $1.tokens[i].type) ++ error ("Undefined string concatenation."); ++ type = $1.tokens[i].type; ++ break; ++ default: ++ /* internal error */ ++ internal_error (__FILE__, __LINE__, ++ "unrecognized type in string concatenation"); ++ } + } +- write_exp_elt_opcode (OP_LONG); +- write_exp_elt_type (parse_type->builtin_char); +- write_exp_elt_longcst ((LONGEST)'\0'); +- write_exp_elt_opcode (OP_LONG); +- write_exp_elt_opcode (OP_ARRAY); +- write_exp_elt_longcst ((LONGEST) 0); +- write_exp_elt_longcst ((LONGEST) ($1.length)); +- write_exp_elt_opcode (OP_ARRAY); +- free ($1.ptr); ++ ++ write_exp_string_vector (type, &$1); ++ for (i = 0; i < $1.len; ++i) ++ free ($1.tokens[i].ptr); ++ free ($1.tokens); + } + ; + +@@ -713,12 +776,13 @@ qualified_name: typebase COLONCOLON name + ; + + variable: qualified_name ++ | COLONCOLON qualified_name + | COLONCOLON name + { + char *name = copy_name ($2); + struct symbol *sym; + struct minimal_symbol *msymbol; +- ++ + sym = + lookup_symbol (name, (const struct block *) NULL, + VAR_DOMAIN, (int *) NULL); +@@ -856,7 +920,7 @@ array_mod: '[' ']' + func_mod: '(' ')' + { $$ = 0; } + | '(' nonempty_typelist ')' +- { free ($2); $$ = 0; } ++ { do_cleanups (typelist_cleanup); $$ = 0; } + ; + + /* We used to try to recognize pointer to member types here, but +@@ -1057,12 +1121,15 @@ typename: TYPENAME + nonempty_typelist + : type + { $$ = (struct type **) malloc (sizeof (struct type *) * 2); ++ typelist_cleanup = make_cleanup (free, $$); + $$[0] = 1; /* Number of types in vector */ + $$[1] = $1; + } + | nonempty_typelist ',' type + { int len = sizeof (struct type *) * (++($1[0]) + 1); + $$ = (struct type **) realloc ((char *) $1, len); ++ discard_cleanups (typelist_cleanup); ++ typelist_cleanup = make_cleanup (free, $$); + $$[$$[0]] = $3; + } + ; +@@ -1361,6 +1428,263 @@ parse_number (p, len, parsed_float, putithere) + return INT; + } + ++/* Temporary obstack used for holding strings. */ ++static struct obstack tempbuf; ++static int tempbuf_init; ++ ++/* Parse a C escape sequence. The initial backslash of the sequence ++ is at (*PTR)[-1]. *PTR will be updated to point to just after the ++ last character of the sequence. If OUTPUT is not NULL, the ++ translated form of the escape sequence will be written there. If ++ OUTPUT is NULL, no output is written and the call will only affect ++ *PTR. If an escape sequence is expressed in target bytes, then the ++ entire sequence will simply be copied to OUTPUT. Return 1 if any ++ character was emitted, 0 otherwise. */ ++ ++int ++c_parse_escape (char **ptr, struct obstack *output) ++{ ++ char *tokptr = *ptr; ++ int result = 1; ++ ++ /* Some escape sequences undergo character set conversion. Those we ++ translate here. */ ++ switch (*tokptr) ++ { ++ /* Hex escapes do not undergo character set conversion, so keep ++ the escape sequence for later. */ ++ case 'x': ++ if (output) ++ obstack_grow_str (output, "\\x"); ++ ++tokptr; ++ if (!isxdigit (*tokptr)) ++ error (_("\\x escape without a following hex digit")); ++ while (isxdigit (*tokptr)) ++ { ++ if (output) ++ obstack_1grow (output, *tokptr); ++ ++tokptr; ++ } ++ break; ++ ++ /* Octal escapes do not undergo character set conversion, so ++ keep the escape sequence for later. */ ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ if (output) ++ obstack_grow_str (output, "\\"); ++ while (isdigit (*tokptr) && *tokptr != '8' && *tokptr != '9') ++ { ++ if (output) ++ obstack_1grow (output, *tokptr); ++ ++tokptr; ++ } ++ break; ++ ++ /* We handle UCNs later. We could handle them here, but that ++ would mean a spurious error in the case where the UCN could ++ be converted to the target charset but not the host ++ charset. */ ++ case 'u': ++ case 'U': ++ { ++ char c = *tokptr; ++ int i, len = c == 'U' ? 8 : 4; ++ if (output) ++ { ++ obstack_1grow (output, '\\'); ++ obstack_1grow (output, *tokptr); ++ } ++ ++tokptr; ++ if (!isxdigit (*tokptr)) ++ error (_("\\%c escape without a following hex digit"), c); ++ for (i = 0; i < len && isxdigit (*tokptr); ++i) ++ { ++ if (output) ++ obstack_1grow (output, *tokptr); ++ ++tokptr; ++ } ++ } ++ break; ++ ++ /* We must pass backslash through so that it does not ++ cause quoting during the second expansion. */ ++ case '\\': ++ if (output) ++ obstack_grow_str (output, "\\\\"); ++ ++tokptr; ++ break; ++ ++ /* Escapes which undergo conversion. */ ++ case 'a': ++ if (output) ++ obstack_1grow (output, '\a'); ++ ++tokptr; ++ break; ++ case 'b': ++ if (output) ++ obstack_1grow (output, '\b'); ++ ++tokptr; ++ break; ++ case 'f': ++ if (output) ++ obstack_1grow (output, '\f'); ++ ++tokptr; ++ break; ++ case 'n': ++ if (output) ++ obstack_1grow (output, '\n'); ++ ++tokptr; ++ break; ++ case 'r': ++ if (output) ++ obstack_1grow (output, '\r'); ++ ++tokptr; ++ break; ++ case 't': ++ if (output) ++ obstack_1grow (output, '\t'); ++ ++tokptr; ++ break; ++ case 'v': ++ if (output) ++ obstack_1grow (output, '\v'); ++ ++tokptr; ++ break; ++ ++ /* GCC extension. */ ++ case 'e': ++ if (output) ++ obstack_1grow (output, HOST_ESCAPE_CHAR); ++ ++tokptr; ++ break; ++ ++ /* Backslash-newline expands to nothing at all. */ ++ case '\n': ++ ++tokptr; ++ result = 0; ++ break; ++ ++ /* A few escapes just expand to the character itself. */ ++ case '\'': ++ case '\"': ++ case '?': ++ /* GCC extensions. */ ++ case '(': ++ case '{': ++ case '[': ++ case '%': ++ /* Unrecognized escapes turn into the character itself. */ ++ default: ++ if (output) ++ obstack_1grow (output, *tokptr); ++ ++tokptr; ++ break; ++ } ++ *ptr = tokptr; ++ return result; ++} ++ ++/* Parse a string or character literal from TOKPTR. The string or ++ character may be wide or unicode. *OUTPTR is set to just after the ++ end of the literal in the input string. The resulting token is ++ stored in VALUE. This returns a token value, either STRING or ++ CHAR, depending on what was parsed. *HOST_CHARS is set to the ++ number of host characters in the literal. */ ++static int ++parse_string_or_char (char *tokptr, char **outptr, struct typed_stoken *value, ++ int *host_chars) ++{ ++ int quote, i; ++ enum c_string_type type; ++ ++ /* Build the gdb internal form of the input string in tempbuf. Note ++ that the buffer is null byte terminated *only* for the ++ convenience of debugging gdb itself and printing the buffer ++ contents when the buffer contains no embedded nulls. Gdb does ++ not depend upon the buffer being null byte terminated, it uses ++ the length string instead. This allows gdb to handle C strings ++ (as well as strings in other languages) with embedded null ++ bytes */ ++ ++ if (!tempbuf_init) ++ tempbuf_init = 1; ++ else ++ obstack_free (&tempbuf, NULL); ++ obstack_init (&tempbuf); ++ ++ /* Record the string type. */ ++ if (*tokptr == 'L') ++ { ++ type = C_WIDE_STRING; ++ ++tokptr; ++ } ++ else if (*tokptr == 'u') ++ { ++ type = C_STRING_16; ++ ++tokptr; ++ } ++ else if (*tokptr == 'U') ++ { ++ type = C_STRING_32; ++ ++tokptr; ++ } ++ else ++ type = C_STRING; ++ ++ /* Skip the quote. */ ++ quote = *tokptr; ++ if (quote == '\'') ++ type |= C_CHAR; ++ ++tokptr; ++ ++ *host_chars = 0; ++ ++ while (*tokptr) ++ { ++ char c = *tokptr; ++ if (c == '\\') ++ { ++ ++tokptr; ++ *host_chars += c_parse_escape (&tokptr, &tempbuf); ++ } ++ else if (c == quote) ++ break; ++ else ++ { ++ obstack_1grow (&tempbuf, c); ++ ++tokptr; ++ /* FIXME: this does the wrong thing with multi-byte host ++ characters. We could use mbrlen here, but that would ++ make "set host-charset" a bit less useful. */ ++ ++*host_chars; ++ } ++ } ++ ++ if (*tokptr != quote) ++ { ++ if (quote == '"') ++ error ("Unterminated string in expression."); ++ else ++ error ("Unmatched single quote."); ++ } ++ ++tokptr; ++ ++ value->type = type; ++ value->ptr = obstack_base (&tempbuf); ++ value->length = obstack_object_size (&tempbuf); ++ ++ *outptr = tokptr; ++ ++ return quote == '"' ? STRING : CHAR; ++} ++ + struct token + { + char *operator; +@@ -1526,23 +1850,33 @@ static int last_was_structop; + static int + yylex () + { ++ /* name_prefix stores the full qualification of a variable that is ++ specified in the expression. It is used to eleminate confusion ++ during lookup.*/ ++ static char* name_prefix = NULL; ++ static int name_prefix_len = 0; ++ static int terminate_prefix = 0; ++ + int c; + int namelen; + unsigned int i; + char *tokstart; +- char *tokptr; +- int tempbufindex; +- static char *tempbuf; +- static int tempbufsize; +- char * token_string = NULL; +- int class_prefix = 0; + int saw_structop = last_was_structop; + char *copy; + + last_was_structop = 0; +- ++ + retry: +- ++ ++ if(terminate_prefix || ++ lexptr != name_prefix + name_prefix_len // Some token was skiped so clear name_prefix ++ ){ ++ name_prefix = NULL; ++ name_prefix_len = 0; ++ } ++ ++ terminate_prefix = 1; ++ + /* Check if this is a macro invocation that we need to expand. */ + if (! scanning_macro_expansion ()) + { +@@ -1570,10 +1904,19 @@ yylex () + for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++) + if (strncmp (tokstart, tokentab2[i].operator, 2) == 0) + { ++ ++ if(tokentab2[i].token == COLONCOLON){ ++ name_prefix_len += 2; ++ terminate_prefix = 0; ++ if(name_prefix == NULL){ ++ name_prefix = lexptr; ++ } ++ } + lexptr += 2; + yylval.opcode = tokentab2[i].opcode; + if (in_parse_field && tokentab2[i].token == ARROW) + last_was_structop = 1; ++ + return tokentab2[i].token; + } + +@@ -1602,51 +1945,13 @@ yylex () + return 0; + + case ' ': ++ name_prefix_len++; ++ terminate_prefix = 0; + case '\t': + case '\n': + lexptr++; + goto retry; + +- case '\'': +- /* We either have a character constant ('0' or '\177' for example) +- or we have a quoted symbol reference ('foo(int,int)' in C++ +- for example). */ +- lexptr++; +- c = *lexptr++; +- if (c == '\\') +- c = parse_escape (&lexptr); +- else if (c == '\'') +- error ("Empty character constant."); +- else if (! host_char_to_target (c, &c)) +- { +- int toklen = lexptr - tokstart + 1; +- char *tok = alloca (toklen + 1); +- memcpy (tok, tokstart, toklen); +- tok[toklen] = '\0'; +- error ("There is no character corresponding to %s in the target " +- "character set `%s'.", tok, target_charset ()); +- } +- +- yylval.typed_val_int.val = c; +- yylval.typed_val_int.type = parse_type->builtin_char; +- +- c = *lexptr++; +- if (c != '\'') +- { +- namelen = skip_quoted (tokstart) - tokstart; +- if (namelen > 2) +- { +- lexptr = tokstart + namelen; +- if (lexptr[-1] != '\'') +- error ("Unmatched single quote."); +- namelen -= 2; +- tokstart++; +- goto tryname; +- } +- error ("Invalid character constant."); +- } +- return INT; +- + case '(': + paren_depth++; + lexptr++; +@@ -1764,70 +2069,33 @@ yylex () + lexptr++; + return c; + ++ case 'L': ++ case 'u': ++ case 'U': ++ if (tokstart[1] != '"' && tokstart[1] != '\'') ++ break; ++ /* Fall through. */ ++ case '\'': + case '"': +- +- /* Build the gdb internal form of the input string in tempbuf, +- translating any standard C escape forms seen. Note that the +- buffer is null byte terminated *only* for the convenience of +- debugging gdb itself and printing the buffer contents when +- the buffer contains no embedded nulls. Gdb does not depend +- upon the buffer being null byte terminated, it uses the length +- string instead. This allows gdb to handle C strings (as well +- as strings in other languages) with embedded null bytes */ +- +- tokptr = ++tokstart; +- tempbufindex = 0; +- +- do { +- char *char_start_pos = tokptr; +- +- /* Grow the static temp buffer if necessary, including allocating +- the first one on demand. */ +- if (tempbufindex + 1 >= tempbufsize) +- { +- tempbuf = (char *) realloc (tempbuf, tempbufsize += 64); +- } +- switch (*tokptr) ++ { ++ int host_len; ++ int result = parse_string_or_char (tokstart, &lexptr, &yylval.tsval, ++ &host_len); ++ if (result == CHAR) + { +- case '\0': +- case '"': +- /* Do nothing, loop will terminate. */ +- break; +- case '\\': +- tokptr++; +- c = parse_escape (&tokptr); +- if (c == -1) ++ if (host_len == 0) ++ error ("Empty character constant."); ++ else if (host_len > 2 && c == '\'') + { +- continue; ++ ++tokstart; ++ namelen = lexptr - tokstart - 1; ++ goto tryname; + } +- tempbuf[tempbufindex++] = c; +- break; +- default: +- c = *tokptr++; +- if (! host_char_to_target (c, &c)) +- { +- int len = tokptr - char_start_pos; +- char *copy = alloca (len + 1); +- memcpy (copy, char_start_pos, len); +- copy[len] = '\0'; +- +- error ("There is no character corresponding to `%s' " +- "in the target character set `%s'.", +- copy, target_charset ()); +- } +- tempbuf[tempbufindex++] = c; +- break; ++ else if (host_len > 1) ++ error ("Invalid character constant."); + } +- } while ((*tokptr != '"') && (*tokptr != '\0')); +- if (*tokptr++ != '"') +- { +- error ("Unterminated string in expression."); +- } +- tempbuf[tempbufindex] = '\0'; /* See note above */ +- yylval.sval.ptr = tempbuf; +- yylval.sval.length = tempbufindex; +- lexptr = tokptr; +- return (STRING); ++ return result; ++ } + } + + if (!(c == '_' || c == '$' +@@ -1836,11 +2104,13 @@ yylex () + error ("Invalid character '%c' in expression.", c); + + /* It's a name. See how long it is. */ ++ + namelen = 0; + for (c = tokstart[namelen]; + (c == '_' || c == '$' || (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');) + { ++ + /* Template parameter lists are part of the name. + FIXME: This mishandles `print $a<4&&$a>3'. */ + +@@ -1904,14 +2174,29 @@ yylex () + currently as names of types; NAME for other symbols. + The caller is not constrained to care about the distinction. */ + { ++ char *tmp = copy; + struct symbol *sym; + int is_a_field_of_this = 0; + int hextype; + +- sym = lookup_symbol (copy, expression_context_block, ++ if(name_prefix != NULL){ ++ tmp = savestring (name_prefix, name_prefix_len+namelen); ++ } ++ ++ sym = lookup_symbol (tmp, expression_context_block, + VAR_DOMAIN, + parse_language->la_language == language_cplus + ? &is_a_field_of_this : (int *) NULL); ++ ++ /* keep this name as prefix for the next name */ ++ if(sym){ ++ if(name_prefix == NULL){ ++ name_prefix = tokstart; ++ } ++ name_prefix_len += namelen; ++ terminate_prefix = 0; ++ } ++ + /* Call lookup_symtab, not lookup_partial_symtab, in case there are + no psymtabs (coff, xcoff, or some future change to blow away the + psymtabs once once symbols are read). */ +@@ -1970,6 +2255,7 @@ yylex () + yylval.ssym.is_a_field_of_this = is_a_field_of_this; + if (in_parse_field && *lexptr == '\0') + saw_name_at_eof = 1; ++ + return NAME; + } + } +diff --git a/gdb/c-lang.c b/gdb/c-lang.c +index 8b5410f..188755b 100644 +--- a/gdb/c-lang.c ++++ b/gdb/c-lang.c +@@ -33,48 +33,304 @@ + #include "demangle.h" + #include "cp-abi.h" + #include "cp-support.h" ++#include "gdb_obstack.h" ++#include ++#include ++#include + + extern void _initialize_c_language (void); +-static void c_emit_char (int c, struct ui_file * stream, int quoter); ++ ++/* Given a C string type, STR_TYPE, return the corresponding target ++ character set name. */ ++ ++static const char * ++charset_for_string_type (enum c_string_type str_type) ++{ ++ switch (str_type & ~C_CHAR) ++ { ++ case C_STRING: ++ return target_charset (); ++ case C_WIDE_STRING: ++ return target_wide_charset (); ++ case C_STRING_16: ++ /* FIXME: UCS-2 is not always correct. */ ++ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) ++ return "UCS-2BE"; ++ else ++ return "UCS-2LE"; ++ case C_STRING_32: ++ /* FIXME: UCS-4 is not always correct. */ ++ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) ++ return "UCS-4BE"; ++ else ++ return "UCS-4LE"; ++ } ++ internal_error (__FILE__, __LINE__, "unhandled c_string_type"); ++} ++ ++/* Classify ELTTYPE according to what kind of character it is. Return ++ the enum constant representing the character type. Also set ++ *ENCODING to the name of the character set to use when converting ++ characters of this type to the host character set. */ ++ ++static enum c_string_type ++classify_type (struct type *elttype, const char **encoding) ++{ ++ struct type *saved_type; ++ enum c_string_type result; ++ ++ /* We do one or two passes -- one on ELTTYPE, and then maybe a ++ second one on a typedef target. */ ++ do ++ { ++ char *name = TYPE_NAME (elttype); ++ ++ if (TYPE_CODE (elttype) == TYPE_CODE_CHAR || !name) ++ { ++ result = C_CHAR; ++ goto done; ++ } ++ ++ if (!strcmp (name, "wchar_t")) ++ { ++ result = C_WIDE_CHAR; ++ goto done; ++ } ++ ++ if (!strcmp (name, "char16_t")) ++ { ++ result = C_CHAR_16; ++ goto done; ++ } ++ ++ if (!strcmp (name, "char32_t")) ++ { ++ result = C_CHAR_32; ++ goto done; ++ } ++ ++ saved_type = elttype; ++ CHECK_TYPEDEF (elttype); ++ } ++ while (elttype != saved_type); ++ ++ /* Punt. */ ++ result = C_CHAR; ++ ++ done: ++ *encoding = charset_for_string_type (result); ++ return result; ++} ++ ++/* Return true if print_wchar can display W without resorting to a ++ numeric escape, false otherwise. */ ++ ++static int ++wchar_printable (wchar_t w) ++{ ++ return (iswprint (w) ++ || w == L'\a' || w == L'\b' || w == L'\f' || w == L'\n' ++ || w == L'\r' || w == L'\t' || w == L'\v'); ++} ++ ++/* A helper function that converts the contents of STRING to wide ++ characters and then appends them to OUTPUT. */ ++ ++static void ++append_string_as_wide (const char *string, struct obstack *output) ++{ ++ for (; *string; ++string) ++ { ++ wchar_t w = btowc (*string); ++ obstack_grow (output, &w, sizeof (wchar_t)); ++ } ++} ++ ++/* Print a wide character W to OUTPUT. ORIG is a pointer to the ++ original (target) bytes representing the character, ORIG_LEN is the ++ number of valid bytes. WIDTH is the number of bytes in a base ++ characters of the type. OUTPUT is an obstack to which wide ++ characters are emitted. QUOTER is a (narrow) character indicating ++ the style of quotes surrounding the character to be printed. ++ NEED_ESCAPE is an in/out flag which is used to track numeric ++ escapes across calls. */ ++ ++static void ++print_wchar (wint_t w, const gdb_byte *orig, int orig_len, ++ int width, struct obstack *output, int quoter, ++ int *need_escapep) ++{ ++ int need_escape = *need_escapep; ++ *need_escapep = 0; ++ if (iswprint (w) && (!need_escape || (!iswdigit (w) ++ && w != L'8' ++ && w != L'9'))) ++ { ++ if (w == btowc (quoter) || w == L'\\') ++ obstack_grow_wstr (output, L"\\"); ++ obstack_grow (output, &w, sizeof (wchar_t)); ++ } ++ else ++ { ++ switch (w) ++ { ++ case L'\a': ++ obstack_grow_wstr (output, L"\\a"); ++ break; ++ case L'\b': ++ obstack_grow_wstr (output, L"\\b"); ++ break; ++ case L'\f': ++ obstack_grow_wstr (output, L"\\f"); ++ break; ++ case L'\n': ++ obstack_grow_wstr (output, L"\\n"); ++ break; ++ case L'\r': ++ obstack_grow_wstr (output, L"\\r"); ++ break; ++ case L'\t': ++ obstack_grow_wstr (output, L"\\t"); ++ break; ++ case L'\v': ++ obstack_grow_wstr (output, L"\\v"); ++ break; ++ default: ++ { ++ int i; ++ ++ for (i = 0; i + width <= orig_len; i += width) ++ { ++ char octal[30]; ++ ULONGEST value = extract_unsigned_integer (&orig[i], width); ++ sprintf (octal, "\\%lo", (long) value); ++ append_string_as_wide (octal, output); ++ } ++ /* If we somehow have extra bytes, print them now. */ ++ while (i < orig_len) ++ { ++ char octal[5]; ++ sprintf (octal, "\\%.3o", orig[i] & 0xff); ++ append_string_as_wide (octal, output); ++ ++i; ++ } ++ ++ *need_escapep = 1; ++ } ++ break; ++ } ++ } ++} + + /* Print the character C on STREAM as part of the contents of a literal + string whose delimiter is QUOTER. Note that that format for printing + characters and strings is language specific. */ + + static void +-c_emit_char (int c, struct ui_file *stream, int quoter) ++c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) + { +- const char *escape; +- int host_char; ++ struct obstack wchar_buf, output; ++ struct cleanup *cleanups; ++ const char *encoding; ++ gdb_byte *buf; ++ struct wchar_iterator *iter; ++ int need_escape = 0; + +- c &= 0xFF; /* Avoid sign bit follies */ ++ classify_type (type, &encoding); + +- escape = c_target_char_has_backslash_escape (c); +- if (escape) +- { +- if (quoter == '"' && strcmp (escape, "0") == 0) +- /* Print nulls embedded in double quoted strings as \000 to +- prevent ambiguity. */ +- fprintf_filtered (stream, "\\000"); +- else +- fprintf_filtered (stream, "\\%s", escape); +- } +- else if (target_char_to_host (c, &host_char) +- && host_char_print_literally (host_char)) ++ buf = alloca (TYPE_LENGTH (type)); ++ pack_long (buf, type, c); ++ ++ iter = make_wchar_iterator (buf, TYPE_LENGTH (type), encoding, ++ TYPE_LENGTH (type)); ++ cleanups = make_cleanup_wchar_iterator (iter); ++ ++ /* This holds the printable form of the wchar_t data. */ ++ obstack_init (&wchar_buf); ++ make_cleanup_obstack_free (&wchar_buf); ++ ++ while (1) + { +- if (host_char == '\\' || host_char == quoter) +- fputs_filtered ("\\", stream); +- fprintf_filtered (stream, "%c", host_char); ++ int num_chars; ++ wchar_t *chars; ++ const gdb_byte *buf; ++ size_t buflen; ++ int print_escape = 1; ++ enum wchar_iterate_result result; ++ ++ num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); ++ if (num_chars < 0) ++ break; ++ if (num_chars > 0) ++ { ++ /* If all characters are printable, print them. Otherwise, ++ we're going to have to print an escape sequence. We ++ check all characters because we want to print the target ++ bytes in the escape sequence, and we don't know character ++ boundaries there. */ ++ int i; ++ ++ print_escape = 0; ++ for (i = 0; i < num_chars; ++i) ++ if (!wchar_printable (chars[i])) ++ { ++ print_escape = 1; ++ break; ++ } ++ ++ if (!print_escape) ++ { ++ for (i = 0; i < num_chars; ++i) ++ print_wchar (chars[i], buf, buflen, TYPE_LENGTH (type), ++ &wchar_buf, quoter, &need_escape); ++ } ++ } ++ ++ /* This handles the NUM_CHARS == 0 case as well. */ ++ if (print_escape) ++ print_wchar (WEOF, buf, buflen, TYPE_LENGTH (type), &wchar_buf, quoter, ++ &need_escape); + } +- else +- fprintf_filtered (stream, "\\%.3o", (unsigned int) c); ++ ++ /* The output in the host encoding. */ ++ obstack_init (&output); ++ make_cleanup_obstack_free (&output); ++ ++ convert_between_encodings ("wchar_t", host_charset (), ++ obstack_base (&wchar_buf), ++ obstack_object_size (&wchar_buf), ++ 1, &output, translit_char); ++ obstack_1grow (&output, '\0'); ++ ++ fputs_filtered (obstack_base (&output), stream); ++ ++ do_cleanups (cleanups); + } + + void +-c_printchar (int c, struct ui_file *stream) ++c_printchar (int c, struct type *type, struct ui_file *stream) + { ++ enum c_string_type str_type; ++ const char *encoding; ++ ++ str_type = classify_type (type, &encoding); ++ switch (str_type) ++ { ++ case C_CHAR: ++ break; ++ case C_WIDE_CHAR: ++ fputc_filtered ('L', stream); ++ break; ++ case C_CHAR_16: ++ fputc_filtered ('u', stream); ++ break; ++ case C_CHAR_32: ++ fputc_filtered ('U', stream); ++ break; ++ } ++ + fputc_filtered ('\'', stream); +- LA_EMIT_CHAR (c, stream, '\''); ++ LA_EMIT_CHAR (c, type, stream, '\''); + fputc_filtered ('\'', stream); + } + +@@ -85,87 +341,206 @@ c_printchar (int c, struct ui_file *stream) + printing LENGTH characters, or if FORCE_ELLIPSES. */ + + void +-c_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, ++ unsigned int length, int force_ellipses, + const struct value_print_options *options) + { + unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; ++ int width = TYPE_LENGTH (type); ++ struct obstack wchar_buf, output; ++ struct cleanup *cleanup; ++ enum c_string_type str_type; ++ const char *encoding; ++ struct wchar_iterator *iter; ++ int finished = 0; ++ int need_escape = 0; + + /* If the string was not truncated due to `set print elements', and + the last byte of it is a null, we don't print that, in traditional C + style. */ + if (!force_ellipses + && length > 0 +- && (extract_unsigned_integer (string + (length - 1) * width, width) +- == '\0')) ++ && (extract_unsigned_integer (string + (length - 1) * width, width) == 0)) + length--; + ++ str_type = classify_type (type, &encoding) & ~C_CHAR; ++ switch (str_type) ++ { ++ case C_STRING: ++ break; ++ case C_WIDE_STRING: ++ fputs_filtered ("L", stream); ++ break; ++ case C_STRING_16: ++ fputs_filtered ("u", stream); ++ break; ++ case C_STRING_32: ++ fputs_filtered ("U", stream); ++ break; ++ } ++ + if (length == 0) + { + fputs_filtered ("\"\"", stream); + return; + } + +- for (i = 0; i < length && things_printed < options->print_max; ++i) ++ if (length == -1) ++ { ++ unsigned long current_char = 1; ++ for (i = 0; current_char; ++i) ++ { ++ QUIT; ++ current_char = extract_unsigned_integer (string + i * width, width); ++ } ++ length = i; ++ } ++ ++ /* Arrange to iterate over the characters, in wchar_t form. */ ++ iter = make_wchar_iterator (string, length * width, encoding, width); ++ cleanup = make_cleanup_wchar_iterator (iter); ++ ++ /* WCHAR_BUF is the obstack we use to represent the string in ++ wchar_t form. */ ++ obstack_init (&wchar_buf); ++ make_cleanup_obstack_free (&wchar_buf); ++ ++ while (!finished && things_printed < options->print_max) + { +- /* Position of the character we are examining +- to see whether it is repeated. */ +- unsigned int rep1; +- /* Number of repetitions we have detected so far. */ +- unsigned int reps; +- unsigned long current_char; ++ int num_chars; ++ enum wchar_iterate_result result; ++ wchar_t *chars; ++ const gdb_byte *buf; ++ size_t buflen; + + QUIT; + + if (need_comma) + { +- fputs_filtered (", ", stream); ++ obstack_grow_wstr (&wchar_buf, L", "); + need_comma = 0; + } + +- current_char = extract_unsigned_integer (string + i * width, width); ++ num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); ++ /* We only look at repetitions when we were able to convert a ++ single character in isolation. This makes the code simpler ++ and probably does the sensible thing in the majority of ++ cases. */ ++ while (num_chars == 1) ++ { ++ /* Count the number of repetitions. */ ++ unsigned int reps = 0; ++ wchar_t current_char = chars[0]; ++ const gdb_byte *orig_buf = buf; ++ int orig_len = buflen; + +- rep1 = i + 1; +- reps = 1; +- while (rep1 < length +- && extract_unsigned_integer (string + rep1 * width, width) +- == current_char) ++ if (need_comma) ++ { ++ obstack_grow_wstr (&wchar_buf, L", "); ++ need_comma = 0; ++ } ++ ++ while (num_chars == 1 && current_char == chars[0]) ++ { ++ num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); ++ ++reps; ++ } ++ ++ /* Emit CURRENT_CHAR according to the repetition count and ++ options. */ ++ if (reps > options->repeat_count_threshold) ++ { ++ if (in_quotes) ++ { ++ if (options->inspect_it) ++ obstack_grow_wstr (&wchar_buf, L"\\\", "); ++ else ++ obstack_grow_wstr (&wchar_buf, L"\", "); ++ in_quotes = 0; ++ } ++ obstack_grow_wstr (&wchar_buf, L"'"); ++ need_escape = 0; ++ print_wchar (current_char, orig_buf, orig_len, width, ++ &wchar_buf, '\'', &need_escape); ++ obstack_grow_wstr (&wchar_buf, L"'"); ++ { ++ /* Painful gyrations. */ ++ int j; ++ char *s = xstrprintf (_(" "), reps); ++ for (j = 0; s[j]; ++j) ++ { ++ wchar_t w = btowc (s[j]); ++ obstack_grow (&wchar_buf, &w, sizeof (wchar_t)); ++ } ++ xfree (s); ++ } ++ things_printed += options->repeat_count_threshold; ++ need_comma = 1; ++ } ++ else ++ { ++ /* Saw the character one or more times, but fewer than ++ the repetition threshold. */ ++ if (!in_quotes) ++ { ++ if (options->inspect_it) ++ obstack_grow_wstr (&wchar_buf, L"\\\""); ++ else ++ obstack_grow_wstr (&wchar_buf, L"\""); ++ in_quotes = 1; ++ need_escape = 0; ++ } ++ ++ while (reps-- > 0) ++ { ++ print_wchar (current_char, orig_buf, orig_len, width, ++ &wchar_buf, '"', &need_escape); ++ ++things_printed; ++ } ++ } ++ } ++ ++ /* NUM_CHARS and the other outputs from wchar_iterate are valid ++ here regardless of which branch was taken above. */ ++ if (num_chars < 0) + { +- ++rep1; +- ++reps; ++ /* Hit EOF. */ ++ finished = 1; ++ break; + } + +- if (reps > options->repeat_count_threshold) ++ switch (result) + { +- if (in_quotes) ++ case wchar_iterate_invalid: ++ if (!in_quotes) + { + if (options->inspect_it) +- fputs_filtered ("\\\", ", stream); ++ obstack_grow_wstr (&wchar_buf, L"\\\""); + else +- fputs_filtered ("\", ", stream); +- in_quotes = 0; ++ obstack_grow_wstr (&wchar_buf, L"\""); ++ in_quotes = 1; + } +- LA_PRINT_CHAR (current_char, stream); +- fprintf_filtered (stream, _(" "), reps); +- i = rep1 - 1; +- things_printed += options->repeat_count_threshold; +- need_comma = 1; +- } +- else +- { +- if (!in_quotes) ++ need_escape = 0; ++ print_wchar (WEOF, buf, buflen, width, &wchar_buf, '"', &need_escape); ++ break; ++ ++ case wchar_iterate_incomplete: ++ if (in_quotes) + { + if (options->inspect_it) +- fputs_filtered ("\\\"", stream); ++ obstack_grow_wstr (&wchar_buf, L"\\\","); + else +- fputs_filtered ("\"", stream); +- in_quotes = 1; ++ obstack_grow_wstr (&wchar_buf, L"\","); ++ in_quotes = 0; + } +- LA_EMIT_CHAR (current_char, stream, '"'); +- ++things_printed; ++ obstack_grow_wstr (&wchar_buf, L" "); ++ finished = 1; ++ break; + } + } + +@@ -173,13 +548,27 @@ c_printstr (struct ui_file *stream, const gdb_byte *string, + if (in_quotes) + { + if (options->inspect_it) +- fputs_filtered ("\\\"", stream); ++ obstack_grow_wstr (&wchar_buf, L"\\\""); + else +- fputs_filtered ("\"", stream); ++ obstack_grow_wstr (&wchar_buf, L"\""); + } + +- if (force_ellipses || i < length) +- fputs_filtered ("...", stream); ++ if (force_ellipses || !finished) ++ obstack_grow_wstr (&wchar_buf, L"..."); ++ ++ /* OUTPUT is where we collect `char's for printing. */ ++ obstack_init (&output); ++ make_cleanup_obstack_free (&output); ++ ++ convert_between_encodings ("wchar_t", host_charset (), ++ obstack_base (&wchar_buf), ++ obstack_object_size (&wchar_buf), ++ 1, &output, translit_char); ++ obstack_1grow (&output, '\0'); ++ ++ fputs_filtered (obstack_base (&output), stream); ++ ++ do_cleanups (cleanup); + } + + /* Obtain a C string from the inferior storing it in a newly allocated +@@ -298,7 +687,285 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, + } + + +-/* Preprocessing and parsing C and C++ expressions. */ ++/* Evaluating C and C++ expressions. */ ++ ++/* Convert a UCN. The digits of the UCN start at P and extend no ++ farther than LIMIT. DEST_CHARSET is the name of the character set ++ into which the UCN should be converted. The results are written to ++ OUTPUT. LENGTH is the maximum length of the UCN, either 4 or 8. ++ Returns a pointer to just after the final digit of the UCN. */ ++ ++static char * ++convert_ucn (char *p, char *limit, const char *dest_charset, ++ struct obstack *output, int length) ++{ ++ unsigned long result = 0; ++ gdb_byte data[4]; ++ int i; ++ ++ for (i = 0; i < length && p < limit && isxdigit (*p); ++i, ++p) ++ result = (result << 4) + host_hex_value (*p); ++ ++ for (i = 3; i >= 0; --i) ++ { ++ data[i] = result & 0xff; ++ result >>= 8; ++ } ++ ++ convert_between_encodings ("UCS-4BE", dest_charset, data, 4, 4, output, ++ translit_none); ++ ++ return p; ++} ++ ++/* Emit a character, VALUE, which was specified numerically, to ++ OUTPUT. TYPE is the target character type. */ ++ ++static void ++emit_numeric_character (struct type *type, unsigned long value, ++ struct obstack *output) ++{ ++ gdb_byte *buffer; ++ ++ buffer = alloca (TYPE_LENGTH (type)); ++ pack_long (buffer, type, value); ++ obstack_grow (output, buffer, TYPE_LENGTH (type)); ++} ++ ++/* Convert an octal escape sequence. TYPE is the target character ++ type. The digits of the escape sequence begin at P and extend no ++ farther than LIMIT. The result is written to OUTPUT. Returns a ++ pointer to just after the final digit of the escape sequence. */ ++ ++static char * ++convert_octal (struct type *type, char *p, char *limit, struct obstack *output) ++{ ++ unsigned long value = 0; ++ ++ while (p < limit && isdigit (*p) && *p != '8' && *p != '9') ++ { ++ value = 8 * value + host_hex_value (*p); ++ ++p; ++ } ++ ++ emit_numeric_character (type, value, output); ++ ++ return p; ++} ++ ++/* Convert a hex escape sequence. TYPE is the target character type. ++ The digits of the escape sequence begin at P and extend no farther ++ than LIMIT. The result is written to OUTPUT. Returns a pointer to ++ just after the final digit of the escape sequence. */ ++ ++static char * ++convert_hex (struct type *type, char *p, char *limit, struct obstack *output) ++{ ++ unsigned long value = 0; ++ ++ while (p < limit && isxdigit (*p)) ++ { ++ value = 16 * value + host_hex_value (*p); ++ ++p; ++ } ++ ++ emit_numeric_character (type, value, output); ++ ++ return p; ++} ++ ++#define ADVANCE \ ++ do { \ ++ ++p; \ ++ if (p == limit) \ ++ error (_("Malformed escape sequence")); \ ++ } while (0) ++ ++/* Convert an escape sequence to a target format. TYPE is the target ++ character type to use, and DEST_CHARSET is the name of the target ++ character set. The backslash of the escape sequence is at *P, and ++ the escape sequence will not extend past LIMIT. The results are ++ written to OUTPUT. Returns a pointer to just past the final ++ character of the escape sequence. */ ++ ++static char * ++convert_escape (struct type *type, const char *dest_charset, ++ char *p, char *limit, struct obstack *output) ++{ ++ /* Skip the backslash. */ ++ ADVANCE; ++ ++ switch (*p) ++ { ++ case '\\': ++ obstack_1grow (output, '\\'); ++ ++p; ++ break; ++ ++ case 'x': ++ ADVANCE; ++ if (!isxdigit (*p)) ++ error (_("\\x used with no following hex digits.")); ++ p = convert_hex (type, p, limit, output); ++ break; ++ ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ p = convert_octal (type, p, limit, output); ++ break; ++ ++ case 'u': ++ case 'U': ++ { ++ int length = *p == 'u' ? 4 : 8; ++ ADVANCE; ++ if (!isxdigit (*p)) ++ error (_("\\u used with no following hex digits")); ++ p = convert_ucn (p, limit, dest_charset, output, length); ++ } ++ } ++ ++ return p; ++} ++ ++/* Given a single string from a (C-specific) OP_STRING list, convert ++ it to a target string, handling escape sequences specially. The ++ output is written to OUTPUT. DATA is the input string, which has ++ length LEN. DEST_CHARSET is the name of the target character set, ++ and TYPE is the type of target character to use. */ ++ ++static void ++parse_one_string (struct obstack *output, char *data, int len, ++ const char *dest_charset, struct type *type) ++{ ++ char *limit; ++ ++ limit = data + len; ++ ++ while (data < limit) ++ { ++ char *p = data; ++ /* Look for next escape, or the end of the input. */ ++ while (p < limit && *p != '\\') ++ ++p; ++ /* If we saw a run of characters, convert them all. */ ++ if (p > data) ++ convert_between_encodings (host_charset (), dest_charset, ++ data, p - data, 1, output, translit_none); ++ /* If we saw an escape, convert it. */ ++ if (p < limit) ++ p = convert_escape (type, dest_charset, p, limit, output); ++ data = p; ++ } ++} ++ ++/* Expression evaluator for the C language family. Most operations ++ are delegated to evaluate_subexp_standard; see that function for a ++ description of the arguments. */ ++ ++static struct value * ++evaluate_subexp_c (struct type *expect_type, struct expression *exp, ++ int *pos, enum noside noside) ++{ ++ enum exp_opcode op = exp->elts[*pos].opcode; ++ ++ switch (op) ++ { ++ case OP_STRING: ++ { ++ int oplen, limit; ++ struct type *type; ++ struct obstack output; ++ struct cleanup *cleanup; ++ struct value *result; ++ enum c_string_type dest_type; ++ const char *dest_charset; ++ ++ obstack_init (&output); ++ cleanup = make_cleanup_obstack_free (&output); ++ ++ ++*pos; ++ oplen = longest_to_int (exp->elts[*pos].longconst); ++ ++ ++*pos; ++ limit = *pos + BYTES_TO_EXP_ELEM (oplen + 1); ++ dest_type ++ = (enum c_string_type) longest_to_int (exp->elts[*pos].longconst); ++ switch (dest_type & ~C_CHAR) ++ { ++ case C_STRING: ++ type = language_string_char_type (current_language, ++ current_gdbarch); ++ break; ++ case C_WIDE_STRING: ++ type = lookup_typename ("wchar_t", NULL, 0); ++ break; ++ case C_STRING_16: ++ type = lookup_typename ("char16_t", NULL, 0); ++ break; ++ case C_STRING_32: ++ type = lookup_typename ("char32_t", NULL, 0); ++ break; ++ default: ++ internal_error (__FILE__, __LINE__, "unhandled c_string_type"); ++ } ++ dest_charset = charset_for_string_type (dest_type); ++ ++ ++*pos; ++ while (*pos < limit) ++ { ++ int len; ++ ++ len = longest_to_int (exp->elts[*pos].longconst); ++ ++ ++*pos; ++ if (noside != EVAL_SKIP) ++ parse_one_string (&output, &exp->elts[*pos].string, len, ++ dest_charset, type); ++ *pos += BYTES_TO_EXP_ELEM (len); ++ } ++ ++ /* Skip the trailing length and opcode. */ ++ *pos += 2; ++ ++ if (noside == EVAL_SKIP) ++ return NULL; ++ ++ if ((dest_type & C_CHAR) != 0) ++ { ++ LONGEST value; ++ ++ if (obstack_object_size (&output) != TYPE_LENGTH (type)) ++ error (_("Could not convert character constant to target character set")); ++ value = unpack_long (type, obstack_base (&output)); ++ result = value_from_longest (type, value); ++ } ++ else ++ { ++ int i; ++ /* Write the terminating character. */ ++ for (i = 0; i < TYPE_LENGTH (type); ++i) ++ obstack_1grow (&output, 0); ++ result = value_typed_string (obstack_base (&output), ++ obstack_object_size (&output), ++ type); ++ } ++ do_cleanups (cleanup); ++ return result; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ return evaluate_subexp_standard (expect_type, exp, pos, noside); ++} + + + +@@ -396,6 +1063,15 @@ c_language_arch_info (struct gdbarch *gdbarch, + lai->bool_type_default = builtin->builtin_int; + } + ++static const struct exp_descriptor exp_descriptor_c = ++{ ++ print_subexp_standard, ++ operator_length_standard, ++ op_name_standard, ++ dump_subexp_body_standard, ++ evaluate_subexp_c ++}; ++ + const struct language_defn c_language_defn = + { + "c", /* Language name */ +@@ -405,7 +1081,7 @@ const struct language_defn c_language_defn = + case_sensitive_on, + array_row_major, + macro_expansion_c, +- &exp_descriptor_standard, ++ &exp_descriptor_c, + c_parse, + c_error, + null_post_parser, +@@ -524,7 +1200,7 @@ const struct language_defn cplus_language_defn = + case_sensitive_on, + array_row_major, + macro_expansion_c, +- &exp_descriptor_standard, ++ &exp_descriptor_c, + c_parse, + c_error, + null_post_parser, +@@ -562,7 +1238,7 @@ const struct language_defn asm_language_defn = + case_sensitive_on, + array_row_major, + macro_expansion_c, +- &exp_descriptor_standard, ++ &exp_descriptor_c, + c_parse, + c_error, + null_post_parser, +@@ -605,7 +1281,7 @@ const struct language_defn minimal_language_defn = + case_sensitive_on, + array_row_major, + macro_expansion_c, +- &exp_descriptor_standard, ++ &exp_descriptor_c, + c_parse, + c_error, + null_post_parser, +diff --git a/gdb/c-lang.h b/gdb/c-lang.h +index 06c5767..ba9d996 100644 +--- a/gdb/c-lang.h ++++ b/gdb/c-lang.h +@@ -29,9 +29,38 @@ struct language_arch_info; + #include "macroexp.h" + + +-extern int c_parse (void); /* Defined in c-exp.y */ +- +-extern void c_error (char *); /* Defined in c-exp.y */ ++/* The various kinds of C string and character. Note that these ++ values are chosen so that they may be or'd together in certain ++ ways. */ ++enum c_string_type ++ { ++ /* An ordinary string: "value". */ ++ C_STRING = 0, ++ /* A wide string: L"value". */ ++ C_WIDE_STRING = 1, ++ /* A 16-bit Unicode string: u"value". */ ++ C_STRING_16 = 2, ++ /* A 32-bit Unicode string: U"value". */ ++ C_STRING_32 = 3, ++ /* An ordinary char: 'v'. This can also be or'd with one of the ++ above to form the corresponding CHAR value from a STRING ++ value. */ ++ C_CHAR = 4, ++ /* A wide char: L'v'. */ ++ C_WIDE_CHAR = 5, ++ /* A 16-bit Unicode char: u'v'. */ ++ C_CHAR_16 = 6, ++ /* A 32-bit Unicode char: U'v'. */ ++ C_CHAR_32 = 7 ++ }; ++ ++/* Defined in c-exp.y. */ ++ ++extern int c_parse (void); ++ ++extern void c_error (char *); ++ ++extern int c_parse_escape (char **, struct obstack *); + + /* Defined in c-typeprint.c */ + extern void c_print_type (struct type *, char *, struct ui_file *, int, +@@ -48,10 +77,10 @@ extern int c_value_print (struct value *, struct ui_file *, + + /* These are in c-lang.c: */ + +-extern void c_printchar (int, struct ui_file *); ++extern void c_printchar (int, struct type *, struct ui_file *); + +-extern void c_printstr (struct ui_file * stream, const gdb_byte *string, +- unsigned int length, int width, ++extern void c_printstr (struct ui_file * stream, struct type *elttype, ++ const gdb_byte *string, unsigned int length, + int force_ellipses, + const struct value_print_options *options); + +diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c +index 0929516..c005fe4 100644 +--- a/gdb/c-typeprint.c ++++ b/gdb/c-typeprint.c +@@ -40,8 +40,6 @@ static void cp_type_print_method_args (struct type *mtype, char *prefix, + char *varstring, int staticp, + struct ui_file *stream); + +-static void c_type_print_args (struct type *, struct ui_file *); +- + static void cp_type_print_derivation_info (struct ui_file *, struct type *); + + static void c_type_print_varspec_prefix (struct type *, struct ui_file *, int, +@@ -199,6 +197,23 @@ cp_type_print_method_args (struct type *mtype, char *prefix, char *varstring, + fprintf_filtered (stream, "void"); + + fprintf_filtered (stream, ")"); ++ ++ /* For non-static methods, read qualifiers from the type of ++ THIS. */ ++ if (!staticp) ++ { ++ struct type *domain; ++ ++ gdb_assert (nargs > 0); ++ gdb_assert (TYPE_CODE (args[0].type) == TYPE_CODE_PTR); ++ domain = TYPE_TARGET_TYPE (args[0].type); ++ ++ if (TYPE_CONST (domain)) ++ fprintf_filtered (stream, " const"); ++ ++ if (TYPE_VOLATILE (domain)) ++ fprintf_filtered (stream, " volatile"); ++ } + } + + +@@ -354,10 +369,12 @@ c_type_print_modifier (struct type *type, struct ui_file *stream, + + /* Print out the arguments of TYPE, which should have TYPE_CODE_METHOD + or TYPE_CODE_FUNC, to STREAM. Artificial arguments, such as "this" +- in non-static methods, are displayed. */ ++ in non-static methods, are displayed if SHOW_ARTIFICIAL is ++ non-zero. */ + +-static void +-c_type_print_args (struct type *type, struct ui_file *stream) ++void ++c_type_print_args (struct type *type, struct ui_file *stream, ++ int show_artificial) + { + int i, len; + struct field *args; +@@ -369,6 +386,9 @@ c_type_print_args (struct type *type, struct ui_file *stream) + + for (i = 0; i < TYPE_NFIELDS (type); i++) + { ++ if (TYPE_FIELD_ARTIFICIAL (type, i) && !show_artificial) ++ continue; ++ + if (printed_any) + { + fprintf_filtered (stream, ", "); +@@ -559,7 +579,12 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, + fprintf_filtered (stream, ")"); + + fprintf_filtered (stream, "["); +- if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 ++ if (TYPE_ARRAY_BOUND_IS_DWARF_BLOCK (type, 1)) ++ { ++ /* No _() - printed sources should not be locale dependent. */ ++ fprintf_filtered (stream, "variable"); ++ } ++ else if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 + && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) + fprintf_filtered (stream, "%d", + (TYPE_LENGTH (type) +@@ -592,7 +617,7 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, + if (passed_a_ptr) + fprintf_filtered (stream, ")"); + if (!demangled_args) +- c_type_print_args (type, stream); ++ c_type_print_args (type, stream, 1); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, + passed_a_ptr, 0); + break; +diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c +index 0b616f7..3433da2 100644 +--- a/gdb/c-valprint.c ++++ b/gdb/c-valprint.c +@@ -55,6 +55,18 @@ print_function_pointer_address (CORE_ADDR address, struct ui_file *stream, + } + + ++/* A helper for textual_element_type. This checks the name of the ++ typedef. This is bogus but it isn't apparent that the compiler ++ provides us the help we may need. */ ++ ++static int ++textual_name (const char *name) ++{ ++ return (!strcmp (name, "wchar_t") ++ || !strcmp (name, "char16_t") ++ || !strcmp (name, "char32_t")); ++} ++ + /* Apply a heuristic to decide whether an array of TYPE or a pointer + to TYPE should be printed as a textual string. Return non-zero if + it should, or zero if it should be treated as an array of integers +@@ -77,6 +89,15 @@ textual_element_type (struct type *type, char format) + /* TYPE_CODE_CHAR is always textual. */ + if (TYPE_CODE (true_type) == TYPE_CODE_CHAR) + return 1; ++ /* Any other character-like types must be integral. */ ++ if (TYPE_CODE (true_type) != TYPE_CODE_INT) ++ return 0; ++ ++ /* Check the names of the type and the typedef. */ ++ if (TYPE_NAME (type) && textual_name (TYPE_NAME (type))) ++ return 1; ++ if (TYPE_NAME (true_type) && textual_name (TYPE_NAME (true_type))) ++ return 1; + + if (format == 's') + { +@@ -115,7 +136,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + { + unsigned int i = 0; /* Number of characters printed */ + unsigned len; +- struct type *elttype; ++ struct type *elttype, *unresolved_elttype; ++ struct type *unresolved_type = type; + unsigned eltlen; + LONGEST val; + CORE_ADDR addr; +@@ -124,8 +146,9 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: +- elttype = check_typedef (TYPE_TARGET_TYPE (type)); +- if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) ++ unresolved_elttype = TYPE_TARGET_TYPE (type); ++ elttype = check_typedef (unresolved_elttype); ++ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (unresolved_elttype) > 0) + { + eltlen = TYPE_LENGTH (elttype); + len = TYPE_LENGTH (type) / eltlen; +@@ -135,7 +158,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + } + + /* Print arrays of textual chars with a string syntax. */ +- if (textual_element_type (elttype, options->format)) ++ if (textual_element_type (unresolved_elttype, options->format)) + { + /* If requested, look for the first null char and only print + elements up to it. */ +@@ -143,15 +166,19 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + { + unsigned int temp_len; + +- /* Look for a NULL char. */ + for (temp_len = 0; +- (valaddr + embedded_offset)[temp_len] +- && temp_len < len && temp_len < options->print_max; +- temp_len++); ++ (temp_len < len ++ && temp_len < options->print_max ++ && extract_unsigned_integer (valaddr + embedded_offset ++ + temp_len * eltlen, ++ eltlen) == 0); ++ ++temp_len) ++ ; + len = temp_len; + } + +- LA_PRINT_STRING (stream, valaddr + embedded_offset, len, eltlen, 0, options); ++ LA_PRINT_STRING (stream, unresolved_elttype, ++ valaddr + embedded_offset, len, 0, options); + i = len; + } + else +@@ -209,7 +236,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + print_function_pointer_address (addr, stream, options->addressprint); + break; + } +- elttype = check_typedef (TYPE_TARGET_TYPE (type)); ++ unresolved_elttype = TYPE_TARGET_TYPE (type); ++ elttype = check_typedef (unresolved_elttype); + { + addr = unpack_pointer (type, valaddr + embedded_offset); + print_unpacked_pointer: +@@ -228,12 +256,11 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + + /* For a pointer to a textual type, also print the string + pointed to, unless pointer is null. */ +- /* FIXME: need to handle wchar_t here... */ + +- if (textual_element_type (elttype, options->format) ++ if (textual_element_type (unresolved_elttype, options->format) + && addr != 0) + { +- i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream, ++ i = val_print_string (unresolved_elttype, addr, -1, stream, + options); + } + else if (cp_is_vtbl_member (type)) +@@ -268,7 +295,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + } + else + { +- wtype = TYPE_TARGET_TYPE (type); ++ wtype = unresolved_elttype; + } + vt_val = value_at (wtype, vt_address); + common_val_print (vt_val, stream, recurse + 1, options, +@@ -442,11 +469,11 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + Since we don't know whether the value is really intended to + be used as an integer or a character, print the character + equivalent as well. */ +- if (textual_element_type (type, options->format)) ++ if (textual_element_type (unresolved_type, options->format)) + { + fputs_filtered (" ", stream); + LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset), +- stream); ++ unresolved_type, stream); + } + } + break; +@@ -468,7 +495,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + else + fprintf_filtered (stream, "%d", (int) val); + fputs_filtered (" ", stream); +- LA_PRINT_CHAR ((unsigned char) val, stream); ++ LA_PRINT_CHAR ((unsigned char) val, unresolved_type, stream); + } + break; + +@@ -540,7 +567,7 @@ int + c_value_print (struct value *val, struct ui_file *stream, + const struct value_print_options *options) + { +- struct type *type, *real_type; ++ struct type *type, *real_type, *val_type; + int full, top, using_enc; + struct value_print_options opts = *options; + +@@ -553,7 +580,11 @@ c_value_print (struct value *val, struct ui_file *stream, + C++: if it is a member pointer, we will take care + of that when we print it. */ + +- type = check_typedef (value_type (val)); ++ /* Preserve the original type before stripping typedefs. We prefer ++ to pass down the original type when possible, but for local ++ checks it is better to look past the typedefs. */ ++ val_type = value_type (val); ++ type = check_typedef (val_type); + + if (TYPE_CODE (type) == TYPE_CODE_PTR + || TYPE_CODE (type) == TYPE_CODE_REF) +@@ -561,11 +592,12 @@ c_value_print (struct value *val, struct ui_file *stream, + /* Hack: remove (char *) for char strings. Their + type is indicated by the quoted string anyway. + (Don't use textual_element_type here; quoted strings +- are always exactly (char *). */ +- if (TYPE_CODE (type) == TYPE_CODE_PTR +- && TYPE_NAME (type) == NULL +- && TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL +- && strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char") == 0) ++ are always exactly (char *), (wchar_t *), or the like. */ ++ if (TYPE_CODE (val_type) == TYPE_CODE_PTR ++ && TYPE_NAME (val_type) == NULL ++ && TYPE_NAME (TYPE_TARGET_TYPE (val_type)) != NULL ++ && (strcmp (TYPE_NAME (TYPE_TARGET_TYPE (val_type)), "char") == 0 ++ || textual_name (TYPE_NAME (TYPE_TARGET_TYPE (val_type))))) + { + /* Print nothing */ + } +@@ -608,6 +640,7 @@ c_value_print (struct value *val, struct ui_file *stream, + } + type_print (type, "", stream, -1); + fprintf_filtered (stream, ") "); ++ val_type = type; + } + else + { +@@ -635,7 +668,7 @@ c_value_print (struct value *val, struct ui_file *stream, + /* Print out object: enclosing type is same as real_type if full */ + return val_print (value_enclosing_type (val), + value_contents_all (val), 0, +- VALUE_ADDRESS (val), stream, 0, ++ value_address (val), stream, 0, + &opts, current_language); + /* Note: When we look up RTTI entries, we don't get any information on + const or volatile attributes */ +@@ -647,14 +680,14 @@ c_value_print (struct value *val, struct ui_file *stream, + TYPE_NAME (value_enclosing_type (val))); + return val_print (value_enclosing_type (val), + value_contents_all (val), 0, +- VALUE_ADDRESS (val), stream, 0, ++ value_address (val), stream, 0, + &opts, current_language); + } + /* Otherwise, we end up at the return outside this "if" */ + } + +- return val_print (type, value_contents_all (val), ++ return val_print (val_type, value_contents_all (val), + value_embedded_offset (val), +- VALUE_ADDRESS (val) + value_offset (val), ++ value_address (val), + stream, 0, &opts, current_language); + } +diff --git a/gdb/charset-list.h b/gdb/charset-list.h +new file mode 100644 +index 0000000..59c64c5 +--- /dev/null ++++ b/gdb/charset-list.h +@@ -0,0 +1,1190 @@ ++/* List of character set names for GDB. ++ ++ Copyright (C) 2009 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 3 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, see . */ ++ ++/* Note that the first entry must always be "auto". ++ The remaining entries were created by running this script: ++ ++ iconv -l | sed -e '/[/]...*$/d' -e 's@^\(.*\)//$@"\1", \\@' ++ ++ .. and then removing the final backslash. It would be nice to ++ separate narrow and wide character sets, but there is no good way ++ to do that. */ ++#define DEFAULT_CHARSET_NAMES \ ++"auto", \ ++"437", \ ++"500", \ ++"500V1", \ ++"850", \ ++"851", \ ++"852", \ ++"855", \ ++"856", \ ++"857", \ ++"860", \ ++"861", \ ++"862", \ ++"863", \ ++"864", \ ++"865", \ ++"866", \ ++"866NAV", \ ++"869", \ ++"874", \ ++"904", \ ++"1026", \ ++"1046", \ ++"1047", \ ++"8859_1", \ ++"8859_2", \ ++"8859_3", \ ++"8859_4", \ ++"8859_5", \ ++"8859_6", \ ++"8859_7", \ ++"8859_8", \ ++"8859_9", \ ++"10646-1:1993", \ ++"ANSI_X3.4-1968", \ ++"ANSI_X3.4-1986", \ ++"ANSI_X3.4", \ ++"ANSI_X3.110-1983", \ ++"ANSI_X3.110", \ ++"ARABIC", \ ++"ARABIC7", \ ++"ARMSCII-8", \ ++"ASCII", \ ++"ASMO-708", \ ++"ASMO_449", \ ++"BALTIC", \ ++"BIG-5", \ ++"BIG-FIVE", \ ++"BIG5-HKSCS", \ ++"BIG5", \ ++"BIG5HKSCS", \ ++"BIGFIVE", \ ++"BRF", \ ++"BS_4730", \ ++"CA", \ ++"CN-BIG5", \ ++"CN-GB", \ ++"CN", \ ++"CP-AR", \ ++"CP-GR", \ ++"CP-HU", \ ++"CP037", \ ++"CP038", \ ++"CP273", \ ++"CP274", \ ++"CP275", \ ++"CP278", \ ++"CP280", \ ++"CP281", \ ++"CP282", \ ++"CP284", \ ++"CP285", \ ++"CP290", \ ++"CP297", \ ++"CP367", \ ++"CP420", \ ++"CP423", \ ++"CP424", \ ++"CP437", \ ++"CP500", \ ++"CP737", \ ++"CP775", \ ++"CP803", \ ++"CP813", \ ++"CP819", \ ++"CP850", \ ++"CP851", \ ++"CP852", \ ++"CP855", \ ++"CP856", \ ++"CP857", \ ++"CP860", \ ++"CP861", \ ++"CP862", \ ++"CP863", \ ++"CP864", \ ++"CP865", \ ++"CP866", \ ++"CP866NAV", \ ++"CP868", \ ++"CP869", \ ++"CP870", \ ++"CP871", \ ++"CP874", \ ++"CP875", \ ++"CP880", \ ++"CP891", \ ++"CP901", \ ++"CP902", \ ++"CP903", \ ++"CP904", \ ++"CP905", \ ++"CP912", \ ++"CP915", \ ++"CP916", \ ++"CP918", \ ++"CP920", \ ++"CP921", \ ++"CP922", \ ++"CP930", \ ++"CP932", \ ++"CP933", \ ++"CP935", \ ++"CP936", \ ++"CP937", \ ++"CP939", \ ++"CP949", \ ++"CP950", \ ++"CP1004", \ ++"CP1008", \ ++"CP1025", \ ++"CP1026", \ ++"CP1046", \ ++"CP1047", \ ++"CP1070", \ ++"CP1079", \ ++"CP1081", \ ++"CP1084", \ ++"CP1089", \ ++"CP1097", \ ++"CP1112", \ ++"CP1122", \ ++"CP1123", \ ++"CP1124", \ ++"CP1125", \ ++"CP1129", \ ++"CP1130", \ ++"CP1132", \ ++"CP1133", \ ++"CP1137", \ ++"CP1140", \ ++"CP1141", \ ++"CP1142", \ ++"CP1143", \ ++"CP1144", \ ++"CP1145", \ ++"CP1146", \ ++"CP1147", \ ++"CP1148", \ ++"CP1149", \ ++"CP1153", \ ++"CP1154", \ ++"CP1155", \ ++"CP1156", \ ++"CP1157", \ ++"CP1158", \ ++"CP1160", \ ++"CP1161", \ ++"CP1162", \ ++"CP1163", \ ++"CP1164", \ ++"CP1166", \ ++"CP1167", \ ++"CP1250", \ ++"CP1251", \ ++"CP1252", \ ++"CP1253", \ ++"CP1254", \ ++"CP1255", \ ++"CP1256", \ ++"CP1257", \ ++"CP1258", \ ++"CP1282", \ ++"CP1361", \ ++"CP1364", \ ++"CP1371", \ ++"CP1388", \ ++"CP1390", \ ++"CP1399", \ ++"CP4517", \ ++"CP4899", \ ++"CP4909", \ ++"CP4971", \ ++"CP5347", \ ++"CP9030", \ ++"CP9066", \ ++"CP9448", \ ++"CP10007", \ ++"CP12712", \ ++"CP16804", \ ++"CPIBM861", \ ++"CSA7-1", \ ++"CSA7-2", \ ++"CSASCII", \ ++"CSA_T500-1983", \ ++"CSA_T500", \ ++"CSA_Z243.4-1985-1", \ ++"CSA_Z243.4-1985-2", \ ++"CSA_Z243.419851", \ ++"CSA_Z243.419852", \ ++"CSDECMCS", \ ++"CSEBCDICATDE", \ ++"CSEBCDICATDEA", \ ++"CSEBCDICCAFR", \ ++"CSEBCDICDKNO", \ ++"CSEBCDICDKNOA", \ ++"CSEBCDICES", \ ++"CSEBCDICESA", \ ++"CSEBCDICESS", \ ++"CSEBCDICFISE", \ ++"CSEBCDICFISEA", \ ++"CSEBCDICFR", \ ++"CSEBCDICIT", \ ++"CSEBCDICPT", \ ++"CSEBCDICUK", \ ++"CSEBCDICUS", \ ++"CSEUCKR", \ ++"CSEUCPKDFMTJAPANESE", \ ++"CSGB2312", \ ++"CSHPROMAN8", \ ++"CSIBM037", \ ++"CSIBM038", \ ++"CSIBM273", \ ++"CSIBM274", \ ++"CSIBM275", \ ++"CSIBM277", \ ++"CSIBM278", \ ++"CSIBM280", \ ++"CSIBM281", \ ++"CSIBM284", \ ++"CSIBM285", \ ++"CSIBM290", \ ++"CSIBM297", \ ++"CSIBM420", \ ++"CSIBM423", \ ++"CSIBM424", \ ++"CSIBM500", \ ++"CSIBM803", \ ++"CSIBM851", \ ++"CSIBM855", \ ++"CSIBM856", \ ++"CSIBM857", \ ++"CSIBM860", \ ++"CSIBM863", \ ++"CSIBM864", \ ++"CSIBM865", \ ++"CSIBM866", \ ++"CSIBM868", \ ++"CSIBM869", \ ++"CSIBM870", \ ++"CSIBM871", \ ++"CSIBM880", \ ++"CSIBM891", \ ++"CSIBM901", \ ++"CSIBM902", \ ++"CSIBM903", \ ++"CSIBM904", \ ++"CSIBM905", \ ++"CSIBM918", \ ++"CSIBM921", \ ++"CSIBM922", \ ++"CSIBM930", \ ++"CSIBM932", \ ++"CSIBM933", \ ++"CSIBM935", \ ++"CSIBM937", \ ++"CSIBM939", \ ++"CSIBM943", \ ++"CSIBM1008", \ ++"CSIBM1025", \ ++"CSIBM1026", \ ++"CSIBM1097", \ ++"CSIBM1112", \ ++"CSIBM1122", \ ++"CSIBM1123", \ ++"CSIBM1124", \ ++"CSIBM1129", \ ++"CSIBM1130", \ ++"CSIBM1132", \ ++"CSIBM1133", \ ++"CSIBM1137", \ ++"CSIBM1140", \ ++"CSIBM1141", \ ++"CSIBM1142", \ ++"CSIBM1143", \ ++"CSIBM1144", \ ++"CSIBM1145", \ ++"CSIBM1146", \ ++"CSIBM1147", \ ++"CSIBM1148", \ ++"CSIBM1149", \ ++"CSIBM1153", \ ++"CSIBM1154", \ ++"CSIBM1155", \ ++"CSIBM1156", \ ++"CSIBM1157", \ ++"CSIBM1158", \ ++"CSIBM1160", \ ++"CSIBM1161", \ ++"CSIBM1163", \ ++"CSIBM1164", \ ++"CSIBM1166", \ ++"CSIBM1167", \ ++"CSIBM1364", \ ++"CSIBM1371", \ ++"CSIBM1388", \ ++"CSIBM1390", \ ++"CSIBM1399", \ ++"CSIBM4517", \ ++"CSIBM4899", \ ++"CSIBM4909", \ ++"CSIBM4971", \ ++"CSIBM5347", \ ++"CSIBM9030", \ ++"CSIBM9066", \ ++"CSIBM9448", \ ++"CSIBM12712", \ ++"CSIBM16804", \ ++"CSIBM11621162", \ ++"CSISO4UNITEDKINGDOM", \ ++"CSISO10SWEDISH", \ ++"CSISO11SWEDISHFORNAMES", \ ++"CSISO14JISC6220RO", \ ++"CSISO15ITALIAN", \ ++"CSISO16PORTUGESE", \ ++"CSISO17SPANISH", \ ++"CSISO18GREEK7OLD", \ ++"CSISO19LATINGREEK", \ ++"CSISO21GERMAN", \ ++"CSISO25FRENCH", \ ++"CSISO27LATINGREEK1", \ ++"CSISO49INIS", \ ++"CSISO50INIS8", \ ++"CSISO51INISCYRILLIC", \ ++"CSISO58GB1988", \ ++"CSISO60DANISHNORWEGIAN", \ ++"CSISO60NORWEGIAN1", \ ++"CSISO61NORWEGIAN2", \ ++"CSISO69FRENCH", \ ++"CSISO84PORTUGUESE2", \ ++"CSISO85SPANISH2", \ ++"CSISO86HUNGARIAN", \ ++"CSISO88GREEK7", \ ++"CSISO89ASMO449", \ ++"CSISO90", \ ++"CSISO92JISC62991984B", \ ++"CSISO99NAPLPS", \ ++"CSISO103T618BIT", \ ++"CSISO111ECMACYRILLIC", \ ++"CSISO121CANADIAN1", \ ++"CSISO122CANADIAN2", \ ++"CSISO139CSN369103", \ ++"CSISO141JUSIB1002", \ ++"CSISO143IECP271", \ ++"CSISO150", \ ++"CSISO150GREEKCCITT", \ ++"CSISO151CUBA", \ ++"CSISO153GOST1976874", \ ++"CSISO646DANISH", \ ++"CSISO2022CN", \ ++"CSISO2022JP", \ ++"CSISO2022JP2", \ ++"CSISO2022KR", \ ++"CSISO2033", \ ++"CSISO5427CYRILLIC", \ ++"CSISO5427CYRILLIC1981", \ ++"CSISO5428GREEK", \ ++"CSISO10367BOX", \ ++"CSISOLATIN1", \ ++"CSISOLATIN2", \ ++"CSISOLATIN3", \ ++"CSISOLATIN4", \ ++"CSISOLATIN5", \ ++"CSISOLATIN6", \ ++"CSISOLATINARABIC", \ ++"CSISOLATINCYRILLIC", \ ++"CSISOLATINGREEK", \ ++"CSISOLATINHEBREW", \ ++"CSKOI8R", \ ++"CSKSC5636", \ ++"CSMACINTOSH", \ ++"CSNATSDANO", \ ++"CSNATSSEFI", \ ++"CSN_369103", \ ++"CSPC8CODEPAGE437", \ ++"CSPC775BALTIC", \ ++"CSPC850MULTILINGUAL", \ ++"CSPC862LATINHEBREW", \ ++"CSPCP852", \ ++"CSSHIFTJIS", \ ++"CSUCS4", \ ++"CSUNICODE", \ ++"CSWINDOWS31J", \ ++"CUBA", \ ++"CWI-2", \ ++"CWI", \ ++"CYRILLIC", \ ++"DE", \ ++"DEC-MCS", \ ++"DEC", \ ++"DECMCS", \ ++"DIN_66003", \ ++"DK", \ ++"DS2089", \ ++"DS_2089", \ ++"E13B", \ ++"EBCDIC-AT-DE-A", \ ++"EBCDIC-AT-DE", \ ++"EBCDIC-BE", \ ++"EBCDIC-BR", \ ++"EBCDIC-CA-FR", \ ++"EBCDIC-CP-AR1", \ ++"EBCDIC-CP-AR2", \ ++"EBCDIC-CP-BE", \ ++"EBCDIC-CP-CA", \ ++"EBCDIC-CP-CH", \ ++"EBCDIC-CP-DK", \ ++"EBCDIC-CP-ES", \ ++"EBCDIC-CP-FI", \ ++"EBCDIC-CP-FR", \ ++"EBCDIC-CP-GB", \ ++"EBCDIC-CP-GR", \ ++"EBCDIC-CP-HE", \ ++"EBCDIC-CP-IS", \ ++"EBCDIC-CP-IT", \ ++"EBCDIC-CP-NL", \ ++"EBCDIC-CP-NO", \ ++"EBCDIC-CP-ROECE", \ ++"EBCDIC-CP-SE", \ ++"EBCDIC-CP-TR", \ ++"EBCDIC-CP-US", \ ++"EBCDIC-CP-WT", \ ++"EBCDIC-CP-YU", \ ++"EBCDIC-CYRILLIC", \ ++"EBCDIC-DK-NO-A", \ ++"EBCDIC-DK-NO", \ ++"EBCDIC-ES-A", \ ++"EBCDIC-ES-S", \ ++"EBCDIC-ES", \ ++"EBCDIC-FI-SE-A", \ ++"EBCDIC-FI-SE", \ ++"EBCDIC-FR", \ ++"EBCDIC-GREEK", \ ++"EBCDIC-INT", \ ++"EBCDIC-INT1", \ ++"EBCDIC-IS-FRISS", \ ++"EBCDIC-IT", \ ++"EBCDIC-JP-E", \ ++"EBCDIC-JP-KANA", \ ++"EBCDIC-PT", \ ++"EBCDIC-UK", \ ++"EBCDIC-US", \ ++"EBCDICATDE", \ ++"EBCDICATDEA", \ ++"EBCDICCAFR", \ ++"EBCDICDKNO", \ ++"EBCDICDKNOA", \ ++"EBCDICES", \ ++"EBCDICESA", \ ++"EBCDICESS", \ ++"EBCDICFISE", \ ++"EBCDICFISEA", \ ++"EBCDICFR", \ ++"EBCDICISFRISS", \ ++"EBCDICIT", \ ++"EBCDICPT", \ ++"EBCDICUK", \ ++"EBCDICUS", \ ++"ECMA-114", \ ++"ECMA-118", \ ++"ECMA-128", \ ++"ECMA-CYRILLIC", \ ++"ECMACYRILLIC", \ ++"ELOT_928", \ ++"ES", \ ++"ES2", \ ++"EUC-CN", \ ++"EUC-JISX0213", \ ++"EUC-JP-MS", \ ++"EUC-JP", \ ++"EUC-KR", \ ++"EUC-TW", \ ++"EUCCN", \ ++"EUCJP-MS", \ ++"EUCJP-OPEN", \ ++"EUCJP-WIN", \ ++"EUCJP", \ ++"EUCKR", \ ++"EUCTW", \ ++"FI", \ ++"FR", \ ++"GB", \ ++"GB2312", \ ++"GB13000", \ ++"GB18030", \ ++"GBK", \ ++"GB_1988-80", \ ++"GB_198880", \ ++"GEORGIAN-ACADEMY", \ ++"GEORGIAN-PS", \ ++"GOST_19768-74", \ ++"GOST_19768", \ ++"GOST_1976874", \ ++"GREEK-CCITT", \ ++"GREEK", \ ++"GREEK7-OLD", \ ++"GREEK7", \ ++"GREEK7OLD", \ ++"GREEK8", \ ++"GREEKCCITT", \ ++"HEBREW", \ ++"HP-GREEK8", \ ++"HP-ROMAN8", \ ++"HP-ROMAN9", \ ++"HP-THAI8", \ ++"HP-TURKISH8", \ ++"HPGREEK8", \ ++"HPROMAN8", \ ++"HPROMAN9", \ ++"HPTHAI8", \ ++"HPTURKISH8", \ ++"HU", \ ++"IBM-803", \ ++"IBM-856", \ ++"IBM-901", \ ++"IBM-902", \ ++"IBM-921", \ ++"IBM-922", \ ++"IBM-930", \ ++"IBM-932", \ ++"IBM-933", \ ++"IBM-935", \ ++"IBM-937", \ ++"IBM-939", \ ++"IBM-943", \ ++"IBM-1008", \ ++"IBM-1025", \ ++"IBM-1046", \ ++"IBM-1047", \ ++"IBM-1097", \ ++"IBM-1112", \ ++"IBM-1122", \ ++"IBM-1123", \ ++"IBM-1124", \ ++"IBM-1129", \ ++"IBM-1130", \ ++"IBM-1132", \ ++"IBM-1133", \ ++"IBM-1137", \ ++"IBM-1140", \ ++"IBM-1141", \ ++"IBM-1142", \ ++"IBM-1143", \ ++"IBM-1144", \ ++"IBM-1145", \ ++"IBM-1146", \ ++"IBM-1147", \ ++"IBM-1148", \ ++"IBM-1149", \ ++"IBM-1153", \ ++"IBM-1154", \ ++"IBM-1155", \ ++"IBM-1156", \ ++"IBM-1157", \ ++"IBM-1158", \ ++"IBM-1160", \ ++"IBM-1161", \ ++"IBM-1162", \ ++"IBM-1163", \ ++"IBM-1164", \ ++"IBM-1166", \ ++"IBM-1167", \ ++"IBM-1364", \ ++"IBM-1371", \ ++"IBM-1388", \ ++"IBM-1390", \ ++"IBM-1399", \ ++"IBM-4517", \ ++"IBM-4899", \ ++"IBM-4909", \ ++"IBM-4971", \ ++"IBM-5347", \ ++"IBM-9030", \ ++"IBM-9066", \ ++"IBM-9448", \ ++"IBM-12712", \ ++"IBM-16804", \ ++"IBM037", \ ++"IBM038", \ ++"IBM256", \ ++"IBM273", \ ++"IBM274", \ ++"IBM275", \ ++"IBM277", \ ++"IBM278", \ ++"IBM280", \ ++"IBM281", \ ++"IBM284", \ ++"IBM285", \ ++"IBM290", \ ++"IBM297", \ ++"IBM367", \ ++"IBM420", \ ++"IBM423", \ ++"IBM424", \ ++"IBM437", \ ++"IBM500", \ ++"IBM775", \ ++"IBM803", \ ++"IBM813", \ ++"IBM819", \ ++"IBM848", \ ++"IBM850", \ ++"IBM851", \ ++"IBM852", \ ++"IBM855", \ ++"IBM856", \ ++"IBM857", \ ++"IBM860", \ ++"IBM861", \ ++"IBM862", \ ++"IBM863", \ ++"IBM864", \ ++"IBM865", \ ++"IBM866", \ ++"IBM866NAV", \ ++"IBM868", \ ++"IBM869", \ ++"IBM870", \ ++"IBM871", \ ++"IBM874", \ ++"IBM875", \ ++"IBM880", \ ++"IBM891", \ ++"IBM901", \ ++"IBM902", \ ++"IBM903", \ ++"IBM904", \ ++"IBM905", \ ++"IBM912", \ ++"IBM915", \ ++"IBM916", \ ++"IBM918", \ ++"IBM920", \ ++"IBM921", \ ++"IBM922", \ ++"IBM930", \ ++"IBM932", \ ++"IBM933", \ ++"IBM935", \ ++"IBM937", \ ++"IBM939", \ ++"IBM943", \ ++"IBM1004", \ ++"IBM1008", \ ++"IBM1025", \ ++"IBM1026", \ ++"IBM1046", \ ++"IBM1047", \ ++"IBM1089", \ ++"IBM1097", \ ++"IBM1112", \ ++"IBM1122", \ ++"IBM1123", \ ++"IBM1124", \ ++"IBM1129", \ ++"IBM1130", \ ++"IBM1132", \ ++"IBM1133", \ ++"IBM1137", \ ++"IBM1140", \ ++"IBM1141", \ ++"IBM1142", \ ++"IBM1143", \ ++"IBM1144", \ ++"IBM1145", \ ++"IBM1146", \ ++"IBM1147", \ ++"IBM1148", \ ++"IBM1149", \ ++"IBM1153", \ ++"IBM1154", \ ++"IBM1155", \ ++"IBM1156", \ ++"IBM1157", \ ++"IBM1158", \ ++"IBM1160", \ ++"IBM1161", \ ++"IBM1162", \ ++"IBM1163", \ ++"IBM1164", \ ++"IBM1166", \ ++"IBM1167", \ ++"IBM1364", \ ++"IBM1371", \ ++"IBM1388", \ ++"IBM1390", \ ++"IBM1399", \ ++"IBM4517", \ ++"IBM4899", \ ++"IBM4909", \ ++"IBM4971", \ ++"IBM5347", \ ++"IBM9030", \ ++"IBM9066", \ ++"IBM9448", \ ++"IBM12712", \ ++"IBM16804", \ ++"IEC_P27-1", \ ++"IEC_P271", \ ++"INIS-8", \ ++"INIS-CYRILLIC", \ ++"INIS", \ ++"INIS8", \ ++"INISCYRILLIC", \ ++"ISIRI-3342", \ ++"ISIRI3342", \ ++"ISO-2022-CN-EXT", \ ++"ISO-2022-CN", \ ++"ISO-2022-JP-2", \ ++"ISO-2022-JP-3", \ ++"ISO-2022-JP", \ ++"ISO-2022-KR", \ ++"ISO-8859-1", \ ++"ISO-8859-2", \ ++"ISO-8859-3", \ ++"ISO-8859-4", \ ++"ISO-8859-5", \ ++"ISO-8859-6", \ ++"ISO-8859-7", \ ++"ISO-8859-8", \ ++"ISO-8859-9", \ ++"ISO-8859-9E", \ ++"ISO-8859-10", \ ++"ISO-8859-11", \ ++"ISO-8859-13", \ ++"ISO-8859-14", \ ++"ISO-8859-15", \ ++"ISO-8859-16", \ ++"ISO-10646", \ ++"ISO-CELTIC", \ ++"ISO-IR-4", \ ++"ISO-IR-6", \ ++"ISO-IR-8-1", \ ++"ISO-IR-9-1", \ ++"ISO-IR-10", \ ++"ISO-IR-11", \ ++"ISO-IR-14", \ ++"ISO-IR-15", \ ++"ISO-IR-16", \ ++"ISO-IR-17", \ ++"ISO-IR-18", \ ++"ISO-IR-19", \ ++"ISO-IR-21", \ ++"ISO-IR-25", \ ++"ISO-IR-27", \ ++"ISO-IR-37", \ ++"ISO-IR-49", \ ++"ISO-IR-50", \ ++"ISO-IR-51", \ ++"ISO-IR-54", \ ++"ISO-IR-55", \ ++"ISO-IR-57", \ ++"ISO-IR-60", \ ++"ISO-IR-61", \ ++"ISO-IR-69", \ ++"ISO-IR-84", \ ++"ISO-IR-85", \ ++"ISO-IR-86", \ ++"ISO-IR-88", \ ++"ISO-IR-89", \ ++"ISO-IR-90", \ ++"ISO-IR-92", \ ++"ISO-IR-98", \ ++"ISO-IR-99", \ ++"ISO-IR-100", \ ++"ISO-IR-101", \ ++"ISO-IR-103", \ ++"ISO-IR-109", \ ++"ISO-IR-110", \ ++"ISO-IR-111", \ ++"ISO-IR-121", \ ++"ISO-IR-122", \ ++"ISO-IR-126", \ ++"ISO-IR-127", \ ++"ISO-IR-138", \ ++"ISO-IR-139", \ ++"ISO-IR-141", \ ++"ISO-IR-143", \ ++"ISO-IR-144", \ ++"ISO-IR-148", \ ++"ISO-IR-150", \ ++"ISO-IR-151", \ ++"ISO-IR-153", \ ++"ISO-IR-155", \ ++"ISO-IR-156", \ ++"ISO-IR-157", \ ++"ISO-IR-166", \ ++"ISO-IR-179", \ ++"ISO-IR-193", \ ++"ISO-IR-197", \ ++"ISO-IR-199", \ ++"ISO-IR-203", \ ++"ISO-IR-209", \ ++"ISO-IR-226", \ ++"ISO646-CA", \ ++"ISO646-CA2", \ ++"ISO646-CN", \ ++"ISO646-CU", \ ++"ISO646-DE", \ ++"ISO646-DK", \ ++"ISO646-ES", \ ++"ISO646-ES2", \ ++"ISO646-FI", \ ++"ISO646-FR", \ ++"ISO646-FR1", \ ++"ISO646-GB", \ ++"ISO646-HU", \ ++"ISO646-IT", \ ++"ISO646-JP-OCR-B", \ ++"ISO646-JP", \ ++"ISO646-KR", \ ++"ISO646-NO", \ ++"ISO646-NO2", \ ++"ISO646-PT", \ ++"ISO646-PT2", \ ++"ISO646-SE", \ ++"ISO646-SE2", \ ++"ISO646-US", \ ++"ISO646-YU", \ ++"ISO2022CN", \ ++"ISO2022CNEXT", \ ++"ISO2022JP", \ ++"ISO2022JP2", \ ++"ISO2022KR", \ ++"ISO6937", \ ++"ISO8859-1", \ ++"ISO8859-2", \ ++"ISO8859-3", \ ++"ISO8859-4", \ ++"ISO8859-5", \ ++"ISO8859-6", \ ++"ISO8859-7", \ ++"ISO8859-8", \ ++"ISO8859-9", \ ++"ISO8859-9E", \ ++"ISO8859-10", \ ++"ISO8859-11", \ ++"ISO8859-13", \ ++"ISO8859-14", \ ++"ISO8859-15", \ ++"ISO8859-16", \ ++"ISO11548-1", \ ++"ISO88591", \ ++"ISO88592", \ ++"ISO88593", \ ++"ISO88594", \ ++"ISO88595", \ ++"ISO88596", \ ++"ISO88597", \ ++"ISO88598", \ ++"ISO88599", \ ++"ISO88599E", \ ++"ISO885910", \ ++"ISO885911", \ ++"ISO885913", \ ++"ISO885914", \ ++"ISO885915", \ ++"ISO885916", \ ++"ISO_646.IRV:1991", \ ++"ISO_2033-1983", \ ++"ISO_2033", \ ++"ISO_5427-EXT", \ ++"ISO_5427", \ ++"ISO_5427:1981", \ ++"ISO_5427EXT", \ ++"ISO_5428", \ ++"ISO_5428:1980", \ ++"ISO_6937-2", \ ++"ISO_6937-2:1983", \ ++"ISO_6937", \ ++"ISO_6937:1992", \ ++"ISO_8859-1", \ ++"ISO_8859-1:1987", \ ++"ISO_8859-2", \ ++"ISO_8859-2:1987", \ ++"ISO_8859-3", \ ++"ISO_8859-3:1988", \ ++"ISO_8859-4", \ ++"ISO_8859-4:1988", \ ++"ISO_8859-5", \ ++"ISO_8859-5:1988", \ ++"ISO_8859-6", \ ++"ISO_8859-6:1987", \ ++"ISO_8859-7", \ ++"ISO_8859-7:1987", \ ++"ISO_8859-7:2003", \ ++"ISO_8859-8", \ ++"ISO_8859-8:1988", \ ++"ISO_8859-9", \ ++"ISO_8859-9:1989", \ ++"ISO_8859-9E", \ ++"ISO_8859-10", \ ++"ISO_8859-10:1992", \ ++"ISO_8859-14", \ ++"ISO_8859-14:1998", \ ++"ISO_8859-15", \ ++"ISO_8859-15:1998", \ ++"ISO_8859-16", \ ++"ISO_8859-16:2001", \ ++"ISO_9036", \ ++"ISO_10367-BOX", \ ++"ISO_10367BOX", \ ++"ISO_11548-1", \ ++"ISO_69372", \ ++"IT", \ ++"JIS_C6220-1969-RO", \ ++"JIS_C6229-1984-B", \ ++"JIS_C62201969RO", \ ++"JIS_C62291984B", \ ++"JOHAB", \ ++"JP-OCR-B", \ ++"JP", \ ++"JS", \ ++"JUS_I.B1.002", \ ++"KOI-7", \ ++"KOI-8", \ ++"KOI8-R", \ ++"KOI8-RU", \ ++"KOI8-T", \ ++"KOI8-U", \ ++"KOI8", \ ++"KOI8R", \ ++"KOI8U", \ ++"KSC5636", \ ++"L1", \ ++"L2", \ ++"L3", \ ++"L4", \ ++"L5", \ ++"L6", \ ++"L7", \ ++"L8", \ ++"L10", \ ++"LATIN-9", \ ++"LATIN-GREEK-1", \ ++"LATIN-GREEK", \ ++"LATIN1", \ ++"LATIN2", \ ++"LATIN3", \ ++"LATIN4", \ ++"LATIN5", \ ++"LATIN6", \ ++"LATIN7", \ ++"LATIN8", \ ++"LATIN10", \ ++"LATINGREEK", \ ++"LATINGREEK1", \ ++"MAC-CENTRALEUROPE", \ ++"MAC-CYRILLIC", \ ++"MAC-IS", \ ++"MAC-SAMI", \ ++"MAC-UK", \ ++"MAC", \ ++"MACCYRILLIC", \ ++"MACINTOSH", \ ++"MACIS", \ ++"MACUK", \ ++"MACUKRAINIAN", \ ++"MIK", \ ++"MS-ANSI", \ ++"MS-ARAB", \ ++"MS-CYRL", \ ++"MS-EE", \ ++"MS-GREEK", \ ++"MS-HEBR", \ ++"MS-MAC-CYRILLIC", \ ++"MS-TURK", \ ++"MS932", \ ++"MS936", \ ++"MSCP949", \ ++"MSCP1361", \ ++"MSMACCYRILLIC", \ ++"MSZ_7795.3", \ ++"MS_KANJI", \ ++"NAPLPS", \ ++"NATS-DANO", \ ++"NATS-SEFI", \ ++"NATSDANO", \ ++"NATSSEFI", \ ++"NC_NC0010", \ ++"NC_NC00-10", \ ++"NC_NC00-10:81", \ ++"NF_Z_62-010", \ ++"NF_Z_62-010_(1973)", \ ++"NF_Z_62-010_1973", \ ++"NF_Z_62010", \ ++"NF_Z_62010_1973", \ ++"NO", \ ++"NO2", \ ++"NS_4551-1", \ ++"NS_4551-2", \ ++"NS_45511", \ ++"NS_45512", \ ++"OS2LATIN1", \ ++"OSF00010001", \ ++"OSF00010002", \ ++"OSF00010003", \ ++"OSF00010004", \ ++"OSF00010005", \ ++"OSF00010006", \ ++"OSF00010007", \ ++"OSF00010008", \ ++"OSF00010009", \ ++"OSF0001000A", \ ++"OSF00010020", \ ++"OSF00010100", \ ++"OSF00010101", \ ++"OSF00010102", \ ++"OSF00010104", \ ++"OSF00010105", \ ++"OSF00010106", \ ++"OSF00030010", \ ++"OSF0004000A", \ ++"OSF0005000A", \ ++"OSF05010001", \ ++"OSF100201A4", \ ++"OSF100201A8", \ ++"OSF100201B5", \ ++"OSF100201F4", \ ++"OSF100203B5", \ ++"OSF1002011C", \ ++"OSF1002011D", \ ++"OSF1002035D", \ ++"OSF1002035E", \ ++"OSF1002035F", \ ++"OSF1002036B", \ ++"OSF1002037B", \ ++"OSF10010001", \ ++"OSF10010004", \ ++"OSF10010006", \ ++"OSF10020025", \ ++"OSF10020111", \ ++"OSF10020115", \ ++"OSF10020116", \ ++"OSF10020118", \ ++"OSF10020122", \ ++"OSF10020129", \ ++"OSF10020352", \ ++"OSF10020354", \ ++"OSF10020357", \ ++"OSF10020359", \ ++"OSF10020360", \ ++"OSF10020364", \ ++"OSF10020365", \ ++"OSF10020366", \ ++"OSF10020367", \ ++"OSF10020370", \ ++"OSF10020387", \ ++"OSF10020388", \ ++"OSF10020396", \ ++"OSF10020402", \ ++"OSF10020417", \ ++"PT", \ ++"PT2", \ ++"PT154", \ ++"R8", \ ++"R9", \ ++"RK1048", \ ++"ROMAN8", \ ++"ROMAN9", \ ++"RUSCII", \ ++"SE", \ ++"SE2", \ ++"SEN_850200_B", \ ++"SEN_850200_C", \ ++"SHIFT-JIS", \ ++"SHIFT_JIS", \ ++"SHIFT_JISX0213", \ ++"SJIS-OPEN", \ ++"SJIS-WIN", \ ++"SJIS", \ ++"SS636127", \ ++"STRK1048-2002", \ ++"ST_SEV_358-88", \ ++"T.61-8BIT", \ ++"T.61", \ ++"T.618BIT", \ ++"TCVN-5712", \ ++"TCVN", \ ++"TCVN5712-1", \ ++"TCVN5712-1:1993", \ ++"THAI8", \ ++"TIS-620", \ ++"TIS620-0", \ ++"TIS620.2529-1", \ ++"TIS620.2533-0", \ ++"TIS620", \ ++"TS-5881", \ ++"TSCII", \ ++"TURKISH8", \ ++"UCS-2", \ ++"UCS-2BE", \ ++"UCS-2LE", \ ++"UCS-4", \ ++"UCS-4BE", \ ++"UCS-4LE", \ ++"UCS2", \ ++"UCS4", \ ++"UHC", \ ++"UJIS", \ ++"UK", \ ++"UNICODE", \ ++"UNICODEBIG", \ ++"UNICODELITTLE", \ ++"US-ASCII", \ ++"US", \ ++"UTF-7", \ ++"UTF-8", \ ++"UTF-16", \ ++"UTF-16BE", \ ++"UTF-16LE", \ ++"UTF-32", \ ++"UTF-32BE", \ ++"UTF-32LE", \ ++"UTF7", \ ++"UTF8", \ ++"UTF16", \ ++"UTF16BE", \ ++"UTF16LE", \ ++"UTF32", \ ++"UTF32BE", \ ++"UTF32LE", \ ++"VISCII", \ ++"WCHAR_T", \ ++"WIN-SAMI-2", \ ++"WINBALTRIM", \ ++"WINDOWS-31J", \ ++"WINDOWS-874", \ ++"WINDOWS-936", \ ++"WINDOWS-1250", \ ++"WINDOWS-1251", \ ++"WINDOWS-1252", \ ++"WINDOWS-1253", \ ++"WINDOWS-1254", \ ++"WINDOWS-1255", \ ++"WINDOWS-1256", \ ++"WINDOWS-1257", \ ++"WINDOWS-1258", \ ++"WINSAMI2", \ ++"WS2", \ ++"YU", +diff --git a/gdb/charset.c b/gdb/charset.c +index 32eb9c3..4850fbf 100644 +--- a/gdb/charset.c ++++ b/gdb/charset.c +@@ -21,6 +21,9 @@ + #include "charset.h" + #include "gdbcmd.h" + #include "gdb_assert.h" ++#include "gdb_obstack.h" ++#include "charset-list.h" ++#include "vec.h" + + #include + #include "gdb_string.h" +@@ -33,15 +36,20 @@ + + /* How GDB's character set support works + +- GDB has two global settings: ++ GDB has three global settings: + + - The `current host character set' is the character set GDB should + use in talking to the user, and which (hopefully) the user's +- terminal knows how to display properly. ++ terminal knows how to display properly. Most users should not ++ change this. + + - The `current target character set' is the character set the + program being debugged uses. + ++ - The `current target wide character set' is the wide character set ++ the program being debugged uses, that is, the encoding used for ++ wchar_t. ++ + There are commands to set each of these, and mechanisms for + choosing reasonable default values. GDB has a global list of + character sets that it can use as its host or target character +@@ -57,118 +65,37 @@ + characters the user enters in expressions (mostly host->target + conversions), + +- and so on. +- +- Now, many of these operations are specific to a particular +- host/target character set pair. If GDB supports N character sets, +- there are N^2 possible pairs. This means that, the larger GDB's +- repertoire of character sets gets, the more expensive it gets to add +- new character sets. +- +- To make sure that GDB can do the right thing for every possible +- pairing of host and target character set, while still allowing +- GDB's repertoire to scale, we use a two-tiered approach: +- +- - We maintain a global table of "translations" --- groups of +- functions specific to a particular pair of character sets. +- +- - However, a translation can be incomplete: some functions can be +- omitted. Where there is not a translation to specify exactly +- what function to use, we provide reasonable defaults. The +- default behaviors try to use the "iconv" library functions, which +- support a wide range of character sets. However, even if iconv +- is not available, there are fallbacks to support trivial +- translations: when the host and target character sets are the +- same. */ +- +- +-/* The character set and translation structures. */ +- +- +-/* A character set GDB knows about. GDB only supports character sets +- with stateless encodings, in which every character is one byte +- long. */ +-struct charset { +- +- /* A singly-linked list of all known charsets. */ +- struct charset *next; +- +- /* The name of the character set. Comparisons on character set +- names are case-sensitive. */ +- const char *name; +- +- /* Non-zero iff this character set can be used as a host character +- set. At present, GDB basically assumes that the host character +- set is a superset of ASCII. */ +- int valid_host_charset; +- +- /* Pointers to charset-specific functions that depend only on a +- single character set, and data pointers to pass to them. */ +- int (*host_char_print_literally) (void *baton, +- int host_char); +- void *host_char_print_literally_baton; +- +- int (*target_char_to_control_char) (void *baton, +- int target_char, +- int *target_ctrl_char); +- void *target_char_to_control_char_baton; +-}; +- +- +-/* A translation from one character set to another. */ +-struct translation { +- +- /* A singly-linked list of all known translations. */ +- struct translation *next; +- +- /* This structure describes functions going from the FROM character +- set to the TO character set. Comparisons on character set names +- are case-sensitive. */ +- const char *from, *to; +- +- /* Pointers to translation-specific functions, and data pointers to +- pass to them. These pointers can be zero, indicating that GDB +- should fall back on the default behavior. We hope the default +- behavior will be correct for many from/to pairs, reducing the +- number of translations that need to be registered explicitly. */ +- +- /* TARGET_CHAR is in the `from' charset. +- Returns a string in the `to' charset. */ +- const char *(*c_target_char_has_backslash_escape) (void *baton, +- int target_char); +- void *c_target_char_has_backslash_escape_baton; +- +- /* HOST_CHAR is in the `from' charset. +- TARGET_CHAR points to a char in the `to' charset. */ +- int (*c_parse_backslash) (void *baton, int host_char, int *target_char); +- void *c_parse_backslash_baton; +- +- /* This is used for the host_char_to_target and target_char_to_host +- functions. */ +- int (*convert_char) (void *baton, int from, int *to); +- void *convert_char_baton; +-}; +- ++ and so on. ++ ++ To avoid excessive code duplication and maintenance efforts, ++ GDB simply requires a capable iconv function. Users on platforms ++ without a suitable iconv can use the GNU iconv library. */ + + + /* The global lists of character sets and translations. */ + + +-#ifndef GDB_DEFAULT_HOST_CHARSET +-#define GDB_DEFAULT_HOST_CHARSET "ISO-8859-1" +-#endif +- + #ifndef GDB_DEFAULT_TARGET_CHARSET + #define GDB_DEFAULT_TARGET_CHARSET "ISO-8859-1" + #endif + +-static const char *host_charset_name = GDB_DEFAULT_HOST_CHARSET; ++#ifndef GDB_DEFAULT_TARGET_WIDE_CHARSET ++#define GDB_DEFAULT_TARGET_WIDE_CHARSET "UCS-4" ++#endif ++ ++static const char *auto_host_charset_name = GDB_DEFAULT_HOST_CHARSET; ++static const char *host_charset_name = "auto"; + static void + show_host_charset_name (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) + { +- fprintf_filtered (file, _("The host character set is \"%s\".\n"), value); ++ if (!strcmp (value, "auto")) ++ fprintf_filtered (file, ++ _("The host character set is \"auto; currently %s\".\n"), ++ auto_host_charset_name); ++ else ++ fprintf_filtered (file, _("The host character set is \"%s\".\n"), value); + } + + static const char *target_charset_name = GDB_DEFAULT_TARGET_CHARSET; +@@ -180,1060 +107,534 @@ show_target_charset_name (struct ui_file *file, int from_tty, + value); + } + +- +-static const char *host_charset_enum[] = ++static const char *target_wide_charset_name = GDB_DEFAULT_TARGET_WIDE_CHARSET; ++static void ++show_target_wide_charset_name (struct ui_file *file, int from_tty, ++ struct cmd_list_element *c, const char *value) + { +- "ASCII", +- "ISO-8859-1", +- 0 +-}; ++ fprintf_filtered (file, _("The target wide character set is \"%s\".\n"), ++ value); ++} + +-static const char *target_charset_enum[] = ++static const char *default_charset_names[] = + { +- "ASCII", +- "ISO-8859-1", +- "EBCDIC-US", +- "IBM1047", ++ DEFAULT_CHARSET_NAMES + 0 + }; + +-/* The global list of all the charsets GDB knows about. */ +-static struct charset *all_charsets; ++static const char **charset_enum; + ++ ++/* If the target wide character set has big- or little-endian ++ variants, these are the corresponding names. */ ++static const char *target_wide_charset_be_name; ++static const char *target_wide_charset_le_name; + +-static void +-register_charset (struct charset *cs) +-{ +- struct charset **ptr; +- +- /* Put the new charset on the end, so that the list ends up in the +- same order as the registrations in the _initialize function. */ +- for (ptr = &all_charsets; *ptr; ptr = &(*ptr)->next) +- ; +- +- cs->next = 0; +- *ptr = cs; +-} +- ++/* A helper function for validate which sets the target wide big- and ++ little-endian character set names, if possible. */ + +-static struct charset * +-lookup_charset (const char *name) ++static void ++set_be_le_names (void) + { +- struct charset *cs; ++ int i, len; + +- for (cs = all_charsets; cs; cs = cs->next) +- if (! strcmp (name, cs->name)) +- return cs; ++ target_wide_charset_le_name = NULL; ++ target_wide_charset_be_name = NULL; + +- return NULL; ++ len = strlen (target_wide_charset_name); ++ for (i = 0; charset_enum[i]; ++i) ++ { ++ if (strncmp (target_wide_charset_name, charset_enum[i], len)) ++ continue; ++ if ((charset_enum[i][len] == 'B' ++ || charset_enum[i][len] == 'L') ++ && charset_enum[i][len + 1] == 'E' ++ && charset_enum[i][len + 2] == '\0') ++ { ++ if (charset_enum[i][len] == 'B') ++ target_wide_charset_be_name = charset_enum[i]; ++ else ++ target_wide_charset_le_name = charset_enum[i]; ++ } ++ } + } + +- +-/* The global list of translations. */ +-static struct translation *all_translations; +- ++/* 'Set charset', 'set host-charset', 'set target-charset', 'set ++ target-wide-charset', 'set charset' sfunc's. */ + + static void +-register_translation (struct translation *t) ++validate (void) + { +- t->next = all_translations; +- all_translations = t; +-} +- +- +-static struct translation * +-lookup_translation (const char *from, const char *to) +-{ +- struct translation *t; +- +- for (t = all_translations; t; t = t->next) +- if (! strcmp (from, t->from) +- && ! strcmp (to, t->to)) +- return t; ++ iconv_t desc; ++ const char *host_cset = host_charset (); + +- return 0; +-} +- +- +- +-/* Constructing charsets. */ +- +-/* Allocate, initialize and return a straightforward charset. +- Use this function, rather than creating the structures yourself, +- so that we can add new fields to the structure in the future without +- having to tweak all the old charset descriptions. */ +-static struct charset * +-simple_charset (const char *name, +- int valid_host_charset, +- int (*host_char_print_literally) (void *baton, int host_char), +- void *host_char_print_literally_baton, +- int (*target_char_to_control_char) (void *baton, +- int target_char, +- int *target_ctrl_char), +- void *target_char_to_control_char_baton) +-{ +- struct charset *cs = xmalloc (sizeof (*cs)); ++ desc = iconv_open (target_wide_charset_name, host_cset); ++ if (desc == (iconv_t) -1) ++ error ("Cannot convert between character sets `%s' and `%s'", ++ target_wide_charset_name, host_cset); ++ iconv_close (desc); + +- memset (cs, 0, sizeof (*cs)); +- cs->name = name; +- cs->valid_host_charset = valid_host_charset; +- cs->host_char_print_literally = host_char_print_literally; +- cs->host_char_print_literally_baton = host_char_print_literally_baton; +- cs->target_char_to_control_char = target_char_to_control_char; +- cs->target_char_to_control_char_baton = target_char_to_control_char_baton; ++ desc = iconv_open (target_charset_name, host_cset); ++ if (desc == (iconv_t) -1) ++ error ("Cannot convert between character sets `%s' and `%s'", ++ target_charset_name, host_cset); ++ iconv_close (desc); + +- return cs; ++ set_be_le_names (); + } + +- +- +-/* ASCII functions. */ +- +-static int +-ascii_print_literally (void *baton, int c) ++/* This is the sfunc for the 'set charset' command. */ ++static void ++set_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) + { +- c &= 0xff; +- +- return (0x20 <= c && c <= 0x7e); ++ /* CAREFUL: set the target charset here as well. */ ++ target_charset_name = host_charset_name; ++ validate (); + } + +- +-static int +-ascii_to_control (void *baton, int c, int *ctrl_char) ++/* 'set host-charset' command sfunc. We need a wrapper here because ++ the function needs to have a specific signature. */ ++static void ++set_host_charset_sfunc (char *charset, int from_tty, ++ struct cmd_list_element *c) + { +- *ctrl_char = (c & 037); +- return 1; ++ validate (); + } + +- +-/* ISO-8859 family functions. */ +- +- +-static int +-iso_8859_print_literally (void *baton, int c) ++/* Wrapper for the 'set target-charset' command. */ ++static void ++set_target_charset_sfunc (char *charset, int from_tty, ++ struct cmd_list_element *c) + { +- c &= 0xff; +- +- return ((0x20 <= c && c <= 0x7e) /* ascii printables */ +- || (! sevenbit_strings && 0xA0 <= c)); /* iso 8859 printables */ ++ validate (); + } + +- +-static int +-iso_8859_to_control (void *baton, int c, int *ctrl_char) ++/* Wrapper for the 'set target-wide-charset' command. */ ++static void ++set_target_wide_charset_sfunc (char *charset, int from_tty, ++ struct cmd_list_element *c) + { +- *ctrl_char = (c & 0200) | (c & 037); +- return 1; ++ validate (); + } + +- +-/* Construct an ISO-8859-like character set. */ +-static struct charset * +-iso_8859_family_charset (const char *name) ++/* sfunc for the 'show charset' command. */ ++static void ++show_charset (struct ui_file *file, int from_tty, struct cmd_list_element *c, ++ const char *name) + { +- return simple_charset (name, 1, +- iso_8859_print_literally, 0, +- iso_8859_to_control, 0); ++ show_host_charset_name (file, from_tty, c, host_charset_name); ++ show_target_charset_name (file, from_tty, c, target_charset_name); ++ show_target_wide_charset_name (file, from_tty, c, target_wide_charset_name); + } + +- + +-/* EBCDIC family functions. */ +- +- +-static int +-ebcdic_print_literally (void *baton, int c) +-{ +- c &= 0xff; +- +- return (64 <= c && c <= 254); +-} +- ++/* Accessor functions. */ + +-static int +-ebcdic_to_control (void *baton, int c, int *ctrl_char) ++const char * ++host_charset (void) + { +- /* There are no control character equivalents in EBCDIC. Use +- numeric escapes. */ +- return 0; ++ if (!strcmp (host_charset_name, "auto")) ++ return auto_host_charset_name; ++ return host_charset_name; + } + +- +-/* Construct an EBCDIC-like character set. */ +-static struct charset * +-ebcdic_family_charset (const char *name) ++const char * ++target_charset (void) + { +- return simple_charset (name, 0, +- ebcdic_print_literally, 0, +- ebcdic_to_control, 0); ++ return target_charset_name; + } +- +- +- +- +- +-/* Fallback functions using iconv. */ +- +-#if defined(HAVE_ICONV) + +-struct cached_iconv { +- struct charset *from, *to; +- iconv_t i; +-}; +- +- +-/* Make sure the iconv cache *CI contains an iconv descriptor +- translating from FROM to TO. If it already does, fine; otherwise, +- close any existing descriptor, and open up a new one. On success, +- return zero; on failure, return -1 and set errno. */ +-static int +-check_iconv_cache (struct cached_iconv *ci, +- struct charset *from, +- struct charset *to) ++const char * ++target_wide_charset (void) + { +- iconv_t i; +- +- /* Does the cached iconv descriptor match the conversion we're trying +- to do now? */ +- if (ci->from == from +- && ci->to == to +- && ci->i != (iconv_t) 0) +- return 0; +- +- /* It doesn't. If we actually had any iconv descriptor open at +- all, close it now. */ +- if (ci->i != (iconv_t) 0) ++ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) + { +- i = ci->i; +- ci->i = (iconv_t) 0; +- +- if (iconv_close (i) == -1) +- error (_("Error closing `iconv' descriptor for " +- "`%s'-to-`%s' character conversion: %s"), +- ci->from->name, ci->to->name, safe_strerror (errno)); ++ if (target_wide_charset_be_name) ++ return target_wide_charset_be_name; + } +- +- /* Open a new iconv descriptor for the required conversion. */ +- i = iconv_open (to->name, from->name); +- if (i == (iconv_t) -1) +- return -1; +- +- ci->i = i; +- ci->from = from; +- ci->to = to; +- +- return 0; +-} +- +- +-/* Convert FROM_CHAR using the cached iconv conversion *CI. Return +- non-zero if the conversion was successful, zero otherwise. */ +-static int +-cached_iconv_convert (struct cached_iconv *ci, int from_char, int *to_char) +-{ +- char from; +- ICONV_CONST char *from_ptr = &from; +- char to, *to_ptr = &to; +- size_t from_left = sizeof (from), to_left = sizeof (to); +- +- gdb_assert (ci->i != (iconv_t) 0); +- +- from = from_char; +- if (iconv (ci->i, &from_ptr, &from_left, &to_ptr, &to_left) +- == (size_t) -1) ++ else + { +- /* These all suggest that the input or output character sets +- have multi-byte encodings of some characters, which means +- it's unsuitable for use as a GDB character set. We should +- never have selected it. */ +- gdb_assert (errno != E2BIG && errno != EINVAL); +- +- /* This suggests a bug in the code managing *CI. */ +- gdb_assert (errno != EBADF); +- +- /* This seems to mean that there is no equivalent character in +- the `to' character set. */ +- if (errno == EILSEQ) +- return 0; +- +- /* Anything else is mysterious. */ +- internal_error (__FILE__, __LINE__, +- _("Error converting character `%d' from `%s' to `%s' " +- "character set: %s"), +- from_char, ci->from->name, ci->to->name, +- safe_strerror (errno)); ++ if (target_wide_charset_le_name) ++ return target_wide_charset_le_name; + } + +- /* If the pointers weren't advanced across the input, that also +- suggests something was wrong. */ +- gdb_assert (from_left == 0 && to_left == 0); +- +- *to_char = (unsigned char) to; +- return 1; ++ return target_wide_charset_name; + } + +- +-static void +-register_iconv_charsets (void) +-{ +- /* Here we should check whether various character sets were +- recognized by the local iconv implementation. +- +- The first implementation registered a bunch of character sets +- recognized by iconv, but then we discovered that iconv on Solaris +- and iconv on GNU/Linux had no character sets in common. So we +- replaced them with the hard-coded tables that appear later in the +- file. */ +-} +- +-#endif /* defined (HAVE_ICONV) */ +- + +-/* Fallback routines for systems without iconv. */ ++/* Host character set management. For the time being, we assume that ++ the host character set is some superset of ASCII. */ + +-#if ! defined (HAVE_ICONV) +-struct cached_iconv { char nothing; }; +- +-static int +-check_iconv_cache (struct cached_iconv *ci, +- struct charset *from, +- struct charset *to) ++char ++host_letter_to_control_character (char c) + { +- errno = EINVAL; +- return -1; ++ if (c == '?') ++ return 0177; ++ return c & 0237; + } + +-static int +-cached_iconv_convert (struct cached_iconv *ci, int from_char, int *to_char) +-{ +- /* This function should never be called. */ +- gdb_assert (0); +-} ++/* Convert a host character, C, to its hex value. C must already have ++ been validated using isxdigit. */ + +-static void +-register_iconv_charsets (void) +-{ +-} +- +-#endif /* ! defined(HAVE_ICONV) */ +- +- +-/* Default trivial conversion functions. */ +- +-static int +-identity_either_char_to_other (void *baton, int either_char, int *other_char) ++int ++host_hex_value (char c) + { +- *other_char = either_char; +- return 1; ++ if (isdigit (c)) ++ return c - '0'; ++ if (c >= 'a' && c <= 'f') ++ return 10 + c - 'a'; ++ gdb_assert (c >= 'A' && c <= 'F'); ++ return 10 + c - 'A'; + } + +- + +-/* Default non-trivial conversion functions. */ +- +- +-static char backslashable[] = "abfnrtv"; +-static char *backslashed[] = {"a", "b", "f", "n", "r", "t", "v", "0"}; +-static char represented[] = "\a\b\f\n\r\t\v"; +- +- +-/* Translate TARGET_CHAR into the host character set, and see if it +- matches any of our standard escape sequences. */ +-static const char * +-default_c_target_char_has_backslash_escape (void *baton, int target_char) +-{ +- int host_char; +- const char *ix; +- +- /* If target_char has no equivalent in the host character set, +- assume it doesn't have a backslashed form. */ +- if (! target_char_to_host (target_char, &host_char)) +- return NULL; +- +- ix = strchr (represented, host_char); +- if (ix) +- return backslashed[ix - represented]; +- else +- return NULL; +-} +- +- +-/* Translate the backslash the way we would in the host character set, +- and then try to translate that into the target character set. */ +-static int +-default_c_parse_backslash (void *baton, int host_char, int *target_char) +-{ +- const char *ix; +- +- ix = strchr (backslashable, host_char); +- +- if (! ix) +- return 0; +- else +- return host_char_to_target (represented[ix - backslashable], +- target_char); +-} ++/* Public character management functions. */ + ++/* A cleanup function which is run to close an iconv descriptor. */ + +-/* Convert using a cached iconv descriptor. */ +-static int +-iconv_convert (void *baton, int from_char, int *to_char) ++static void ++cleanup_iconv (void *p) + { +- struct cached_iconv *ci = baton; +- return cached_iconv_convert (ci, from_char, to_char); ++ iconv_t *descp = p; ++ iconv_close (*descp); + } + ++void ++convert_between_encodings (const char *from, const char *to, ++ const gdb_byte *bytes, unsigned int num_bytes, ++ int width, struct obstack *output, ++ enum transliterations translit) ++{ ++ iconv_t desc; ++ struct cleanup *cleanups; ++ size_t inleft; ++ char *inp; ++ unsigned int space_request; ++ ++ /* Often, the host and target charsets will be the same. */ ++ if (!strcmp (from, to)) ++ { ++ obstack_grow (output, bytes, num_bytes); ++ return; ++ } + +- +-/* Conversion tables. */ +- +- +-/* I'd much rather fall back on iconv whenever possible. But the +- character set names you use with iconv aren't standardized at all, +- a lot of platforms have really meager character set coverage, etc. +- I wanted to have at least something we could use to exercise the +- test suite on all platforms. +- +- In the long run, we should have a configure-time process explore +- somehow which character sets the host platform supports, and some +- arrangement that allows GDB users to use platform-indepedent names +- for character sets. */ +- +- +-/* We generated these tables using iconv on a GNU/Linux machine. */ +- +- +-static int ascii_to_iso_8859_1_table[] = { +- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ +- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ +- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 80 */ +- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 96 */ +- 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 112 */ +- 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 128 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +-}; +- +- +-static int ascii_to_ebcdic_us_table[] = { +- 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ +- 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ +- 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ +- 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ +- 215,216,217,226,227,228,229,230,231,232,233, -1,224, -1, -1,109, /* 96 */ +- 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ +- 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +-}; +- +- +-static int ascii_to_ibm1047_table[] = { +- 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ +- 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ +- 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ +- 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ +- 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109, /* 96 */ +- 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ +- 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +-}; +- +- +-static int iso_8859_1_to_ascii_table[] = { +- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ +- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ +- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 80 */ +- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 96 */ +- 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 112 */ +- 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 128 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +-}; +- +- +-static int iso_8859_1_to_ebcdic_us_table[] = { +- 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ +- 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ +- 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ +- 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ +- 215,216,217,226,227,228,229,230,231,232,233, -1,224, -1, -1,109, /* 96 */ +- 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ +- 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ +- 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, /* 144 */ +- 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255, /* 160 */ +- -1, -1, 74, -1, -1, -1,106, -1, -1, -1, -1, -1, 95, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 240 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 256 */ +-}; +- +- +-static int iso_8859_1_to_ibm1047_table[] = { +- 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, /* 32 */ +- 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, /* 48 */ +- 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, /* 64 */ +- 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, /* 80 */ +- 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109, /* 96 */ +- 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, /* 112 */ +- 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, /* 128 */ +- 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, /* 144 */ +- 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255, /* 160 */ +- 65,170, 74,177,159,178,106,181,187,180,154,138,176,202,175,188, /* 176 */ +- 144,143,234,250,190,160,182,179,157,218,155,139,183,184,185,171, /* 192 */ +- 100,101, 98,102, 99,103,158,104,116,113,114,115,120,117,118,119, /* 208 */ +- 172,105,237,238,235,239,236,191,128,253,254,251,252,186,174, 89, /* 224 */ +- 68, 69, 66, 70, 67, 71,156, 72, 84, 81, 82, 83, 88, 85, 86, 87, /* 240 */ +- 140, 73,205,206,203,207,204,225,112,221,222,219,220,141,142,223 /* 256 */ +-}; +- +- +-static int ebcdic_us_to_ascii_table[] = { +- 0, 1, 2, 3, -1, 9, -1,127, -1, -1, -1, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, -1, -1, 8, -1, 24, 25, -1, -1, 28, 29, 30, 31, /* 32 */ +- -1, -1, -1, -1, -1, 10, 23, 27, -1, -1, -1, -1, -1, 5, 6, 7, /* 48 */ +- -1, -1, 22, -1, -1, -1, -1, 4, -1, -1, -1, -1, 20, 21, -1, 26, /* 64 */ +- 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 60, 40, 43,124, /* 80 */ +- 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59, -1, /* 96 */ +- 45, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 37, 95, 62, 63, /* 112 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ +- -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ +- 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ +- 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1 /* 256 */ +-}; +- +- +-static int ebcdic_us_to_iso_8859_1_table[] = { +- 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, /* 32 */ +- 128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, /* 48 */ +- 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, /* 64 */ +- 32, -1, -1, -1, -1, -1, -1, -1, -1, -1,162, 46, 60, 40, 43,124, /* 80 */ +- 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59,172, /* 96 */ +- 45, 47, -1, -1, -1, -1, -1, -1, -1, -1,166, 44, 37, 95, 62, 63, /* 112 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ +- -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ +- 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ +- 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,159 /* 256 */ +-}; +- +- +-static int ebcdic_us_to_ibm1047_table[] = { +- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ +- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ +- 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, /* 80 */ +- 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, 92, 93, 94,176, /* 96 */ +- 96, 97, -1, -1, -1, -1, -1, -1, -1, -1,106,107,108,109,110,111, /* 112 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1,121,122,123,124,125,126,127, /* 128 */ +- -1,129,130,131,132,133,134,135,136,137, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1,145,146,147,148,149,150,151,152,153, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1,161,162,163,164,165,166,167,168,169, -1, -1, -1, -1, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- 192,193,194,195,196,197,198,199,200,201, -1, -1, -1, -1, -1, -1, /* 208 */ +- 208,209,210,211,212,213,214,215,216,217, -1, -1, -1, -1, -1, -1, /* 224 */ +- 224, -1,226,227,228,229,230,231,232,233, -1, -1, -1, -1, -1, -1, /* 240 */ +- 240,241,242,243,244,245,246,247,248,249, -1, -1, -1, -1, -1,255 /* 256 */ +-}; +- +- +-static int ibm1047_to_ascii_table[] = { +- 0, 1, 2, 3, -1, 9, -1,127, -1, -1, -1, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, -1, -1, 8, -1, 24, 25, -1, -1, 28, 29, 30, 31, /* 32 */ +- -1, -1, -1, -1, -1, 10, 23, 27, -1, -1, -1, -1, -1, 5, 6, 7, /* 48 */ +- -1, -1, 22, -1, -1, -1, -1, 4, -1, -1, -1, -1, 20, 21, -1, 26, /* 64 */ +- 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 60, 40, 43,124, /* 80 */ +- 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 36, 42, 41, 59, 94, /* 96 */ +- 45, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 37, 95, 62, 63, /* 112 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, 58, 35, 64, 39, 61, 34, /* 128 */ +- -1, 97, 98, 99,100,101,102,103,104,105, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1,106,107,108,109,110,111,112,113,114, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1,126,115,116,117,118,119,120,121,122, -1, -1, -1, 91, -1, -1, /* 176 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, /* 192 */ +- 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, -1, -1, -1, -1, -1, /* 208 */ +- 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, -1, -1, -1, -1, /* 224 */ +- 92, -1, 83, 84, 85, 86, 87, 88, 89, 90, -1, -1, -1, -1, -1, -1, /* 240 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1 /* 256 */ +-}; +- +- +-static int ibm1047_to_iso_8859_1_table[] = { +- 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, /* 32 */ +- 128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, /* 48 */ +- 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, /* 64 */ +- 32,160,226,228,224,225,227,229,231,241,162, 46, 60, 40, 43,124, /* 80 */ +- 38,233,234,235,232,237,238,239,236,223, 33, 36, 42, 41, 59, 94, /* 96 */ +- 45, 47,194,196,192,193,195,197,199,209,166, 44, 37, 95, 62, 63, /* 112 */ +- 248,201,202,203,200,205,206,207,204, 96, 58, 35, 64, 39, 61, 34, /* 128 */ +- 216, 97, 98, 99,100,101,102,103,104,105,171,187,240,253,254,177, /* 144 */ +- 176,106,107,108,109,110,111,112,113,114,170,186,230,184,198,164, /* 160 */ +- 181,126,115,116,117,118,119,120,121,122,161,191,208, 91,222,174, /* 176 */ +- 172,163,165,183,169,167,182,188,189,190,221,168,175, 93,180,215, /* 192 */ +- 123, 65, 66, 67, 68, 69, 70, 71, 72, 73,173,244,246,242,243,245, /* 208 */ +- 125, 74, 75, 76, 77, 78, 79, 80, 81, 82,185,251,252,249,250,255, /* 224 */ +- 92,247, 83, 84, 85, 86, 87, 88, 89, 90,178,212,214,210,211,213, /* 240 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,179,219,220,217,218,159 /* 256 */ +-}; +- +- +-static int ibm1047_to_ebcdic_us_table[] = { +- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ +- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 32 */ +- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 48 */ +- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 64 */ +- 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, 75, 76, 77, 78, 79, /* 80 */ +- 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 91, 92, 93, 94, -1, /* 96 */ +- 96, 97, -1, -1, -1, -1, -1, -1, -1, -1,106,107,108,109,110,111, /* 112 */ +- -1, -1, -1, -1, -1, -1, -1, -1, -1,121,122,123,124,125,126,127, /* 128 */ +- -1,129,130,131,132,133,134,135,136,137, -1, -1, -1, -1, -1, -1, /* 144 */ +- -1,145,146,147,148,149,150,151,152,153, -1, -1, -1, -1, -1, -1, /* 160 */ +- -1,161,162,163,164,165,166,167,168,169, -1, -1, -1, -1, -1, -1, /* 176 */ +- 95, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 */ +- 192,193,194,195,196,197,198,199,200,201, -1, -1, -1, -1, -1, -1, /* 208 */ +- 208,209,210,211,212,213,214,215,216,217, -1, -1, -1, -1, -1, -1, /* 224 */ +- 224, -1,226,227,228,229,230,231,232,233, -1, -1, -1, -1, -1, -1, /* 240 */ +- 240,241,242,243,244,245,246,247,248,249, -1, -1, -1, -1, -1,255 /* 256 */ +-}; ++ desc = iconv_open (to, from); ++ if (desc == (iconv_t) -1) ++ perror_with_name ("Converting character sets"); ++ cleanups = make_cleanup (cleanup_iconv, &desc); + ++ inleft = num_bytes; ++ inp = (char *) bytes; + +-static int +-table_convert_char (void *baton, int from, int *to) +-{ +- int *table = (int *) baton; ++ space_request = num_bytes; + +- if (0 <= from && from <= 255 +- && table[from] != -1) ++ while (inleft > 0) + { +- *to = table[from]; +- return 1; ++ char *outp; ++ size_t outleft, r; ++ int old_size; ++ ++ old_size = obstack_object_size (output); ++ obstack_blank (output, space_request); ++ ++ outp = obstack_base (output) + old_size; ++ outleft = space_request; ++ ++ r = iconv (desc, &inp, &inleft, &outp, &outleft); ++ ++ /* Now make sure that the object on the obstack only includes ++ bytes we have converted. */ ++ obstack_blank (output, - (int) outleft); ++ ++ if (r == (size_t) -1) ++ { ++ switch (errno) ++ { ++ case EILSEQ: ++ { ++ int i; ++ ++ /* Invalid input sequence. */ ++ if (translit == translit_none) ++ error (_("Could not convert character to `%s' character set"), ++ to); ++ ++ /* We emit escape sequence for the bytes, skip them, ++ and try again. */ ++ for (i = 0; i < width; ++i) ++ { ++ char octal[5]; ++ ++ sprintf (octal, "\\%.3o", *inp & 0xff); ++ obstack_grow_str (output, octal); ++ ++ ++inp; ++ --inleft; ++ } ++ } ++ break; ++ ++ case E2BIG: ++ /* We ran out of space in the output buffer. Make it ++ bigger next time around. */ ++ space_request *= 2; ++ break; ++ ++ case EINVAL: ++ /* Incomplete input sequence. FIXME: ought to report this ++ to the caller somehow. */ ++ inleft = 0; ++ break; ++ ++ default: ++ perror_with_name ("Internal error while converting character sets"); ++ } ++ } + } +- else +- return 0; +-} +- + +-static struct translation * +-table_translation (const char *from, const char *to, int *table, +- const char *(*c_target_char_has_backslash_escape) +- (void *baton, int target_char), +- void *c_target_char_has_backslash_escape_baton, +- int (*c_parse_backslash) (void *baton, +- int host_char, +- int *target_char), +- void *c_parse_backslash_baton) +-{ +- struct translation *t = xmalloc (sizeof (*t)); +- +- memset (t, 0, sizeof (*t)); +- t->from = from; +- t->to = to; +- t->c_target_char_has_backslash_escape = c_target_char_has_backslash_escape; +- t->c_target_char_has_backslash_escape_baton +- = c_target_char_has_backslash_escape_baton; +- t->c_parse_backslash = c_parse_backslash; +- t->c_parse_backslash_baton = c_parse_backslash_baton; +- t->convert_char = table_convert_char; +- t->convert_char_baton = (void *) table; +- +- return t; ++ do_cleanups (cleanups); + } + +- +-static struct translation * +-simple_table_translation (const char *from, const char *to, int *table) +-{ +- return table_translation (from, to, table, 0, 0, 0, 0); +-} +- +- + +-/* Setting and retrieving the host and target charsets. */ +- +- +-/* The current host and target character sets. */ +-static struct charset *current_host_charset, *current_target_charset; +- +-/* The current functions and batons we should use for the functions in +- charset.h. */ +- +-static const char *(*c_target_char_has_backslash_escape_func) +- (void *baton, int target_char); +-static void *c_target_char_has_backslash_escape_baton; +- +-static int (*c_parse_backslash_func) (void *baton, +- int host_char, +- int *target_char); +-static void *c_parse_backslash_baton; +- +-static int (*host_char_to_target_func) (void *baton, +- int host_char, +- int *target_char); +-static void *host_char_to_target_baton; +- +-static int (*target_char_to_host_func) (void *baton, +- int target_char, +- int *host_char); +-static void *target_char_to_host_baton; + +- +-/* Cached iconv conversions, that might be useful to fallback +- routines. */ +-static struct cached_iconv cached_iconv_host_to_target; +-static struct cached_iconv cached_iconv_target_to_host; +- +- +-/* Charset structures manipulation functions. */ +- +-static struct charset * +-lookup_charset_or_error (const char *name) ++/* An iterator that returns host wchar_t's from a target string. */ ++struct wchar_iterator + { +- struct charset *cs = lookup_charset (name); ++ /* The underlying iconv descriptor. */ ++ iconv_t desc; + +- if (! cs) +- error (_("GDB doesn't know of any character set named `%s'."), name); ++ /* The input string. This is updated as convert characters. */ ++ char *input; ++ /* The number of bytes remaining in the input. */ ++ size_t bytes; + +- return cs; +-} ++ /* The width of an input character. */ ++ size_t width; + +-static void +-check_valid_host_charset (struct charset *cs) +-{ +- if (! cs->valid_host_charset) +- error (_("GDB can't use `%s' as its host character set."), cs->name); +-} ++ /* The output buffer and its size. */ ++ wchar_t *out; ++ size_t out_size; ++}; + +-/* Set the host and target character sets to HOST and TARGET. */ +-static void +-set_host_and_target_charsets (struct charset *host, struct charset *target) ++/* Create a new iterator. */ ++struct wchar_iterator * ++make_wchar_iterator (const gdb_byte *input, size_t bytes, const char *charset, ++ size_t width) + { +- struct translation *h2t, *t2h; +- +- /* If they're not both initialized yet, then just do nothing for +- now. As soon as we're done running our initialize function, +- everything will be initialized. */ +- if (! host || ! target) +- { +- current_host_charset = host; +- current_target_charset = target; +- return; +- } +- +- h2t = lookup_translation (host->name, target->name); +- t2h = lookup_translation (target->name, host->name); +- +- /* If the translations don't provide conversion functions, make sure +- iconv can back them up. Do this *before* modifying any state. */ +- if (host != target) +- { +- if (! h2t || ! h2t->convert_char) +- { +- if (check_iconv_cache (&cached_iconv_host_to_target, host, target) +- < 0) +- error (_("GDB can't convert from the `%s' character set to `%s'."), +- host->name, target->name); +- } +- if (! t2h || ! t2h->convert_char) +- { +- if (check_iconv_cache (&cached_iconv_target_to_host, target, host) +- < 0) +- error (_("GDB can't convert from the `%s' character set to `%s'."), +- target->name, host->name); +- } +- } +- +- if (t2h && t2h->c_target_char_has_backslash_escape) +- { +- c_target_char_has_backslash_escape_func +- = t2h->c_target_char_has_backslash_escape; +- c_target_char_has_backslash_escape_baton +- = t2h->c_target_char_has_backslash_escape_baton; +- } +- else +- c_target_char_has_backslash_escape_func +- = default_c_target_char_has_backslash_escape; +- +- if (h2t && h2t->c_parse_backslash) +- { +- c_parse_backslash_func = h2t->c_parse_backslash; +- c_parse_backslash_baton = h2t->c_parse_backslash_baton; +- } +- else +- c_parse_backslash_func = default_c_parse_backslash; +- +- if (h2t && h2t->convert_char) +- { +- host_char_to_target_func = h2t->convert_char; +- host_char_to_target_baton = h2t->convert_char_baton; +- } +- else if (host == target) +- host_char_to_target_func = identity_either_char_to_other; +- else +- { +- host_char_to_target_func = iconv_convert; +- host_char_to_target_baton = &cached_iconv_host_to_target; +- } ++ struct wchar_iterator *result; ++ iconv_t desc; + +- if (t2h && t2h->convert_char) +- { +- target_char_to_host_func = t2h->convert_char; +- target_char_to_host_baton = t2h->convert_char_baton; +- } +- else if (host == target) +- target_char_to_host_func = identity_either_char_to_other; +- else +- { +- target_char_to_host_func = iconv_convert; +- target_char_to_host_baton = &cached_iconv_target_to_host; +- } ++ desc = iconv_open ("wchar_t", charset); ++ if (desc == (iconv_t) -1) ++ perror_with_name ("Converting character sets"); + +- current_host_charset = host; +- current_target_charset = target; +-} +- +-/* Do the real work of setting the host charset. */ +-static void +-set_host_charset (const char *charset) +-{ +- struct charset *cs = lookup_charset_or_error (charset); +- check_valid_host_charset (cs); +- set_host_and_target_charsets (cs, current_target_charset); +-} ++ result = XNEW (struct wchar_iterator); ++ result->desc = desc; ++ result->input = (char *) input; ++ result->bytes = bytes; ++ result->width = width; + +-/* Do the real work of setting the target charset. */ +-static void +-set_target_charset (const char *charset) +-{ +- struct charset *cs = lookup_charset_or_error (charset); ++ result->out = XNEW (wchar_t); ++ result->out_size = 1; + +- set_host_and_target_charsets (current_host_charset, cs); ++ return result; + } + +- +-/* 'Set charset', 'set host-charset', 'set target-charset', 'show +- charset' sfunc's. */ +- +-/* This is the sfunc for the 'set charset' command. */ + static void +-set_charset_sfunc (char *charset, int from_tty, struct cmd_list_element *c) ++do_cleanup_iterator (void *p) + { +- struct charset *cs = lookup_charset_or_error (host_charset_name); +- check_valid_host_charset (cs); +- /* CAREFUL: set the target charset here as well. */ +- target_charset_name = host_charset_name; +- set_host_and_target_charsets (cs, cs); +-} ++ struct wchar_iterator *iter = p; + +-/* 'set host-charset' command sfunc. We need a wrapper here because +- the function needs to have a specific signature. */ +-static void +-set_host_charset_sfunc (char *charset, int from_tty, +- struct cmd_list_element *c) +-{ +- set_host_charset (host_charset_name); ++ iconv_close (iter->desc); ++ xfree (iter->out); ++ xfree (iter); + } + +-/* Wrapper for the 'set target-charset' command. */ +-static void +-set_target_charset_sfunc (char *charset, int from_tty, +- struct cmd_list_element *c) ++struct cleanup * ++make_cleanup_wchar_iterator (struct wchar_iterator *iter) + { +- set_target_charset (target_charset_name); ++ return make_cleanup (do_cleanup_iterator, iter); + } + +-/* sfunc for the 'show charset' command. */ +-static void +-show_charset (struct ui_file *file, int from_tty, struct cmd_list_element *c, +- const char *name) +-{ +- if (current_host_charset == current_target_charset) +- fprintf_filtered (file, +- _("The current host and target character set is `%s'.\n"), +- host_charset ()); +- else ++int ++wchar_iterate (struct wchar_iterator *iter, ++ enum wchar_iterate_result *out_result, ++ wchar_t **out_chars, ++ const gdb_byte **ptr, ++ size_t *len) ++{ ++ size_t out_request; ++ ++ /* Try to convert some characters. At first we try to convert just ++ a single character. The reason for this is that iconv does not ++ necessarily update its outgoing arguments when it encounters an ++ invalid input sequence -- but we want to reliably report this to ++ our caller so it can emit an escape sequence. */ ++ out_request = 1; ++ while (iter->bytes > 0) + { +- fprintf_filtered (file, _("The current host character set is `%s'.\n"), +- host_charset ()); +- fprintf_filtered (file, _("The current target character set is `%s'.\n"), +- target_charset ()); ++ char *outptr = (char *) &iter->out[0]; ++ char *orig_inptr = iter->input; ++ size_t orig_in = iter->bytes; ++ size_t out_avail = out_request * sizeof (wchar_t); ++ size_t num; ++ wchar_t result; ++ ++ size_t r = iconv (iter->desc, (char **) &iter->input, &iter->bytes, ++ &outptr, &out_avail); ++ if (r == (size_t) -1) ++ { ++ switch (errno) ++ { ++ case EILSEQ: ++ /* Invalid input sequence. Skip it, and let the caller ++ know about it. */ ++ *out_result = wchar_iterate_invalid; ++ *ptr = iter->input; ++ *len = iter->width; ++ iter->input += iter->width; ++ iter->bytes -= iter->width; ++ return 0; ++ ++ case E2BIG: ++ /* We ran out of space. We still might have converted a ++ character; if so, return it. Otherwise, grow the ++ buffer and try again. */ ++ if (out_avail < out_request * sizeof (wchar_t)) ++ break; ++ ++ ++out_request; ++ if (out_request > iter->out_size) ++ { ++ iter->out_size = out_request; ++ iter->out = xrealloc (iter->out, ++ out_request * sizeof (wchar_t)); ++ } ++ continue; ++ ++ case EINVAL: ++ /* Incomplete input sequence. Let the caller know, and ++ arrange for future calls to see EOF. */ ++ *out_result = wchar_iterate_incomplete; ++ *ptr = iter->input; ++ *len = iter->bytes; ++ iter->bytes = 0; ++ return 0; ++ ++ default: ++ perror_with_name ("Internal error while converting character sets"); ++ } ++ } ++ ++ /* We converted something. */ ++ num = out_request - out_avail / sizeof (wchar_t); ++ *out_result = wchar_iterate_ok; ++ *out_chars = iter->out; ++ *ptr = orig_inptr; ++ *len = orig_in - iter->bytes; ++ return num; + } ++ ++ /* Really done. */ ++ *out_result = wchar_iterate_eof; ++ return -1; + } + + +-/* Accessor functions. */ ++/* The charset.c module initialization function. */ + +-const char * +-host_charset (void) +-{ +- return current_host_charset->name; +-} ++extern initialize_file_ftype _initialize_charset; /* -Wmissing-prototype */ + +-const char * +-target_charset (void) +-{ +- return current_target_charset->name; +-} ++typedef char *char_ptr; ++DEF_VEC_P (char_ptr); + ++static VEC (char_ptr) *charsets; + +- +-/* Public character management functions. */ ++#ifdef HAVE_ICONVLIST + ++/* A helper function that adds some character sets to the vector of ++ all character sets. This is a callback function for iconvlist. */ + +-const char * +-c_target_char_has_backslash_escape (int target_char) ++static int ++add_one (unsigned int count, const char *const *names, void *data) + { +- return ((*c_target_char_has_backslash_escape_func) +- (c_target_char_has_backslash_escape_baton, target_char)); +-} ++ unsigned int i; + ++ for (i = 0; i < count; ++i) ++ VEC_safe_push (char_ptr, charsets, xstrdup (names[i])); + +-int +-c_parse_backslash (int host_char, int *target_char) +-{ +- return (*c_parse_backslash_func) (c_parse_backslash_baton, +- host_char, target_char); ++ return 0; + } + +- +-int +-host_char_print_literally (int host_char) ++static void ++find_charset_names (void) + { +- return ((*current_host_charset->host_char_print_literally) +- (current_host_charset->host_char_print_literally_baton, +- host_char)); ++ iconvlist (add_one, NULL); ++ VEC_safe_push (char_ptr, charsets, NULL); + } + ++#else + +-int +-target_char_to_control_char (int target_char, int *target_ctrl_char) ++static void ++find_charset_names (void) + { +- return ((*current_target_charset->target_char_to_control_char) +- (current_target_charset->target_char_to_control_char_baton, +- target_char, target_ctrl_char)); +-} ++ FILE *in; + ++ in = popen ("iconv -l", "r"); ++ /* It is ok to ignore errors; we'll fall back on a default. */ ++ if (!in) ++ return; + +-int +-host_char_to_target (int host_char, int *target_char) +-{ +- return ((*host_char_to_target_func) +- (host_char_to_target_baton, host_char, target_char)); +-} ++ /* POSIX says that iconv -l uses an unspecified format. We parse ++ the glibc format; feel free to add others as needed. */ ++ while (!feof (in)) ++ { ++ /* The size of buf is chosen arbitrarily. A character set name ++ longer than this would not be very nice. */ ++ char buf[80]; ++ int len; ++ char *r = fgets (buf, sizeof (buf), in); ++ if (!r) ++ break; ++ len = strlen (r); ++ if (len <= 3) ++ continue; ++ if (buf[len - 2] == '/' && buf[len - 3] == '/') ++ buf[len - 3] = '\0'; ++ VEC_safe_push (char_ptr, charsets, xstrdup (buf)); ++ } + ++ pclose (in); + +-int +-target_char_to_host (int target_char, int *host_char) +-{ +- return ((*target_char_to_host_func) +- (target_char_to_host_baton, target_char, host_char)); ++ VEC_safe_push (char_ptr, charsets, NULL); + } + +- +- +-/* The charset.c module initialization function. */ +- +-extern initialize_file_ftype _initialize_charset; /* -Wmissing-prototype */ ++#endif /* HAVE_ICONVLIST */ + + void + _initialize_charset (void) + { + struct cmd_list_element *new_cmd; + +- /* Register all the character set GDB knows about. +- +- You should use the same names that iconv does, where possible, to +- take advantage of the iconv-based default behaviors. +- +- CAUTION: if you register a character set, you must also register +- as many translations as are necessary to make that character set +- interoperate correctly with all the other character sets. We do +- provide default behaviors when no translation is available, or +- when a translation's function pointer for a particular operation +- is zero. Hopefully, these defaults will be correct often enough +- that we won't need to provide too many translations. */ +- register_charset (simple_charset ("ASCII", 1, +- ascii_print_literally, 0, +- ascii_to_control, 0)); +- register_charset (iso_8859_family_charset ("ISO-8859-1")); +- register_charset (ebcdic_family_charset ("EBCDIC-US")); +- register_charset (ebcdic_family_charset ("IBM1047")); +- register_iconv_charsets (); +- +- { +- struct { char *from; char *to; int *table; } tlist[] = { +- { "ASCII", "ISO-8859-1", ascii_to_iso_8859_1_table }, +- { "ASCII", "EBCDIC-US", ascii_to_ebcdic_us_table }, +- { "ASCII", "IBM1047", ascii_to_ibm1047_table }, +- { "ISO-8859-1", "ASCII", iso_8859_1_to_ascii_table }, +- { "ISO-8859-1", "EBCDIC-US", iso_8859_1_to_ebcdic_us_table }, +- { "ISO-8859-1", "IBM1047", iso_8859_1_to_ibm1047_table }, +- { "EBCDIC-US", "ASCII", ebcdic_us_to_ascii_table }, +- { "EBCDIC-US", "ISO-8859-1", ebcdic_us_to_iso_8859_1_table }, +- { "EBCDIC-US", "IBM1047", ebcdic_us_to_ibm1047_table }, +- { "IBM1047", "ASCII", ibm1047_to_ascii_table }, +- { "IBM1047", "ISO-8859-1", ibm1047_to_iso_8859_1_table }, +- { "IBM1047", "EBCDIC-US", ibm1047_to_ebcdic_us_table } +- }; +- +- int i; +- +- for (i = 0; i < (sizeof (tlist) / sizeof (tlist[0])); i++) +- register_translation (simple_table_translation (tlist[i].from, +- tlist[i].to, +- tlist[i].table)); +- } +- +- set_host_charset (host_charset_name); +- set_target_charset (target_charset_name); ++ /* The first element is always "auto"; then we skip it for the ++ commands where it is not allowed. */ ++ VEC_safe_push (char_ptr, charsets, "auto"); ++ find_charset_names (); ++ ++ if (VEC_length (char_ptr, charsets) > 1) ++ charset_enum = default_charset_names; ++ else ++ charset_enum = (const char **) VEC_address (char_ptr, charsets); ++ ++#ifdef HAVE_LANGINFO_CODESET ++ auto_host_charset_name = nl_langinfo (CODESET); ++ target_charset_name = auto_host_charset_name; ++ ++ set_be_le_names (); ++#endif + + add_setshow_enum_cmd ("charset", class_support, +- host_charset_enum, &host_charset_name, _("\ ++ &charset_enum[1], &host_charset_name, _("\ + Set the host and target character sets."), _("\ + Show the host and target character sets."), _("\ + The `host character set' is the one used by the system GDB is running on.\n\ +@@ -1249,7 +650,7 @@ To see a list of the character sets GDB supports, type `set charset '."), + &setlist, &showlist); + + add_setshow_enum_cmd ("host-charset", class_support, +- host_charset_enum, &host_charset_name, _("\ ++ charset_enum, &host_charset_name, _("\ + Set the host character set."), _("\ + Show the host character set."), _("\ + The `host character set' is the one used by the system GDB is running on.\n\ +@@ -1261,7 +662,7 @@ To see a list of the character sets GDB supports, type `set host-charset '. + &setlist, &showlist); + + add_setshow_enum_cmd ("target-charset", class_support, +- target_charset_enum, &target_charset_name, _("\ ++ &charset_enum[1], &target_charset_name, _("\ + Set the target character set."), _("\ + Show the target character set."), _("\ + The `target character set' is the one used by the program being debugged.\n\ +@@ -1271,4 +672,19 @@ To see a list of the character sets GDB supports, type `set target-charset' + set_target_charset_sfunc, + show_target_charset_name, + &setlist, &showlist); ++ ++ add_setshow_enum_cmd ("target-wide-charset", class_support, ++ &charset_enum[1], &target_wide_charset_name, ++ _("\ ++Set the target wide character set."), _("\ ++Show the target wide character set."), _("\ ++The `target wide character set' is the one used by the program being debugged.\n\ ++In particular it is the encoding used by `wchar_t'.\n\ ++GDB translates characters and strings between the host and target\n\ ++character sets as needed.\n\ ++To see a list of the character sets GDB supports, type\n\ ++`set target-wide-charset'"), ++ set_target_wide_charset_sfunc, ++ show_target_wide_charset_name, ++ &setlist, &showlist); + } +diff --git a/gdb/charset.h b/gdb/charset.h +index 21780b6..2455355 100644 +--- a/gdb/charset.h ++++ b/gdb/charset.h +@@ -19,6 +19,7 @@ + #ifndef CHARSET_H + #define CHARSET_H + ++#include + + /* If the target program uses a different character set than the host, + GDB has some support for translating between the two; GDB converts +@@ -26,82 +27,123 @@ + them, and converts characters and strings appearing in expressions + entered by the user to the target character set. + +- At the moment, GDB only supports single-byte, stateless character +- sets. This includes the ISO-8859 family (ASCII extended with +- accented characters, and (I think) Cyrillic, for European +- languages), and the EBCDIC family (used on IBM's mainframes). +- Unfortunately, it excludes many Asian scripts, the fixed- and +- variable-width Unicode encodings, and other desireable things. +- Patches are welcome! (For example, it would be nice if the Java +- string support could simply get absorbed into some more general +- multi-byte encoding support.) +- +- Furthermore, GDB's code pretty much assumes that the host character +- set is some superset of ASCII; there are plenty if ('0' + n) +- expressions and the like. +- +- When the `iconv' library routine supports a character set meeting +- the requirements above, it's easy to plug an entry into GDB's table +- that uses iconv to handle the details. */ ++ GDB's code pretty much assumes that the host character set is some ++ superset of ASCII; there are plenty if ('0' + n) expressions and ++ the like. */ + + /* Return the name of the current host/target character set. The + result is owned by the charset module; the caller should not free + it. */ + const char *host_charset (void); + const char *target_charset (void); +- +-/* In general, the set of C backslash escapes (\n, \f) is specific to +- the character set. Not all character sets will have form feed +- characters, for example. +- +- The following functions allow GDB to parse and print control +- characters in a character-set-independent way. They are both +- language-specific (to C and C++) and character-set-specific. +- Putting them here is a compromise. */ +- +- +-/* If the target character TARGET_CHAR have a backslash escape in the +- C language (i.e., a character like 'n' or 't'), return the host +- character string that should follow the backslash. Otherwise, +- return zero. +- +- When this function returns non-zero, the string it returns is +- statically allocated; the caller is not responsible for freeing it. */ +-const char *c_target_char_has_backslash_escape (int target_char); +- +- +-/* If the host character HOST_CHAR is a valid backslash escape in the +- C language for the target character set, return non-zero, and set +- *TARGET_CHAR to the target character the backslash escape represents. +- Otherwise, return zero. */ +-int c_parse_backslash (int host_char, int *target_char); +- +- +-/* Return non-zero if the host character HOST_CHAR can be printed +- literally --- that is, if it can be readably printed as itself in a +- character or string constant. Return zero if it should be printed +- using some kind of numeric escape, like '\031' in C, '^(25)' in +- Chill, or #25 in Pascal. */ +-int host_char_print_literally (int host_char); +- +- +-/* If the host character HOST_CHAR has an equivalent in the target +- character set, set *TARGET_CHAR to that equivalent, and return +- non-zero. Otherwise, return zero. */ +-int host_char_to_target (int host_char, int *target_char); +- +- +-/* If the target character TARGET_CHAR has an equivalent in the host +- character set, set *HOST_CHAR to that equivalent, and return +- non-zero. Otherwise, return zero. */ +-int target_char_to_host (int target_char, int *host_char); +- +- +-/* If the target character TARGET_CHAR has a corresponding control +- character (also in the target character set), set *TARGET_CTRL_CHAR +- to the control character, and return non-zero. Otherwise, return +- zero. */ +-int target_char_to_control_char (int target_char, int *target_ctrl_char); +- ++const char *target_wide_charset (void); ++ ++/* These values are used to specify the type of transliteration done ++ by convert_between_encodings. */ ++enum transliterations ++ { ++ /* Error on failure to convert. */ ++ translit_none, ++ /* Transliterate to host char. */ ++ translit_char ++ }; ++ ++/* Convert between two encodings. ++ ++ FROM is the name of the source encoding. ++ TO is the name of the target encoding. ++ BYTES holds the bytes to convert; this is assumed to be characters ++ in the target encoding. ++ NUM_BYTES is the number of bytes. ++ WIDTH is the width of a character from the FROM charset, in bytes. ++ For a variable width encoding, WIDTH should be the size of a "base ++ character". ++ OUTPUT is an obstack where the converted data is written. The ++ caller is responsible for initializing the obstack, and for ++ destroying the obstack should an error occur. ++ TRANSLIT specifies how invalid conversions should be handled. */ ++void convert_between_encodings (const char *from, const char *to, ++ const gdb_byte *bytes, unsigned int num_bytes, ++ int width, struct obstack *output, ++ enum transliterations translit); ++ ++ ++/* These values are used by wchar_iterate to report errors. */ ++enum wchar_iterate_result ++ { ++ /* Ordinary return. */ ++ wchar_iterate_ok, ++ /* Invalid input sequence. */ ++ wchar_iterate_invalid, ++ /* Incomplete input sequence at the end of the input. */ ++ wchar_iterate_incomplete, ++ /* EOF. */ ++ wchar_iterate_eof ++ }; ++ ++/* Declaration of the opaque wchar iterator type. */ ++struct wchar_iterator; ++ ++/* Create a new character iterator which returns wchar_t's. INPUT is ++ the input buffer. BYTES is the number of bytes in the input ++ buffer. CHARSET is the name of the character set in which INPUT is ++ encoded. WIDTH is the number of bytes in a base character of ++ CHARSET. ++ ++ This function either returns a new character set iterator, or calls ++ error. The result can be freed using a cleanup; see ++ make_cleanup_wchar_iterator. */ ++struct wchar_iterator *make_wchar_iterator (const gdb_byte *input, size_t bytes, ++ const char *charset, ++ size_t width); ++ ++/* Return a new cleanup suitable for destroying the wchar iterator ++ ITER. */ ++struct cleanup *make_cleanup_wchar_iterator (struct wchar_iterator *iter); ++ ++/* Perform a single iteration of a wchar_t iterator. ++ ++ Returns the number of characters converted. A negative result ++ means that EOF has been reached. A positive result indicates the ++ number of valid wchar_ts in the result; *OUT_CHARS is updated to ++ point to the first valid character. ++ ++ In all cases aside from EOF, *PTR is set to point to the first ++ converted target byte. *LEN is set to the number of bytes ++ converted. ++ ++ A zero result means one of several unusual results. *OUT_RESULT is ++ set to indicate the type of un-ordinary return. ++ ++ wchar_iterate_invalid means that an invalid input character was ++ seen. The iterator is advanced by WIDTH (the argument to ++ make_wchar_iterator) bytes. ++ ++ wchar_iterate_incomplete means that an incomplete character was ++ seen at the end of the input sequence. ++ ++ wchar_iterate_eof means that all bytes were successfully ++ converted. The other output arguments are not set. */ ++int wchar_iterate (struct wchar_iterator *iter, ++ enum wchar_iterate_result *out_result, ++ wchar_t **out_chars, ++ const gdb_byte **ptr, size_t *len); ++ ++ ++ ++/* GDB needs to know a few details of its execution character set. ++ This knowledge is isolated here and in charset.c. */ ++ ++/* The escape character. */ ++#define HOST_ESCAPE_CHAR 27 ++ ++/* Convert a letter, like 'c', to its corresponding control ++ character. */ ++char host_letter_to_control_character (char c); ++ ++/* Convert a hex digit character to its numeric value. E.g., 'f' is ++ converted to 15. This function assumes that C is a valid hex ++ digit. Both upper- and lower-case letters are recognized. */ ++int host_hex_value (char c); + + #endif /* CHARSET_H */ +diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c +index 4d9c4f3..5fbe398 100644 +--- a/gdb/cli/cli-cmds.c ++++ b/gdb/cli/cli-cmds.c +@@ -45,6 +45,8 @@ + #include "cli/cli-setshow.h" + #include "cli/cli-cmds.h" + ++#include "python/python.h" ++ + #ifdef TUI + #include "tui/tui.h" /* For tui_active et.al. */ + #endif +@@ -178,6 +180,7 @@ struct cmd_list_element *showchecklist; + + /* Command tracing state. */ + ++static int source_python = 0; + int source_verbose = 0; + int trace_commands = 0; + +@@ -439,6 +442,7 @@ source_script (char *file, int from_tty) + struct cleanup *old_cleanups; + char *full_pathname = NULL; + int fd; ++ int is_python; + + if (file == NULL || *file == 0) + { +@@ -471,8 +475,16 @@ source_script (char *file, int from_tty) + } + } + ++ is_python = source_python; ++ if (strlen (file) > 3 && !strcmp (&file[strlen (file) - 3], ".py")) ++ is_python = 1; ++ + stream = fdopen (fd, FOPEN_RT); +- script_from_file (stream, file); ++ ++ if (is_python) ++ source_python_script (stream, file); ++ else ++ script_from_file (stream, file); + + do_cleanups (old_cleanups); + } +@@ -486,15 +498,30 @@ source_verbose_cleanup (void *old_value) + xfree (old_value); + } + ++/* A helper for source_command. Look for an argument in *ARGS. ++ Update *ARGS by stripping leading whitespace. If an argument is ++ found, return it (a character). Otherwise, return 0. */ ++static int ++find_argument (char **args) ++{ ++ int result = 0; ++ while (isspace ((*args)[0])) ++ ++*args; ++ if ((*args)[0] == '-' && isalpha ((*args)[1])) ++ { ++ result = (*args)[1]; ++ *args += 3; ++ } ++ return result; ++} ++ + static void + source_command (char *args, int from_tty) + { + struct cleanup *old_cleanups; +- char *file = args; +- int *old_source_verbose = xmalloc (sizeof(int)); + +- *old_source_verbose = source_verbose; +- old_cleanups = make_cleanup (source_verbose_cleanup, old_source_verbose); ++ old_cleanups = make_cleanup_restore_integer (&source_verbose); ++ make_cleanup_restore_integer (&source_python); + + /* -v causes the source command to run in verbose mode. + We still have to be able to handle filenames with spaces in a +@@ -502,23 +529,28 @@ source_command (char *args, int from_tty) + + if (args) + { +- /* Make sure leading white space does not break the comparisons. */ +- while (isspace(args[0])) +- args++; +- +- /* Is -v the first thing in the string? */ +- if (args[0] == '-' && args[1] == 'v' && isspace (args[2])) ++ while (1) + { +- source_verbose = 1; +- +- /* Trim -v and whitespace from the filename. */ +- file = &args[3]; +- while (isspace (file[0])) +- file++; ++ int arg = find_argument (&args); ++ if (!arg) ++ break; ++ switch (arg) ++ { ++ case 'v': ++ source_verbose = 1; ++ break; ++ case 'p': ++ source_python = 1; ++ break; ++ default: ++ error (_("unrecognized option -%c"), arg); ++ } + } + } + +- source_script (file, from_tty); ++ source_script (args, from_tty); ++ ++ do_cleanups (old_cleanups); + } + + +@@ -1282,7 +1314,9 @@ Read commands from a file named FILE.\n\ + Optional -v switch (before the filename) causes each command in\n\ + FILE to be echoed as it is executed.\n\ + Note that the file \"%s\" is read automatically in this way\n\ +-when GDB is started."), gdbinit); ++when GDB is started.\n\ ++Optional -p switch (before the filename) causes FILE to be evaluated\n\ ++as Python code."), gdbinit); + c = add_cmd ("source", class_support, source_command, + source_help_text, &cmdlist); + set_cmd_completer (c, filename_completer); +diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c +index ee29f2a..96e6111 100644 +--- a/gdb/cli/cli-dump.c ++++ b/gdb/cli/cli-dump.c +@@ -296,7 +296,7 @@ dump_value_to_file (char *cmd, char *mode, char *file_format) + + if (VALUE_LVAL (val)) + { +- vaddr = VALUE_ADDRESS (val); ++ vaddr = value_address (val); + } + else + { +diff --git a/gdb/coffread.c b/gdb/coffread.c +index 6059d68..47ee601 100644 +--- a/gdb/coffread.c ++++ b/gdb/coffread.c +@@ -346,7 +346,7 @@ coff_alloc_type (int index) + We will fill it in later if we find out how. */ + if (type == NULL) + { +- type = alloc_type (current_objfile); ++ type = alloc_type (current_objfile, NULL); + *type_addr = type; + } + return type; +@@ -2101,6 +2101,7 @@ static struct sym_fns coff_sym_fns = + coff_new_init, /* sym_new_init: init anything gbl to entire symtab */ + coff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + coff_symfile_read, /* sym_read: read a symbol file into symtab */ ++ NULL, /* sym_read_psymbols */ + coff_symfile_finish, /* sym_finish: finished with file, cleanup */ + default_symfile_offsets, /* sym_offsets: xlate external to internal form */ + default_symfile_segments, /* sym_segments: Get segment information from +diff --git a/gdb/config.in b/gdb/config.in +index 6aaf77a..0c8ccab 100644 +--- a/gdb/config.in ++++ b/gdb/config.in +@@ -42,6 +42,12 @@ + language is requested. */ + #undef ENABLE_NLS + ++/* Global directory for GDB data files. */ ++#undef GDB_DATADIR ++ ++/* Define if GDB datadir should be relocated when GDB is moved. */ ++#undef GDB_DATADIR_RELOCATABLE ++ + /* Define to be a string naming the default host character set. */ + #undef GDB_DEFAULT_HOST_CHARSET + +@@ -169,12 +175,18 @@ + /* Define if you have the iconv() function. */ + #undef HAVE_ICONV + ++/* Define to 1 if you have the `iconvlist' function. */ ++#undef HAVE_ICONVLIST ++ + /* Define if your compiler supports the #include_next directive. */ + #undef HAVE_INCLUDE_NEXT + + /* Define to 1 if you have the header file. */ + #undef HAVE_INTTYPES_H + ++/* Define if you have and nl_langinfo(CODESET). */ ++#undef HAVE_LANGINFO_CODESET ++ + /* Define if your file defines LC_MESSAGES. */ + #undef HAVE_LC_MESSAGES + +@@ -618,6 +630,9 @@ + 'ptrdiff_t'. */ + #undef PTRDIFF_T_SUFFIX + ++/* Define to install path for Python sources */ ++#undef PYTHONDIR ++ + /* Bug reporting address */ + #undef REPORT_BUGS_TO + +diff --git a/gdb/configure b/gdb/configure +index 7579c84..3a5b582 100755 +--- a/gdb/configure ++++ b/gdb/configure +@@ -314,7 +314,7 @@ ac_subdirs_all="$ac_subdirs_all doc testsuite" + ac_subdirs_all="$ac_subdirs_all gdbtk" + ac_subdirs_all="$ac_subdirs_all multi-ice" + ac_subdirs_all="$ac_subdirs_all gdbserver" +-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os am__leading_dot DEPDIR CCDEPMODE MAKE GMAKE_TRUE GMAKE_FALSE SET_MAKE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK AMTAR am__tar am__untar am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH am__fastdepCC_TRUE am__fastdepCC_FALSE subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT PYTHON_CFLAGS ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBICONV LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS' ++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os am__leading_dot DEPDIR CCDEPMODE MAKE GMAKE_TRUE GMAKE_FALSE SET_MAKE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK AMTAR am__tar am__untar am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH am__fastdepCC_TRUE am__fastdepCC_FALSE GDB_DATADIR_PATH pythondir subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG LIBICONV LIBICONV_INCLUDE LIBICONV_LIBDIR READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT PYTHON_CFLAGS ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS' + ac_subst_files='host_makefile_frag' + ac_pwd=`pwd` + +@@ -882,9 +882,14 @@ Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-separate-debug-dir=path Look for global separate debug info in this path LIBDIR/debug ++ --with-gdb-datadir look for global separate data files in this path ++ [DATADIR/gdb] ++ --with-pythondir install Python data files in this path ++ [DATADIR/gdb/python] + --with-libunwind Use libunwind frame unwinding support + --with-pkgversion=PKG Use PKG in the version string in place of "GDB" + --with-bugurl=URL Direct users to URL to report a bug ++ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib + --with-system-readline use installed readline library + --with-expat include expat support (auto/yes/no) + --with-gnu-ld assume the C compiler uses GNU ld default=no +@@ -899,7 +904,6 @@ Optional Packages: + --with-tcl directory containing tcl configuration (tclConfig.sh) + --with-tk directory containing tk configuration (tkConfig.sh) + --with-x use the X Window System +- --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib + + Some influential environment variables: + CC C compiler command +@@ -7130,6 +7134,75 @@ _ACEOF + ;; + esac + ++# GDB's datadir relocation ++ ++gdbdatadir=${datadir}/gdb ++ ++ ++# Check whether --with-gdb-datadir or --without-gdb-datadir was given. ++if test "${with_gdb_datadir+set}" = set; then ++ withval="$with_gdb_datadir" ++ gdbdatadir="${withval}" ++fi; ++ ++ ++ test "x$prefix" = xNONE && prefix="$ac_default_prefix" ++ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' ++ ac_define_dir=`eval echo $gdbdatadir` ++ ac_define_dir=`eval echo $ac_define_dir` ++ ++cat >>confdefs.h <<_ACEOF ++#define GDB_DATADIR "$ac_define_dir" ++_ACEOF ++ ++ ++ ++if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then ++ if test "x$prefix" = xNONE; then ++ test_prefix=/usr/local ++ else ++ test_prefix=$prefix ++ fi ++else ++ test_prefix=$exec_prefix ++fi ++ ++case ${gdbdatadir} in ++ "${test_prefix}"|"${test_prefix}/"*|\ ++ '${exec_prefix}'|'${exec_prefix}/'*) ++ ++cat >>confdefs.h <<\_ACEOF ++#define GDB_DATADIR_RELOCATABLE 1 ++_ACEOF ++ ++ ;; ++esac ++GDB_DATADIR_PATH=${gdbdatadir} ++ ++ ++ ++# Check whether --with-pythondir or --without-pythondir was given. ++if test "${with_pythondir+set}" = set; then ++ withval="$with_pythondir" ++ pythondir="${withval}" ++else ++ pythondir=no ++fi; ++ ++# If the user passed in a path, define it. Otherwise, compute it at ++# runtime based on the possibly-relocatable datadir. ++if test "$pythondir" = "no"; then ++ pythondir='$(GDB_DATADIR_PATH)/python' ++else ++ ++cat >>confdefs.h <<_ACEOF ++#define PYTHONDIR "$pythondir" ++_ACEOF ++ ++fi ++ ++ ++ + + + subdirs="$subdirs doc testsuite" +@@ -9989,6 +10062,226 @@ if test "$ac_cv_search_dlgetmodinfo" != no; then + fi + + ++ ++ ++ ++# Check whether --with-libiconv-prefix or --without-libiconv-prefix was given. ++if test "${with_libiconv_prefix+set}" = set; then ++ withval="$with_libiconv_prefix" ++ ++ for dir in `echo "$withval" | tr : ' '`; do ++ if test -d $dir/include; then LIBICONV_INCLUDE="-I$dir/include"; CPPFLAGS="$CPPFLAGS -I$dir/include"; fi ++ if test -d $dir/lib; then LIBICONV_LIBDIR="-L$dir/lib"; LDFLAGS="$LDFLAGS -L$dir/lib"; fi ++ done ++ ++fi; ++ ++ echo "$as_me:$LINENO: checking for iconv" >&5 ++echo $ECHO_N "checking for iconv... $ECHO_C" >&6 ++if test "${am_cv_func_iconv+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ ++ am_cv_func_iconv="no, consider installing GNU libiconv" ++ am_cv_lib_iconv=no ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++#include ++int ++main () ++{ ++iconv_t cd = iconv_open("",""); ++ iconv(cd,NULL,NULL,NULL,NULL); ++ iconv_close(cd); ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext conftest$ac_exeext ++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ++ (eval $ac_link) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest$ac_exeext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ am_cv_func_iconv=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ if test "$am_cv_func_iconv" != yes; then ++ am_save_LIBS="$LIBS" ++ LIBS="$LIBS -liconv" ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++#include ++int ++main () ++{ ++iconv_t cd = iconv_open("",""); ++ iconv(cd,NULL,NULL,NULL,NULL); ++ iconv_close(cd); ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext conftest$ac_exeext ++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ++ (eval $ac_link) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest$ac_exeext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ am_cv_lib_iconv=yes ++ am_cv_func_iconv=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ LIBS="$am_save_LIBS" ++ fi ++ ++fi ++echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5 ++echo "${ECHO_T}$am_cv_func_iconv" >&6 ++ if test "$am_cv_func_iconv" = yes; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_ICONV 1 ++_ACEOF ++ ++ echo "$as_me:$LINENO: checking for iconv declaration" >&5 ++echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6 ++ if test "${am_cv_proto_iconv+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++ ++#include ++#include ++extern ++#ifdef __cplusplus ++"C" ++#endif ++#if defined(__STDC__) || defined(__cplusplus) ++size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); ++#else ++size_t iconv(); ++#endif ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ am_cv_proto_iconv_arg1="" ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++am_cv_proto_iconv_arg1="const" ++fi ++rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ++ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" ++fi ++ ++ am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` ++ echo "$as_me:$LINENO: result: ${ac_t:- ++ }$am_cv_proto_iconv" >&5 ++echo "${ECHO_T}${ac_t:- ++ }$am_cv_proto_iconv" >&6 ++ ++cat >>confdefs.h <<_ACEOF ++#define ICONV_CONST $am_cv_proto_iconv_arg1 ++_ACEOF ++ ++ fi ++ LIBICONV= ++ if test "$am_cv_lib_iconv" = yes; then ++ LIBICONV="-liconv" ++ fi ++ ++ ++ ++ ++ + # On alpha-osf, it appears that libtermcap and libcurses are not compatible. + # There is a very specific comment in /usr/include/curses.h explaining that + # termcap routines built into libcurses must not be used. +@@ -11418,6 +11711,8 @@ _ACEOF + CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)" + CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)" + CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)" ++ CONFIG_INSTALL="$CONFIG_INSTALL install-python" ++ CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python" + ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)" + + # Flags needed to compile Python code (taken from python-config --cflags). +@@ -15445,10 +15740,11 @@ fi + + + ++ + for ac_func in canonicalize_file_name realpath getrusage getuid \ + getgid poll pread64 sbrk setpgid setpgrp setsid \ + sigaction sigprocmask sigsetmask socketpair syscall \ +- ttrace wborder setlocale ++ ttrace wborder setlocale iconvlist + do + as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` + echo "$as_me:$LINENO: checking for $ac_func" >&5 +@@ -15550,6 +15846,70 @@ fi + done + + ++ echo "$as_me:$LINENO: checking for nl_langinfo and CODESET" >&5 ++echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6 ++if test "${am_cv_langinfo_codeset+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++int ++main () ++{ ++char* cs = nl_langinfo(CODESET); ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext conftest$ac_exeext ++if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ++ (eval $ac_link) 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -z "$ac_c_werror_flag" ++ || test ! -s conftest.err' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } && ++ { ac_try='test -s conftest$ac_exeext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ am_cv_langinfo_codeset=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++am_cv_langinfo_codeset=no ++fi ++rm -f conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ ++fi ++echo "$as_me:$LINENO: result: $am_cv_langinfo_codeset" >&5 ++echo "${ECHO_T}$am_cv_langinfo_codeset" >&6 ++ if test $am_cv_langinfo_codeset = yes; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_LANGINFO_CODESET 1 ++_ACEOF ++ ++ fi ++ ++ + # Check the return and argument types of ptrace. No canned test for + # this, so roll our own. + gdb_ptrace_headers=' +@@ -20776,230 +21136,11 @@ done + + + +- + cat >>confdefs.h <<\_ACEOF +-#define GDB_DEFAULT_HOST_CHARSET "ISO-8859-1" ++#define GDB_DEFAULT_HOST_CHARSET "UTF-8" + _ACEOF + + +- +- +- +-# Check whether --with-libiconv-prefix or --without-libiconv-prefix was given. +-if test "${with_libiconv_prefix+set}" = set; then +- withval="$with_libiconv_prefix" +- +- for dir in `echo "$withval" | tr : ' '`; do +- if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi +- if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi +- done +- +-fi; +- +- echo "$as_me:$LINENO: checking for iconv" >&5 +-echo $ECHO_N "checking for iconv... $ECHO_C" >&6 +-if test "${am_cv_func_iconv+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- +- am_cv_func_iconv="no, consider installing GNU libiconv" +- am_cv_lib_iconv=no +- cat >conftest.$ac_ext <<_ACEOF +-/* confdefs.h. */ +-_ACEOF +-cat confdefs.h >>conftest.$ac_ext +-cat >>conftest.$ac_ext <<_ACEOF +-/* end confdefs.h. */ +-#include +-#include +-int +-main () +-{ +-iconv_t cd = iconv_open("",""); +- iconv(cd,NULL,NULL,NULL,NULL); +- iconv_close(cd); +- ; +- return 0; +-} +-_ACEOF +-rm -f conftest.$ac_objext conftest$ac_exeext +-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 +- (eval $ac_link) 2>conftest.er1 +- ac_status=$? +- grep -v '^ *+' conftest.er1 >conftest.err +- rm -f conftest.er1 +- cat conftest.err >&5 +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); } && +- { ac_try='test -z "$ac_c_werror_flag" +- || test ! -s conftest.err' +- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +- (eval $ac_try) 2>&5 +- ac_status=$? +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); }; } && +- { ac_try='test -s conftest$ac_exeext' +- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +- (eval $ac_try) 2>&5 +- ac_status=$? +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); }; }; then +- am_cv_func_iconv=yes +-else +- echo "$as_me: failed program was:" >&5 +-sed 's/^/| /' conftest.$ac_ext >&5 +- +-fi +-rm -f conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- if test "$am_cv_func_iconv" != yes; then +- am_save_LIBS="$LIBS" +- LIBS="$LIBS -liconv" +- cat >conftest.$ac_ext <<_ACEOF +-/* confdefs.h. */ +-_ACEOF +-cat confdefs.h >>conftest.$ac_ext +-cat >>conftest.$ac_ext <<_ACEOF +-/* end confdefs.h. */ +-#include +-#include +-int +-main () +-{ +-iconv_t cd = iconv_open("",""); +- iconv(cd,NULL,NULL,NULL,NULL); +- iconv_close(cd); +- ; +- return 0; +-} +-_ACEOF +-rm -f conftest.$ac_objext conftest$ac_exeext +-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 +- (eval $ac_link) 2>conftest.er1 +- ac_status=$? +- grep -v '^ *+' conftest.er1 >conftest.err +- rm -f conftest.er1 +- cat conftest.err >&5 +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); } && +- { ac_try='test -z "$ac_c_werror_flag" +- || test ! -s conftest.err' +- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +- (eval $ac_try) 2>&5 +- ac_status=$? +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); }; } && +- { ac_try='test -s conftest$ac_exeext' +- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +- (eval $ac_try) 2>&5 +- ac_status=$? +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); }; }; then +- am_cv_lib_iconv=yes +- am_cv_func_iconv=yes +-else +- echo "$as_me: failed program was:" >&5 +-sed 's/^/| /' conftest.$ac_ext >&5 +- +-fi +-rm -f conftest.err conftest.$ac_objext \ +- conftest$ac_exeext conftest.$ac_ext +- LIBS="$am_save_LIBS" +- fi +- +-fi +-echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5 +-echo "${ECHO_T}$am_cv_func_iconv" >&6 +- if test "$am_cv_func_iconv" = yes; then +- +-cat >>confdefs.h <<\_ACEOF +-#define HAVE_ICONV 1 +-_ACEOF +- +- echo "$as_me:$LINENO: checking for iconv declaration" >&5 +-echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6 +- if test "${am_cv_proto_iconv+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- +- cat >conftest.$ac_ext <<_ACEOF +-/* confdefs.h. */ +-_ACEOF +-cat confdefs.h >>conftest.$ac_ext +-cat >>conftest.$ac_ext <<_ACEOF +-/* end confdefs.h. */ +- +-#include +-#include +-extern +-#ifdef __cplusplus +-"C" +-#endif +-#if defined(__STDC__) || defined(__cplusplus) +-size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +-#else +-size_t iconv(); +-#endif +- +-int +-main () +-{ +- +- ; +- return 0; +-} +-_ACEOF +-rm -f conftest.$ac_objext +-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 +- (eval $ac_compile) 2>conftest.er1 +- ac_status=$? +- grep -v '^ *+' conftest.er1 >conftest.err +- rm -f conftest.er1 +- cat conftest.err >&5 +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); } && +- { ac_try='test -z "$ac_c_werror_flag" +- || test ! -s conftest.err' +- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +- (eval $ac_try) 2>&5 +- ac_status=$? +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); }; } && +- { ac_try='test -s conftest.$ac_objext' +- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 +- (eval $ac_try) 2>&5 +- ac_status=$? +- echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); }; }; then +- am_cv_proto_iconv_arg1="" +-else +- echo "$as_me: failed program was:" >&5 +-sed 's/^/| /' conftest.$ac_ext >&5 +- +-am_cv_proto_iconv_arg1="const" +-fi +-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +- am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" +-fi +- +- am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` +- echo "$as_me:$LINENO: result: ${ac_t:- +- }$am_cv_proto_iconv" >&5 +-echo "${ECHO_T}${ac_t:- +- }$am_cv_proto_iconv" >&6 +- +-cat >>confdefs.h <<_ACEOF +-#define ICONV_CONST $am_cv_proto_iconv_arg1 +-_ACEOF +- +- fi +- LIBICONV= +- if test "$am_cv_lib_iconv" = yes; then +- LIBICONV="-liconv" +- fi +- +- +- + ac_config_files="$ac_config_files Makefile .gdbinit:gdbinit.in gnulib/Makefile" + ac_config_commands="$ac_config_commands default" + cat >confcache <<\_ACEOF +@@ -21865,6 +22006,8 @@ s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t + s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t + s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t + s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t ++s,@GDB_DATADIR_PATH@,$GDB_DATADIR_PATH,;t t ++s,@pythondir@,$pythondir,;t t + s,@subdirs@,$subdirs,;t t + s,@TARGET_OBS@,$TARGET_OBS,;t t + s,@PKGVERSION@,$PKGVERSION,;t t +@@ -21880,6 +22023,9 @@ s,@WINDRES@,$WINDRES,;t t + s,@ac_ct_WINDRES@,$ac_ct_WINDRES,;t t + s,@MIG@,$MIG,;t t + s,@ac_ct_MIG@,$ac_ct_MIG,;t t ++s,@LIBICONV@,$LIBICONV,;t t ++s,@LIBICONV_INCLUDE@,$LIBICONV_INCLUDE,;t t ++s,@LIBICONV_LIBDIR@,$LIBICONV_LIBDIR,;t t + s,@READLINE@,$READLINE,;t t + s,@READLINE_DEPS@,$READLINE_DEPS,;t t + s,@READLINE_CFLAGS@,$READLINE_CFLAGS,;t t +@@ -21944,7 +22090,6 @@ s,@CONFIG_UNINSTALL@,$CONFIG_UNINSTALL,;t t + s,@target_subdir@,$target_subdir,;t t + s,@frags@,$frags,;t t + s,@nm_h@,$nm_h,;t t +-s,@LIBICONV@,$LIBICONV,;t t + s,@LIBOBJS@,$LIBOBJS,;t t + s,@LTLIBOBJS@,$LTLIBOBJS,;t t + s,@gl_LIBOBJS@,$gl_LIBOBJS,;t t +diff --git a/gdb/configure.ac b/gdb/configure.ac +index 3f81ff2..ff76053 100644 +--- a/gdb/configure.ac ++++ b/gdb/configure.ac +@@ -1,6 +1,6 @@ + dnl Autoconf configure script for GDB, the GNU debugger. + dnl Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +-dnl 2005, 2006, 2007, 2008 ++dnl 2005, 2006, 2007, 2008, 2009 + dnl Free Software Foundation, Inc. + dnl + dnl This file is part of GDB. +@@ -118,6 +118,51 @@ case ${debugdir} in + ;; + esac + ++# GDB's datadir relocation ++ ++gdbdatadir=${datadir}/gdb ++ ++AC_ARG_WITH([gdb-datadir], ++ [AS_HELP_STRING([--with-gdb-datadir], ++ [look for global separate data files in this path [DATADIR/gdb]])], [gdbdatadir="${withval}"]) ++ ++AC_DEFINE_DIR(GDB_DATADIR, gdbdatadir, ++ [Global directory for GDB data files. ]) ++ ++if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then ++ if test "x$prefix" = xNONE; then ++ test_prefix=/usr/local ++ else ++ test_prefix=$prefix ++ fi ++else ++ test_prefix=$exec_prefix ++fi ++ ++case ${gdbdatadir} in ++ "${test_prefix}"|"${test_prefix}/"*|\ ++ '${exec_prefix}'|'${exec_prefix}/'*) ++ AC_DEFINE(GDB_DATADIR_RELOCATABLE, 1, [Define if GDB datadir should be relocated when GDB is moved.]) ++ ;; ++esac ++GDB_DATADIR_PATH=${gdbdatadir} ++AC_SUBST(GDB_DATADIR_PATH) ++ ++AC_ARG_WITH([pythondir], ++ [AS_HELP_STRING([--with-pythondir], ++ [install Python data files in this path [DATADIR/gdb/python]])], [pythondir="${withval}"], [pythondir=no]) ++ ++# If the user passed in a path, define it. Otherwise, compute it at ++# runtime based on the possibly-relocatable datadir. ++if test "$pythondir" = "no"; then ++ pythondir='$(GDB_DATADIR_PATH)/python' ++else ++ AC_DEFINE_UNQUOTED(PYTHONDIR, "$pythondir", ++ [Define to install path for Python sources]) ++fi ++AC_SUBST(pythondir) ++ ++ + AC_CONFIG_SUBDIRS(doc testsuite) + + # Check whether to support alternative target configurations +@@ -430,6 +475,8 @@ AC_SEARCH_LIBS(zlibVersion, z, [AC_CHECK_HEADERS(zlib.h)]) + # On HP/UX we may need libxpdl for dlgetmodinfo (used by solib-pa64.c). + AC_SEARCH_LIBS(dlgetmodinfo, [dl xpdl]) + ++AM_ICONV ++ + # On alpha-osf, it appears that libtermcap and libcurses are not compatible. + # There is a very specific comment in /usr/include/curses.h explaining that + # termcap routines built into libcurses must not be used. +@@ -649,6 +696,8 @@ if test "${have_libpython}" = yes; then + CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)" + CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)" + CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)" ++ CONFIG_INSTALL="$CONFIG_INSTALL install-python" ++ CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python" + ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)" + + # Flags needed to compile Python code (taken from python-config --cflags). +@@ -776,7 +825,8 @@ AC_FUNC_VFORK + AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid \ + getgid poll pread64 sbrk setpgid setpgrp setsid \ + sigaction sigprocmask sigsetmask socketpair syscall \ +- ttrace wborder setlocale]) ++ ttrace wborder setlocale iconvlist]) ++AM_LANGINFO_CODESET + + # Check the return and argument types of ptrace. No canned test for + # this, so roll our own. +@@ -1930,17 +1980,10 @@ dnl Check for exe extension set on certain hosts (e.g. Win32) + AC_EXEEXT + + dnl Detect the character set used by this host. +- +-dnl At the moment, we just assume it's ISO-8859-1 (which is a +-dnl superset of ASCII containing the characters needed for French, +-dnl German, Spanish, Italian, and possibly others), but if were +-dnl *were* to support any host character sets other than ISO-8859-1, +-dnl here's where we'd detect it. +-AC_DEFINE(GDB_DEFAULT_HOST_CHARSET, "ISO-8859-1", ++dnl At the moment, we just assume it's UTF-8. ++AC_DEFINE(GDB_DEFAULT_HOST_CHARSET, "UTF-8", + [Define to be a string naming the default host character set.]) + +-AM_ICONV +- + AC_OUTPUT(Makefile .gdbinit:gdbinit.in gnulib/Makefile, + [ + dnl Autoconf doesn't provide a mechanism for modifying definitions +diff --git a/gdb/configure.tgt b/gdb/configure.tgt +index 65c3e25..f0cca7d 100644 +--- a/gdb/configure.tgt ++++ b/gdb/configure.tgt +@@ -36,7 +36,7 @@ alpha*-*-osf*) + alpha*-*-linux*) + # Target: Little-endian Alpha running Linux + gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-linux-tdep.o \ +- solib.o solib-svr4.o" ++ solib.o solib-svr4.o linux-tdep.o" + ;; + alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu) + # Target: FreeBSD/alpha +@@ -63,7 +63,7 @@ alpha*-*-*) + am33_2.0*-*-linux*) + # Target: Matsushita mn10300 (AM33) running Linux + gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o corelow.o \ +- solib.o solib-svr4.o" ++ solib.o solib-svr4.o linux-tdep.o" + ;; + + arm*-wince-pe | arm*-*-mingw32ce*) +@@ -128,7 +128,7 @@ hppa*-*-hpux*) + hppa*-*-linux*) + # Target: HP PA-RISC running Linux + gdb_target_obs="hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o \ +- solib.o solib-svr4.o symfile-mem.o" ++ solib.o solib-svr4.o symfile-mem.o linux-tdep.o" + ;; + hppa*-*-netbsd*) + # Target: NetBSD/hppa +@@ -218,7 +218,7 @@ i[34567]86-*-*) + ia64-*-linux*) + # Target: Intel IA-64 running GNU/Linux + gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o \ +- solib.o solib-svr4.o symfile-mem.o" ++ solib.o solib-svr4.o symfile-mem.o linux-tdep.o" + build_gdbserver=yes + ;; + ia64*-*-*) +@@ -242,7 +242,8 @@ m32c-*-*) + m32r*-*-linux*) + # Target: Renesas M32R running GNU/Linux + gdb_target_obs="m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o \ +- glibc-tdep.o solib.o solib-svr4.o symfile-mem.o" ++ glibc-tdep.o solib.o solib-svr4.o symfile-mem.o \ ++ linux-tdep.o" + gdb_sim=../sim/m32r/libsim.a + build_gdbserver=yes + ;; +@@ -267,7 +268,7 @@ fido-*-elf*) + m68*-*-linux*) + # Target: Motorola m68k with a.out and ELF + gdb_target_obs="m68k-tdep.o m68klinux-tdep.o solib.o solib-svr4.o \ +- glibc-tdep.o symfile-mem.o" ++ glibc-tdep.o symfile-mem.o linux-tdep.o" + build_gdbserver=yes + ;; + m68*-*-netbsd* | m68*-*-knetbsd*-gnu) +@@ -303,7 +304,8 @@ mips*-sgi-irix6*) + mips*-*-linux*) + # Target: Linux/MIPS + gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \ +- corelow.o solib.o solib-svr4.o symfile-mem.o" ++ corelow.o solib.o solib-svr4.o symfile-mem.o \ ++ linux-tdep.o" + gdb_sim=../sim/mips/libsim.a + build_gdbserver=yes + ;; +@@ -354,7 +356,8 @@ powerpc-*-aix* | rs6000-*-*) + powerpc-*-linux* | powerpc64-*-linux*) + # Target: PowerPC running Linux + gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \ +- solib.o solib-svr4.o corelow.o symfile-mem.o" ++ solib.o solib-svr4.o corelow.o symfile-mem.o \ ++ linux-tdep.o" + gdb_sim=../sim/ppc/libsim.a + build_gdbserver=yes + ;; +@@ -381,7 +384,8 @@ score-*-*) + sh*-*-linux*) + # Target: GNU/Linux Super-H + gdb_target_obs="sh-tdep.o sh64-tdep.o sh-linux-tdep.o monitor.o \ +- dsrec.o solib.o solib-svr4.o symfile-mem.o glibc-tdep.o" ++ dsrec.o solib.o solib-svr4.o symfile-mem.o glibc-tdep.o \ ++ linux-tdep.o" + gdb_sim=../sim/sh/libsim.a + build_gdbserver=yes + ;; +@@ -409,13 +413,14 @@ sh*) + sparc-*-linux*) + # Target: GNU/Linux SPARC + gdb_target_obs="sparc-tdep.o sparc-sol2-tdep.o sol2-tdep.o \ +- sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o" ++ sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o \ ++ linux-tdep.o" + ;; + sparc64-*-linux*) + # Target: GNU/Linux UltraSPARC + gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sol2-tdep.o \ + sparc64-linux-tdep.o sparc-tdep.o sparc-sol2-tdep.o \ +- sparc-linux-tdep.o solib.o solib-svr4.o" ++ sparc-linux-tdep.o solib.o solib-svr4.o linux-tdep.o" + build_gdbserver=yes + ;; + sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu) +@@ -542,7 +547,8 @@ x86_64-*-openbsd*) + xtensa*-*-linux*) gdb_target=linux + # Target: GNU/Linux Xtensa + gdb_target_obs="xtensa-tdep.o xtensa-config.o xtensa-linux-tdep.o \ +- solib.o solib-svr4.o corelow.o symfile-mem.o" ++ solib.o solib-svr4.o corelow.o symfile-mem.o \ ++ linux-tdep.o" + build_gdbserver=yes + ;; + xtensa*) +diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y +index 5f5ee3a..a8f8f30 100644 +--- a/gdb/cp-name-parser.y ++++ b/gdb/cp-name-parser.y +@@ -1,7 +1,6 @@ + /* YACC parser for C++ names, for GDB. + +- Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 +- Free Software Foundation, Inc. ++ Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. + + Parts of the lexer are based on c-exp.y from GDB. + +@@ -501,7 +500,7 @@ operator : OPERATOR NEW + | OPERATOR ARROW + { $$ = make_operator ("->", 2); } + | OPERATOR '(' ')' +- { $$ = make_operator ("()", 0); } ++ { $$ = make_operator ("()", 2); } + | OPERATOR '[' ']' + { $$ = make_operator ("[]", 2); } + ; +diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c +index c6c5617..eace9c4 100644 +--- a/gdb/cp-namespace.c ++++ b/gdb/cp-namespace.c +@@ -30,26 +30,13 @@ + #include "dictionary.h" + #include "command.h" + #include "frame.h" ++#include "buildsym.h" + + /* List of using directives that are active in the current file. */ + +-static struct using_direct *using_list; +- +-static struct using_direct *cp_add_using (const char *name, +- unsigned int inner_len, +- unsigned int outer_len, +- struct using_direct *next); +- + static struct using_direct *cp_copy_usings (struct using_direct *using, + struct obstack *obstack); + +-static struct symbol *lookup_namespace_scope (const char *name, +- const char *linkage_name, +- const struct block *block, +- const domain_enum domain, +- const char *scope, +- int scope_len); +- + static struct symbol *lookup_symbol_file (const char *name, + const char *linkage_name, + const struct block *block, +@@ -78,31 +65,6 @@ static struct symbol *lookup_possible_namespace_symbol (const char *name); + + static void maintenance_cplus_namespace (char *args, int from_tty); + +-/* Set up support for dealing with C++ namespace info in the current +- symtab. */ +- +-void cp_initialize_namespace () +-{ +- using_list = NULL; +-} +- +-/* Add all the using directives we've gathered to the current symtab. +- STATIC_BLOCK should be the symtab's static block; OBSTACK is used +- for allocation. */ +- +-void +-cp_finalize_namespace (struct block *static_block, +- struct obstack *obstack) +-{ +- if (using_list != NULL) +- { +- block_set_using (static_block, +- cp_copy_usings (using_list, obstack), +- obstack); +- using_list = NULL; +- } +-} +- + /* Check to see if SYMBOL refers to an object contained within an + anonymous namespace; if so, add an appropriate using directive. */ + +@@ -136,14 +98,17 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol) + "(anonymous namespace)", + ANONYMOUS_NAMESPACE_LEN) == 0) + { ++ int outer_len = (previous_component == 0 ? 0 : previous_component - 2); ++ char outer[outer_len+1]; ++ ++ strncpy(outer, name, outer_len); ++ ++ outer[outer_len] = '\0'; + /* We've found a component of the name that's an + anonymous namespace. So add symbols in it to the + namespace given by the previous component if there is + one, or to the global namespace if there isn't. */ +- cp_add_using_directive (name, +- previous_component == 0 +- ? 0 : previous_component - 2, +- next_component); ++ cp_add_using_directive (outer, name, "", "", 0); + } + /* The "+ 2" is for the "::". */ + previous_component = next_component + 2; +@@ -154,32 +119,27 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol) + } + } + +-/* Add a using directive to using_list. NAME is the start of a string +- that should contain the namespaces we want to add as initial +- substrings, OUTER_LENGTH is the end of the outer namespace, and +- INNER_LENGTH is the end of the inner namespace. If the using +- directive in question has already been added, don't add it +- twice. */ ++/* Add a using directive to using_list. If the using directive in question ++ has already been added, don't add it twice. */ + + void +-cp_add_using_directive (const char *name, unsigned int outer_length, +- unsigned int inner_length) ++cp_add_using_directive (const char *outer, const char *inner, const char* alias, ++ const char *declaration, const int line_number) + { + struct using_direct *current; + struct using_direct *new; + + /* Has it already been added? */ + +- for (current = using_list; current != NULL; current = current->next) ++ for (current = using_directives; current != NULL; current = current->next) + { +- if ((strncmp (current->inner, name, inner_length) == 0) +- && (strlen (current->inner) == inner_length) +- && (strlen (current->outer) == outer_length)) ++ if (strcmp (current->inner, inner) == 0 ++ && strcmp (current->outer, outer) == 0) + return; + } + +- using_list = cp_add_using (name, inner_length, outer_length, +- using_list); ++ using_directives = cp_add_using (outer, inner, alias, declaration, ++ line_number,using_directives); + } + + /* Record the namespace that the function defined by SYMBOL was +@@ -230,26 +190,31 @@ cp_is_anonymous (const char *namespace) + != NULL); + } + +-/* Create a new struct using direct whose inner namespace is the +- initial substring of NAME of leng INNER_LEN and whose outer +- namespace is the initial substring of NAME of length OUTER_LENGTH. ++/* Create a new struct using direct whose inner namespace is INNER ++ and whose outer namespace is OUTER. ALIAS is the name of the imported ++ namespace in the current scope. If ALIAS is an empty string then the ++ namespace is known by its original name. + Set its next member in the linked list to NEXT; allocate all memory + using xmalloc. It copies the strings, so NAME can be a temporary + string. */ + +-static struct using_direct * +-cp_add_using (const char *name, +- unsigned int inner_len, +- unsigned int outer_len, ++struct using_direct * ++cp_add_using (const char *outer, ++ const char *inner, ++ const char *alias, ++ const char *declaration, ++ const int line_number, + struct using_direct *next) + { + struct using_direct *retval; + +- gdb_assert (outer_len < inner_len); +- + retval = xmalloc (sizeof (struct using_direct)); +- retval->inner = savestring (name, inner_len); +- retval->outer = savestring (name, outer_len); ++ retval->inner = savestring (inner, strlen(inner)); ++ retval->outer = savestring (outer, strlen(outer)); ++ retval->alias = savestring (alias, strlen(alias)); ++ retval->declaration = savestring (declaration, strlen(declaration)); ++ retval->line_number = line_number; ++ + retval->next = next; + + return retval; +@@ -274,11 +239,17 @@ cp_copy_usings (struct using_direct *using, + retval->inner = obsavestring (using->inner, strlen (using->inner), + obstack); + retval->outer = obsavestring (using->outer, strlen (using->outer), +- obstack); ++ obstack); ++ retval->alias = obsavestring (using->alias, strlen (using->alias), ++ obstack); ++ retval->declaration = obsavestring (using->declaration, strlen (using->declaration), ++ obstack); + retval->next = cp_copy_usings (using->next, obstack); + + xfree (using->inner); + xfree (using->outer); ++ xfree (using->alias); ++ xfree (using->declaration); + xfree (using); + + return retval; +@@ -299,8 +270,14 @@ cp_lookup_symbol_nonlocal (const char *name, + const struct block *block, + const domain_enum domain) + { +- return lookup_namespace_scope (name, linkage_name, block, domain, +- block_scope (block), 0); ++ ++ struct symbol* sym = lookup_namespace_scope(name, linkage_name, block, ++ domain, block_scope(block), 0); ++ ++ if (sym != NULL) ++ return sym; ++ ++ return lookup_symbol_file(name, linkage_name, block, domain, 0); + } + + /* Lookup NAME at namespace scope (or, in C terms, in static and +@@ -318,7 +295,7 @@ cp_lookup_symbol_nonlocal (const char *name, + "A::x", and if that call fails, then the first call looks for + "x". */ + +-static struct symbol * ++struct symbol * + lookup_namespace_scope (const char *name, + const char *linkage_name, + const struct block *block, +@@ -354,10 +331,43 @@ lookup_namespace_scope (const char *name, + namespace = alloca (scope_len + 1); + strncpy (namespace, scope, scope_len); + namespace[scope_len] = '\0'; +- return cp_lookup_symbol_namespace (namespace, name, linkage_name, ++ return cp_lookup_symbol_namespace_incremental (namespace, name, linkage_name, + block, domain); + } + ++/* Searches the for the given NAME in the given NAMESPACE, using import ++ statements implied by the given BLOCK, *and its' parents*. */ ++struct symbol * ++cp_lookup_symbol_namespace_incremental (const char *namespace, ++ const char *name, ++ const char *linkage_name, ++ const struct block *block, ++ const domain_enum domain) ++{ ++ struct symbol *sym; ++ const struct block *global_block = block_global_block (block); ++ ++ /* Check if either no block is specified or it's a global block. */ ++ ++ if (global_block == NULL) ++ return NULL; ++ ++ while (block != global_block) ++ { ++ sym = cp_lookup_symbol_namespace (namespace, name, linkage_name, block, domain); ++ ++ if (sym != NULL) ++ return sym; ++ ++ block = BLOCK_SUPERBLOCK (block); ++ } ++ ++ /* We've reached the global block without finding a result. */ ++ ++ return NULL; ++} ++ ++ + /* Look up NAME in the C++ namespace NAMESPACE, applying the using + directives that are active in BLOCK. Other arguments are as in + cp_lookup_symbol_nonlocal. */ +@@ -370,7 +380,7 @@ cp_lookup_symbol_namespace (const char *namespace, + const domain_enum domain) + { + const struct using_direct *current; +- struct symbol *sym; ++ struct symbol *sym = NULL; + + /* First, go through the using directives. If any of them add new + names to the namespace we're searching in, see if we can find a +@@ -380,15 +390,50 @@ cp_lookup_symbol_namespace (const char *namespace, + current != NULL; + current = current->next) + { +- if (strcmp (namespace, current->outer) == 0) ++ ++ int current_line = find_pc_line (get_frame_pc (get_current_frame ()), 0).line; ++ ++ if (strcmp (namespace, current->outer) == 0 && current->line_number < current_line) + { +- sym = cp_lookup_symbol_namespace (current->inner, +- name, +- linkage_name, +- block, +- domain); +- if (sym != NULL) ++ ++ /* If there is an import of a single declaration, compare the imported ++ declaration with the sought out name. If there is a match pass ++ current->inner as NAMESPACE to direct the search towards the ++ imported namespace. */ ++ if (strcmp ("", current->declaration) != 0) ++ { ++ if(strcmp (name, current->declaration) == 0){ ++ sym = cp_lookup_symbol_namespace (current->inner, ++ name, ++ linkage_name, ++ block, ++ domain); ++ } ++ ++ } ++ else if(strcmp (name, current->alias) == 0) ++ /* If the import is creating an alias and the alias matches the ++ sought name. Pass current->inner as the NAME to direct the ++ search towards the aliased namespace */ ++ { ++ sym = cp_lookup_symbol_namespace (namespace, ++ current->inner, ++ linkage_name, ++ block, ++ domain); ++ }else if(strcmp ("", current->alias) == 0){ ++ /* If this import statement creates no alias, pass current->inner as ++ NAMESPACE to direct the search towards the imported namespace. */ ++ sym = cp_lookup_symbol_namespace (current->inner, ++ name, ++ linkage_name, ++ block, ++ domain); ++ } ++ ++ if (sym != NULL){ + return sym; ++ } + } + } + +@@ -398,8 +443,10 @@ cp_lookup_symbol_namespace (const char *namespace, + + if (namespace[0] == '\0') + { +- return lookup_symbol_file (name, linkage_name, block, +- domain, 0); ++ sym = lookup_symbol_file (name, linkage_name, ++ block, domain, ++ cp_is_anonymous (namespace)); ++ return sym; + } + else + { +diff --git a/gdb/cp-support.c b/gdb/cp-support.c +index bf42636..9f04c86 100644 +--- a/gdb/cp-support.c ++++ b/gdb/cp-support.c +@@ -175,7 +175,8 @@ mangled_name_to_comp (const char *mangled_name, int options, + return ret; + } + +-/* Return the name of the class containing method PHYSNAME. */ ++/* Return the name of the class or namespace containing ++ function, method, or variable PHYSNAME. */ + + char * + cp_class_name_from_physname (const char *physname) +diff --git a/gdb/cp-support.h b/gdb/cp-support.h +index 837ca6c..23f8d5b 100644 +--- a/gdb/cp-support.h ++++ b/gdb/cp-support.h +@@ -38,14 +38,28 @@ struct demangle_component; + + /* This struct is designed to store data from using directives. It + says that names from namespace INNER should be visible within +- namespace OUTER. OUTER should always be a strict initial substring +- of INNER. These form a linked list; NEXT is the next element of +- the list. */ ++ namespace OUTER These form a linked list; NEXT is the next element of ++ the list. ALIAS is set to a non empty string if the imported namespace ++ has been aliased.Eg: ++ namespace C=A::B; ++ ALIAS = "C" ++ DECLARATION is the name of the imported declaration, if this import ++ statement represents one. Eg: ++ using A::x; ++ Where x is variable in namespace A. declaration is set to x. ++*/ + + struct using_direct + { + char *inner; + char *outer; ++ ++ char *alias; ++ ++ char *declaration; ++ ++ int line_number; ++ + struct using_direct *next; + }; + +@@ -54,6 +68,7 @@ struct using_direct + + extern char *cp_canonicalize_string (const char *string); + ++ + extern char *cp_class_name_from_physname (const char *physname); + + extern char *method_name_from_physname (const char *physname); +@@ -76,9 +91,18 @@ extern struct type *cp_lookup_rtti_type (const char *name, + + extern int cp_is_anonymous (const char *namespace); + +-extern void cp_add_using_directive (const char *name, +- unsigned int outer_length, +- unsigned int inner_length); ++extern void cp_add_using_directive (const char *outer, ++ const char *inner, ++ const char *alias, ++ const char *declaration, ++ const int line_number); ++ ++extern struct using_direct *cp_add_using (const char *outer, ++ const char *inner, ++ const char *alias, ++ const char *declaration, ++ const int line_number, ++ struct using_direct *next); + + extern void cp_initialize_namespace (void); + +@@ -98,6 +122,19 @@ extern struct symbol *cp_lookup_symbol_nonlocal (const char *name, + const struct block *block, + const domain_enum domain); + ++extern struct symbol *lookup_namespace_scope (const char *name, ++ const char *linkage_name, ++ const struct block *block, ++ const domain_enum domain, ++ const char *scope, ++ int scope_len); ++ ++extern struct symbol *cp_lookup_symbol_namespace_incremental (const char *namespace, ++ const char *name, ++ const char *linkage_name, ++ const struct block *block, ++ const domain_enum domain); ++ + extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, + const char *name, + const char *linkage_name, +diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c +index 8b7d868..4e33fa0 100644 +--- a/gdb/cp-valprint.c ++++ b/gdb/cp-valprint.c +@@ -36,6 +36,7 @@ + #include "valprint.h" + #include "cp-support.h" + #include "language.h" ++#include "python/python.h" + + /* Controls printing of vtbl's */ + static void +@@ -418,12 +419,27 @@ cp_print_value (struct type *type, struct type *real_type, + if (skip >= 1) + fprintf_filtered (stream, ""); + else +- cp_print_value_fields (baseclass, thistype, base_valaddr, +- thisoffset + boffset, address + boffset, +- stream, recurse, options, +- ((struct type **) +- obstack_base (&dont_print_vb_obstack)), +- 0); ++ { ++ int result = 0; ++ ++ /* Attempt to run the Python pretty-printers on the ++ baseclass if possible. */ ++ if (!options->raw) ++ result = apply_val_pretty_printer (baseclass, base_valaddr, ++ thisoffset + boffset, ++ address + boffset, ++ stream, recurse, ++ options, ++ current_language); ++ ++ if (!result) ++ cp_print_value_fields (baseclass, thistype, base_valaddr, ++ thisoffset + boffset, address + boffset, ++ stream, recurse, options, ++ ((struct type **) ++ obstack_base (&dont_print_vb_obstack)), ++ 0); ++ } + fputs_filtered (", ", stream); + + flush_it: +@@ -461,6 +477,7 @@ cp_print_static_field (struct type *type, + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + { + CORE_ADDR *first_dont_print; ++ CORE_ADDR addr; + int i; + + first_dont_print +@@ -470,7 +487,7 @@ cp_print_static_field (struct type *type, + + while (--i >= 0) + { +- if (VALUE_ADDRESS (val) == first_dont_print[i]) ++ if (value_address (val) == first_dont_print[i]) + { + fputs_filtered ("", +@@ -479,12 +496,13 @@ cp_print_static_field (struct type *type, + } + } + +- obstack_grow (&dont_print_statmem_obstack, (char *) &VALUE_ADDRESS (val), ++ addr = value_address (val); ++ obstack_grow (&dont_print_statmem_obstack, (char *) &addr, + sizeof (CORE_ADDR)); + + CHECK_TYPEDEF (type); + cp_print_value_fields (type, type, value_contents_all (val), +- value_embedded_offset (val), VALUE_ADDRESS (val), ++ value_embedded_offset (val), value_address (val), + stream, recurse, options, NULL, 1); + return; + } +@@ -492,7 +510,7 @@ cp_print_static_field (struct type *type, + opts = *options; + opts.deref_ref = 0; + val_print (type, value_contents_all (val), +- value_embedded_offset (val), VALUE_ADDRESS (val), ++ value_embedded_offset (val), value_address (val), + stream, recurse, &opts, current_language); + } + +diff --git a/gdb/dbxread.c b/gdb/dbxread.c +index 115bdef..23ea50c 100644 +--- a/gdb/dbxread.c ++++ b/gdb/dbxread.c +@@ -1,6 +1,6 @@ + /* Read dbx symbol tables and convert to internal format, for GDB. + Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, +- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008. ++ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009. + Free Software Foundation, Inc. + + This file is part of GDB. +@@ -1198,6 +1198,8 @@ read_dbx_symtab (struct objfile *objfile) + bfd *abfd; + int textlow_not_set; + int data_sect_index; ++ char *sym_name; ++ int sym_len; + + /* Current partial symtab */ + struct partial_symtab *pst; +@@ -1681,6 +1683,28 @@ pos %d"), + if (!p) + continue; /* Not a debugging symbol. */ + ++ sym_len = 0; ++ if (psymtab_language == language_cplus) ++ { ++ char *new_name, *name = alloca (p - namestring + 1); ++ memcpy (name, namestring, p - namestring); ++ name[p - namestring] = '\0'; ++ new_name = cp_canonicalize_string (name); ++ if (new_name != NULL) ++ { ++ sym_len = strlen (new_name); ++ sym_name = obsavestring (new_name, sym_len, ++ &objfile->objfile_obstack); ++ xfree (new_name); ++ } ++ } ++ ++ if (sym_len == 0) ++ { ++ sym_name = namestring; ++ sym_len = p - namestring; ++ } ++ + /* Main processing section for debugging symbols which + the initial read through the symbol tables needs to worry + about. If we reach this point, the symbol which we are +@@ -1698,7 +1722,7 @@ pos %d"), + namestring = gdbarch_static_transform_name (gdbarch, + namestring); + +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + VAR_DOMAIN, LOC_STATIC, + &objfile->static_psymbols, + 0, nlist.n_value, +@@ -1710,7 +1734,7 @@ pos %d"), + data_sect_index); + /* The addresses in these entries are reported to be + wrong. See the code that reads 'G's for symtabs. */ +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + VAR_DOMAIN, LOC_STATIC, + &objfile->global_psymbols, + 0, nlist.n_value, +@@ -1728,7 +1752,7 @@ pos %d"), + || (p == namestring + 1 + && namestring[0] != ' ')) + { +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + STRUCT_DOMAIN, LOC_TYPEDEF, + &objfile->static_psymbols, + nlist.n_value, 0, +@@ -1736,7 +1760,7 @@ pos %d"), + if (p[2] == 't') + { + /* Also a typedef with the same name. */ +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + VAR_DOMAIN, LOC_TYPEDEF, + &objfile->static_psymbols, + nlist.n_value, 0, +@@ -1749,7 +1773,7 @@ pos %d"), + case 't': + if (p != namestring) /* a name is there, not just :T... */ + { +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + VAR_DOMAIN, LOC_TYPEDEF, + &objfile->static_psymbols, + nlist.n_value, 0, +@@ -1829,7 +1853,7 @@ pos %d"), + + case 'c': + /* Constant, e.g. from "const" in Pascal. */ +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + VAR_DOMAIN, LOC_CONST, + &objfile->static_psymbols, nlist.n_value, + 0, psymtab_language, objfile); +@@ -1893,7 +1917,7 @@ pos %d"), + pst->textlow = nlist.n_value; + textlow_not_set = 0; + } +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + VAR_DOMAIN, LOC_BLOCK, + &objfile->static_psymbols, + 0, nlist.n_value, +@@ -1961,7 +1985,7 @@ pos %d"), + pst->textlow = nlist.n_value; + textlow_not_set = 0; + } +- add_psymbol_to_list (namestring, p - namestring, ++ add_psymbol_to_list (sym_name, sym_len, + VAR_DOMAIN, LOC_BLOCK, + &objfile->global_psymbols, + 0, nlist.n_value, +@@ -3547,6 +3571,7 @@ static struct sym_fns aout_sym_fns = + dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */ + dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + dbx_symfile_read, /* sym_read: read a symbol file into symtab */ ++ NULL, /* sym_read_psymbols */ + dbx_symfile_finish, /* sym_finish: finished with file, cleanup */ + default_symfile_offsets, /* sym_offsets: parse user's offsets to + internal form */ +diff --git a/gdb/defs.h b/gdb/defs.h +index 845b320..ad6e7d7 100644 +--- a/gdb/defs.h ++++ b/gdb/defs.h +@@ -151,6 +151,9 @@ extern int dbx_commands; + /* System root path, used to find libraries etc. */ + extern char *gdb_sysroot; + ++/* GDB datadir, used to store data files. */ ++extern char *gdb_datadir; ++ + /* Search path for separate debug files. */ + extern char *debug_file_directory; + +@@ -366,6 +369,9 @@ extern struct cleanup *make_cleanup_fclose (FILE *file); + + extern struct cleanup *make_cleanup_bfd_close (bfd *abfd); + ++struct obstack; ++extern struct cleanup *make_cleanup_obstack_free (struct obstack *obstack); ++ + extern struct cleanup *make_cleanup_restore_integer (int *variable); + + extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *); +diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo +index 10e7388..c4ab391 100644 +--- a/gdb/doc/gdb.texinfo ++++ b/gdb/doc/gdb.texinfo +@@ -955,8 +955,10 @@ Connect to process ID @var{number}, as with the @code{attach} command. + @itemx -x @var{file} + @cindex @code{--command} + @cindex @code{-x} +-Execute @value{GDBN} commands from file @var{file}. @xref{Command +-Files,, Command files}. ++Execute commands from file @var{file}. If @var{file} ends in ++@samp{.py}, then the file is evaluated as Python code. If Python ++support is not enabled in this @value{GDBN}, then an error occurs. ++@xref{Command Files,, Command files}. + + @item -eval-command @var{command} + @itemx -ex @var{command} +@@ -1148,6 +1150,16 @@ for remote debugging. + Run using @var{device} for your program's standard input and output. + @c FIXME: kingdon thinks there is more to -tty. Investigate. + ++@item -P ++@cindex @code{-P} ++@itemx --python ++@cindex @code{--python} ++Change interpretation of command line so that the argument immediately ++following this switch is taken to be the name of a Python script file. ++This option stops option processing; subsequent options are passed to ++Python as @code{sys.argv}. This option is only available if Python ++scripting support was enabled when @value{GDBN} was configured. ++ + @c resolve the situation of these eventually + @item -tui + @cindex @code{--tui} +@@ -3636,6 +3648,98 @@ A failed Ada assertion. + A call to @code{exec}. This is currently only available for HP-UX + and @sc{gnu}/Linux. + ++@item syscall ++@itemx syscall @r{[}@var{name} @r{|} @var{number}@r{]} @r{...} ++@cindex break on a system call. ++A call to or return from a @code{syscall}. If no argument is specified, ++then it catches a call to or return from any system call. ++ ++@var{name} can be any valid system call name in the system. You can ++use the @value{GDBN} command-line completion facilities to list the ++available choices. @xref{Completion,, Command Completion}, for ++details on how to do this. ++ ++You may also specify the system call numerically. This may be useful ++if @value{GDBN} does not fully support your system's list of system ++calls. ++ ++The example below illustrates how this command works if you don't provide ++arguments to it: ++ ++@smallexample ++(@value{GDBP}) catch syscall ++Catchpoint 1 (syscall) ++(@value{GDBP}) r ++Starting program: /tmp/catch-syscall ++ ++Catchpoint 1 (call to syscall 'close'), 0xffffe424 in __kernel_vsyscall () ++(@value{GDBP}) c ++Continuing. ++ ++Catchpoint 1 (returned from syscall 'close'), 0xffffe424 in __kernel_vsyscall () ++(@value{GDBP}) ++@end smallexample ++ ++Here is an example of catching a system call by name: ++ ++@smallexample ++(@value{GDBP}) catch syscall chroot ++Catchpoint 1 (syscall(s) 'chroot') ++(@value{GDBP}) r ++Starting program: /tmp/catch-syscall ++ ++Catchpoint 1 (call to syscall 'chroot'), 0xffffe424 in __kernel_vsyscall () ++(@value{GDBP}) c ++Continuing. ++ ++Catchpoint 1 (returned from syscall 'chroot'), 0xffffe424 in __kernel_vsyscall () ++(@value{GDBP}) ++@end smallexample ++ ++And last but not least, an example of specifying a system call ++numerically: ++ ++@smallexample ++(@value{GDBP}) catch syscall 252 ++Catchpoint 1 (syscall(s) 'exit_group') ++(@value{GDBP}) r ++Starting program: /tmp/catch-syscall ++ ++Catchpoint 1 (call to syscall 'exit_group'), 0xffffe424 in __kernel_vsyscall () ++(@value{GDBP}) c ++Continuing. ++ ++Program exited normally. ++(@value{GDBP}) ++@end smallexample ++ ++If you configure @value{GDBN} using the @samp{--without-expat} option, ++it will not be able to display syscall names. Also, if your ++architecture does not have an XML file describing its system calls, ++you will not be able to see the syscall names. In either case, you ++will see a warning like this: ++ ++@smallexample ++(@value{GDBP}) catch syscall ++warning: Could not open "syscalls/i386-linux.xml" ++warning: Could not load the syscall XML file 'syscalls/i386-linux.xml'. ++GDB will not be able to display syscall names. ++Catchpoint 1 (syscall) ++(@value{GDBP}) ++@end smallexample ++ ++Of course, the file name will change depending on your architecture and system. ++ ++Still using the example above, you can also try to catch a syscall by its ++number. In this case, you would see something like: ++ ++@smallexample ++(@value{GDBP}) catch syscall 252 ++Catchpoint 1 (syscall(s) 252) ++@end smallexample ++ ++Again, in this case @value{GDBN} would not be able to display syscall's names. ++ + @item fork + A call to @code{fork}. This is currently only available for HP-UX + and @sc{gnu}/Linux. +@@ -4711,6 +4815,24 @@ the program to report that some thread has stopped before prompting for + another command. In background execution, @value{GDBN} immediately gives + a command prompt so that you can issue other commands while your program runs. + ++You need to explicitly enable asynchronous mode before you can use ++background execution commands. You can use these commands to ++manipulate the asynchronous mode setting: ++ ++@table @code ++@kindex set target-async ++@item set target-async on ++Enable asynchronous mode. ++@item set target-async off ++Disable asynchronous mode. ++@kindex show target-async ++@item show target-async ++Show the current target-async setting. ++@end table ++ ++If the target doesn't support async mode, @value{GDBN} issues an error ++message if you attempt to use the background execution commands. ++ + To specify background execution, add a @code{&} to the command. For example, + the background form of the @code{continue} command is @code{continue&}, or + just @code{c&}. The execution commands that accept background execution +@@ -4776,11 +4898,6 @@ only the current thread. To stop the whole program in non-stop mode, + use @code{interrupt -a}. + @end table + +-You may need to explicitly enable async mode before you can use background +-execution commands, with the @code{set target-async 1} command. If the +-target doesn't support async mode, @value{GDBN} issues an error message +-if you attempt to use the background execution commands. +- + @node Thread-Specific Breakpoints + @subsection Thread-Specific Breakpoints + +@@ -6536,6 +6653,12 @@ Without this format, @value{GDBN} displays pointers to and arrays of + @code{char}, @w{@code{unsigned char}}, and @w{@code{signed char}} as + strings. Single-byte members of a vector are displayed as an integer + array. ++ ++@item r ++@cindex raw printing ++Print using the @samp{raw} formatting. By default, @value{GDBN} will ++use a type-specific pretty-printer. The @samp{r} format bypasses any ++pretty-printer which might exist for the value's type. + @end table + + For example, to print the program counter in hex (@pxref{Registers}), type +@@ -7408,6 +7531,20 @@ On HP-UX systems, if you refer to a function or variable name that + begins with a dollar sign, @value{GDBN} searches for a user or system + name first, before it searches for a convenience variable. + ++@cindex convenience functions ++@value{GDBN} also supplies some @dfn{convenience functions}. These ++have a syntax similar to convenience variables. A convenience ++function can be used in an expression just like an ordinary function; ++however, a convenience function is implemented internally to ++@value{GDBN}. ++ ++@table @code ++@item help function ++@kindex help function ++@cindex show all convenience functions ++Print a list of all convenience functions. ++@end table ++ + @node Registers + @section Registers + +@@ -7931,13 +8068,17 @@ support: + @table @code + @item set target-charset @var{charset} + @kindex set target-charset +-Set the current target character set to @var{charset}. We list the +-character set names @value{GDBN} recognizes below, but if you type +-@code{set target-charset} followed by @key{TAB}@key{TAB}, @value{GDBN} will +-list the target character sets it supports. +-@end table ++Set the current target character set to @var{charset}. If you type ++@code{set target-charset} followed by @key{TAB}@key{TAB}, @value{GDBN} ++will list the target character sets it supports. ++ ++@item set target-wide-charset @var{charset} ++@kindex set target-wide-charset ++Set the current target wide character set to @var{charset}. The ++target wide character set is the character set used by @code{wchar_t}. ++If you type @code{set target-charset} followed by @key{TAB}@key{TAB}, ++@value{GDBN} will list the target character sets it supports. + +-@table @code + @item set host-charset @var{charset} + @kindex set host-charset + Set the current host character set to @var{charset}. +@@ -7947,10 +8088,9 @@ system it is running on; you can override that default using the + @code{set host-charset} command. + + @value{GDBN} can only use certain character sets as its host character +-set. We list the character set names @value{GDBN} recognizes below, and +-indicate which can be host character sets, but if you type +-@code{set target-charset} followed by @key{TAB}@key{TAB}, @value{GDBN} will +-list the host character sets it supports. ++set. If you type @code{set target-charset} followed by ++@key{TAB}@key{TAB}, @value{GDBN} will list the host character sets it ++supports. + + @item set charset @var{charset} + @kindex set charset +@@ -7974,37 +8114,6 @@ Show the name of the current target charset. + + @end table + +-@value{GDBN} currently includes support for the following character +-sets: +- +-@table @code +- +-@item ASCII +-@cindex ASCII character set +-Seven-bit U.S. @sc{ascii}. @value{GDBN} can use this as its host +-character set. +- +-@item ISO-8859-1 +-@cindex ISO 8859-1 character set +-@cindex ISO Latin 1 character set +-The ISO Latin 1 character set. This extends @sc{ascii} with accented +-characters needed for French, German, and Spanish. @value{GDBN} can use +-this as its host character set. +- +-@item EBCDIC-US +-@itemx IBM1047 +-@cindex EBCDIC character set +-@cindex IBM1047 character set +-Variants of the @sc{ebcdic} character set, used on some of IBM's +-mainframe operating systems. (@sc{gnu}/Linux on the S/390 uses U.S. @sc{ascii}.) +-@value{GDBN} cannot use these as its host character set. +- +-@end table +- +-Note that these are all single-byte character sets. More work inside +-@value{GDBN} is needed to support multi-byte or variable-width character +-encodings, like the UTF-8 and UCS-2 encodings of Unicode. +- + Here is an example of @value{GDBN}'s character set support in action. + Assume that the following source code has been placed in the file + @file{charset-test.c}: +@@ -12481,6 +12590,53 @@ returned. In contrast, the @code{finish} command (@pxref{Continuing + and Stepping, ,Continuing and Stepping}) resumes execution until the + selected stack frame returns naturally. + ++@value{GDBN} needs to know how the @var{expression} argument should be set for ++the inferior. The concrete registers assignment depends on the OS ABI and the ++type being returned by the selected stack frame. For example it is common for ++OS ABI to return floating point values in FPU registers while integer values in ++CPU registers. Still some ABIs return even floating point values in CPU ++registers. Larger integer widths (such as @code{long long int}) also have ++specific placement rules. @value{GDBN} already knows the OS ABI from its ++current target so it needs to find out also the type being returned to make the ++assignment into the right register(s). ++ ++Normally, the selected stack frame has debug info. @value{GDBN} will always ++use the debug info instead of the implicit type of @var{expression} when the ++debug info is available. For example, if you type @kbd{return -1}, and the ++function in the current stack frame is declared to return a @code{long long ++int}, @value{GDBN} transparently converts the implicit @code{int} value of -1 ++into a @code{long long int}: ++ ++@smallexample ++Breakpoint 1, func () at gdb.base/return-nodebug.c:29 ++29 return 31; ++(@value{GDBP}) return -1 ++Make func return now? (y or n) y ++#0 0x004004f6 in main () at gdb.base/return-nodebug.c:43 ++43 printf ("result=%lld\n", func ()); ++(@value{GDBP}) ++@end smallexample ++ ++However, if the selected stack frame does not have a debug info, e.g., if the ++function was compiled without debug info, @value{GDBN} has to find out the type ++to return from user. Specifying a different type by mistake may set the value ++in different inferior registers than the caller code expects. For example, ++typing @kbd{return -1} with its implicit type @code{int} would set only a part ++of a @code{long long int} result for a debug info less function (on 32-bit ++architectures). Therefore the user is required to specify the return type by ++an appropriate cast explicitly: ++ ++@smallexample ++Breakpoint 2, 0x0040050b in func () ++(@value{GDBP}) return -1 ++Return value type not available for selected stack frame. ++Please use an explicit cast of the value to return. ++(@value{GDBP}) return (long long int) -1 ++Make selected stack frame return now? (y or n) y ++#0 0x00400526 in main () ++(@value{GDBP}) ++@end smallexample ++ + @node Calling + @section Calling Program Functions + +@@ -12510,6 +12666,12 @@ It is possible for the function you call via the @code{print} or + the function, or if you passed it incorrect arguments). What happens + in that case is controlled by the @code{set unwindonsignal} command. + ++Similarly, with a C++ program it is possible for the function you ++call via the @code{print} or @code{call} command to generate an ++exception that is not handled due to the constraints of the dummy ++frame. What happens in that case is controlled by the ++@code{set unwind-on-terminating-exception} command. ++ + @table @code + @item set unwindonsignal + @kindex set unwindonsignal +@@ -12526,6 +12688,23 @@ received. + @kindex show unwindonsignal + Show the current setting of stack unwinding in the functions called by + @value{GDBN}. ++ ++@item set unwind-on-terminating-exception ++@kindex set unwind-on-terminating-exception ++@cindex unwind stack in called functions ++@cindex call dummy stack unwinding on unhandled exception. ++Set unwinding of the stack if a C++ exception is raised but unhandled ++while in a function that @value{GDBN} called in the program being ++debugged. If set to on (the default), @value{GDBN} unwinds the stack ++it created for the call and restores the context to what it was before ++the call. If set to off, @value{GDBN} the exception is delivered to ++the default C++ exception handler. ++ ++@item show unwind-on-terminating-exception ++@kindex show unwind-on-terminating-exception ++Show the current setting of stack unwinding in the functions called by ++@value{GDBN}. ++ + @end table + + @cindex weak alias functions +@@ -17815,7 +17994,7 @@ command: + @table @code + @kindex source + @cindex execute commands from a file +-@item source [@code{-v}] @var{filename} ++@item source [@code{-v}] [@code{-p}] @var{filename} + Execute the command file @var{filename}. + @end table + +@@ -17832,6 +18011,11 @@ If @code{-v}, for verbose mode, is given then @value{GDBN} displays + each command as it is executed. The option must be given before + @var{filename}, and is interpreted as part of the filename anywhere else. + ++If @var{filename} ends in @samp{.py}, or if @code{-p}, for Python, is ++given then @value{GDBN} evaluates the contents of the file as Python ++code. If Python support is not compiled in to @value{GDBN}, then an ++error occurs. ++ + Commands that would ask for confirmation if used interactively proceed + without asking when used in a command file. Many @value{GDBN} commands that + normally print messages to say what they are doing omit the messages +@@ -18093,8 +18277,6 @@ containing @code{end}. For example: + + @smallexample + (@value{GDBP}) python +-Type python script +-End with a line saying just "end". + >print 23 + >end + 23 +@@ -18107,6 +18289,14 @@ in a Python script. This can be controlled using @code{maint set + python print-stack}: if @code{on}, the default, then Python stack + printing is enabled; if @code{off}, then Python stack printing is + disabled. ++ ++@kindex maint set python auto-load ++@item maint set python auto-load ++By default, @value{GDBN} will attempt to automatically load Python ++code when an object file is opened. This can be controlled using ++@code{maint set python auto-load}: if @code{on}, the default, then ++Python auto-loading is enabled; if @code{off}, then Python ++auto-loading is disabled. + @end table + + @node Python API +@@ -18114,6 +18304,14 @@ disabled. + @cindex python api + @cindex programming in python + ++You can get quick online help for @value{GDBN}'s Python API by issuing ++the command @w{@kbd{python help (gdb)}}. ++ ++Functions and methods which have two or more optional arguments allow ++them to be specified using keyword syntax. This allows passing some ++optional arguments while skipping others. Example: ++@w{@code{gdb.some_function ('foo', bar = 1, baz = 2)}}. ++ + @cindex python stdout + @cindex python pagination + At startup, @value{GDBN} overrides Python's @code{sys.stdout} and +@@ -18125,8 +18323,17 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown. + @menu + * Basic Python:: Basic Python Functions. + * Exception Handling:: +-* Values From Inferior:: ++* Auto-loading:: Automatically loading Python code. ++* Values From Inferior:: Python representation of values. ++* Types In Python:: Python representation of types. ++* Pretty Printing:: Pretty-printing values. ++* Threads In Python:: Accessing inferior threads from Python. + * Commands In Python:: Implementing new commands in Python. ++* Parameters In Python:: Adding new @value{GDBN} parameters. ++* Functions In Python:: Writing new convenience functions. ++* Objfiles In Python:: Object files. ++* Breakpoints In Python:: Manipulating breakpoints using Python. ++* Frames In Python:: Acessing inferior stack frames from Python. + @end menu + + @node Basic Python +@@ -18152,10 +18359,30 @@ command as having originated from the user invoking it interactively. + It must be a boolean value. If omitted, it defaults to @code{False}. + @end defun + +-@findex gdb.get_parameter +-@defun get_parameter parameter +-Return the value of a @value{GDBN} parameter. @var{parameter} is a +-string naming the parameter to look up; @var{parameter} may contain ++@findex gdb.current_objfile ++@defun current_objfile ++When auto-loading a Python script (@pxref{Auto-loading}), @value{GDBN} ++sets the ``current objfile'' to the corresponding objfile. This ++function returns the current objfile. If there is no current objfile, ++this function returns @code{None}. ++@end defun ++ ++@findex gdb.breakpoints ++@defun breakpoints ++Return a sequence holding all of @value{GDBN}'s breakpoints. ++@xref{Breakpoints In Python}, for more information. ++@end defun ++ ++@findex gdb.objfiles ++@defun objfiles ++Return a sequence of all the objfiles current known to @value{GDBN}. ++@xref{Objfiles In Python}. ++@end defun ++ ++@findex gdb.parameter ++@defun parameter name ++Return the value of the named @value{GDBN} parameter. @var{name} is a ++string naming the parameter to look up; @var{name} may contain + spaces if the parameter has a multi-part name. For example, + @samp{print object} is a valid parameter name. + +@@ -18179,6 +18406,28 @@ If no exception is raised, the return value is always an instance of + @code{gdb.Value} (@pxref{Values From Inferior}). + @end defun + ++@findex gdb.parse_and_eval ++@defun parse_and_eval expression ++Parse @var{expression} as an expression in the current language, ++evaluate it, and return the result as a @code{gdb.Value}. ++@var{expression} must be a string. ++@end defun ++ ++@findex gdb.post_event ++@defun post_event event ++Put @var{event}, a callable object taking no arguments, into ++@value{GDBN}'s internal event queue. This callable will be invoked at ++some later point, during @value{GDBN}'s event processing. Events ++posted using @code{post_event} will be run in the order in which they ++were posted; however, there is no way to know when they will be ++processed relative to other events inside @value{GDBN}. ++ ++@value{GDBN} is not thread-safe. If your Python program uses multiple ++threads, you must be careful to only call @value{GDBN}-specific ++functions in the main @value{GDBN} thread. @code{post_event} ensures ++this. ++@end defun ++ + @findex gdb.write + @defun write string + Print a string to @value{GDBN}'s paginated standard output stream. +@@ -18193,6 +18442,66 @@ Flush @value{GDBN}'s paginated standard output stream. Flushing + function. + @end defun + ++@findex gdb.frames ++@defun frames ++Return a tuple of all frame objects. ++@end defun ++ ++@findex gdb.newest_frame ++@defun newest_frame ++Return the newest frame object. ++@end defun ++ ++@findex gdb.selected_frame ++@defun selected_frame ++Return the selected frame object. ++@end defun ++ ++@findex gdb.frame_stop_reason_string ++@defun frame_stop_reason_string @var{reason} ++Return a string explaining the reason why @value{GDBN} stopped unwinding ++frames, as expressed by the given @var{reason} code (an integer, see the ++@code{unwind_stop_reason} method in ++@xref{Frames In Python,,Accessing inferior stack frames from Python}.) ++@end defun ++ ++@findex gdb.read_memory ++@defun read_memory @var{address} @var{length} ++Read @var{length} bytes of memory from the inferior, starting at @var{address}. ++Returns a buffer object, which behaves much like an array or a string. It ++can be modified and given to the @code{gdb.write_memory} function. ++@end defun ++ ++@findex gdb.write_memory ++@defun write_memory @var{address} @var{buffer} @r{[}@var{length}@r{]} ++Write the contents of @var{buffer} (a Python object which supports the buffer ++protocol, i.e., a string, an array or the object returned from ++@code{gdb.read_memory}) to the inferior, starting at @var{address}. If given, ++@var{length} determines the number of bytes from @var{buffer} to be written. ++@end defun ++ ++@findex gdb.search_memory ++@defun search_memory @var{address} @var{length} @var{pattern} @r{[}@var{size}@r{]} @r{[}@var{max_count}@r{]} ++Search a region of the inferior memory starting at @var{address} with the given ++@var{length}. @var{pattern} can be a string, a byte array, a buffer object, ++a number, a @code{gdb.Value} object (@pxref{Values From Inferior}) or a list ++or tuple with elements in any combination of those types. If @var{size} is ++given and is non-zero, it specifies the size in bytes of a Python scalar or ++@code{gdb.Value} in the search pattern. If @var{size} is zero or not specified, ++ it is taken from the value's type in the current language. ++This is useful when one wants to specify the search ++pattern as a mixture of types. ++Note that this means, for example, that in the case of C-like languages ++a search for an untyped 0x42 will search for @samp{(int) 0x42} ++which is typically four bytes. @var{max_count} is the highest number of matches ++to search for. ++@end defun ++ ++@findex gdb.solib_address ++@defun solib_address @var{address} ++Return the name of the shared library holding the given address, or None. ++@end defun ++ + @node Exception Handling + @subsubsection Exception Handling + @cindex python exceptions +@@ -18224,6 +18533,44 @@ message as its value, and the Python call stack backtrace at the + Python statement closest to where the @value{GDBN} error occured as the + traceback. + ++@node Auto-loading ++@subsubsection Auto-loading ++ ++When a new object file (@pxref{Objfiles In Python}) is read (for ++example, due to the @code{file} command, or because the inferior has ++loaded a shared library), @value{GDBN} will look for a file named by ++adding @samp{-gdb.py} to the object file's real name (the name formed ++after following all symlinks and resolving @code{.} and @code{..} ++components). If this file exists and is readable, @value{GDBN} will ++evaluate it as a Python script. ++ ++If this file does not exist, and if the parameter ++@code{debug-file-directory} is set, then @value{GDBN} will append the ++object file's real name to the value of this parameter, and try again. ++ ++Finally, if this file does not exist, then @value{GDBN} will look in ++subdirectory of @code{gdb_datadir} (whose value is available from ++@code{maint show gdb_datadir}). Specifically, @value{GDBN} will take ++the value of @code{gdb_datadir}, append @samp{python/auto-load}, and ++then append the object file's real name. ++ ++Also, if a separate debug file is used, @value{GDBN} will look for the ++@samp{-gdb.py} file both in the directory associated with the ++application and the directory associated with the separate debug file. ++ ++When reading a @samp{-gdb.py} file, @value{GDBN} sets the ``current ++objfile''. This is available via the @code{gdb.current_objfile} ++function. This can be useful for registering objfile-specific ++pretty-printers. ++ ++This feature is useful for supplying application-specific debugging ++commands and scripts. It can be disabled using @code{maint set python ++auto-load}. ++ ++@value{GDBN} does not track which files it has already auto-loaded. ++So, your @samp{-gdb.py} file should take care to ensure that it may be ++evaluated multiple times without error. ++ + @node Values From Inferior + @subsubsection Values From Inferior + @cindex values from inferior, with Python +@@ -18258,8 +18605,36 @@ bar = some_val['foo'] + + Again, @code{bar} will also be a @code{gdb.Value} object. + +-For pointer data types, @code{gdb.Value} provides a method for +-dereferencing the pointer to obtain the object it points to. ++The following attributes are provided: ++ ++@table @code ++@defivar Value address ++If this object is addressable, this read-only attribute holds a ++@code{gdb.Value} object representing the address. Otherwise, ++this attribute holds @code{None}. ++@end defivar ++ ++@cindex optimized out value in Python ++@defivar Value is_optimized_out ++This read-only boolean attribute is true if the compiler optimized out ++this value, thus it is not available for fetching from the inferior. ++@end defivar ++ ++@defivar Value type ++The type of this @code{gdb.Value}. The result is a @code{gdb.Type} ++object. ++@end defivar ++@end table ++ ++The following methods are provided: ++ ++@table @code ++@defmethod Value cast type ++Cast the @code{gdb.Value} to the type represented by @var{type}, and ++return a new @code{gdb.Value}. @var{type} must be a @code{gdb.Type} ++object. If the cast cannot be performed for some reason, an exception ++is thrown. ++@end defmethod + + @defmethod Value dereference + This method returns a new @code{gdb.Value} object whose contents is +@@ -18282,7 +18657,7 @@ The result @code{bar} will be a @code{gdb.Value} object holding the + value pointed to by @code{foo}. + @end defmethod + +-@defmethod Value string @r{[}encoding @r{[}errors@r{]}@r{]} ++@defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]} + If this @code{gdb.Value} represents a string, then this method + converts the contents to a Python string. Otherwise, this method will + throw an exception. +@@ -18308,6 +18683,465 @@ will be used, if the current language is able to supply one. + The optional @var{errors} argument is the same as the corresponding + argument to Python's @code{string.decode} method. + @end defmethod ++@end table ++ ++@node Types In Python ++@subsubsection Types In Python ++@cindex types in Python ++@cindex Python, working with types ++ ++@tindex gdb.Type ++@value{GDBN} represents types from the inferior using the class ++@code{gdb.Type}. ++ ++The following type-related functions are available in the @code{gdb} ++module: ++ ++@findex gdb.lookup_type ++@defun lookup_type name [block] ++This function looks up a type by name. @var{name} is the name of the ++type to look up. It must be a string. ++ ++If @var{block} is given, then @var{name} is looked up in that scope. ++Otherwise, it is searched for globally. ++ ++Ordinarily, this function will return an instance of @code{gdb.Type}. ++If the named type cannot be found, it will throw an exception. ++@end defun ++ ++An instance of @code{Type} has the following attributes: ++ ++@table @code ++@defivar Type code ++The type code for this type. The type code will be one of the ++@code{TYPE_CODE_} constants defined below. ++@end defivar ++ ++@defivar Type sizeof ++The size of this type, in target @code{char} units. Usually, a ++target's @code{char} type will be an 8-bit byte. However, on some ++unusual platforms, this type may have a different size. ++@end defivar ++ ++@defivar Type tag ++The tag name for this type. The tag name is the name after ++@code{struct}, @code{union}, or @code{enum} in C and C@t{++}; not all ++languages have this concept. If this type has no tag name, then ++@code{None} is returned. ++@end defivar ++@end table ++ ++The following methods are provided: ++ ++@table @code ++@defmethod Type fields ++For structure and union types, this method returns the fields. Range ++types have two fields, the minimum and maximum values. Enum types ++have one field per enum constant. Function and method types have one ++field per parameter. The base types of C@t{++} classes are also ++represented as fields. If the type has no fields, or does not fit ++into one of these categories, an empty sequence will be returned. ++ ++Each field is an object, with some pre-defined attributes: ++@table @code ++@item bitpos ++This attribute is not available for @code{static} fields (as in ++C@t{++} or Java). For non-@code{static} fields, the value is the bit ++position of the field. ++ ++@item name ++The name of the field, or @code{None} for anonymous fields. ++ ++@item artificial ++This is @code{True} if the field is artificial, usually meaning that ++it was provided by the compiler and not the user. This attribute is ++always provided, and is @code{False} if the field is not artificial. ++ ++@item bitsize ++If the field is packed, or is a bitfield, then this will have a ++non-zero value, which is the size of the field in bits. Otherwise, ++this will be zero; in this case the field's size is given by its type. ++ ++@item type ++The type of the field. This is usually an instance of @code{Type}, ++but it can be @code{None} in some situations. ++@end table ++@end defmethod ++ ++@defmethod Type const ++Return a new @code{gdb.Type} object which represents a ++@code{const}-qualified variant of this type. ++@end defmethod ++ ++@defmethod Type volatile ++Return a new @code{gdb.Type} object which represents a ++@code{volatile}-qualified variant of this type. ++@end defmethod ++ ++@defmethod Type unqualified ++Return a new @code{gdb.Type} object which represents an unqualified ++variant of this type. That is, the result is neither @code{const} nor ++@code{volatile}. ++@end defmethod ++ ++@defmethod Type reference ++Return a new @code{gdb.Type} object which represents a reference to this ++type. ++@end defmethod ++ ++@defmethod Type strip_typedefs ++Return a new @code{gdb.Type} that represents the real type, ++after removing all layers of typedefs. ++@end defmethod ++ ++@defmethod Type target ++Return a new @code{gdb.Type} object which represents the target type ++of this type. ++ ++For a pointer type, the target type is the type of the pointed-to ++object. For an array type (meaning C-like arrays), the target type is ++the type of the elements of the array. For a function or method type, ++the target type is the type of the return value. For a complex type, ++the target type is the type of the elements. For a typedef, the ++target type is the aliased type. ++ ++If the type does not have a target, this method will throw an ++exception. ++@end defmethod ++ ++@defmethod Type template_argument n [block] ++If this @code{gdb.Type} is an instantiation of a template, this will ++return a new @code{gdb.Type} which represents the type of the ++@var{n}th template argument. ++ ++If this @code{gdb.Type} is not a template type, this will throw an ++exception. Ordinarily, only C@t{++} code will have template types. ++ ++If @var{block} is given, then @var{name} is looked up in that scope. ++Otherwise, it is searched for globally. ++@end defmethod ++@end table ++ ++ ++Each type has a code, which indicates what category this type falls ++into. The available type categories are represented by constants ++defined in the @code{gdb} module: ++ ++@table @code ++@findex TYPE_CODE_PTR ++@findex gdb.TYPE_CODE_PTR ++@item TYPE_CODE_PTR ++The type is a pointer. ++ ++@findex TYPE_CODE_ARRAY ++@findex gdb.TYPE_CODE_ARRAY ++@item TYPE_CODE_ARRAY ++The type is an array. ++ ++@findex TYPE_CODE_STRUCT ++@findex gdb.TYPE_CODE_STRUCT ++@item TYPE_CODE_STRUCT ++The type is a structure. ++ ++@findex TYPE_CODE_UNION ++@findex gdb.TYPE_CODE_UNION ++@item TYPE_CODE_UNION ++The type is a union. ++ ++@findex TYPE_CODE_ENUM ++@findex gdb.TYPE_CODE_ENUM ++@item TYPE_CODE_ENUM ++The type is an enum. ++ ++@findex TYPE_CODE_FLAGS ++@findex gdb.TYPE_CODE_FLAGS ++@item TYPE_CODE_FLAGS ++A bit flags type, used for things such as status registers. ++ ++@findex TYPE_CODE_FUNC ++@findex gdb.TYPE_CODE_FUNC ++@item TYPE_CODE_FUNC ++The type is a function. ++ ++@findex TYPE_CODE_INT ++@findex gdb.TYPE_CODE_INT ++@item TYPE_CODE_INT ++The type is an integer type. ++ ++@findex TYPE_CODE_FLT ++@findex gdb.TYPE_CODE_FLT ++@item TYPE_CODE_FLT ++A floating point type. ++ ++@findex TYPE_CODE_VOID ++@findex gdb.TYPE_CODE_VOID ++@item TYPE_CODE_VOID ++The special type @code{void}. ++ ++@findex TYPE_CODE_SET ++@findex gdb.TYPE_CODE_SET ++@item TYPE_CODE_SET ++A Pascal set type. ++ ++@findex TYPE_CODE_RANGE ++@findex gdb.TYPE_CODE_RANGE ++@item TYPE_CODE_RANGE ++A range type, that is, an integer type with bounds. ++ ++@findex TYPE_CODE_STRING ++@findex gdb.TYPE_CODE_STRING ++@item TYPE_CODE_STRING ++A string type. Note that this is only used for certain languages with ++language-defined string types; C strings are not represented this way. ++ ++@findex TYPE_CODE_BITSTRING ++@findex gdb.TYPE_CODE_BITSTRING ++@item TYPE_CODE_BITSTRING ++A string of bits. ++ ++@findex TYPE_CODE_ERROR ++@findex gdb.TYPE_CODE_ERROR ++@item TYPE_CODE_ERROR ++An unknown or erroneous type. ++ ++@findex TYPE_CODE_METHOD ++@findex gdb.TYPE_CODE_METHOD ++@item TYPE_CODE_METHOD ++A method type, as found in C++ or Java. ++ ++@findex TYPE_CODE_METHODPTR ++@findex gdb.TYPE_CODE_METHODPTR ++@item TYPE_CODE_METHODPTR ++A pointer-to-member-function. ++ ++@findex TYPE_CODE_MEMBERPTR ++@findex gdb.TYPE_CODE_MEMBERPTR ++@item TYPE_CODE_MEMBERPTR ++A pointer-to-member. ++ ++@findex TYPE_CODE_REF ++@findex gdb.TYPE_CODE_REF ++@item TYPE_CODE_REF ++A reference type. ++ ++@findex TYPE_CODE_CHAR ++@findex gdb.TYPE_CODE_CHAR ++@item TYPE_CODE_CHAR ++A character type. ++ ++@findex TYPE_CODE_BOOL ++@findex gdb.TYPE_CODE_BOOL ++@item TYPE_CODE_BOOL ++A boolean type. ++ ++@findex TYPE_CODE_COMPLEX ++@findex gdb.TYPE_CODE_COMPLEX ++@item TYPE_CODE_COMPLEX ++A complex float type. ++ ++@findex TYPE_CODE_TYPEDEF ++@findex gdb.TYPE_CODE_TYPEDEF ++@item TYPE_CODE_TYPEDEF ++A typedef to some other type. ++ ++@findex TYPE_CODE_NAMESPACE ++@findex gdb.TYPE_CODE_NAMESPACE ++@item TYPE_CODE_NAMESPACE ++A C++ namespace. ++ ++@findex TYPE_CODE_DECFLOAT ++@findex gdb.TYPE_CODE_DECFLOAT ++@item TYPE_CODE_DECFLOAT ++A decimal floating point type. ++ ++@findex TYPE_CODE_INTERNAL_FUNCTION ++@findex gdb.TYPE_CODE_INTERNAL_FUNCTION ++@item TYPE_CODE_INTERNAL_FUNCTION ++A function internal to @value{GDBN}. This is the type used to represent ++convenience functions. ++@end table ++ ++@node Pretty Printing ++@subsubsection Pretty Printing ++ ++@value{GDBN} provides a mechanism to allow pretty-printing of values ++using Python code. This mechanism works for both MI and the CLI. ++ ++A pretty-printer is an object that implements a specific interface. ++There is no predefined base class for pretty-printers. ++ ++@defop Operation {pretty printer} __init__ (self, val) ++When printing a value, @value{GDBN} constructs an instance of the ++pretty-printer. @var{val} is the value to be printed, an instance of ++@code{gdb.Value}. ++@end defop ++ ++@defop Operation {pretty printer} children (self) ++When printing a value, @value{GDBN} will call this method to compute ++the children of the value passed to the object's constructor. ++ ++This method must return an object conforming to the Python iterator ++protocol. Each element returned by the iterator must be a tuple ++holding two elements. The first element is the ``name'' of the child; ++the second element is the child's value. The value can be any Python ++object which is convertible to a @value{GDBN} value. ++ ++This method is optional. If it does not exist, @value{GDBN} will act ++as though the value has no children. ++@end defop ++ ++@defop Operation {pretty printer} display_hint (self) ++This method must return a string. The CLI may use this to change the ++formatting of children of a value. The result will also be supplied ++to an MI consumer as a @samp{displayhint} attribute of the variable ++being printed. ++ ++Some display hints are predefined by @value{GDBN}: ++ ++@table @samp ++@item array ++Indicate that the object being printed is ``array-like''. The CLI ++uses this to respect parameters such as @code{set print elements} and ++@code{set print array}. ++ ++@item map ++Indicate that the object being printed is ``map-like'', and that the ++children of this value can be assumed to alternate between keys and ++values. ++ ++@item string ++Indicate that the object being printed is ``string-like''. If the ++printer's @code{to_string} method returns a Python string of some ++kind, then @value{GDBN} will call its internal language-specific ++string-printing function to format the string. For the CLI this means ++adding quotation marks, possibly escaping some characters, respecting ++@code{set print elements}, and the like. ++@end table ++@end defop ++ ++@defop Operation {pretty printer} to_string (self) ++@value{GDBN} will call this method to display the string ++representation of the value passed to the object's constructor. ++ ++When printing from the CLI, if the @code{to_string} method exists, ++then @value{GDBN} will prepend its result to the values returned by ++@code{children}. ++ ++If this method returns a string, it is printed verbatim. Otherwise, ++the result is converted to a @code{gdb.Value}, following the usual ++algorithm. Then @value{GDBN} prints this value; this may possibly ++result in a call to another pretty-printer. If the result is not ++convertible to @code{gdb.Value}, an exception is raised. ++@end defop ++ ++@subsubsection Selecting Pretty-Printers ++ ++The Python list @code{gdb.pretty_printers} contains an array of ++functions that have been registered via addition as a pretty-printer. ++Each function will be called with a @code{gdb.Value} to be ++pretty-printed. Each @code{gdb.Objfile} also contains a ++@code{pretty_printers} attribute. A function on one of these lists ++takes a single @code{gdb.Value} argument and returns a pretty-printer ++object conforming to the interface definition above. If this function ++cannot create a pretty-printer for the value, it should return ++@code{None}. ++ ++@value{GDBN} first checks the @code{pretty_printers} attribute of each ++@code{gdb.Objfile} and iteratively calls each function in the list for ++that @code{gdb.Objfile} until it receives a pretty-printer object. ++After these @code{gdb.Objfile} have been exhausted, it tries the ++global @code{gdb.pretty-printers} list, again calling each function ++until an object is returned. ++ ++The order in which the objfiles are searched is not specified. ++Functions are always invoked from the head of the ++@code{gdb.pretty-printers} list, and iterated over sequentially until ++the end of the list, or a printer object is returned. ++ ++Here is an example showing how a @code{std::string} printer might be ++written: ++ ++@smallexample ++class StdStringPrinter: ++ "Print a std::string" ++ ++ def __init__ (self, val): ++ self.val = val ++ ++ def to_string (self): ++ return self.val['_M_dataplus']['_M_p'] ++@end smallexample ++ ++And here is an example showing how a lookup function for ++the printer example above might be written. ++ ++@smallexample ++def str_lookup_function (val): ++ ++ lookup_tag = val.type.tag ++ regex = re.compile ("^std::basic_string$") ++ if lookup_tag == None: ++ return None ++ if regex.match (lookup_tag): ++ return StdStringPrinter (val) ++ ++ return None ++@end smallexample ++ ++The example lookup function extracts the value's type, and attempts to ++match it to a type that it can pretty-print. If it is a type the ++printer can pretty-print, it will return a printer object. If not, it ++returns: @code{None}. ++ ++We recommend that you put your core pretty-printers into a versioned ++python package, and then restrict your auto-loaded code to idempotent ++behavior -- for example, just @code{import}s of your printer modules, ++followed by a call to a register pretty-printers with the current ++objfile. This approach will scale more nicely to multiple inferiors, ++potentially using different library versions. ++ ++For example, in addition to the above, this code might appear in ++@code{gdb.libstdcxx.v6}: ++ ++@smallexample ++def register_printers (objfile): ++ objfile.pretty_printers.add (str_lookup_function) ++@end smallexample ++ ++And then the corresponding contents of the auto-load file would be: ++ ++@smallexample ++import gdb.libstdcxx.v6 ++gdb.libstdcxx.v6.register_printers (gdb.current_objfile ()) ++@end smallexample ++ ++@node Threads In Python ++@subsubsection Threads In Python ++ ++Python scripts can access information about the inferior's threads ++using some functions provided by @value{GDBN}. Like all of ++@value{GDBN}'s Python additions, these are in the @code{gdb} module: ++ ++@findex gdb.threads ++@defun threads ++This function returns a tuple holding all the thread IDs which are ++valid when the function is called. If there are no valid threads, ++this will return @code{None}. ++@end defun ++ ++@findex gdb.current_thread ++@defun current_thread ++This function returns the thread ID of the selected thread. If there ++is no selected thread, this will return @code{None}. ++@end defun ++ ++@findex gdb.switch_to_thread ++@defun switch_to_thread id ++This changes @value{GDBN}'s currently selected thread to the thread ++given by @var{id}. @var{id} must be a valid thread ID as returned by ++@code{threads}. If @var{id} is invalid, this function throws an ++exception. ++@end defun + + @node Commands In Python + @subsubsection Commands In Python +@@ -18320,7 +19154,7 @@ You can implement new @value{GDBN} CLI commands in Python. A CLI + command is implemented using an instance of the @code{gdb.Command} + class, most commonly using a subclass. + +-@defmethod Command __init__ name @var{command-class} @r{[}@var{completer-class} @var{prefix}@r{]} ++@defmethod Command __init__ name @var{command_class} @r{[}@var{completer_class}@r{]} @r{[}@var{prefix}@r{]} + The object initializer for @code{Command} registers the new command + with @value{GDBN}. This initializer is normally invoked from the + subclass' own @code{__init__} method. +@@ -18332,11 +19166,11 @@ an exception is raised. + + There is no support for multi-line commands. + +-@var{command-class} should be one of the @samp{COMMAND_} constants ++@var{command_class} should be one of the @samp{COMMAND_} constants + defined below. This argument tells @value{GDBN} how to categorize the + new command in the help system. + +-@var{completer-class} is an optional argument. If given, it should be ++@var{completer_class} is an optional argument. If given, it should be + one of the @samp{COMPLETE_} constants defined below. This argument + tells @value{GDBN} how to perform completion for this command. If not + given, @value{GDBN} will attempt to complete using the object's +@@ -18563,6 +19397,374 @@ registration of the command with @value{GDBN}. Depending on how the + Python code is read into @value{GDBN}, you may need to import the + @code{gdb} module explicitly. + ++ ++@node Parameters In Python ++@subsubsection Parameters In Python ++ ++@cindex parameters in python ++@cindex python parameters ++@tindex gdb.Parameter ++@tindex Parameter ++You can implement new @value{GDBN} parameters using Python. A new ++parameter is implemented as an instance of the @code{gdb.Parameter} ++class. Parameters are exposed to the user via the @code{set} and ++@code{show} commands. ++ ++@defmethod Parameter __init__ name @var{command-class} @var{parameter-class} @r{[}@var{enum-sequence}@r{]} ++The object initializer for @code{Parameter} registers the new ++parameter with @value{GDBN}. This initializer is normally invoked ++from the subclass' own @code{__init__} method. ++ ++@var{name} is the name of the new parameter. If @var{name} consists ++of multiple words, then the initial words are looked for as prefix ++commands. In this case, if one of the prefix commands does not exist, ++an exception is raised. ++ ++@var{command-class} should be one of the @samp{COMMAND_} constants ++(@pxref{Commands In Python}). This argument tells @value{GDBN} how to ++categorize the new parameter in the help system. ++ ++@var{parameter-class} should be one of the @samp{PARAM_} constants ++defined below. This argument tells @value{GDBN} the type of the new ++parameter; this information is used for input validation and ++completion. ++ ++If @var{parameter-class} is @code{PARAM_ENUM}, then ++@var{enum-sequence} must be a sequence of strings. These strings ++represent the possible values for the parameter. ++ ++If @var{parameter-class} is not @code{PARAM_ENUM}, then the presence ++of a fourth argument will cause an exception to be thrown. ++ ++The help text for the new parameter is taken from the Python ++documentation string for the parameter's class, if there is one. If ++there is no documentation string, a default value is used. ++@end defmethod ++ ++@defivar Parameter set_doc ++If this attribute exists, and is a string, then its value is used as ++the help text for this parameter's @code{set} command. The value is ++examined when @code{Parameter.__init__} is invoked; subsequent changes ++have no effect. ++@end defivar ++ ++@defivar Parameter show_doc ++If this attribute exists, and is a string, then its value is used as ++the help text for this parameter's @code{show} command. The value is ++examined when @code{Parameter.__init__} is invoked; subsequent changes ++have no effect. ++@end defivar ++ ++@defivar Parameter value ++The @code{value} attribute holds the underlying value of the ++parameter. It can be read and assigned to just as any other ++attribute. @value{GDBN} does validation when assignments are made. ++@end defivar ++ ++ ++When a new parameter is defined, its type must be specified. The ++available types are represented by constants defined in the @code{gdb} ++module: ++ ++@table @code ++@findex PARAM_BOOLEAN ++@findex gdb.PARAM_BOOLEAN ++@item PARAM_BOOLEAN ++The value is a plain boolean. The Python boolean values, @code{True} ++and @code{False} are the only valid values. ++ ++@findex PARAM_AUTO_BOOLEAN ++@findex gdb.PARAM_AUTO_BOOLEAN ++@item PARAM_AUTO_BOOLEAN ++The value has three possible states: true, false, and @samp{auto}. In ++Python, true and false are represented using boolean constants, and ++@samp{auto} is represented using @code{None}. ++ ++@findex PARAM_UINTEGER ++@findex gdb.PARAM_UINTEGER ++@item PARAM_UINTEGER ++The value is an unsigned integer. The value of 0 should be ++interpreted to mean ``unlimited''. ++ ++@findex PARAM_INTEGER ++@findex gdb.PARAM_INTEGER ++@item PARAM_INTEGER ++The value is a signed integer. The value of 0 should be interpreted ++to mean ``unlimited''. ++ ++@findex PARAM_STRING ++@findex gdb.PARAM_STRING ++@item PARAM_STRING ++The value is a string. When the user modifies the string, escapes are ++translated. ++ ++@findex PARAM_STRING_NOESCAPE ++@findex gdb.PARAM_STRING_NOESCAPE ++@item PARAM_STRING_NOESCAPE ++The value is a string. When the user modifies the string, escapes are ++passed through untranslated. ++ ++@findex PARAM_OPTIONAL_FILENAME ++@findex gdb.PARAM_OPTIONAL_FILENAME ++@item PARAM_OPTIONAL_FILENAME ++The value is a either a filename (a string), or @code{None}. ++ ++@findex PARAM_FILENAME ++@findex gdb.PARAM_FILENAME ++@item PARAM_FILENAME ++The value is a filename (a string). ++ ++@findex PARAM_ZINTEGER ++@findex gdb.PARAM_ZINTEGER ++@item PARAM_ZINTEGER ++The value is an integer. This is like @code{PARAM_INTEGER}, except 0 ++is interpreted as itself. ++ ++@findex PARAM_ENUM ++@findex gdb.PARAM_ENUM ++@item PARAM_ENUM ++The value is a string, which must be one of a collection string ++constants provided when the parameter is created. ++@end table ++ ++@node Functions In Python ++@subsubsection Writing new convenience functions ++ ++@cindex writing convenience functions ++@cindex convenience functions in python ++@cindex python convenience functions ++@tindex gdb.Function ++@tindex Function ++You can implement new convenience functions (@pxref{Convenience Vars}) ++in Python. A convenience function is an instance of a subclass of the ++class @code{gdb.Function}. ++ ++@defmethod Function __init__ name ++The initializer for @code{Function} registers the new function with ++@value{GDBN}. The argument @var{name} is the name of the function, ++a string. The function will be visible to the user as a convenience ++variable of type @code{internal function}, whose name is the same as ++the given @var{name}. ++ ++The documentation for the new function is taken from the documentation ++string for the new class. ++@end defmethod ++ ++@defmethod Function invoke @var{*args} ++When a convenience function is evaluated, its arguments are converted ++to instances of @code{gdb.Value}, and then the function's ++@code{invoke} method is called. Note that @value{GDBN} does not ++predetermine the arity of convenience functions. Instead, all ++available arguments are passed to @code{invoke}, following the ++standard Python calling convention. In particular, a convenience ++function can have default values for parameters without ill effect. ++ ++The return value of this method is used as its value in the enclosing ++expression. If an ordinary Python value is returned, it is converted ++to a @code{gdb.Value} following the usual rules. ++@end defmethod ++ ++The following code snippet shows how a trivial convenience function can ++be implemented in Python: ++ ++@smallexample ++class Greet (gdb.Function): ++ """Return string to greet someone. ++Takes a name as argument.""" ++ ++ def __init__ (self): ++ super (Greet, self).__init__ ("greet") ++ ++ def invoke (self, name): ++ return "Hello, %s!" % name.string () ++ ++Greet () ++@end smallexample ++ ++The last line instantiates the class, and is necessary to trigger the ++registration of the function with @value{GDBN}. Depending on how the ++Python code is read into @value{GDBN}, you may need to import the ++@code{gdb} module explicitly. ++ ++@node Objfiles In Python ++@subsubsection Objfiles In Python ++ ++@cindex objfiles in python ++@cindex python objfiles ++@tindex gdb.Objfile ++@tindex Objfile ++@value{GDBN} loads symbols for an inferior from various ++symbol-containing files. These include the primary executable file, ++any shared libraries used by the inferior, and any separate debug info ++files. @value{GDBN} calls these symbol-containing files ++@dfn{objfiles}. ++ ++Each objfile is represented by an instance of the @code{gdb.Objfile} ++class. ++ ++@defivar Objfile filename ++The file name of the objfile as a string. ++@end defivar ++ ++@defivar Objfile pretty_printers ++The @code{pretty_printers} attribute is used to look up ++pretty-printers by type. This is a dictionary which maps regular ++expressions (strings) to pretty-printing objects. @xref{Pretty ++Printing}, for more information. ++@end defivar ++ ++@node Breakpoints In Python ++@subsubsection Manipulating breakpoints using Python ++ ++@cindex breakpoints in python ++@cindex python breakpoints ++@tindex gdb.Breakpoint ++@tindex Breakpoint ++Python code can manipulate breakpoints via the @code{gdb.Breakpoint} ++class. ++ ++@defmethod Breakpoint __init__ location ++Create a new breakpoint. @var{location} is a string naming the ++location of the breakpoint. The contents can be any location ++recognized by the @code{break} command. ++@end defmethod ++ ++@defmethod Breakpoint is_valid ++Return @code{True} if this @code{Breakpoint} object is valid, ++@code{False} otherwise. A @code{Breakpoint} object can become invalid ++if the user deletes the breakpoint. In this case, the object still ++exists, but the underlying breakpoint does not. ++@end defmethod ++ ++@defivar Breakpoint enabled ++This attribute is @code{True} if the breakpoint is enabled, and ++@code{False} otherwise. This attribute is writable. ++@end defivar ++ ++@defivar Breakpoint silent ++This attribute is @code{True} if the breakpoint is silent, and ++@code{False} otherwise. This attribute is writable. ++ ++Note that a breakpoint can also be silent if it has commands and the ++first command is @code{silent}. This is not reported by the ++@code{silent} attribute. ++@end defivar ++ ++@defivar Breakpoint thread ++If the breakpoint is thread-specific, this attribute holds the thread ++id. If the breakpoint is not thread-specific, this attribute is ++@code{None}. This attribute is writable. ++@end defivar ++ ++@defivar Breakpoint ignore_count ++This attribute holds the ignore count for the breakpoint, an integer. ++This attribute is writable. ++@end defivar ++ ++@defivar Breakpoint number ++This attribute holds the breakpoint's number -- the identifier used by ++the user to manipulate the breakpoint. This attribute is not writable. ++@end defivar ++ ++@defivar Breakpoint hit_count ++This attribute holds the hit count for the breakpoint, an integer. ++This attribute is writable, but currently it can only be set to zero. ++@end defivar ++ ++@defivar Breakpoint location ++This attribute holds the location of the breakpoint, as specified by ++the user. It is a string. This attribute is not writable. ++@end defivar ++ ++@defivar Breakpoint condition ++This attribute holds the condition of the breakpoint, as specified by ++the user. It is a string. If there is no condition, this attribute's ++value is @code{None}. This attribute is writable. ++@end defivar ++ ++@defivar Breakpoint commands ++This attribute holds the commands attached to the breakpoint. If ++there are commands, this returns a string holding all the commands, ++separated by newlines. If there are no commands, this attribute is ++@code{None}. This attribute is not writable. ++@end defivar ++ ++@node Frames In Python ++@subsubsection Accessing inferior stack frames from Python. ++ ++@cindex frames in python ++@tindex gdb.Frame ++@tindex Frame ++When the debugged program stops, @value{GDBN} is able to analyse its call ++stack (@pxref{Frames,,Stack frames}). The @code{gdb.Frame} class ++represents a frame in the stack. You can get a tuple containing all the ++frames in the stack with the @code{gdb.frames} function, the newest ++frame with the @code{gdb.newest_frame} function, and the selected frame ++with the @code{gdb.selected_frame} function ++(see @xref{Selection,,Selecting a Frame}.) See ++@xref{Basic Python,,Basic Python}. ++ ++A @code{gdb.Frame} object has the following methods: ++ ++@table @code ++@defmethod Frame equals @code{frame} ++Compare frames. ++@end defmethod ++ ++@defmethod Frame is_valid ++Returns true if the @code{gdb.Frame} object is valid, false if not. ++A frame object can become invalid if the frame it refers to doesn't ++exist anymore in the inferior. All @code{gdb.Frame} methods will throw ++an exception if it is invalid at the time the method call is made. ++@end defmethod ++ ++@defmethod Frame name ++Returns the function name of the frame, or @code{None} if it can't be ++obtained. ++@end defmethod ++ ++@defmethod Frame type ++Returns the type of the frame. The value can be one of ++@code{gdb.NORMAL_FRAME}, @code{gdb.DUMMY_FRAME}, @code{gdb.SIGTRAMP_FRAME} ++or @code{gdb.SENTINEL_FRAME}. ++@end defmethod ++ ++@defmethod Frame unwind_stop_reason ++Return an integer representing the reason why it's not possible to find ++frames older than this. Use @code{gdb.frame_stop_reason_string} to convert ++the value returned by this function to a string. ++@end defmethod ++ ++@defmethod Frame pc ++Returns the frame's resume address. ++@end defmethod ++ ++@defmethod Frame block ++Returns the frame's code block. @c (see @xref{Block,,Code Blocks and Scopes}). ++@end defmethod ++ ++@defmethod Frame address_in_block ++Returns an address which falls within the frame's code block. ++@end defmethod ++ ++@defmethod Frame older ++Return the frame immediately older (outer) to this frame. ++@end defmethod ++ ++@defmethod Frame newer ++Return the frame immediately newer (inner) to this frame. ++@end defmethod ++ ++@defmethod Frame find_sal ++Return the frame's symtab and line object. @c (see @xref{Symtab_and_line,, Symtab and line}). ++@end defmethod ++ ++@defmethod Frame read_var @var{variable} ++Return the value of the given variable in this frame. @code{variable} can be ++either a string or a @code{gdb.Symbol} object. @c (@pxref{Symbols In Python}). ++@end defmethod ++@end table ++ + @node Interpreters + @chapter Command Interpreters + @cindex command interpreters +@@ -22273,6 +23475,103 @@ Unfreezing a variable does not update it, only subsequent + (gdb) + @end smallexample + ++@subheading The @code{-var-set-visualizer} command ++@findex -var-set-visualizer ++@anchor{-var-set-visualizer} ++ ++@subsubheading Synopsis ++ ++@smallexample ++ -var-set-visualizer @var{name} @var{visualizer} ++@end smallexample ++ ++@subheading The @code{-var-set-child-range} command ++@findex -var-set-child-range ++@anchor{-var-set-child-range} ++ ++Set a visualizer for the variable object @var{name}. ++ ++@var{visualizer} is the visualizer to use. The special value ++@samp{None} means to disable any visualizer in use. ++ ++If not @samp{None}, @var{visualizer} must be a Python expression. ++This expression must evaluate to a callable object which accepts a ++single argument. @value{GDBN} will call this object with the value of ++the varobj @var{name} as an argument. This function must return an ++object which conforms to the pretty-printing interface (@pxref{Pretty ++Printing}). ++ ++The pre-defined function @code{gdb.default_visualizer} may be used ++to select a visualizer according to the type of the varobj. This is ++called when a varobj is created, and so ordinarily is not needed. ++ ++@code{gdb.default_visualizer} looks in the global dictionary named ++@code{gdb.pretty_printers}. ++ ++This feature is only available if Python support is enabled. ++ ++@subsubheading Example ++ ++Resetting the visualizer: ++ ++@smallexample ++(gdb) ++-var-set-visualizer V None ++^done ++@end smallexample ++ ++Reselecting the default (type-based) visualizer: ++ ++@smallexample ++(gdb) ++-var-set-visualizer V gdb.default_visualizer ++^done ++@end smallexample ++ ++Suppose @code{SomeClass} is a visualizer class. A lambda expression ++can be used to instantiate this class for a varobj: ++ ++@smallexample ++(gdb) ++-var-set-visualizer V "lambda val: SomeClass()" ++^done ++@end smallexample ++ ++@subsubheading Synopsis ++ ++@smallexample ++ -var-set-child-range @var{name} @var{from} @var{to} ++@end smallexample ++ ++Select a sub-range of the children of the variable object @var{name}; ++future calls to @code{-var-list-children} will only report the ++selected range of children. This allows an MI consumer to avoid ++inefficiencies if the varobj has very many children. ++ ++If either @var{from} or @var{to} is less than zero, then sub-range ++selection is disabled, and @code{-var-list-children} will report all ++children. ++ ++Otherwise, @var{from} and @var{to} are indexes into the array of ++children. Children starting at @var{from} and stopping jsut before ++@var{to} will be reported. ++ ++@subsubheading Example ++ ++@smallexample ++(gdb) ++ -var-list-children n ++ ^done,numchild=3,children=[@{name="a",numchild=0,type="int"@}, ++ @{name="b",numchild=0,type="int"@}, ++ @{name="c",numchild=0,type="int"@}] ++(gdb) ++ -var-set-child-range n 1 2 ++(gdb) ++ -var-list-children n ++ ^done,numchild=3,children=[@{name="b",numchild=0,type="int"@}, ++ @{name="c",numchild=0,type="int"@}] ++@end smallexample ++ + + @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + @node GDB/MI Data Manipulation +@@ -23832,6 +25131,10 @@ as possible presense of the @code{frozen} field in the output + of @code{-varobj-create}. + @item pending-breakpoints + Indicates presence of the @option{-f} option to the @code{-break-insert} command. ++@item python ++Indicates presence of Python scripting support, Python-based ++pretty-printing commands, and possible presence of the ++@samp{display_hint} field in the output of @code{-var-list-children} + @item thread-info + Indicates presence of the @code{-thread-info} command. + +@@ -25402,28 +26705,6 @@ data in a @file{gmon.out} file, be sure to move it to a safe location. + Configuring with @samp{--enable-profiling} arranges for @value{GDBN} to be + compiled with the @samp{-pg} compiler option. + +-@kindex maint set linux-async +-@kindex maint show linux-async +-@cindex asynchronous support +-@item maint set linux-async +-@itemx maint show linux-async +-Control the GNU/Linux native asynchronous support +-(@pxref{Background Execution}) of @value{GDBN}. +- +-GNU/Linux native asynchronous support will be disabled until you use +-the @samp{maint set linux-async} command to enable it. +- +-@kindex maint set remote-async +-@kindex maint show remote-async +-@cindex asynchronous support +-@item maint set remote-async +-@itemx maint show remote-async +-Control the remote asynchronous support +-(@pxref{Background Execution}) of @value{GDBN}. +- +-Remote asynchronous support will be disabled until you use +-the @samp{maint set remote-async} command to enable it. +- + @kindex maint show-debug-regs + @cindex x86 hardware debug registers + @item maint show-debug-regs +diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c +index ce11d89..eaa6a13 100644 +--- a/gdb/dwarf2-frame.c ++++ b/gdb/dwarf2-frame.c +@@ -38,6 +38,7 @@ + + #include "complaints.h" + #include "dwarf2-frame.h" ++#include "addrmap.h" + + struct comp_unit; + +@@ -1499,6 +1500,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc) + struct dwarf2_fde *fde; + CORE_ADDR offset; + ++ if (objfile->quick_addrmap) ++ { ++ if (!addrmap_find (objfile->quick_addrmap, *pc)) ++ continue; ++ } ++ /* FIXME: Read-in only .debug_frame/.eh_frame without .debug_info? */ ++ require_partial_symbols (objfile); ++ + fde = objfile_data (objfile, dwarf2_frame_objfile_data); + if (fde == NULL) + continue; +diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c +index 75a4ec7..aa8ab33 100644 +--- a/gdb/dwarf2expr.c ++++ b/gdb/dwarf2expr.c +@@ -752,6 +752,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, + ctx->initialized = 0; + goto no_push; + ++ case DW_OP_push_object_address: ++ if (ctx->get_object_address == NULL) ++ error (_("DWARF-2 expression error: DW_OP_push_object_address must " ++ "have a value to push.")); ++ result = (ctx->get_object_address) (ctx->baton); ++ break; ++ + default: + error (_("Unhandled dwarf expression opcode 0x%x"), op); + } +diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h +index 7047922..a287b6f 100644 +--- a/gdb/dwarf2expr.h ++++ b/gdb/dwarf2expr.h +@@ -67,10 +67,10 @@ struct dwarf_expr_context + The result must be live until the current expression evaluation + is complete. */ + unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length); ++#endif + + /* Return the `object address' for DW_OP_push_object_address. */ + CORE_ADDR (*get_object_address) (void *baton); +-#endif + + /* The current depth of dwarf expression recursion, via DW_OP_call*, + DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum +diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c +index cad3db8..2251e48 100644 +--- a/gdb/dwarf2loc.c ++++ b/gdb/dwarf2loc.c +@@ -107,6 +107,9 @@ struct dwarf_expr_baton + { + struct frame_info *frame; + struct objfile *objfile; ++ /* From DW_TAG_variable's DW_AT_location (not DW_TAG_type's ++ DW_AT_data_location) for DW_OP_push_object_address. */ ++ CORE_ADDR object_address; + }; + + /* Helper functions for dwarf2_evaluate_loc_desc. */ +@@ -163,22 +166,32 @@ dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length) + *start = find_location_expression (symbaton, length, + get_frame_address_in_block (frame)); + } +- else ++ else if (SYMBOL_OPS (framefunc) == &dwarf2_locexpr_funcs) + { + struct dwarf2_locexpr_baton *symbaton; ++ + symbaton = SYMBOL_LOCATION_BATON (framefunc); +- if (symbaton != NULL) +- { +- *length = symbaton->size; +- *start = symbaton->data; +- } +- else +- *start = NULL; ++ gdb_assert (symbaton != NULL); ++ *start = symbaton->data; ++ *length = symbaton->size; ++ } ++ else if (SYMBOL_OPS (framefunc) == &dwarf2_missing_funcs) ++ { ++ struct dwarf2_locexpr_baton *symbaton; ++ ++ symbaton = SYMBOL_LOCATION_BATON (framefunc); ++ gdb_assert (symbaton == NULL); ++ *start = NULL; ++ *length = 0; /* unused */ + } ++ else ++ internal_error (__FILE__, __LINE__, ++ _("Unsupported SYMBOL_OPS %p for \"%s\""), ++ SYMBOL_OPS (framefunc), SYMBOL_PRINT_NAME (framefunc)); + + if (*start == NULL) + error (_("Could not find the frame base for \"%s\"."), +- SYMBOL_NATURAL_NAME (framefunc)); ++ SYMBOL_PRINT_NAME (framefunc)); + } + + /* Using the objfile specified in BATON, find the address for the +@@ -191,6 +204,119 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset) + return target_translate_tls_address (debaton->objfile, offset); + } + ++static CORE_ADDR ++dwarf_expr_object_address (void *baton) ++{ ++ struct dwarf_expr_baton *debaton = baton; ++ ++ /* The message is suppressed in DWARF_BLOCK_EXEC. */ ++ if (debaton->object_address == 0) ++ error (_("Cannot resolve DW_OP_push_object_address for a missing object")); ++ ++ return debaton->object_address; ++} ++ ++/* Address of the variable we are currently referring to. It is set from ++ DW_TAG_variable's DW_AT_location (not DW_TAG_type's DW_AT_data_location) for ++ DW_OP_push_object_address. */ ++ ++static CORE_ADDR object_address; ++ ++/* Callers use object_address_set while their callers use the result set so we ++ cannot run the cleanup at the local block of our direct caller. Still we ++ should reset OBJECT_ADDRESS at least for the next GDB command. */ ++ ++static void ++object_address_cleanup (void *prev_save_voidp) ++{ ++ CORE_ADDR *prev_save = prev_save_voidp; ++ ++ object_address = *prev_save; ++ xfree (prev_save); ++} ++ ++/* Set the base address - DW_AT_location - of a variable. It is being later ++ used to derive other object addresses by DW_OP_push_object_address. ++ ++ It would be useful to sanity check ADDRESS - such as for some objects with ++ unset VALUE_ADDRESS - but some valid addresses may be zero (such as first ++ objects in relocatable .o files). */ ++ ++void ++object_address_set (CORE_ADDR address) ++{ ++ CORE_ADDR *prev_save; ++ ++ prev_save = xmalloc (sizeof *prev_save); ++ *prev_save = object_address; ++ make_cleanup (object_address_cleanup, prev_save); ++ ++ object_address = address; ++} ++ ++/* Evaluate DWARF expression at DATA ... DATA + SIZE with its result readable ++ by dwarf_expr_fetch (RETVAL, 0). FRAME parameter can be NULL to call ++ get_selected_frame to find it. Returned dwarf_expr_context freeing is ++ pushed on the cleanup chain. */ ++ ++static struct dwarf_expr_context * ++dwarf_expr_prep_ctx (struct frame_info *frame, gdb_byte *data, ++ unsigned short size, struct dwarf2_per_cu_data *per_cu) ++{ ++ struct dwarf_expr_context *ctx; ++ struct dwarf_expr_baton baton; ++ ++ if (!frame) ++ frame = get_selected_frame (NULL); ++ ++ baton.frame = frame; ++ baton.objfile = dwarf2_per_cu_objfile (per_cu); ++ baton.object_address = object_address; ++ ++ ctx = new_dwarf_expr_context (); ++ ctx->gdbarch = get_objfile_arch (baton.objfile); ++ ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); ++ ctx->baton = &baton; ++ ctx->read_reg = dwarf_expr_read_reg; ++ ctx->read_mem = dwarf_expr_read_mem; ++ ctx->get_frame_base = dwarf_expr_frame_base; ++ ctx->get_tls_address = dwarf_expr_tls_address; ++ ctx->get_object_address = dwarf_expr_object_address; ++ ++ make_cleanup ((make_cleanup_ftype *) free_dwarf_expr_context, ctx); ++ ++ dwarf_expr_eval (ctx, data, size); ++ ++ /* It was used only during dwarf_expr_eval. */ ++ ctx->baton = NULL; ++ ++ return ctx; ++} ++ ++/* Evaluate DWARF expression at DLBATON expecting it produces exactly one ++ CORE_ADDR result on the DWARF stack stack. */ ++ ++CORE_ADDR ++dwarf_locexpr_baton_eval (struct dwarf2_locexpr_baton *dlbaton) ++{ ++ struct dwarf_expr_context *ctx; ++ CORE_ADDR retval; ++ struct cleanup *back_to = make_cleanup (null_cleanup, 0); ++ ++ ctx = dwarf_expr_prep_ctx (NULL, dlbaton->data, dlbaton->size, ++ dlbaton->per_cu); ++ if (ctx->num_pieces > 0) ++ error (_("DW_OP_*piece is unsupported for DW_FORM_block")); ++ else if (ctx->in_reg) ++ error (_("Register result is unsupported for DW_FORM_block")); ++ ++ retval = dwarf_expr_fetch (ctx, 0); ++ ++ do_cleanups (back_to); ++ ++ return retval; ++} ++ + /* Evaluate a location description, starting at DATA and with length + SIZE, to find the current location of variable VAR in the context + of FRAME. */ +@@ -200,8 +326,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + struct dwarf2_per_cu_data *per_cu) + { + struct value *retval; +- struct dwarf_expr_baton baton; + struct dwarf_expr_context *ctx; ++ struct cleanup *back_to = make_cleanup (null_cleanup, 0); + + if (size == 0) + { +@@ -211,19 +337,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + return retval; + } + +- baton.frame = frame; +- baton.objfile = dwarf2_per_cu_objfile (per_cu); ++ ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu); + +- ctx = new_dwarf_expr_context (); +- ctx->gdbarch = get_objfile_arch (baton.objfile); +- ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); +- ctx->baton = &baton; +- ctx->read_reg = dwarf_expr_read_reg; +- ctx->read_mem = dwarf_expr_read_mem; +- ctx->get_frame_base = dwarf_expr_frame_base; +- ctx->get_tls_address = dwarf_expr_tls_address; +- +- dwarf_expr_eval (ctx, data, size); + if (ctx->num_pieces > 0) + { + int i; +@@ -261,15 +376,19 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + { + CORE_ADDR address = dwarf_expr_fetch (ctx, 0); + ++ /* object_address_set called here is required in ALLOCATE_VALUE's ++ CHECK_TYPEDEF for the object's possible DW_OP_push_object_address. */ ++ object_address_set (address); ++ + retval = allocate_value (SYMBOL_TYPE (var)); + VALUE_LVAL (retval) = lval_memory; + set_value_lazy (retval, 1); +- VALUE_ADDRESS (retval) = address; ++ set_value_address (retval, address); + } + + set_value_initialized (retval, ctx->initialized); + +- free_dwarf_expr_context (ctx); ++ do_cleanups (back_to); + + return retval; + } +@@ -587,7 +706,7 @@ static int + loclist_describe_location (struct symbol *symbol, struct ui_file *stream) + { + /* FIXME: Could print the entire list of locations. */ +- fprintf_filtered (stream, "a variable with multiple locations"); ++ fprintf_filtered (stream, _("a variable with multiple locations")); + return 1; + } + +@@ -603,16 +722,56 @@ loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax, + + data = find_location_expression (dlbaton, &size, ax->scope); + if (data == NULL) +- error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol)); ++ error (_("Variable \"%s\" is not available."), SYMBOL_PRINT_NAME (symbol)); + + dwarf2_tracepoint_var_ref (symbol, ax, value, data, size); + } + +-/* The set of location functions used with the DWARF-2 expression +- evaluator and location lists. */ ++/* The set of location functions used with the DWARF-2 location lists. */ + const struct symbol_ops dwarf2_loclist_funcs = { + loclist_read_variable, + loclist_read_needs_frame, + loclist_describe_location, + loclist_tracepoint_var_ref + }; ++ ++static struct value * ++missing_read_variable (struct symbol *symbol, struct frame_info *frame) ++{ ++ struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); ++ ++ gdb_assert (dlbaton == NULL); ++ error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol)); ++} ++ ++static int ++missing_read_needs_frame (struct symbol *symbol) ++{ ++ return 0; ++} ++ ++static int ++missing_describe_location (struct symbol *symbol, struct ui_file *stream) ++{ ++ fprintf_filtered (stream, _("a variable we are unable to resolve")); ++ return 1; ++} ++ ++static void ++missing_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax, ++ struct axs_value *value) ++{ ++ struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); ++ ++ gdb_assert (dlbaton == NULL); ++ error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol)); ++} ++ ++/* The set of location functions used with the DWARF-2 evaluator when we are ++ unable to resolve the symbols. */ ++const struct symbol_ops dwarf2_missing_funcs = { ++ missing_read_variable, ++ missing_read_needs_frame, ++ missing_describe_location, ++ missing_tracepoint_var_ref ++}; +diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h +index 76577f1..bf46761 100644 +--- a/gdb/dwarf2loc.h ++++ b/gdb/dwarf2loc.h +@@ -71,5 +71,11 @@ struct dwarf2_loclist_baton + + extern const struct symbol_ops dwarf2_locexpr_funcs; + extern const struct symbol_ops dwarf2_loclist_funcs; ++extern const struct symbol_ops dwarf2_missing_funcs; ++ ++extern void object_address_set (CORE_ADDR address); ++ ++extern CORE_ADDR dwarf_locexpr_baton_eval ++ (struct dwarf2_locexpr_baton *dlbaton); + + #endif /* dwarf2loc.h */ +diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c +index 55868da..9c1b90d 100644 +--- a/gdb/dwarf2read.c ++++ b/gdb/dwarf2read.c +@@ -1,8 +1,7 @@ + /* DWARF 2 debugging format support for GDB. + + Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, +- 2004, 2005, 2006, 2007, 2008, 2009 +- Free Software Foundation, Inc. ++ 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, + Inc. with support from Florida State University (under contract +@@ -47,6 +46,9 @@ + #include "command.h" + #include "gdbcmd.h" + #include "addrmap.h" ++#include "f-lang.h" ++#include "c-lang.h" ++#include "typeprint.h" + + #include + #include "gdb_string.h" +@@ -103,7 +105,7 @@ typedef struct pubnames_header + _PUBNAMES_HEADER; + #define _ACTUAL_PUBNAMES_HEADER_SIZE 13 + +-/* .debug_pubnames header ++/* .debug_aranges header + Because of alignment constraints, this structure has padding and cannot + be mapped directly onto the beginning of the .debug_info section. */ + typedef struct aranges_header +@@ -299,9 +301,6 @@ struct dwarf2_cu + /* Hash table holding all the loaded partial DIEs. */ + htab_t partial_dies; + +- /* `.debug_ranges' offset for this `DW_TAG_compile_unit' DIE. */ +- unsigned int ranges_offset; +- + /* Storage for things with the same lifetime as this read-in compilation + unit, including partial DIEs. */ + struct obstack comp_unit_obstack; +@@ -349,9 +348,6 @@ struct dwarf2_cu + DIEs for namespaces, we don't need to try to infer them + from mangled names. */ + unsigned int has_namespace_info : 1; +- +- /* Field `ranges_offset' is filled in; flag as the value may be zero. */ +- unsigned int has_ranges_offset : 1; + }; + + /* Persistent data held for a compilation unit, even when not +@@ -451,17 +447,12 @@ struct partial_die_info + /* DWARF-2 tag for this DIE. */ + ENUM_BITFIELD(dwarf_tag) tag : 16; + +- /* Language code associated with this DIE. This is only used +- for the compilation unit DIE. */ +- unsigned int language : 8; +- + /* Assorted flags describing the data found in this DIE. */ + unsigned int has_children : 1; + unsigned int is_external : 1; + unsigned int is_declaration : 1; + unsigned int has_type : 1; + unsigned int has_specification : 1; +- unsigned int has_stmt_list : 1; + unsigned int has_pc_info : 1; + + /* Flag set if the SCOPE field of this structure has been +@@ -472,10 +463,12 @@ struct partial_die_info + unsigned int has_byte_size : 1; + + /* The name of this DIE. Normally the value of DW_AT_name, but +- sometimes DW_TAG_MIPS_linkage_name or a string computed in some +- other fashion. */ ++ sometimes a default name for unnamed DIEs. */ + char *name; +- char *dirname; ++ ++ /* The linkage name of this DIE, from DW_AT_MIPS_linkage_name, or ++ NULL if no linkage name was present. */ ++ char *linkage_name; + + /* The scope to prepend to our children. This is generally + allocated on the comp_unit_obstack, so will disappear +@@ -498,9 +491,6 @@ struct partial_die_info + DW_AT_extension). */ + unsigned int spec_offset; + +- /* If HAS_STMT_LIST, the offset of the Line Number Information data. */ +- unsigned int line_offset; +- + /* Pointers to this DIE's parent, first child, and next sibling, + if any. */ + struct partial_die_info *die_parent, *die_child, *die_sibling; +@@ -523,6 +513,15 @@ struct attr_abbrev + ENUM_BITFIELD(dwarf_form) form : 16; + }; + ++/* Additional GDB-specific attribute forms. */ ++enum ++ { ++ /* A string which has been updated to GDB's internal ++ representation (e.g. converted to canonical form) and does not ++ need to be updated again. */ ++ GDB_FORM_cached_string = 0xff ++ }; ++ + /* Attributes have a name and a value */ + struct attribute + { +@@ -756,7 +755,7 @@ static void dwarf2_create_include_psymtab (char *, struct partial_symtab *, + struct objfile *); + + static void dwarf2_build_include_psymtabs (struct dwarf2_cu *, +- struct partial_die_info *, ++ struct die_info *, + struct partial_symtab *); + + static void dwarf2_build_psymtabs_hard (struct objfile *, int); +@@ -768,6 +767,9 @@ static void scan_partial_symbols (struct partial_die_info *, + static void add_partial_symbol (struct partial_die_info *, + struct dwarf2_cu *); + ++static gdb_byte *read_comp_unit_head (struct comp_unit_head *, gdb_byte *, ++ bfd *); ++ + static int pdi_needs_namespace (enum dwarf_tag tag); + + static void add_partial_namespace (struct partial_die_info *pdi, +@@ -794,6 +796,10 @@ static void dwarf2_psymtab_to_symtab (struct partial_symtab *); + + static void psymtab_to_symtab_1 (struct partial_symtab *); + ++static gdb_byte *dwarf2_read_section_1 (struct objfile *objfile, ++ struct obstack *obstack, ++ asection *sectp); ++ + gdb_byte *dwarf2_read_section (struct objfile *, asection *); + + static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu); +@@ -929,7 +935,8 @@ static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, + struct dwarf2_cu *, struct partial_symtab *); + + static int dwarf2_get_pc_bounds (struct die_info *, +- CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *); ++ CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *, ++ struct partial_symtab *pst); + + static void get_scope_pc_bounds (struct die_info *, + CORE_ADDR *, CORE_ADDR *, +@@ -960,6 +967,8 @@ static void read_common_block (struct die_info *, struct dwarf2_cu *); + + static void read_namespace (struct die_info *die, struct dwarf2_cu *); + ++static void read_import_statement (struct die_info *die, struct dwarf2_cu *); ++ + static void read_module (struct die_info *die, struct dwarf2_cu *cu); + + static const char *namespace_name (struct die_info *die, +@@ -993,6 +1002,9 @@ static void process_die (struct die_info *, struct dwarf2_cu *); + + static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *); + ++static char *dwarf2_canonicalize_name (char *, struct dwarf2_cu *, ++ struct obstack *); ++ + static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *); + + static struct die_info *dwarf2_extension (struct die_info *die, +@@ -1030,7 +1042,14 @@ static void store_in_ref_table (struct die_info *, + + static unsigned int dwarf2_get_ref_die_offset (struct attribute *); + +-static int dwarf2_get_attr_constant_value (struct attribute *, int); ++enum dwarf2_get_attr_constant_value ++ { ++ dwarf2_attr_unknown, ++ dwarf2_attr_const, ++ dwarf2_attr_block ++ }; ++static enum dwarf2_get_attr_constant_value dwarf2_get_attr_constant_value ++ (struct attribute *attr, int *val_return); + + static struct die_info *follow_die_ref (struct die_info *, + struct attribute *, +@@ -1085,6 +1104,9 @@ static void age_cached_comp_units (void); + + static void free_one_cached_comp_unit (void *); + ++static void fetch_die_type_attrs (struct die_info *die, struct type *type, ++ struct dwarf2_cu *cu); ++ + static struct type *set_die_type (struct die_info *, struct type *, + struct dwarf2_cu *); + +@@ -1104,19 +1126,28 @@ static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); + + static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu); + ++static struct dwarf2_locexpr_baton *dwarf2_attr_to_locexpr_baton ++ (struct attribute *attr, struct dwarf2_cu *cu); ++ + /* Try to locate the sections we need for DWARF 2 debugging + information and return true if we have enough to do something. */ + + int + dwarf2_has_info (struct objfile *objfile) + { +- struct dwarf2_per_objfile *data; ++ int update_sizes = 0; + + /* Initialize per-objfile state. */ +- data = obstack_alloc (&objfile->objfile_obstack, sizeof (*data)); +- memset (data, 0, sizeof (*data)); +- set_objfile_data (objfile, dwarf2_objfile_data_key, data); +- dwarf2_per_objfile = data; ++ dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); ++ if (!dwarf2_per_objfile) ++ { ++ struct dwarf2_per_objfile *data ++ = obstack_alloc (&objfile->objfile_obstack, sizeof (*data)); ++ memset (data, 0, sizeof (*data)); ++ set_objfile_data (objfile, dwarf2_objfile_data_key, data); ++ dwarf2_per_objfile = data; ++ update_sizes = 1; ++ } + + dwarf_info_section = 0; + dwarf_abbrev_section = 0; +@@ -1127,8 +1158,9 @@ dwarf2_has_info (struct objfile *objfile) + dwarf_eh_frame_section = 0; + dwarf_ranges_section = 0; + dwarf_loc_section = 0; ++ dwarf_aranges_section = 0; + +- bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL); ++ bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, &update_sizes); + return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL); + } + +@@ -1149,51 +1181,61 @@ section_is_p (asection *sectp, const char *name) + in. */ + + static void +-dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr) ++dwarf2_locate_sections (bfd *abfd, asection *sectp, void *user_data) + { ++ int update_sizes = * (int *) user_data; + if (section_is_p (sectp, INFO_SECTION)) + { +- dwarf2_per_objfile->info_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->info_size = bfd_get_section_size (sectp); + dwarf_info_section = sectp; + } + else if (section_is_p (sectp, ABBREV_SECTION)) + { +- dwarf2_per_objfile->abbrev_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->abbrev_size = bfd_get_section_size (sectp); + dwarf_abbrev_section = sectp; + } + else if (section_is_p (sectp, LINE_SECTION)) + { +- dwarf2_per_objfile->line_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->line_size = bfd_get_section_size (sectp); + dwarf_line_section = sectp; + } + else if (section_is_p (sectp, PUBNAMES_SECTION)) + { +- dwarf2_per_objfile->pubnames_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->pubnames_size = bfd_get_section_size (sectp); + dwarf_pubnames_section = sectp; + } + else if (section_is_p (sectp, ARANGES_SECTION)) + { +- dwarf2_per_objfile->aranges_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->aranges_size = bfd_get_section_size (sectp); + dwarf_aranges_section = sectp; + } + else if (section_is_p (sectp, LOC_SECTION)) + { +- dwarf2_per_objfile->loc_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->loc_size = bfd_get_section_size (sectp); + dwarf_loc_section = sectp; + } + else if (section_is_p (sectp, MACINFO_SECTION)) + { +- dwarf2_per_objfile->macinfo_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->macinfo_size = bfd_get_section_size (sectp); + dwarf_macinfo_section = sectp; + } + else if (section_is_p (sectp, STR_SECTION)) + { +- dwarf2_per_objfile->str_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->str_size = bfd_get_section_size (sectp); + dwarf_str_section = sectp; + } + else if (section_is_p (sectp, FRAME_SECTION)) + { +- dwarf2_per_objfile->frame_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->frame_size = bfd_get_section_size (sectp); + dwarf_frame_section = sectp; + } + else if (section_is_p (sectp, EH_FRAME_SECTION)) +@@ -1201,13 +1243,15 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr) + flagword aflag = bfd_get_section_flags (ignore_abfd, sectp); + if (aflag & SEC_HAS_CONTENTS) + { +- dwarf2_per_objfile->eh_frame_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->eh_frame_size = bfd_get_section_size (sectp); + dwarf_eh_frame_section = sectp; + } + } + else if (section_is_p (sectp, RANGES_SECTION)) + { +- dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp); ++ if (update_sizes) ++ dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp); + dwarf_ranges_section = sectp; + } + +@@ -1250,6 +1294,86 @@ dwarf2_resize_section (asection *sectp, bfd_size_type new_size) + sectp->name); + } + ++/* A cleanup that frees an obstack. */ ++static void ++finalize_obstack (void *o) ++{ ++ struct obstack *ob = o; ++ obstack_free (o, 0); ++} ++ ++/* Read the .debug_aranges section and construct an address map. */ ++ ++void ++dwarf2_create_quick_addrmap (struct objfile *objfile) ++{ ++ char *aranges_buffer, *aranges_ptr; ++ bfd *abfd = objfile->obfd; ++ CORE_ADDR baseaddr; ++ struct cleanup *old; ++ struct obstack temp_obstack; ++ struct addrmap *mutable_map; ++ ++ if (!dwarf_aranges_section) ++ return; ++ ++ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ++ ++ aranges_buffer = dwarf2_read_section_1 (objfile, NULL, dwarf_aranges_section); ++ aranges_ptr = aranges_buffer; ++ old = make_cleanup (xfree, aranges_buffer); ++ ++ obstack_init (&temp_obstack); ++ make_cleanup (finalize_obstack, &temp_obstack); ++ mutable_map = addrmap_create_mutable (&temp_obstack); ++ ++ while ((aranges_ptr - aranges_buffer) < dwarf2_per_objfile->aranges_size) ++ { ++ struct comp_unit_head cu_header; ++ unsigned int bytes_read, segment_size, delta; ++ LONGEST info_offset; ++ struct dwarf2_cu cu; ++ ++ cu_header.initial_length_size = 0; ++ aranges_ptr = read_comp_unit_head (&cu_header, aranges_ptr, abfd); ++ ++ segment_size = read_1_byte (abfd, aranges_ptr); ++ aranges_ptr += 1; ++ ++ /* Align the pointer to twice the pointer size. I didn't see ++ this in the spec but it appears to be required. */ ++ delta = (aranges_ptr - aranges_buffer) % (2 * cu_header.addr_size); ++ delta = (2 * cu_header.addr_size - delta) % (2 * cu_header.addr_size); ++ aranges_ptr += delta; ++ ++ memset (&cu, 0, sizeof (cu)); ++ cu.header.addr_size = cu_header.addr_size; ++ ++ while (1) ++ { ++ CORE_ADDR address, length; ++ ++ address = read_address (abfd, aranges_ptr, &cu, &bytes_read); ++ aranges_ptr += bytes_read; ++ ++ length = read_address (abfd, aranges_ptr, &cu, &bytes_read); ++ aranges_ptr += bytes_read; ++ ++ if (address == 0 && length == 0) ++ break; ++ ++ address += baseaddr; ++ ++ addrmap_set_empty (mutable_map, address, address + length, objfile); ++ } ++ } ++ ++ objfile->quick_addrmap = addrmap_create_fixed (mutable_map, ++ &objfile->objfile_obstack); ++ do_cleanups (old); ++} ++ ++ + /* Build a partial symbol table. */ + + void +@@ -1453,22 +1577,24 @@ dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst, + + /* Read the Line Number Program data and extract the list of files + included by the source file represented by PST. Build an include +- partial symtab for each of these included files. +- +- This procedure assumes that there *is* a Line Number Program in +- the given CU. Callers should check that PDI->HAS_STMT_LIST is set +- before calling this procedure. */ ++ partial symtab for each of these included files. */ + + static void + dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, +- struct partial_die_info *pdi, ++ struct die_info *die, + struct partial_symtab *pst) + { + struct objfile *objfile = cu->objfile; + bfd *abfd = objfile->obfd; +- struct line_header *lh; ++ struct line_header *lh = NULL; ++ struct attribute *attr; + +- lh = dwarf_decode_line_header (pdi->line_offset, abfd, cu); ++ attr = dwarf2_attr (die, DW_AT_stmt_list, cu); ++ if (attr) ++ { ++ unsigned int line_offset = DW_UNSND (attr); ++ lh = dwarf_decode_line_header (line_offset, abfd, cu); ++ } + if (lh == NULL) + return; /* No linetable, so no includes. */ + +@@ -1477,6 +1603,36 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, + free_line_header (lh); + } + ++/* Find the base address of the compilation unit for range lists and ++ location lists. It will normally be specified by DW_AT_low_pc. ++ In DWARF-3 draft 4, the base address could be overridden by ++ DW_AT_entry_pc. It's been removed, but GCC still uses this for ++ compilation units with discontinuous ranges. */ ++ ++static void ++dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu) ++{ ++ struct attribute *attr; ++ ++ cu->base_known = 0; ++ cu->base_address = 0; ++ ++ attr = dwarf2_attr (die, DW_AT_entry_pc, cu); ++ if (attr) ++ { ++ cu->base_address = DW_ADDR (attr); ++ cu->base_known = 1; ++ } ++ else ++ { ++ attr = dwarf2_attr (die, DW_AT_low_pc, cu); ++ if (attr) ++ { ++ cu->base_address = DW_ADDR (attr); ++ cu->base_known = 1; ++ } ++ } ++} + + /* Build the partial symbol table by doing a quick pass through the + .debug_info and .debug_abbrev sections. */ +@@ -1489,7 +1645,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + bfd *abfd = objfile->obfd; + gdb_byte *info_ptr; + gdb_byte *beg_of_comp_unit; +- struct partial_die_info comp_unit_die; ++ struct die_info *comp_unit_die; + struct partial_symtab *pst; + struct cleanup *back_to; + CORE_ADDR baseaddr; +@@ -1523,9 +1679,12 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + { + struct cleanup *back_to_inner; + struct dwarf2_cu cu; +- struct abbrev_info *abbrev; + unsigned int bytes_read; + struct dwarf2_per_cu_data *this_cu; ++ int has_children, has_pc_info; ++ struct attribute *attr; ++ const char *name; ++ CORE_ADDR best_lowpc, best_highpc; + + beg_of_comp_unit = info_ptr; + +@@ -1551,11 +1710,10 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + this_cu = dwarf2_find_comp_unit (cu.header.offset, objfile); + + /* Read the compilation unit die */ +- abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu); +- info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, +- abfd, info_ptr, &cu); ++ info_ptr = read_full_die (&comp_unit_die, abfd, info_ptr, &cu, ++ &has_children); + +- if (comp_unit_die.tag == DW_TAG_partial_unit) ++ if (comp_unit_die->tag == DW_TAG_partial_unit) + { + info_ptr = (beg_of_comp_unit + cu.header.length + + cu.header.initial_length_size); +@@ -1564,20 +1722,27 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + } + + /* Set the language we're debugging */ +- set_cu_language (comp_unit_die.language, &cu); ++ attr = dwarf2_attr (comp_unit_die, DW_AT_language, &cu); ++ if (attr != NULL) ++ set_cu_language (DW_UNSND (attr), &cu); ++ else ++ set_cu_language (language_minimal, &cu); + + /* Allocate a new partial symbol table structure */ +- pst = start_psymtab_common (objfile, objfile->section_offsets, +- comp_unit_die.name ? comp_unit_die.name : "", ++ attr = dwarf2_attr (comp_unit_die, DW_AT_name, &cu); ++ if (attr != NULL) ++ name = DW_STRING (attr); ++ else ++ name = ""; ++ pst = start_psymtab_common (objfile, objfile->section_offsets, name, + /* TEXTLOW and TEXTHIGH are set below. */ + 0, + objfile->global_psymbols.next, + objfile->static_psymbols.next); + +- if (comp_unit_die.dirname) +- pst->dirname = obsavestring (comp_unit_die.dirname, +- strlen (comp_unit_die.dirname), +- &objfile->objfile_obstack); ++ attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu); ++ if (attr != NULL) ++ pst->dirname = xstrdup (DW_STRING (attr)); + + pst->read_symtab_private = (char *) this_cu; + +@@ -1607,24 +1772,17 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + + /* Possibly set the default values of LOWPC and HIGHPC from + `DW_AT_ranges'. */ +- if (cu.has_ranges_offset) +- { +- if (dwarf2_ranges_read (cu.ranges_offset, &comp_unit_die.lowpc, +- &comp_unit_die.highpc, &cu, pst)) +- comp_unit_die.has_pc_info = 1; +- } +- else if (comp_unit_die.has_pc_info +- && comp_unit_die.lowpc < comp_unit_die.highpc) +- /* Store the contiguous range if it is not empty; it can be empty for +- CUs with no code. */ +- addrmap_set_empty (objfile->psymtabs_addrmap, +- comp_unit_die.lowpc + baseaddr, +- comp_unit_die.highpc + baseaddr - 1, pst); ++ has_pc_info = 0; ++ ++ if (dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc, &best_highpc, &cu, ++ pst)) ++ has_pc_info = 1; ++ dwarf2_find_base_address (comp_unit_die, &cu); + + /* Check if comp unit has_children. + If so, read the rest of the partial symbols from this comp unit. + If not, there's no more debug_info for this comp unit. */ +- if (comp_unit_die.has_children) ++ if (has_children) + { + struct partial_die_info *first_die; + CORE_ADDR lowpc, highpc; +@@ -1635,7 +1793,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + first_die = load_partial_dies (abfd, info_ptr, 1, &cu); + + scan_partial_symbols (first_die, &lowpc, &highpc, +- ! comp_unit_die.has_pc_info, &cu); ++ ! has_pc_info, &cu); + + /* If we didn't find a lowpc, set it to highpc to avoid + complaints from `maint check'. */ +@@ -1644,14 +1802,21 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + + /* If the compilation unit didn't have an explicit address range, + then use the information extracted from its child dies. */ +- if (! comp_unit_die.has_pc_info) ++ if (! has_pc_info) + { +- comp_unit_die.lowpc = lowpc; +- comp_unit_die.highpc = highpc; ++ best_lowpc = lowpc; ++ best_highpc = highpc; + } + } +- pst->textlow = comp_unit_die.lowpc + baseaddr; +- pst->texthigh = comp_unit_die.highpc + baseaddr; ++ pst->textlow = best_lowpc + baseaddr; ++ pst->texthigh = best_highpc + baseaddr; ++ ++ /* Store the contiguous range; `DW_AT_ranges' range is stored above. The ++ range can be also empty for CUs with no code. */ ++ if (dwarf2_attr (comp_unit_die, DW_AT_ranges, &cu) == NULL ++ && pst->textlow < pst->texthigh) ++ addrmap_set_empty (objfile->psymtabs_addrmap, pst->textlow, ++ pst->texthigh - 1, pst); + + pst->n_global_syms = objfile->global_psymbols.next - + (objfile->global_psymbols.list + pst->globals_offset); +@@ -1667,12 +1832,9 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) + info_ptr = beg_of_comp_unit + cu.header.length + + cu.header.initial_length_size; + +- if (comp_unit_die.has_stmt_list) +- { +- /* Get the list of files included in the current compilation unit, +- and build a psymtab for each of them. */ +- dwarf2_build_include_psymtabs (&cu, &comp_unit_die, pst); +- } ++ /* Get the list of files included in the current compilation unit, ++ and build a psymtab for each of them. */ ++ dwarf2_build_include_psymtabs (&cu, comp_unit_die, pst); + + do_cleanups (back_to_inner); + } +@@ -1690,11 +1852,12 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) + { + bfd *abfd = objfile->obfd; + gdb_byte *info_ptr, *beg_of_comp_unit; +- struct partial_die_info comp_unit_die; ++ struct die_info *comp_unit_die; + struct dwarf2_cu *cu; +- struct abbrev_info *abbrev; + unsigned int bytes_read; + struct cleanup *back_to; ++ struct attribute *attr; ++ int has_children; + + info_ptr = dwarf2_per_objfile->info_buffer + this_cu->offset; + beg_of_comp_unit = info_ptr; +@@ -1716,12 +1879,15 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) + back_to = make_cleanup (dwarf2_free_abbrev_table, cu); + + /* Read the compilation unit die. */ +- abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu); +- info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, +- abfd, info_ptr, cu); ++ info_ptr = read_full_die (&comp_unit_die, abfd, info_ptr, cu, ++ &has_children); + + /* Set the language we're debugging. */ +- set_cu_language (comp_unit_die.language, cu); ++ attr = dwarf2_attr (comp_unit_die, DW_AT_language, cu); ++ if (attr) ++ set_cu_language (DW_UNSND (attr), cu); ++ else ++ set_cu_language (language_minimal, cu); + + /* Link this compilation unit into the compilation unit tree. */ + this_cu->cu = cu; +@@ -1731,7 +1897,7 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) + /* Check if comp unit has_children. + If so, read the rest of the partial symbols from this comp unit. + If not, there's no more debug_info for this comp unit. */ +- if (comp_unit_die.has_children) ++ if (has_children) + load_partial_dies (abfd, info_ptr, 0, cu); + + do_cleanups (back_to); +@@ -1948,7 +2114,7 @@ partial_die_parent_scope (struct partial_die_info *pdi, + ignoring them. */ + complaint (&symfile_complaints, + _("unhandled containing DIE tag %d for DIE at %d"), +- parent->tag, pdi->offset); ++ parent->tag, real_pdi->offset); + parent->scope = grandparent_scope; + } + +@@ -1963,12 +2129,37 @@ partial_die_full_name (struct partial_die_info *pdi, + struct dwarf2_cu *cu) + { + char *parent_scope; ++ struct partial_die_info *real_pdi; + +- parent_scope = partial_die_parent_scope (pdi, cu); +- if (parent_scope == NULL) +- return NULL; +- else ++ /* We need to look at our parent DIE; if we have a DW_AT_specification, ++ then this means the parent of the specification DIE. ++ partial_die_parent_scope does this loop also, but we do it here ++ since we need to examine real_pdi->parent ourselves. */ ++ ++ real_pdi = pdi; ++ while (real_pdi->has_specification) ++ real_pdi = find_partial_die (real_pdi->spec_offset, cu); ++ ++ parent_scope = partial_die_parent_scope (real_pdi, cu); ++ if (parent_scope != NULL) + return typename_concat (NULL, parent_scope, pdi->name, cu); ++ ++ if (!cu->has_namespace_info && pdi->linkage_name ++ && !real_pdi->die_parent) ++ { ++ char *actual_scope ++ = language_class_name_from_physname (cu->language_defn, ++ pdi->linkage_name); ++ if (actual_scope != NULL) ++ { ++ char *actual_name = typename_concat (NULL, actual_scope, ++ pdi->name, cu); ++ xfree (actual_scope); ++ return actual_name; ++ } ++ } ++ ++ return NULL; + } + + static void +@@ -1984,7 +2175,9 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) + + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + +- if (pdi_needs_namespace (pdi->tag)) ++ if (pdi->linkage_name != NULL) ++ actual_name = pdi->linkage_name; ++ else if (pdi_needs_namespace (pdi->tag)) + { + actual_name = partial_die_full_name (pdi, cu); + if (actual_name) +@@ -2133,9 +2326,8 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) + if (cu->language == language_cplus + && cu->has_namespace_info == 0 + && psym != NULL +- && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL) +- cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym), +- objfile); ++ && pdi->linkage_name != NULL) ++ cp_check_possible_namespace_symbols (actual_name, objfile); + + if (built_actual_name) + xfree (actual_name); +@@ -2158,6 +2350,14 @@ pdi_needs_namespace (enum dwarf_tag tag) + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + case DW_TAG_enumerator: ++ case DW_TAG_subprogram: ++ case DW_TAG_variable: ++ return 1; ++ case DW_TAG_member: ++ /* The only time we will encounter member variables in this ++ function is when we are creating a "linkage" name for them; ++ therefore they must be static members, so they do need a ++ class prefix. */ + return 1; + default: + return 0; +@@ -2290,11 +2490,11 @@ guess_structure_name (struct partial_die_info *struct_pdi, + + while (child_pdi != NULL) + { +- if (child_pdi->tag == DW_TAG_subprogram) ++ if (child_pdi->tag == DW_TAG_subprogram && child_pdi->linkage_name) + { + char *actual_class_name + = language_class_name_from_physname (cu->language_defn, +- child_pdi->name); ++ child_pdi->linkage_name); + if (actual_class_name != NULL) + { + struct_pdi->name +@@ -2741,7 +2941,6 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) + CORE_ADDR lowpc, highpc; + struct symtab *symtab; + struct cleanup *back_to; +- struct attribute *attr; + CORE_ADDR baseaddr; + + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); +@@ -2751,30 +2950,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) + + cu->list_in_scope = &file_symbols; + +- /* Find the base address of the compilation unit for range lists and +- location lists. It will normally be specified by DW_AT_low_pc. +- In DWARF-3 draft 4, the base address could be overridden by +- DW_AT_entry_pc. It's been removed, but GCC still uses this for +- compilation units with discontinuous ranges. */ +- +- cu->base_known = 0; +- cu->base_address = 0; +- +- attr = dwarf2_attr (cu->dies, DW_AT_entry_pc, cu); +- if (attr) +- { +- cu->base_address = DW_ADDR (attr); +- cu->base_known = 1; +- } +- else +- { +- attr = dwarf2_attr (cu->dies, DW_AT_low_pc, cu); +- if (attr) +- { +- cu->base_address = DW_ADDR (attr); +- cu->base_known = 1; +- } +- } ++ dwarf2_find_base_address (cu->dies, cu); + + /* Do line number decoding in read_file_scope () */ + process_die (cu->dies, cu); +@@ -2805,6 +2981,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) + static void + process_die (struct die_info *die, struct dwarf2_cu *cu) + { ++ + switch (die->tag) + { + case DW_TAG_padding: +@@ -2849,6 +3026,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) + + case DW_TAG_base_type: + case DW_TAG_subrange_type: ++ case DW_TAG_typedef: + /* Add a typedef symbol for the type definition, if it has a + DW_AT_name. */ + new_symbol (die, read_type_die (die, cu), cu); +@@ -2867,14 +3045,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) + break; + case DW_TAG_imported_declaration: + case DW_TAG_imported_module: +- /* FIXME: carlton/2002-10-16: Eventually, we should use the +- information contained in these. DW_TAG_imported_declaration +- dies shouldn't have children; DW_TAG_imported_module dies +- shouldn't in the C++ case, but conceivably could in the +- Fortran case. */ + processing_has_namespace_info = 1; +- complaint (&symfile_complaints, _("unsupported tag: '%s'"), +- dwarf_tag_name (die->tag)); ++ if (die->child != NULL && (die->tag == DW_TAG_imported_declaration ++ || cu->language != language_fortran)) ++ complaint (&symfile_complaints, _("Tag '%s' has unexpected children"), ++ dwarf_tag_name (die->tag)); ++ read_import_statement (die, cu); + break; + default: + new_symbol (die, NULL, cu); +@@ -2904,22 +3080,130 @@ dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu) + return name; + + /* If no prefix is necessary for this type of DIE, return the +- unqualified name. The other three tags listed could be handled +- in pdi_needs_namespace, but that requires broader changes. */ +- if (!pdi_needs_namespace (die->tag) +- && die->tag != DW_TAG_subprogram +- && die->tag != DW_TAG_variable +- && die->tag != DW_TAG_member) ++ unqualified name. */ ++ if (!pdi_needs_namespace (die->tag)) + return name; + + prefix = determine_prefix (die, cu); + if (*prefix != '\0') +- name = typename_concat (&cu->objfile->objfile_obstack, prefix, +- name, cu); ++ { ++ char *prefixed_name = typename_concat (NULL, prefix, name, cu); ++ buf = mem_fileopen (); ++ fputs_unfiltered (prefixed_name, buf); ++ xfree (prefixed_name); ++ } ++ ++ if (cu->language == language_cplus && die->tag == DW_TAG_subprogram) ++ { ++ struct type *type = read_type_die (die, cu); ++ ++ if (buf == NULL) ++ { ++ buf = mem_fileopen (); ++ fputs_unfiltered (name, buf); ++ } ++ ++ c_type_print_args (type, buf, 0); ++ } ++ ++ if (buf != NULL) ++ { ++ long length; ++ name = ui_file_obsavestring (buf, &cu->objfile->objfile_obstack, ++ &length); ++ ui_file_delete (buf); ++ } + + return name; + } + ++/* read the given die's decl_line number. Return -1 if in case of an error */ ++static int dwarf2_read_decl_line (struct die_info *die, struct dwarf2_cu *cu){ ++ struct attribute *line_attr; ++ ++ line_attr = dwarf2_attr (die, DW_AT_decl_line, cu); ++ if (line_attr){ ++ return DW_UNSND (line_attr); ++ } ++ ++ return -1; ++} ++ ++/* Read the import statement specified by the given die and record it. */ ++ ++static void ++read_import_statement (struct die_info *die, struct dwarf2_cu *cu) ++{ ++ struct attribute *import_attr; ++ struct die_info *imported_die; ++ const char *imported_name; ++ const char *imported_name_prefix; ++ char *canonical_name; ++ const char *import_alias; ++ const char *imported_declaration = ""; ++ const char *import_prefix; ++ ++ int line_number = -1; ++ ++ int is_anonymous = 0; ++ ++ import_attr = dwarf2_attr (die, DW_AT_import, cu); ++ if (import_attr == NULL) ++ { ++ complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"), ++ dwarf_tag_name (die->tag)); ++ return; ++ } ++ ++ imported_die = follow_die_ref (die, import_attr, &cu); ++ imported_name = namespace_name (imported_die, &is_anonymous, cu); ++ if (imported_name == NULL) ++ { ++ /* C++ imports from std:: DW_TAG_base_type with no DW_AT_name - why? */ ++ return; ++ } ++ ++ /* Figure out the local name after import. */ ++ import_alias = dwarf2_name(die, cu); ++ if(import_alias == NULL){ ++ import_alias = ""; ++ } ++ ++ /* Determine the line number at which the import was made */ ++ line_number = dwarf2_read_decl_line(die, cu); ++ ++ /* Figure out where the statement is being imported to */ ++ import_prefix = determine_prefix (die, cu); ++ ++ /* ++ Figure out what the scope of the imported die is and prepend it ++ to the name of the imported die ++ */ ++ imported_name_prefix = determine_prefix (imported_die, cu); ++ ++ if(imported_die->tag != DW_TAG_namespace){ ++ imported_declaration = imported_name; ++ canonical_name = (char*)imported_name_prefix; ++ }else{ ++ if(strlen (imported_name_prefix) > 0){ ++ canonical_name = alloca (strlen (imported_name_prefix) + 2 + strlen (imported_name) + 1); ++ strcpy (canonical_name, imported_name_prefix); ++ strcat (canonical_name, "::"); ++ strcat (canonical_name, imported_name); ++ }else{ ++ canonical_name = alloca (strlen (imported_name) + 1); ++ strcpy (canonical_name, imported_name); ++ } ++ } ++ ++ using_directives = cp_add_using (import_prefix, ++ canonical_name, ++ import_alias, ++ imported_declaration, ++ line_number, ++ using_directives); ++} ++ + static void + initialize_cu_func_list (struct dwarf2_cu *cu) + { +@@ -3076,6 +3360,103 @@ add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc, + cu->last_fn = thisfn; + } + ++static int ++unsigned_int_compar (const void *ap, const void *bp) ++{ ++ unsigned int a = *(unsigned int *) ap; ++ unsigned int b = *(unsigned int *) bp; ++ ++ return (a > b) - (b > a); ++} ++ ++static void explore_abstract_origin(struct die_info *die, struct dwarf2_cu *cu, unsigned* die_children_p){ ++ struct attribute *attr; ++ unsigned die_children = *die_children_p; ++ struct die_info *child_die; ++ ++ attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); ++ ++ /* GCC currently uses DW_AT_specification to indicate die inheritence ++ in the case of import statements. The following is to accommodate that */ ++ if(!attr){ ++ attr = dwarf2_attr (die, DW_AT_specification, cu); ++ } ++ ++ if (attr) ++ { ++ /* For the list of CHILD_DIEs. */ ++ unsigned *offsets; ++ unsigned *offsets_end, *offsetp; ++ struct die_info *origin_die, *origin_child_die; ++ struct cleanup *cleanups; ++ ++ origin_die = follow_die_ref (die, attr, &cu); ++ if (die->tag != origin_die->tag) ++ complaint (&symfile_complaints, ++ _("DIE 0x%x and its abstract origin 0x%x have different " ++ "tags"), ++ die->offset, origin_die->offset); ++ ++ offsets = xmalloc (sizeof (*offsets) * die_children); ++ cleanups = make_cleanup (xfree, offsets); ++ ++ offsets_end = offsets; ++ child_die = die->child; ++ while (child_die && child_die->tag) ++ { ++ attr = dwarf2_attr (child_die, DW_AT_abstract_origin, cu); ++ if (!attr) ++ complaint (&symfile_complaints, ++ _("Child DIE 0x%x of DIE 0x%x has missing " ++ "DW_AT_abstract_origin"), ++ child_die->offset, die->offset); ++ else ++ { ++ struct die_info *child_origin_die; ++ ++ child_origin_die = follow_die_ref (child_die, attr, &cu); ++ if (child_die->tag != child_origin_die->tag) ++ complaint (&symfile_complaints, ++ _("Child DIE 0x%x and its abstract origin 0x%x have " ++ "different tags"), ++ child_die->offset, child_origin_die->offset); ++ *offsets_end++ = child_origin_die->offset; ++ } ++ child_die = sibling_die (child_die); ++ } ++ qsort (offsets, offsets_end - offsets, sizeof (*offsets), ++ unsigned_int_compar); ++ /* Disabled as excessively expensive - check if we may ever complain. */ ++ if (0) ++ { ++ for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++) ++ if (offsetp[-1] == *offsetp) ++ complaint (&symfile_complaints, ++ _("Child DIEs of DIE 0x%x duplicitly abstract-origin " ++ "referenced DIE 0x%x"), ++ die->offset, *offsetp); ++ } ++ ++ offsetp = offsets; ++ origin_child_die = origin_die->child; ++ while (origin_child_die && origin_child_die->tag) ++ { ++ /* Is origin_child_die referenced by any of the DIE children? */ ++ while (offsetp < offsets_end && *offsetp < origin_child_die->offset) ++ offsetp++; ++ if (offsetp >= offsets_end || *offsetp > origin_child_die->offset) ++ { ++ /* Found that origin_child_die is really not referenced. */ ++ process_die (origin_child_die, cu); ++ } ++ origin_child_die = sibling_die (origin_child_die); ++ } ++ ++ do_cleanups (cleanups); ++ } ++ ++} ++ + static void + read_func_scope (struct die_info *die, struct dwarf2_cu *cu) + { +@@ -3088,15 +3469,27 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) + char *name; + CORE_ADDR baseaddr; + struct block *block; ++ unsigned die_children; + + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + +- name = dwarf2_linkage_name (die, cu); ++ name = dwarf2_name (die, cu); + + /* Ignore functions with missing or empty names and functions with + missing or invalid low and high pc attributes. */ +- if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu)) ++ if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)){ ++ /* explore abstract origins if present. They might contain useful information ++ such as import statements. */ ++ child_die = die->child; ++ die_children = 0; ++ while (child_die && child_die->tag) ++ { ++ child_die = sibling_die (child_die); ++ die_children++; ++ } ++ explore_abstract_origin(die, cu, &die_children); + return; ++ } + + lowpc += baseaddr; + highpc += baseaddr; +@@ -3124,14 +3517,87 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) + + cu->list_in_scope = &local_symbols; + +- if (die->child != NULL) ++ child_die = die->child; ++ die_children = 0; ++ while (child_die && child_die->tag) ++ { ++ process_die (child_die, cu); ++ child_die = sibling_die (child_die); ++ die_children++; ++ } ++ ++ attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); ++ if (attr) + { ++ /* For the list of CHILD_DIEs. */ ++ unsigned *offsets; ++ unsigned *offsets_end, *offsetp; ++ struct die_info *origin_die, *origin_child_die; ++ struct cleanup *cleanups; ++ ++ origin_die = follow_die_ref (die, attr, &cu); ++ if (die->tag != origin_die->tag) ++ complaint (&symfile_complaints, ++ _("DIE 0x%x and its abstract origin 0x%x have different " ++ "tags"), ++ die->offset, origin_die->offset); ++ ++ offsets = xmalloc (sizeof (*offsets) * die_children); ++ cleanups = make_cleanup (xfree, offsets); ++ ++ offsets_end = offsets; + child_die = die->child; + while (child_die && child_die->tag) + { +- process_die (child_die, cu); ++ attr = dwarf2_attr (child_die, DW_AT_abstract_origin, cu); ++ if (!attr) ++ complaint (&symfile_complaints, ++ _("Child DIE 0x%x of DIE 0x%x has missing " ++ "DW_AT_abstract_origin"), ++ child_die->offset, die->offset); ++ else ++ { ++ struct die_info *child_origin_die; ++ ++ child_origin_die = follow_die_ref (child_die, attr, &cu); ++ if (child_die->tag != child_origin_die->tag) ++ complaint (&symfile_complaints, ++ _("Child DIE 0x%x and its abstract origin 0x%x have " ++ "different tags"), ++ child_die->offset, child_origin_die->offset); ++ *offsets_end++ = child_origin_die->offset; ++ } + child_die = sibling_die (child_die); + } ++ qsort (offsets, offsets_end - offsets, sizeof (*offsets), ++ unsigned_int_compar); ++ /* Disabled as excessively expensive - check if we may ever complain. */ ++ if (0) ++ { ++ for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++) ++ if (offsetp[-1] == *offsetp) ++ complaint (&symfile_complaints, ++ _("Child DIEs of DIE 0x%x duplicitly abstract-origin " ++ "referenced DIE 0x%x"), ++ die->offset, *offsetp); ++ } ++ ++ offsetp = offsets; ++ origin_child_die = origin_die->child; ++ while (origin_child_die && origin_child_die->tag) ++ { ++ /* Is origin_child_die referenced by any of the DIE children? */ ++ while (offsetp < offsets_end && *offsetp < origin_child_die->offset) ++ offsetp++; ++ if (offsetp >= offsets_end || *offsetp > origin_child_die->offset) ++ { ++ /* Found that origin_child_die is really not referenced. */ ++ process_die (origin_child_die, cu); ++ } ++ origin_child_die = sibling_die (origin_child_die); ++ } ++ ++ do_cleanups (cleanups); + } + + new = pop_context (); +@@ -3154,6 +3620,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) + back to building a containing block's symbol lists. */ + local_symbols = new->locals; + param_symbols = new->params; ++ using_directives = new->using_directives; + + /* If we've finished processing a top-level function, subsequent + symbols go in the file symbol list. */ +@@ -3180,7 +3647,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) + as multiple lexical blocks? Handling children in a sane way would + be nasty. Might be easier to properly extend generic blocks to + describe ranges. */ +- if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu)) ++ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) + return; + lowpc += baseaddr; + highpc += baseaddr; +@@ -3197,7 +3664,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) + } + new = pop_context (); + +- if (local_symbols != NULL) ++ if (local_symbols != NULL || using_directives!= NULL ) + { + struct block *block + = finish_block (0, &local_symbols, new->old_blocks, new->start_addr, +@@ -3216,6 +3683,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) + dwarf2_record_block_ranges (die, block, baseaddr, cu); + } + local_symbols = new->locals; ++ using_directives = new->using_directives; + } + + /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. +@@ -3351,7 +3819,8 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, + discontinuous, i.e. derived from DW_AT_ranges information. */ + static int + dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, +- CORE_ADDR *highpc, struct dwarf2_cu *cu) ++ CORE_ADDR *highpc, struct dwarf2_cu *cu, ++ struct partial_symtab *pst) + { + struct attribute *attr; + CORE_ADDR low = 0; +@@ -3379,7 +3848,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, + { + /* Value of the DW_AT_ranges attribute is the offset in the + .debug_ranges section. */ +- if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu, NULL)) ++ if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu, pst)) + return 0; + /* Found discontinuous range of addresses. */ + ret = -1; +@@ -3418,7 +3887,7 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die, + CORE_ADDR low, high; + struct die_info *child = die->child; + +- if (dwarf2_get_pc_bounds (die, &low, &high, cu)) ++ if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL)) + { + *lowpc = min (*lowpc, low); + *highpc = max (*highpc, high); +@@ -3455,7 +3924,7 @@ get_scope_pc_bounds (struct die_info *die, + CORE_ADDR best_high = (CORE_ADDR) 0; + CORE_ADDR current_low, current_high; + +- if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu)) ++ if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL)) + { + best_low = current_low; + best_high = current_high; +@@ -3750,8 +4219,14 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, + if (fieldname == NULL) + return; + +- /* Get physical name. */ ++ /* Get physical name. We prefer the linkage name if one was specified, ++ because this lets GDB find a non-debugging version of the symbol. ++ Otherwise construct the full name from type information. Ideally, ++ when GDB supports canonicalization of C++ symbol names, we will not ++ need the linkage name for anything. */ + physname = dwarf2_linkage_name (die, cu); ++ if (physname == NULL) ++ physname = (char *) dwarf2_full_name (die, cu); + + /* The name is already allocated along with this objfile, so we don't + need to duplicate it for the type. */ +@@ -3881,8 +4356,14 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, + if (fieldname == NULL) + return; + +- /* Get the mangled name. */ ++ /* Get physical name. We prefer the linkage name if one was specified, ++ because this lets GDB find a non-debugging version of the symbol. ++ Otherwise construct the full name from type information. Ideally, ++ when GDB supports canonicalization of C++ symbol names, we will not ++ need the linkage name for anything. */ + physname = dwarf2_linkage_name (die, cu); ++ if (physname == NULL) ++ physname = (char *) dwarf2_full_name (die, cu); + + /* Look up member function name in fieldlist. */ + for (i = 0; i < fip->nfnfields; i++) +@@ -3926,7 +4407,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, + /* The name is already allocated along with this objfile, so we don't + need to duplicate it for the type. */ + fnp->physname = physname ? physname : ""; +- fnp->type = alloc_type (objfile); ++ fnp->type = alloc_type (objfile, NULL); + this_type = read_type_die (die, cu); + if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) + { +@@ -4110,7 +4591,7 @@ quirk_gcc_member_function_pointer (struct die_info *die, struct dwarf2_cu *cu) + return NULL; + + domain_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0)); +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + smash_to_method_type (type, domain_type, TYPE_TARGET_TYPE (pfn_type), + TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type), + TYPE_VARARGS (pfn_type)); +@@ -4147,7 +4628,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) + if (type) + return type; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + INIT_CPLUS_SPECIFIC (type); + name = dwarf2_name (die, cu); + if (name != NULL) +@@ -4360,7 +4841,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) + struct attribute *attr; + const char *name; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + + TYPE_CODE (type) = TYPE_CODE_ENUM; + name = dwarf2_full_name (die, cu); +@@ -4410,10 +4891,15 @@ determine_class_name (struct die_info *die, struct dwarf2_cu *cu) + { + if (child->tag == DW_TAG_subprogram) + { +- char *phys_prefix ++ char *phys_prefix; ++ char *linkage_name = dwarf2_linkage_name (child, cu); ++ ++ if (linkage_name == NULL) ++ continue; ++ ++ phys_prefix + = language_class_name_from_physname (cu->language_defn, +- dwarf2_linkage_name +- (child, cu)); ++ linkage_name); + + if (phys_prefix != NULL) + { +@@ -4510,6 +4996,29 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) + new_symbol (die, this_type, cu); + } + ++/* Create a new array dimension referencing its target type TYPE. ++ ++ Multidimensional arrays are internally represented as a stack of ++ singledimensional arrays being referenced by their TYPE_TARGET_TYPE. */ ++ ++static struct type * ++create_single_array_dimension (struct type *type, struct type *range_type, ++ struct die_info *die, struct dwarf2_cu *cu) ++{ ++ type = create_array_type (NULL, type, range_type); ++ ++ /* These generic type attributes need to be fetched by ++ evaluate_subexp_standard 's call of ++ value_subscripted_rvalue only for the innermost array type. */ ++ fetch_die_type_attrs (die, type, cu); ++ ++ /* These generic type attributes are checked for allocated/associated ++ validity while accessing FIELD_LOC_KIND_DWARF_BLOCK. */ ++ fetch_die_type_attrs (die, range_type, cu); ++ ++ return type; ++} ++ + /* Extract all information from a DW_TAG_array_type DIE and put it in + the DIE's type field. For now, this only handles one dimensional + arrays. */ +@@ -4523,7 +5032,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) + struct type *element_type, *range_type, *index_type; + struct type **range_types = NULL; + struct attribute *attr; +- int ndim = 0; ++ int ndim = 0, i; + struct cleanup *back_to; + char *name; + +@@ -4570,16 +5079,11 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) + type = element_type; + + if (read_array_order (die, cu) == DW_ORD_col_major) +- { +- int i = 0; +- while (i < ndim) +- type = create_array_type (NULL, type, range_types[i++]); +- } +- else +- { +- while (ndim-- > 0) +- type = create_array_type (NULL, type, range_types[ndim]); +- } ++ for (i = 0; i < ndim; i++) ++ type = create_single_array_dimension (type, range_types[i], die, cu); ++ else /* (read_array_order (die, cu) == DW_ORD_row_major) */ ++ for (i = ndim - 1; i >= 0; i--) ++ type = create_single_array_dimension (type, range_types[i], die, cu); + + /* Understand Dwarf2 support for vector types (like they occur on + the PowerPC w/ AltiVec). Gcc just adds another attribute to the +@@ -4646,12 +5150,14 @@ read_set_type (struct die_info *die, struct dwarf2_cu *cu) + return set_die_type (die, set_type, cu); + } + +-/* First cut: install each common block member as a global variable. */ ++/* Create appropriate locally-scoped variables for all the DW_TAG_common_block ++ entries. Create also TYPE_CODE_STRUCT listing all such variables to be ++ available for `info common'. COMMON_BLOCK_DOMAIN is used to sepate the ++ common blocks name namespace from regular variable names. */ + + static void + read_common_block (struct die_info *die, struct dwarf2_cu *cu) + { +- struct die_info *child_die; + struct attribute *attr; + struct symbol *sym; + CORE_ADDR base = (CORE_ADDR) 0; +@@ -4676,10 +5182,40 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu) + } + if (die->child != NULL) + { ++ struct objfile *objfile = cu->objfile; ++ struct die_info *child_die; ++ struct type *type; ++ struct field *field; ++ char *name; ++ struct symbol *sym; ++ ++ type = alloc_type (objfile, NULL); ++ TYPE_CODE (type) = TYPE_CODE_STRUCT; ++ /* Artificial type to be used only by `info common'. */ ++ TYPE_NAME (type) = ""; ++ + child_die = die->child; + while (child_die && child_die->tag) + { ++ TYPE_NFIELDS (type)++; ++ child_die = sibling_die (child_die); ++ } ++ ++ TYPE_FIELDS (type) = obstack_alloc (&objfile->objfile_obstack, ++ sizeof (*TYPE_FIELDS (type)) ++ * TYPE_NFIELDS (type)); ++ memset (TYPE_FIELDS (type), 0, sizeof (*TYPE_FIELDS (type)) ++ * TYPE_NFIELDS (type)); ++ ++ field = TYPE_FIELDS (type); ++ child_die = die->child; ++ while (child_die && child_die->tag) ++ { ++ /* Create the symbol in the DW_TAG_common_block block in the current ++ symbol scope. */ + sym = new_symbol (child_die, NULL, cu); ++ ++ /* Undocumented in DWARF3, when it can be present? */ + attr = dwarf2_attr (child_die, DW_AT_data_member_location, cu); + if (attr) + { +@@ -4687,8 +5223,25 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu) + base + decode_locdesc (DW_BLOCK (attr), cu); + add_symbol_to_list (sym, &global_symbols); + } ++ ++ if (SYMBOL_CLASS (sym) == LOC_STATIC) ++ SET_FIELD_PHYSADDR (*field, SYMBOL_VALUE_ADDRESS (sym)); ++ else ++ SET_FIELD_PHYSNAME (*field, SYMBOL_LINKAGE_NAME (sym)); ++ FIELD_TYPE (*field) = SYMBOL_TYPE (sym); ++ FIELD_NAME (*field) = SYMBOL_NATURAL_NAME (sym); ++ field++; + child_die = sibling_die (child_die); + } ++ ++ /* TYPE_LENGTH (type) is left 0 - it is only a virtual structure even ++ with no consecutive address space. */ ++ ++ sym = new_symbol (die, type, cu); ++ /* SYMBOL_VALUE_ADDRESS never gets used as all its fields are static. */ ++ SYMBOL_VALUE_ADDRESS (sym) = base; ++ ++ set_die_type (die, type, cu); + } + } + +@@ -4756,9 +5309,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) + if (is_anonymous) + { + const char *previous_prefix = determine_prefix (die, cu); +- cp_add_using_directive (TYPE_NAME (type), +- strlen (previous_prefix), +- strlen (TYPE_NAME (type))); ++ cp_add_using_directive (previous_prefix, TYPE_NAME (type), "", "", dwarf2_read_decl_line(die, cu)); + } + } + +@@ -4951,29 +5502,95 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) + struct objfile *objfile = cu->objfile; + struct type *type, *range_type, *index_type, *char_type; + struct attribute *attr; +- unsigned int length; ++ int length; ++ ++ index_type = builtin_type_int32; ++ /* RANGE_TYPE is allocated from OBJFILE, not OBJFILE_INTERNAL. */ ++ range_type = alloc_type (objfile, index_type); ++ /* LOW_BOUND and HIGH_BOUND are set for real below. */ ++ range_type = create_range_type (range_type, index_type, 0, -1); ++ ++ /* C/C++ should probably have the low bound 0 but C/C++ does not use ++ DW_TAG_string_type. */ ++ TYPE_LOW_BOUND (range_type) = 1; + + attr = dwarf2_attr (die, DW_AT_string_length, cu); +- if (attr) +- { +- length = DW_UNSND (attr); +- } +- else +- { +- /* check for the DW_AT_byte_size attribute */ ++ switch (dwarf2_get_attr_constant_value (attr, &length)) ++ { ++ case dwarf2_attr_const: ++ /* We currently do not support a constant address where the location ++ should be read from - DWARF2_ATTR_BLOCK is expected instead. See ++ DWARF for the DW_AT_STRING_LENGTH vs. DW_AT_BYTE_SIZE difference. */ ++ /* PASSTHRU */ ++ case dwarf2_attr_unknown: + attr = dwarf2_attr (die, DW_AT_byte_size, cu); +- if (attr) +- { +- length = DW_UNSND (attr); +- } +- else +- { +- length = 1; +- } ++ switch (dwarf2_get_attr_constant_value (attr, &length)) ++ { ++ case dwarf2_attr_unknown: ++ length = 1; ++ /* PASSTHRU */ ++ case dwarf2_attr_const: ++ TYPE_HIGH_BOUND (range_type) = length; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = ++ dwarf2_attr_to_locexpr_baton (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ break; ++ } ++ break; ++ case dwarf2_attr_block: ++ /* Security check for a size overflow. */ ++ if (DW_BLOCK (attr)->size + 2 < DW_BLOCK (attr)->size) ++ { ++ TYPE_HIGH_BOUND (range_type) = 1; ++ break; ++ } ++ /* Extend the DWARF block by a new DW_OP_deref/DW_OP_deref_size ++ instruction as DW_AT_string_length specifies the length location, not ++ its value. */ ++ { ++ struct dwarf2_locexpr_baton *length_baton; ++ struct attribute *size_attr; ++ ++ length_baton = obstack_alloc (&cu->comp_unit_obstack, ++ sizeof (*length_baton)); ++ length_baton->per_cu = cu->per_cu; ++ length_baton->data = obstack_alloc (&cu->comp_unit_obstack, ++ DW_BLOCK (attr)->size + 2); ++ memcpy (length_baton->data, DW_BLOCK (attr)->data, ++ DW_BLOCK (attr)->size); ++ ++ /* DW_AT_BYTE_SIZE existing together with DW_AT_STRING_LENGTH specifies ++ the size of an integer to fetch. */ ++ ++ size_attr = dwarf2_attr (die, DW_AT_byte_size, cu); ++ if (size_attr) ++ { ++ length_baton->size = DW_BLOCK (attr)->size + 2; ++ length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref_size; ++ length_baton->data[DW_BLOCK (attr)->size + 1] ++ = DW_UNSND (size_attr); ++ if (length_baton->data[DW_BLOCK (attr)->size + 1] ++ != DW_UNSND (size_attr)) ++ complaint (&symfile_complaints, ++ _("DW_AT_string_length's DW_AT_byte_size integer " ++ "exceeds the byte size storage")); ++ } ++ else ++ { ++ length_baton->size = DW_BLOCK (attr)->size + 1; ++ length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref; ++ } ++ ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = length_baton; ++ TYPE_DYNAMIC (range_type) = 1; ++ } ++ break; + } + +- index_type = builtin_type_int32; +- range_type = create_range_type (NULL, index_type, 1, length); + type = create_string_type (NULL, range_type); + + return set_die_type (die, type, cu); +@@ -5067,7 +5684,6 @@ static struct type * + read_typedef (struct die_info *die, struct dwarf2_cu *cu) + { + struct objfile *objfile = cu->objfile; +- struct attribute *attr; + const char *name = NULL; + struct type *this_type; + +@@ -5175,8 +5791,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) + struct type *base_type; + struct type *range_type; + struct attribute *attr; +- int low = 0; +- int high = -1; ++ int low, high, byte_stride_int; ++ enum dwarf2_get_attr_constant_value high_type; + char *name; + + base_type = die_type (die, cu); +@@ -5189,42 +5805,90 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) + 0, NULL, cu->objfile); + } + +- if (cu->language == language_fortran) +- { +- /* FORTRAN implies a lower bound of 1, if not given. */ +- low = 1; +- } ++ /* LOW_BOUND and HIGH_BOUND are set for real below. */ ++ range_type = create_range_type (NULL, base_type, 0, -1); + +- /* FIXME: For variable sized arrays either of these could be +- a variable rather than a constant value. We'll allow it, +- but we don't know how to handle it. */ + attr = dwarf2_attr (die, DW_AT_lower_bound, cu); +- if (attr) +- low = dwarf2_get_attr_constant_value (attr, 0); ++ switch (dwarf2_get_attr_constant_value (attr, &low)) ++ { ++ case dwarf2_attr_unknown: ++ if (cu->language == language_fortran) ++ { ++ /* FORTRAN implies a lower bound of 1, if not given. */ ++ low = 1; ++ } ++ else ++ { ++ /* According to DWARF we should assume the value 0 only for ++ LANGUAGE_C and LANGUAGE_CPLUS. */ ++ low = 0; ++ } ++ /* PASSTHRU */ ++ case dwarf2_attr_const: ++ TYPE_LOW_BOUND (range_type) = low; ++ if (low >= 0) ++ TYPE_UNSIGNED (range_type) = 1; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 0); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 0) = dwarf2_attr_to_locexpr_baton ++ (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ /* For setting a default if DW_AT_UPPER_BOUND would be missing. */ ++ low = 0; ++ break; ++ } + + attr = dwarf2_attr (die, DW_AT_upper_bound, cu); +- if (attr) +- { +- if (attr->form == DW_FORM_block1) +- { +- /* GCC encodes arrays with unspecified or dynamic length +- with a DW_FORM_block1 attribute. +- FIXME: GDB does not yet know how to handle dynamic +- arrays properly, treat them as arrays with unspecified +- length for now. +- +- FIXME: jimb/2003-09-22: GDB does not really know +- how to handle arrays of unspecified length +- either; we just represent them as zero-length +- arrays. Choose an appropriate upper bound given +- the lower bound we've computed above. */ +- high = low - 1; +- } +- else +- high = dwarf2_get_attr_constant_value (attr, 1); ++ high_type = dwarf2_get_attr_constant_value (attr, &high); ++ if (high_type == dwarf2_attr_unknown) ++ { ++ attr = dwarf2_attr (die, DW_AT_count, cu); ++ high_type = dwarf2_get_attr_constant_value (attr, &high); ++ /* It does not hurt but it is needlessly ineffective in check_typedef. */ ++ if (high_type != dwarf2_attr_unknown) ++ { ++ TYPE_RANGE_HIGH_BOUND_IS_COUNT (range_type) = 1; ++ TYPE_DYNAMIC (range_type) = 1; ++ } ++ /* Pass it now as the regular DW_AT_upper_bound. */ ++ } ++ switch (high_type) ++ { ++ case dwarf2_attr_unknown: ++ TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type) = 1; ++ high = low - 1; ++ /* PASSTHRU */ ++ case dwarf2_attr_const: ++ TYPE_HIGH_BOUND (range_type) = high; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = dwarf2_attr_to_locexpr_baton ++ (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ break; + } + +- range_type = create_range_type (NULL, base_type, low, high); ++ /* DW_AT_bit_stride is currently unsupported as we count in bytes. */ ++ attr = dwarf2_attr (die, DW_AT_byte_stride, cu); ++ switch (dwarf2_get_attr_constant_value (attr, &byte_stride_int)) ++ { ++ case dwarf2_attr_unknown: ++ break; ++ case dwarf2_attr_const: ++ if (byte_stride_int == 0) ++ complaint (&symfile_complaints, ++ _("Found DW_AT_byte_stride with unsupported value 0")); ++ TYPE_BYTE_STRIDE (range_type) = byte_stride_int; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 2); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 2) = dwarf2_attr_to_locexpr_baton ++ (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ break; ++ } + + name = dwarf2_name (die, cu); + if (name) +@@ -5386,10 +6050,13 @@ read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd, + } + + /* Decompress a section that was compressed using zlib. Store the +- decompressed buffer, and its size, in OUTBUF and OUTSIZE. */ ++ decompressed buffer, and its size, in OUTBUF and OUTSIZE. The ++ result is allocated on OBSTACK; if OBSTACK is NULL, xmalloc is ++ used. */ + + static void +-zlib_decompress_section (struct objfile *objfile, asection *sectp, ++zlib_decompress_section (struct objfile *objfile, struct obstack *obstack, ++ asection *sectp, + gdb_byte **outbuf, bfd_size_type *outsize) + { + bfd *abfd = objfile->obfd; +@@ -5405,6 +6072,7 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp, + z_stream strm; + int rc; + int header_size = 12; ++ struct cleanup *old = NULL; + + if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 + || bfd_bread (compressed_buffer, compressed_size, abfd) != compressed_size) +@@ -5434,8 +6102,13 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp, + strm.avail_in = compressed_size - header_size; + strm.next_in = (Bytef*) compressed_buffer + header_size; + strm.avail_out = uncompressed_size; +- uncompressed_buffer = obstack_alloc (&objfile->objfile_obstack, +- uncompressed_size); ++ if (obstack) ++ uncompressed_buffer = obstack_alloc (obstack, uncompressed_size); ++ else ++ { ++ uncompressed_buffer = xmalloc (uncompressed_size); ++ old = make_cleanup (xfree, uncompressed_buffer); ++ } + rc = inflateInit (&strm); + while (strm.avail_in > 0) + { +@@ -5456,6 +6129,8 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp, + error (_("Dwarf Error: concluding DWARF uncompression in '%s': %d"), + bfd_get_filename (abfd), rc); + ++ if (old) ++ discard_cleanups (old); + xfree (compressed_buffer); + *outbuf = uncompressed_buffer; + *outsize = uncompressed_size; +@@ -5463,17 +6138,20 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp, + } + + +-/* Read the contents of the section at OFFSET and of size SIZE from the +- object file specified by OBJFILE into the objfile_obstack and return it. +- If the section is compressed, uncompress it before returning. */ ++/* Read the contents of the section at OFFSET and of size SIZE from ++ the object file specified by OBJFILE into OBSTACK and return it. ++ If OBSTACK is NULL, xmalloc is used instead. If the section is ++ compressed, uncompress it before returning. */ + +-gdb_byte * +-dwarf2_read_section (struct objfile *objfile, asection *sectp) ++static gdb_byte * ++dwarf2_read_section_1 (struct objfile *objfile, struct obstack *obstack, ++ asection *sectp) + { + bfd *abfd = objfile->obfd; + gdb_byte *buf, *retbuf; + bfd_size_type size = bfd_get_section_size (sectp); + unsigned char header[4]; ++ struct cleanup *old = NULL; + + if (size == 0) + return NULL; +@@ -5486,30 +6164,49 @@ dwarf2_read_section (struct objfile *objfile, asection *sectp) + /* Upon decompression, update the buffer and its size. */ + if (strncmp (header, "ZLIB", sizeof (header)) == 0) + { +- zlib_decompress_section (objfile, sectp, &buf, &size); ++ zlib_decompress_section (objfile, obstack, sectp, &buf, &size); + dwarf2_resize_section (sectp, size); + return buf; + } + } + + /* If we get here, we are a normal, not-compressed section. */ +- buf = obstack_alloc (&objfile->objfile_obstack, size); ++ if (obstack) ++ buf = obstack_alloc (obstack, size); ++ else ++ { ++ buf = xmalloc (size); ++ old = make_cleanup (xfree, buf); ++ } + /* When debugging .o files, we may need to apply relocations; see + http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . + We never compress sections in .o files, so we only need to + try this when the section is not compressed. */ + retbuf = symfile_relocate_debug_section (abfd, sectp, buf); + if (retbuf != NULL) +- return retbuf; ++ { ++ if (old) ++ discard_cleanups (old); ++ return retbuf; ++ } + + if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 + || bfd_bread (buf, size, abfd) != size) + error (_("Dwarf Error: Can't read DWARF data from '%s'"), + bfd_get_filename (abfd)); + ++ if (old) ++ discard_cleanups (old); ++ + return buf; + } + ++gdb_byte * ++dwarf2_read_section (struct objfile *objfile, asection *sectp) ++{ ++ return dwarf2_read_section_1 (objfile, &objfile->objfile_obstack, sectp); ++} ++ + /* In DWARF version 2, the description of the debugging information is + stored in a separate .debug_abbrev section. Before we read any + dies from a section we read in all abbreviations and install them +@@ -5914,15 +6611,6 @@ read_partial_die (struct partial_die_info *part_die, + struct attribute attr; + int has_low_pc_attr = 0; + int has_high_pc_attr = 0; +- CORE_ADDR base_address = 0; +- enum +- { +- base_address_none, +- base_address_low_pc, +- /* Overrides BASE_ADDRESS_LOW_PC. */ +- base_address_entry_pc +- } +- base_address_type = base_address_none; + + memset (part_die, 0, sizeof (struct partial_die_info)); + +@@ -5945,47 +6633,35 @@ read_partial_die (struct partial_die_info *part_die, + switch (attr.name) + { + case DW_AT_name: +- +- /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */ +- if (part_die->name == NULL) +- part_die->name = DW_STRING (&attr); +- break; +- case DW_AT_comp_dir: +- if (part_die->dirname == NULL) +- part_die->dirname = DW_STRING (&attr); ++ switch (part_die->tag) ++ { ++ case DW_TAG_compile_unit: ++ /* Compilation units have a DW_AT_name that is a filename, not ++ a source language identifier. */ ++ case DW_TAG_enumeration_type: ++ case DW_TAG_enumerator: ++ /* These tags always have simple identifiers already; no need ++ to canonicalize them. */ ++ part_die->name = DW_STRING (&attr); ++ break; ++ default: ++ part_die->name ++ = dwarf2_canonicalize_name (DW_STRING (&attr), cu, ++ &cu->comp_unit_obstack); ++ break; ++ } + break; + case DW_AT_MIPS_linkage_name: +- part_die->name = DW_STRING (&attr); ++ part_die->linkage_name = DW_STRING (&attr); + break; + case DW_AT_low_pc: + has_low_pc_attr = 1; + part_die->lowpc = DW_ADDR (&attr); +- if (part_die->tag == DW_TAG_compile_unit +- && base_address_type < base_address_low_pc) +- { +- base_address = DW_ADDR (&attr); +- base_address_type = base_address_low_pc; +- } + break; + case DW_AT_high_pc: + has_high_pc_attr = 1; + part_die->highpc = DW_ADDR (&attr); + break; +- case DW_AT_entry_pc: +- if (part_die->tag == DW_TAG_compile_unit +- && base_address_type < base_address_entry_pc) +- { +- base_address = DW_ADDR (&attr); +- base_address_type = base_address_entry_pc; +- } +- break; +- case DW_AT_ranges: +- if (part_die->tag == DW_TAG_compile_unit) +- { +- cu->ranges_offset = DW_UNSND (&attr); +- cu->has_ranges_offset = 1; +- } +- break; + case DW_AT_location: + /* Support the .debug_loc offsets */ + if (attr_form_is_block (&attr)) +@@ -6002,9 +6678,6 @@ read_partial_die (struct partial_die_info *part_die, + "partial symbol information"); + } + break; +- case DW_AT_language: +- part_die->language = DW_UNSND (&attr); +- break; + case DW_AT_external: + part_die->is_external = DW_UNSND (&attr); + break; +@@ -6029,10 +6702,6 @@ read_partial_die (struct partial_die_info *part_die, + part_die->sibling = dwarf2_per_objfile->info_buffer + + dwarf2_get_ref_die_offset (&attr); + break; +- case DW_AT_stmt_list: +- part_die->has_stmt_list = 1; +- part_die->line_offset = DW_UNSND (&attr); +- break; + case DW_AT_byte_size: + part_die->has_byte_size = 1; + break; +@@ -6074,13 +6743,6 @@ read_partial_die (struct partial_die_info *part_die, + || dwarf2_per_objfile->has_section_at_zero)) + part_die->has_pc_info = 1; + +- if (base_address_type != base_address_none && !cu->base_known) +- { +- gdb_assert (part_die->tag == DW_TAG_compile_unit); +- cu->base_known = 1; +- cu->base_address = base_address; +- } +- + return info_ptr; + } + +@@ -6173,7 +6835,9 @@ fixup_partial_die (struct partial_die_info *part_die, + /* If we found a reference attribute and the DIE has no name, try + to find a name in the referred to DIE. */ + +- if (part_die->name == NULL && part_die->has_specification) ++ if (part_die->has_specification ++ && (part_die->name == NULL || part_die->linkage_name == NULL ++ || !part_die->is_external)) + { + struct partial_die_info *spec_die; + +@@ -6189,6 +6853,9 @@ fixup_partial_die (struct partial_die_info *part_die, + if (spec_die->is_external) + part_die->is_external = spec_die->is_external; + } ++ ++ if (spec_die->linkage_name) ++ part_die->linkage_name = spec_die->linkage_name; + } + + /* Set default names for some unnamed DIEs. */ +@@ -7512,10 +8179,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym, + (i.e. when the value of a register or memory location is + referenced, or a thread-local block, etc.). Then again, it might + not be worthwhile. I'm assuming that it isn't unless performance +- or memory numbers show me otherwise. */ ++ or memory numbers show me otherwise. ++ ++ SYMBOL_CLASS may get overriden by dwarf2_symbol_mark_computed. */ + +- dwarf2_symbol_mark_computed (attr, sym, cu); + SYMBOL_CLASS (sym) = LOC_COMPUTED; ++ dwarf2_symbol_mark_computed (attr, sym, cu); + } + + /* Given a pointer to a DWARF information entry, figure out if we need +@@ -7538,20 +8207,43 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + if (die->tag != DW_TAG_namespace) +- name = dwarf2_linkage_name (die, cu); ++ name = dwarf2_name (die, cu); + else + name = TYPE_NAME (type); + + if (name) + { ++ const char *linkagename; ++ + sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack, + sizeof (struct symbol)); + OBJSTAT (objfile, n_syms++); + memset (sym, 0, sizeof (struct symbol)); ++ /* Some methods are called without checking SYMBOL_OPS validity. */ ++ SYMBOL_OPS (sym) = &dwarf2_missing_funcs; + +- /* Cache this symbol's name and the name's demangled form (if any). */ + SYMBOL_LANGUAGE (sym) = cu->language; +- SYMBOL_SET_NAMES (sym, name, strlen (name), objfile); ++ ++ /* Cache this symbol's name and the name's demangled form (if any). */ ++ ++ linkagename = dwarf2_linkage_name (die, cu); ++ if (linkagename) ++ /* We use the linkage name if available, for the same reason ++ we used it for TYPE_FN_FIELD_PHYSNAME earlier in this file. ++ This usage can be removed someday. */ ++ SYMBOL_SET_NAMES (sym, linkagename, strlen (linkagename), objfile); ++ else if (die->tag == DW_TAG_namespace) ++ SYMBOL_SET_LINKAGE_NAME (sym, name); ++ else ++ { ++ linkagename = dwarf2_full_name (die, cu); ++ ++ /* Set just the "linkage" name to the fully qualified name. ++ While this is not really a linkage name, it should match ++ the demangled version of the corresponding minimal symbol ++ if there is one. */ ++ SYMBOL_SET_LINKAGE_NAME (sym, (char *) linkagename); ++ } + + /* Default assumptions. + Use the passed type or decode it from the die. */ +@@ -7637,7 +8329,15 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) + if (attr) + { + var_decode_location (attr, sym, cu); +- attr2 = dwarf2_attr (die, DW_AT_external, cu); ++ ++ /* Fortran explicitely imports any global symbols to the local ++ scope by DW_TAG_common_block. DW_AT_external means for ++ Fortran the variable is importable versus it is automatically ++ imported. */ ++ if (cu->language == language_fortran) ++ attr2 = NULL; ++ else ++ attr2 = dwarf2_attr (die, DW_AT_external, cu); + if (attr2 && (DW_UNSND (attr2) != 0)) + add_symbol_to_list (sym, &global_symbols); + else +@@ -7656,7 +8356,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) + && dwarf2_attr (die, DW_AT_type, cu) != NULL) + { + SYMBOL_CLASS (sym) = LOC_UNRESOLVED; +- add_symbol_to_list (sym, &global_symbols); ++ add_symbol_to_list (sym, cu->list_in_scope); + } + } + break; +@@ -7780,6 +8480,11 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + add_symbol_to_list (sym, &global_symbols); + break; ++ case DW_TAG_common_block: ++ SYMBOL_CLASS (sym) = LOC_STATIC; ++ SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN; ++ add_symbol_to_list (sym, cu->list_in_scope); ++ break; + default: + /* Not a tag we recognize. Hopefully we aren't processing + trash data, but since we must specifically ignore things +@@ -8048,6 +8753,9 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu) + break; + } + ++ if (this_type) ++ finalize_type (this_type); ++ + return this_type; + } + +@@ -8128,6 +8836,19 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) + members; no typedefs, no member functions, et cetera. + So it does not need a prefix. */ + return ""; ++ ++ case DW_TAG_subprogram: ++ /* A class's symbol, or a variable's symbol, will live ++ directly in a function's block, so no prefix is ++ appropriate. However, what about methods of a ++ function-local class? They end up in the global symbol ++ table because they are separate functions... their mangling ++ normally would make them inaccessible. They'll show up ++ wrong in breakpoints too. This is a symptom of the ++ inconsistent way we handle symbol tables. Namespaces and ++ classes should have dictionaries just like blocks do. */ ++ return ""; ++ + default: + return determine_prefix (parent, cu); + } +@@ -8192,23 +8913,62 @@ dwarf2_linkage_name (struct die_info *die, struct dwarf2_cu *cu) + attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + if (attr && DW_STRING (attr)) + return DW_STRING (attr); +- attr = dwarf2_attr (die, DW_AT_name, cu); +- if (attr && DW_STRING (attr)) +- return DW_STRING (attr); + return NULL; + } + + /* Get name of a die, return NULL if not found. */ + + static char * ++dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu, ++ struct obstack *obstack) ++{ ++ if (name && cu->language == language_cplus) ++ { ++ char *canon_name = cp_canonicalize_string (name); ++ ++ if (canon_name != NULL) ++ { ++ if (strcmp (canon_name, name) != 0) ++ name = obsavestring (canon_name, strlen (canon_name), ++ obstack); ++ xfree (canon_name); ++ } ++ } ++ ++ return name; ++} ++ ++/* Get name of a die, return NULL if not found. */ ++ ++static char * + dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) + { + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_name, cu); +- if (attr && DW_STRING (attr)) +- return DW_STRING (attr); +- return NULL; ++ if (!attr || !DW_STRING (attr)) ++ return NULL; ++ ++ switch (die->tag) ++ { ++ case DW_TAG_compile_unit: ++ /* Compilation units have a DW_AT_name that is a filename, not ++ a source language identifier. */ ++ case DW_TAG_enumeration_type: ++ case DW_TAG_enumerator: ++ /* These tags always have simple identifiers already; no need ++ to canonicalize them. */ ++ return DW_STRING (attr); ++ default: ++ if (attr->form != GDB_FORM_cached_string) ++ { ++ DW_STRING (attr) ++ = dwarf2_canonicalize_name (DW_STRING (attr), cu, ++ &cu->objfile->objfile_obstack); ++ attr->form = GDB_FORM_cached_string; ++ } ++ return DW_STRING (attr); ++ } + } + + /* Return the die that this die in an extension of, or NULL if there +@@ -8703,6 +9463,8 @@ dwarf_form_name (unsigned form) + return "DW_FORM_ref_udata"; + case DW_FORM_indirect: + return "DW_FORM_indirect"; ++ case GDB_FORM_cached_string: ++ return "GDB_FORM_cached_string"; + default: + return "DW_FORM_"; + } +@@ -9353,26 +10115,35 @@ dwarf2_get_ref_die_offset (struct attribute *attr) + return result; + } + +-/* Return the constant value held by the given attribute. Return -1 +- if the value held by the attribute is not constant. */ ++/* (*val_return) is filled only if returning dwarf2_attr_const. */ + +-static int +-dwarf2_get_attr_constant_value (struct attribute *attr, int default_value) ++static enum dwarf2_get_attr_constant_value ++dwarf2_get_attr_constant_value (struct attribute *attr, int *val_return) + { ++ if (attr == NULL) ++ return dwarf2_attr_unknown; + if (attr->form == DW_FORM_sdata) +- return DW_SND (attr); +- else if (attr->form == DW_FORM_udata +- || attr->form == DW_FORM_data1 +- || attr->form == DW_FORM_data2 +- || attr->form == DW_FORM_data4 +- || attr->form == DW_FORM_data8) +- return DW_UNSND (attr); +- else + { +- complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), +- dwarf_form_name (attr->form)); +- return default_value; ++ *val_return = DW_SND (attr); ++ return dwarf2_attr_const; + } ++ if (attr->form == DW_FORM_udata ++ || attr->form == DW_FORM_data1 ++ || attr->form == DW_FORM_data2 ++ || attr->form == DW_FORM_data4 ++ || attr->form == DW_FORM_data8) ++ { ++ *val_return = DW_UNSND (attr); ++ return dwarf2_attr_const; ++ } ++ if (attr->form == DW_FORM_block ++ || attr->form == DW_FORM_block1 ++ || attr->form == DW_FORM_block2 ++ || attr->form == DW_FORM_block4) ++ return dwarf2_attr_block; ++ complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), ++ dwarf_form_name (attr->form)); ++ return dwarf2_attr_unknown; + } + + /* THIS_CU has a reference to PER_CU. If necessary, load the new compilation +@@ -9963,6 +10734,17 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, + { + gdb_byte *mac_ptr, *mac_end; + struct macro_source_file *current_file = 0; ++ enum dwarf_macinfo_record_type macinfo_type; ++ ++ /* Flag is in use by the second pass and determines if GDB is still before ++ first DW_MACINFO_start_file. If true GDB is still reading the definitions ++ from command line. First DW_MACINFO_start_file will need to be ignored as ++ it was already executed to create CURRENT_FILE for the main source holding ++ also the command line definitions. On first met DW_MACINFO_start_file ++ this flag is reset to normally execute all the remaining ++ DW_MACINFO_start_file macinfos. */ ++ ++ int at_commandline; + + if (dwarf2_per_objfile->macinfo_buffer == NULL) + { +@@ -9970,19 +10752,24 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, + return; + } + ++ /* Start the first pass to find ahead the main source file name. GDB has to ++ create CURRENT_FILE where to place the macros given to the compiler ++ from the command line. Such command line macros are present before first ++ DW_MACINFO_start_file but still those macros are associated to the ++ compilation unit. The compilation unit GDB identifies by its main source ++ file name. */ ++ + mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset; + mac_end = dwarf2_per_objfile->macinfo_buffer + + dwarf2_per_objfile->macinfo_size; + +- for (;;) ++ do + { +- enum dwarf_macinfo_record_type macinfo_type; +- + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + dwarf2_macros_too_long_complaint (); +- return; ++ break; + } + + macinfo_type = read_1_byte (abfd, mac_ptr); +@@ -9993,7 +10780,81 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, + /* A zero macinfo type indicates the end of the macro + information. */ + case 0: +- return; ++ break; ++ ++ case DW_MACINFO_define: ++ case DW_MACINFO_undef: ++ /* Only skip the data by MAC_PTR. */ ++ { ++ unsigned int bytes_read; ++ ++ read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); ++ mac_ptr += bytes_read; ++ read_string (abfd, mac_ptr, &bytes_read); ++ mac_ptr += bytes_read; ++ } ++ break; ++ ++ case DW_MACINFO_start_file: ++ { ++ unsigned int bytes_read; ++ int line, file; ++ ++ line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); ++ mac_ptr += bytes_read; ++ file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); ++ mac_ptr += bytes_read; ++ ++ current_file = macro_start_file (file, line, current_file, comp_dir, ++ lh, cu->objfile); ++ } ++ break; ++ ++ case DW_MACINFO_end_file: ++ /* No data to skip by MAC_PTR. */ ++ break; ++ ++ case DW_MACINFO_vendor_ext: ++ /* Only skip the data by MAC_PTR. */ ++ { ++ unsigned int bytes_read; ++ ++ read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); ++ mac_ptr += bytes_read; ++ read_string (abfd, mac_ptr, &bytes_read); ++ mac_ptr += bytes_read; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ } while (macinfo_type != 0 && current_file == NULL); ++ ++ /* Here is the second pass to read in the macros starting from the ones ++ defined at the command line. */ ++ ++ mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset; ++ at_commandline = 1; ++ ++ do ++ { ++ /* Do we at least have room for a macinfo type byte? */ ++ if (mac_ptr >= mac_end) ++ { ++ /* Complaint is in the first pass above. */ ++ break; ++ } ++ ++ macinfo_type = read_1_byte (abfd, mac_ptr); ++ mac_ptr++; ++ ++ switch (macinfo_type) ++ { ++ /* A zero macinfo type indicates the end of the macro ++ information. */ ++ case 0: ++ break; + + case DW_MACINFO_define: + case DW_MACINFO_undef: +@@ -10008,19 +10869,31 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, + mac_ptr += bytes_read; + + if (! current_file) ++ { ++ /* DWARF violation as no main source is present. */ ++ complaint (&symfile_complaints, ++ _("debug info with no main source gives macro %s " ++ "on line %d: %s"), ++ macinfo_type == ++ DW_MACINFO_define ? _("definition") : macinfo_type == ++ DW_MACINFO_undef ? _("undefinition") : ++ "something-or-other", line, body); ++ break; ++ } ++ if (at_commandline != (line == 0)) + complaint (&symfile_complaints, +- _("debug info gives macro %s outside of any file: %s"), ++ _("debug info gives %s macro %s with %s line %d: %s"), ++ at_commandline ? _("command-line") : _("in-file"), + macinfo_type == +- DW_MACINFO_define ? "definition" : macinfo_type == +- DW_MACINFO_undef ? "undefinition" : +- "something-or-other", body); +- else +- { +- if (macinfo_type == DW_MACINFO_define) +- parse_macro_definition (current_file, line, body); +- else if (macinfo_type == DW_MACINFO_undef) +- macro_undef (current_file, line, body); +- } ++ DW_MACINFO_define ? _("definition") : macinfo_type == ++ DW_MACINFO_undef ? _("undefinition") : ++ "something-or-other", ++ line == 0 ? _("zero") : _("non-zero"), line, body); ++ ++ if (macinfo_type == DW_MACINFO_define) ++ parse_macro_definition (current_file, line, body); ++ else if (macinfo_type == DW_MACINFO_undef) ++ macro_undef (current_file, line, body); + } + break; + +@@ -10034,9 +10907,22 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, + file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + +- current_file = macro_start_file (file, line, +- current_file, comp_dir, +- lh, cu->objfile); ++ if (at_commandline != (line == 0)) ++ complaint (&symfile_complaints, ++ _("debug info gives source %d included " ++ "from %s at %s line %d"), ++ file, at_commandline ? _("command-line") : _("file"), ++ line == 0 ? _("zero") : _("non-zero"), line); ++ ++ if (at_commandline) ++ { ++ /* This DW_MACINFO_start_file was executed in the pass one. */ ++ at_commandline = 0; ++ } ++ else ++ current_file = macro_start_file (file, line, ++ current_file, comp_dir, ++ lh, cu->objfile); + } + break; + +@@ -10090,7 +10976,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, + } + break; + } +- } ++ } while (macinfo_type != 0); + } + + /* Check if the attribute's form is a DW_FORM_block* +@@ -10150,6 +11036,34 @@ attr_form_is_constant (struct attribute *attr) + } + } + ++/* Convert DW_BLOCK into struct dwarf2_locexpr_baton. ATTR must be a DW_BLOCK ++ attribute type. */ ++ ++static struct dwarf2_locexpr_baton * ++dwarf2_attr_to_locexpr_baton (struct attribute *attr, struct dwarf2_cu *cu) ++{ ++ struct dwarf2_locexpr_baton *baton; ++ ++ gdb_assert (attr_form_is_block (attr)); ++ ++ baton = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (*baton)); ++ baton->per_cu = cu->per_cu; ++ gdb_assert (baton->per_cu); ++ ++ /* Note that we're just copying the block's data pointer ++ here, not the actual data. We're still pointing into the ++ info_buffer for SYM's objfile; right now we never release ++ that buffer, but when we do clean up properly this may ++ need to change. */ ++ baton->size = DW_BLOCK (attr)->size; ++ baton->data = DW_BLOCK (attr)->data; ++ gdb_assert (baton->size == 0 || baton->data != NULL); ++ ++ return baton; ++} ++ ++/* SYM may get its SYMBOL_CLASS overriden on invalid ATTR content. */ ++ + static void + dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + struct dwarf2_cu *cu) +@@ -10179,35 +11093,24 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + SYMBOL_OPS (sym) = &dwarf2_loclist_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + } ++ else if (attr_form_is_block (attr)) ++ { ++ SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs; ++ SYMBOL_LOCATION_BATON (sym) = dwarf2_attr_to_locexpr_baton (attr, cu); ++ } + else + { +- struct dwarf2_locexpr_baton *baton; ++ dwarf2_invalid_attrib_class_complaint ("location description", ++ SYMBOL_NATURAL_NAME (sym)); + +- baton = obstack_alloc (&cu->objfile->objfile_obstack, +- sizeof (struct dwarf2_locexpr_baton)); +- baton->per_cu = cu->per_cu; +- gdb_assert (baton->per_cu); ++ /* Some methods are called without checking SYMBOL_OPS validity. */ ++ SYMBOL_OPS (sym) = &dwarf2_missing_funcs; ++ SYMBOL_LOCATION_BATON (sym) = NULL; + +- if (attr_form_is_block (attr)) +- { +- /* Note that we're just copying the block's data pointer +- here, not the actual data. We're still pointing into the +- info_buffer for SYM's objfile; right now we never release +- that buffer, but when we do clean up properly this may +- need to change. */ +- baton->size = DW_BLOCK (attr)->size; +- baton->data = DW_BLOCK (attr)->data; +- } +- else +- { +- dwarf2_invalid_attrib_class_complaint ("location description", +- SYMBOL_NATURAL_NAME (sym)); +- baton->size = 0; +- baton->data = NULL; +- } +- +- SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs; +- SYMBOL_LOCATION_BATON (sym) = baton; ++ /* For functions a missing DW_AT_frame_base does not optimize out the ++ whole function definition, only its frame base resolving. */ ++ if (attr->name == DW_AT_location) ++ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + } + } + +@@ -10482,6 +11385,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) + return ofs_lhs->offset == ofs_rhs->offset; + } + ++/* Fill in generic attributes applicable for type DIEs. */ ++ ++static void ++fetch_die_type_attrs (struct die_info *die, struct type *type, ++ struct dwarf2_cu *cu) ++{ ++ struct attribute *attr; ++ ++ attr = dwarf2_attr (die, DW_AT_data_location, cu); ++ if (attr_form_is_block (attr)) ++ TYPE_DATA_LOCATION_DWARF_BLOCK (type) = dwarf2_attr_to_locexpr_baton (attr, ++ cu); ++ gdb_assert (!TYPE_DATA_LOCATION_IS_ADDR (type)); ++ ++ attr = dwarf2_attr (die, DW_AT_allocated, cu); ++ if (attr_form_is_block (attr)) ++ TYPE_ALLOCATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu); ++ gdb_assert (!TYPE_NOT_ALLOCATED (type)); ++ ++ attr = dwarf2_attr (die, DW_AT_associated, cu); ++ if (attr_form_is_block (attr)) ++ TYPE_ASSOCIATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu); ++ gdb_assert (!TYPE_NOT_ASSOCIATED (type)); ++} ++ + /* Set the type associated with DIE to TYPE. Save it in CU's hash + table if necessary. For convenience, return TYPE. */ + +@@ -10490,6 +11418,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) + { + struct dwarf2_offset_and_type **slot, ofs; + ++ fetch_die_type_attrs (die, type, cu); ++ + if (cu->type_hash == NULL) + { + gdb_assert (cu->per_cu != NULL); +diff --git a/gdb/elfread.c b/gdb/elfread.c +index ff220a2..13158f4 100644 +--- a/gdb/elfread.c ++++ b/gdb/elfread.c +@@ -727,10 +727,18 @@ elf_symfile_read (struct objfile *objfile, int mainline) + str_sect->filepos, + bfd_section_size (abfd, str_sect)); + } ++ ++ if (dwarf2_has_info (objfile)) ++ dwarf2_create_quick_addrmap (objfile); ++} ++ ++static void ++read_psyms (struct objfile *objfile) ++{ + if (dwarf2_has_info (objfile)) + { + /* DWARF 2 sections */ +- dwarf2_build_psymtabs (objfile, mainline); ++ dwarf2_build_psymtabs (objfile, 0); + } + + /* FIXME: kettenis/20030504: This still needs to be integrated with +@@ -880,6 +888,7 @@ static struct sym_fns elf_sym_fns = + elf_new_init, /* sym_new_init: init anything gbl to entire symtab */ + elf_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + elf_symfile_read, /* sym_read: read a symbol file into symtab */ ++ read_psyms, /* sym_read_psymbols */ + elf_symfile_finish, /* sym_finish: finished with file, cleanup */ + default_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */ + elf_symfile_segments, /* sym_segments: Get segment information from +diff --git a/gdb/eval.c b/gdb/eval.c +index 1d35571..6a97e09 100644 +--- a/gdb/eval.c ++++ b/gdb/eval.c +@@ -39,10 +39,16 @@ + #include "exceptions.h" + #include "regcache.h" + #include "user-regs.h" ++#include "python/python.h" + #include "valprint.h" ++#include "dwarf2loc.h" ++#include "gdb_obstack.h" ++#include "objfiles.h" + + #include "gdb_assert.h" + ++#include ++ + /* This is defined in valops.c */ + extern int overload_resolution; + +@@ -651,6 +657,64 @@ ptrmath_type_p (struct type *type) + } + } + ++/* Compares the two method/function types T1 and T2 for "equality" ++ with respect to the the methods' parameters. If the types of the ++ two parameter lists are the same, returns 1; 0 otherwise. This ++ comparison ignores any artificial this pointer. */ ++int ++compare_parameters (struct type *t1, struct type *t2) ++{ ++ int i, has_this; ++ /* Hacky: we don't know a priori whether or not t1 is a static ++ method, so we skip any artificial "this" pointer and hope ++ for the best. t2, which comes as user input, never contains a ++ "this" pointer (a user would never enter it into expressions. */ ++ if (TYPE_NFIELDS (t1) > 0) ++ has_this = TYPE_FIELD_ARTIFICIAL (t1, 0) ? 1 : 0; ++ else ++ has_this = 0; ++ ++ /* Special case: a method taking void. t1 will contain either ++ no fields or just "this". t2 will contain TYPE_CODE_VOID. */ ++ if ((TYPE_NFIELDS (t1) - has_this) == 0 && TYPE_NFIELDS (t2) == 1 ++ && TYPE_CODE (TYPE_FIELD_TYPE (t2, 0)) == TYPE_CODE_VOID) ++ return 1; ++ ++ if ((TYPE_NFIELDS (t1) - has_this) == TYPE_NFIELDS (t2)) ++ { ++ for (i = has_this; i < TYPE_NFIELDS (t1); ++i) ++ { ++ if (rank_one_type (TYPE_FIELD_TYPE (t1, i), ++ TYPE_FIELD_TYPE (t2, i - has_this)) ++ != 0) ++ return 0; ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/* Constructs a fake method with the given parameter types. */ ++ ++static struct type * ++make_params (int num_types, struct type **param_types) ++{ ++ struct type *type = alloc_type (NULL, NULL); ++ TYPE_LENGTH (type) = 1; ++ TYPE_CODE (type) = TYPE_CODE_METHOD; ++ TYPE_NFIELDS (type) = num_types; ++ TYPE_FIELDS (type) = (struct field *) ++ TYPE_ALLOC (type, sizeof (struct field) * num_types); ++ memset (TYPE_FIELDS (type), 0, sizeof (struct field) * num_types); ++ ++ while (num_types-- > 0) ++ TYPE_FIELD_TYPE (type, num_types) = param_types[num_types]; ++ ++ return type; ++} ++ + struct value * + evaluate_subexp_standard (struct type *expect_type, + struct expression *exp, int *pos, +@@ -671,6 +735,7 @@ evaluate_subexp_standard (struct type *expect_type, + long mem_offset; + struct type **arg_types; + int save_pos1; ++ struct cleanup *old_chain; + + pc = (*pos)++; + op = exp->elts[pc].opcode; +@@ -684,7 +749,7 @@ evaluate_subexp_standard (struct type *expect_type, + goto nosideret; + arg1 = value_aggregate_elt (exp->elts[pc + 1].type, + &exp->elts[pc + 3].string, +- 0, noside); ++ expect_type, 0, noside); + if (arg1 == NULL) + error (_("There is no field named %s"), &exp->elts[pc + 3].string); + return arg1; +@@ -1208,9 +1273,9 @@ evaluate_subexp_standard (struct type *expect_type, + if (TYPE_CODE (value_type (method)) != TYPE_CODE_FUNC) + error (_("method address has symbol information with non-function type; skipping")); + if (struct_return) +- VALUE_ADDRESS (method) = value_as_address (msg_send_stret); ++ set_value_address (method, value_as_address (msg_send_stret)); + else +- VALUE_ADDRESS (method) = value_as_address (msg_send); ++ set_value_address (method, value_as_address (msg_send)); + called_method = method; + } + else +@@ -1284,7 +1349,6 @@ evaluate_subexp_standard (struct type *expect_type, + argvec = (struct value **) alloca (sizeof (struct value *) * (nargs + 3)); + if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) + { +- nargs++; + /* First, evaluate the structure into arg2 */ + pc2 = (*pos)++; + +@@ -1308,21 +1372,40 @@ evaluate_subexp_standard (struct type *expect_type, + + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + +- if (TYPE_CODE (check_typedef (value_type (arg1))) +- != TYPE_CODE_METHODPTR) +- error (_("Non-pointer-to-member value used in pointer-to-member " +- "construct")); +- +- if (noside == EVAL_AVOID_SIDE_EFFECTS) ++ type = check_typedef (value_type (arg1)); ++ switch (TYPE_CODE (type)) + { +- struct type *method_type = check_typedef (value_type (arg1)); +- arg1 = value_zero (method_type, not_lval); ++ case TYPE_CODE_METHODPTR: ++ if (noside == EVAL_AVOID_SIDE_EFFECTS) ++ arg1 = value_zero (TYPE_TARGET_TYPE (type), not_lval); ++ else ++ arg1 = cplus_method_ptr_to_value (&arg2, arg1); ++ ++ /* Now, say which argument to start evaluating from */ ++ nargs++; ++ tem = 2; ++ argvec[1] = arg2; ++ break; ++ ++ case TYPE_CODE_MEMBERPTR: ++ /* Now, convert these values to an address. */ ++ arg2 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)), ++ arg2); ++ ++ mem_offset = value_as_long (arg1); ++ ++ arg1 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), ++ value_as_long (arg2) + mem_offset); ++ arg1 = value_ind (arg1); ++ tem = 1; ++ break; ++ ++ default: ++ error (_("Non-pointer-to-member value used in pointer-to-member " ++ "construct")); + } +- else +- arg1 = cplus_method_ptr_to_value (&arg2, arg1); + +- /* Now, say which argument to start evaluating from */ +- tem = 2; ++ argvec[0] = arg1; + } + else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) + { +@@ -1434,7 +1517,7 @@ evaluate_subexp_standard (struct type *expect_type, + of the ``this'' pointer if necessary, so modify argvec[1] to + reflect any ``this'' changes. */ + arg2 = value_from_longest (lookup_pointer_type(value_type (temp)), +- VALUE_ADDRESS (temp) + value_offset (temp) ++ value_address (temp) + + value_embedded_offset (temp)); + argvec[1] = arg2; /* the ``this'' pointer */ + } +@@ -1448,8 +1531,7 @@ evaluate_subexp_standard (struct type *expect_type, + } + else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) + { +- argvec[1] = arg2; +- argvec[0] = arg1; ++ /* Pointer to member. argvec is already set up. */ + } + else if (op == OP_VAR_VALUE) + { +@@ -1512,6 +1594,9 @@ evaluate_subexp_standard (struct type *expect_type, + else + error (_("Expression of type other than \"Function returning ...\" used as function")); + } ++ if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_INTERNAL_FUNCTION) ++ return call_internal_function (argvec[0], nargs, argvec + 1); ++ + return call_function_by_hand (argvec[0], nargs, argvec + 1); + /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve */ + +@@ -1529,7 +1614,10 @@ evaluate_subexp_standard (struct type *expect_type, + + /* First determine the type code we are dealing with. */ + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); ++ old_chain = make_cleanup (null_cleanup, 0); ++ object_address_set (VALUE_ADDRESS (arg1)); + type = check_typedef (value_type (arg1)); ++ do_cleanups (old_chain); + code = TYPE_CODE (type); + + if (code == TYPE_CODE_PTR) +@@ -1696,6 +1784,37 @@ evaluate_subexp_standard (struct type *expect_type, + error (_("non-pointer-to-member value used in pointer-to-member construct")); + } + ++ case TYPE_INSTANCE: ++ nargs = longest_to_int (exp->elts[pc + 1].longconst); ++ arg_types = (struct type **) alloca (nargs * sizeof (struct type *)); ++ for (ix = 0; ix < nargs; ++ix) ++ arg_types[ix] = exp->elts[pc + 1 + ix + 1].type; ++ ++ expect_type = make_params (nargs, arg_types); ++ *(pos) += 3 + nargs; ++ return evaluate_subexp_standard (expect_type, exp, pos, noside); ++ ++ case TYPE_INSTANCE_LOOKUP: ++ { ++ int i; ++ struct symbol *sym; ++ struct type **arg_types; ++ (*pos) += 3; ++ printf ("TYPE_INSTANCE_LOOKUP\n"); ++ arg_types = (struct type **) alloca (TYPE_NFIELDS (expect_type) ++ * sizeof (struct type *)); ++ for (i = 0; i < TYPE_NFIELDS (expect_type); ++i) ++ arg_types[i] = TYPE_FIELD_TYPE (expect_type, i); ++ (void) find_overload_match (arg_types, TYPE_NFIELDS (expect_type), ++ NULL /* no need for name */, ++ 0 /* not method */, ++ 0 /* strict match */, ++ NULL, exp->elts[pc + 1].symbol, NULL, ++ &sym, NULL); ++ i = 0; ++ } ++ break; ++ + case BINOP_CONCAT: + arg1 = evaluate_subexp_with_coercion (exp, pos, noside); + arg2 = evaluate_subexp_with_coercion (exp, pos, noside); +@@ -1963,13 +2082,19 @@ evaluate_subexp_standard (struct type *expect_type, + { + int subscript_array[MAX_FORTRAN_DIMS]; + int array_size_array[MAX_FORTRAN_DIMS]; ++ int byte_stride_array[MAX_FORTRAN_DIMS]; + int ndimensions = 1, i; + struct type *tmp_type; + int offset_item; /* The array offset where the item lives */ ++ CORE_ADDR offset_byte; /* byte_stride based offset */ ++ unsigned element_size; + + if (nargs > MAX_FORTRAN_DIMS) + error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS); + ++ old_chain = make_cleanup (null_cleanup, 0); ++ object_address_set (VALUE_ADDRESS (arg1)); ++ + tmp_type = check_typedef (value_type (arg1)); + ndimensions = calc_f77_array_dims (type); + +@@ -1999,6 +2124,9 @@ evaluate_subexp_standard (struct type *expect_type, + upper = f77_get_upperbound (tmp_type); + lower = f77_get_lowerbound (tmp_type); + ++ byte_stride_array[nargs - i - 1] = ++ TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type); ++ + array_size_array[nargs - i - 1] = upper - lower + 1; + + /* Zero-normalize subscripts so that offsetting will work. */ +@@ -2017,17 +2145,25 @@ evaluate_subexp_standard (struct type *expect_type, + tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type)); + } + +- /* Now let us calculate the offset for this item */ ++ /* Kept for the f77_get_upperbound / f77_get_lowerbound calls above. */ ++ do_cleanups (old_chain); + +- offset_item = subscript_array[ndimensions - 1]; ++ /* Now let us calculate the offset for this item */ + +- for (i = ndimensions - 1; i > 0; --i) +- offset_item = +- array_size_array[i - 1] * offset_item + subscript_array[i - 1]; ++ offset_item = 0; ++ offset_byte = 0; + +- /* Construct a value node with the value of the offset */ ++ for (i = ndimensions - 1; i >= 0; --i) ++ { ++ offset_item *= array_size_array[i]; ++ if (byte_stride_array[i] == 0) ++ offset_item += subscript_array[i]; ++ else ++ offset_byte += subscript_array[i] * byte_stride_array[i]; ++ } + +- arg2 = value_from_longest (builtin_type_int32, offset_item); ++ element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tmp_type)); ++ offset_byte += offset_item * element_size; + + /* Let us now play a dirty trick: we will take arg1 + which is a value node pointing to the topmost level +@@ -2037,7 +2173,7 @@ evaluate_subexp_standard (struct type *expect_type, + returns the correct type value */ + + deprecated_set_value_type (arg1, tmp_type); +- return value_subscripted_rvalue (arg1, arg2, 0); ++ return value_subscripted_rvalue (arg1, offset_byte); + } + + case BINOP_LOGICAL_AND: +@@ -2475,7 +2611,17 @@ evaluate_subexp_standard (struct type *expect_type, + if (noside == EVAL_SKIP) + goto nosideret; + else if (noside == EVAL_AVOID_SIDE_EFFECTS) +- return allocate_value (exp->elts[pc + 1].type); ++ { ++ struct type *type = exp->elts[pc + 1].type; ++ /* If this is a typedef, then find its immediate target. We ++ use check_typedef to resolve stubs, but we ignore its ++ result because we do not want to dig past all ++ typedefs. */ ++ check_typedef (type); ++ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) ++ type = TYPE_TARGET_TYPE (type); ++ return allocate_value (type); ++ } + else + error (_("Attempt to use a type name as an expression")); + +@@ -2568,7 +2714,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, + (*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1); + x = value_aggregate_elt (exp->elts[pc + 1].type, + &exp->elts[pc + 3].string, +- 1, noside); ++ NULL, 1, noside); + if (x == NULL) + error (_("There is no field named %s"), &exp->elts[pc + 3].string); + return x; +@@ -2613,7 +2759,7 @@ evaluate_subexp_with_coercion (struct expression *exp, + { + enum exp_opcode op; + int pc; +- struct value *val; ++ struct value *val = NULL; + struct symbol *var; + struct type *type; + +@@ -2624,12 +2770,17 @@ evaluate_subexp_with_coercion (struct expression *exp, + { + case OP_VAR_VALUE: + var = exp->elts[pc + 2].symbol; ++ /* address_of_variable will call object_address_set for check_typedef. ++ Call it only if required as it can error-out on VAR in register. */ ++ if (TYPE_DYNAMIC (SYMBOL_TYPE (var))) ++ val = address_of_variable (var, exp->elts[pc + 1].block); + type = check_typedef (SYMBOL_TYPE (var)); + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && CAST_IS_CONVERSION) + { + (*pos) += 4; +- val = address_of_variable (var, exp->elts[pc + 1].block); ++ if (!val) ++ val = address_of_variable (var, exp->elts[pc + 1].block); + return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)), + val); + } +@@ -2681,9 +2832,13 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos) + + case OP_VAR_VALUE: + (*pos) += 4; +- type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol)); +- return +- value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); ++ /* We do not need to call read_var_value but the object evaluation may ++ need to have executed object_address_set which needs valid ++ SYMBOL_VALUE_ADDRESS of the symbol. Still VALUE returned by ++ read_var_value we left as lazy. */ ++ type = value_type (read_var_value (exp->elts[pc + 2].symbol, ++ deprecated_safe_get_selected_frame ())); ++ return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); + + default: + val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); +diff --git a/gdb/expprint.c b/gdb/expprint.c +index 89bae03..f768940 100644 +--- a/gdb/expprint.c ++++ b/gdb/expprint.c +@@ -186,8 +186,8 @@ print_subexp_standard (struct expression *exp, int *pos, + If necessary, we can temporarily set it to zero, or pass it as an + additional parameter to LA_PRINT_STRING. -fnf */ + get_user_print_options (&opts); +- LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 1, 0, +- &opts); ++ LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char, ++ &exp->elts[pc + 2].string, nargs, 0, &opts); + } + return; + +@@ -205,8 +205,8 @@ print_subexp_standard (struct expression *exp, int *pos, + (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1); + fputs_filtered ("@\"", stream); + get_user_print_options (&opts); +- LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 1, 0, +- &opts); ++ LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char, ++ &exp->elts[pc + 2].string, nargs, 0, &opts); + fputs_filtered ("\"", stream); + } + return; +@@ -291,8 +291,8 @@ print_subexp_standard (struct expression *exp, int *pos, + { + struct value_print_options opts; + get_user_print_options (&opts); +- LA_PRINT_STRING (stream, tempstr, nargs - 1, 1, 0, +- &opts); ++ LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char, ++ tempstr, nargs - 1, 0, &opts); + (*pos) = pc; + } + else +diff --git a/gdb/expression.h b/gdb/expression.h +index 12163e3..789cb89 100644 +--- a/gdb/expression.h ++++ b/gdb/expression.h +@@ -88,6 +88,16 @@ enum exp_opcode + when X is a pointer instead of an aggregate. */ + STRUCTOP_MPTR, + ++ /* TYPE_INSTANCE is used when the user specifies a specific ++ type instantiation for overloaded methods/functions. The format ++ is: TYPE_INSTANCE num_types type0 ... typeN num_types TYPE_INSTANCE*/ ++ TYPE_INSTANCE, ++ ++ /* TYPE_INSTANCE_LOOKUP is used when the user specifies a specific ++ type instantiation of a function (not a method). In this case, ++ we must toss the results of the parser and manually do the lookup. */ ++ TYPE_INSTANCE_LOOKUP, ++ + /* end of C++. */ + + /* For Modula-2 integer division DIV */ +@@ -426,6 +436,8 @@ enum noside + extern struct value *evaluate_subexp_standard + (struct type *, struct expression *, int *, enum noside); + ++extern int compare_parameters (struct type *, struct type *); ++ + /* From expprint.c */ + + extern void print_expression (struct expression *, struct ui_file *); +@@ -435,4 +447,5 @@ extern char *op_string (enum exp_opcode); + extern void dump_raw_expression (struct expression *, struct ui_file *, char *); + extern void dump_prefix_expression (struct expression *, struct ui_file *); + ++ + #endif /* !defined (EXPRESSION_H) */ +diff --git a/gdb/f-exp.y b/gdb/f-exp.y +index d91c413..c984e85 100644 +--- a/gdb/f-exp.y ++++ b/gdb/f-exp.y +@@ -198,6 +198,7 @@ static int parse_number (char *, int, int, YYSTYPE *); + /* Special type cases, put in to allow the parser to distinguish different + legal basetypes. */ + %token INT_KEYWORD INT_S2_KEYWORD LOGICAL_S1_KEYWORD LOGICAL_S2_KEYWORD ++%token LOGICAL_S8_KEYWORD + %token LOGICAL_KEYWORD REAL_KEYWORD REAL_S8_KEYWORD REAL_S16_KEYWORD + %token COMPLEX_S8_KEYWORD COMPLEX_S16_KEYWORD COMPLEX_S32_KEYWORD + %token BOOL_AND BOOL_OR BOOL_NOT +@@ -608,6 +609,8 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ + { $$ = parse_f_type->builtin_integer_s2; } + | CHARACTER + { $$ = parse_f_type->builtin_character; } ++ | LOGICAL_S8_KEYWORD ++ { $$ = parse_f_type->builtin_logical_s8;} + | LOGICAL_KEYWORD + { $$ = parse_f_type->builtin_logical; } + | LOGICAL_S2_KEYWORD +@@ -860,6 +863,7 @@ static const struct token f77_keywords[] = + { "integer_2", INT_S2_KEYWORD, BINOP_END }, + { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END }, + { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END }, ++ { "logical_8", LOGICAL_S8_KEYWORD, BINOP_END }, + { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END }, + { "integer", INT_KEYWORD, BINOP_END }, + { "logical", LOGICAL_KEYWORD, BINOP_END }, +diff --git a/gdb/f-lang.c b/gdb/f-lang.c +index 6359841..1754c44 100644 +--- a/gdb/f-lang.c ++++ b/gdb/f-lang.c +@@ -55,23 +55,10 @@ typedef struct saved_bf_symnum SAVED_BF, *SAVED_BF_PTR; + /* Local functions */ + + extern void _initialize_f_language (void); +-#if 0 +-static void clear_function_list (void); +-static long get_bf_for_fcn (long); +-static void clear_bf_list (void); +-static void patch_all_commons_by_name (char *, CORE_ADDR, int); +-static SAVED_F77_COMMON_PTR find_first_common_named (char *); +-static void add_common_entry (struct symbol *); +-static void add_common_block (char *, CORE_ADDR, int, char *); +-static SAVED_FUNCTION *allocate_saved_function_node (void); +-static SAVED_BF_PTR allocate_saved_bf_node (void); +-static COMMON_ENTRY_PTR allocate_common_entry_node (void); +-static SAVED_F77_COMMON_PTR allocate_saved_f77_common_node (void); +-static void patch_common_entries (SAVED_F77_COMMON_PTR, CORE_ADDR, int); +-#endif +- +-static void f_printchar (int c, struct ui_file * stream); +-static void f_emit_char (int c, struct ui_file * stream, int quoter); ++ ++static void f_printchar (int c, struct type *type, struct ui_file * stream); ++static void f_emit_char (int c, struct type *type, ++ struct ui_file * stream, int quoter); + + /* Print the character C on STREAM as part of the contents of a literal + string whose delimiter is QUOTER. Note that that format for printing +@@ -80,7 +67,7 @@ static void f_emit_char (int c, struct ui_file * stream, int quoter); + be replaced with a true F77 version. */ + + static void +-f_emit_char (int c, struct ui_file *stream, int quoter) ++f_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) + { + c &= 0xFF; /* Avoid sign bit follies */ + +@@ -126,10 +113,10 @@ f_emit_char (int c, struct ui_file *stream, int quoter) + be replaced with a true F77version. */ + + static void +-f_printchar (int c, struct ui_file *stream) ++f_printchar (int c, struct type *type, struct ui_file *stream) + { + fputs_filtered ("'", stream); +- LA_EMIT_CHAR (c, stream, '\''); ++ LA_EMIT_CHAR (c, type, stream, '\''); + fputs_filtered ("'", stream); + } + +@@ -141,14 +128,15 @@ f_printchar (int c, struct ui_file *stream) + be replaced with a true F77 version. */ + + static void +-f_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, ++ unsigned int length, int force_ellipses, + const struct value_print_options *options) + { + unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; ++ int width = TYPE_LENGTH (type); + + if (length == 0) + { +@@ -190,7 +178,7 @@ f_printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("', ", stream); + in_quotes = 0; + } +- f_printchar (string[i], stream); ++ f_printchar (string[i], type, stream); + fprintf_filtered (stream, " ", reps); + i = rep1 - 1; + things_printed += options->repeat_count_threshold; +@@ -206,7 +194,7 @@ f_printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("'", stream); + in_quotes = 1; + } +- LA_EMIT_CHAR (string[i], stream, '"'); ++ LA_EMIT_CHAR (string[i], type, stream, '"'); + ++things_printed; + } + } +@@ -257,6 +245,7 @@ enum f_primitive_types { + f_primitive_type_logical, + f_primitive_type_logical_s1, + f_primitive_type_logical_s2, ++ f_primitive_type_logical_s8, + f_primitive_type_integer, + f_primitive_type_integer_s2, + f_primitive_type_real, +@@ -287,6 +276,8 @@ f_language_arch_info (struct gdbarch *gdbarch, + = builtin->builtin_logical_s1; + lai->primitive_type_vector [f_primitive_type_logical_s2] + = builtin->builtin_logical_s2; ++ lai->primitive_type_vector [f_primitive_type_logical_s8] ++ = builtin->builtin_logical_s8; + lai->primitive_type_vector [f_primitive_type_real] + = builtin->builtin_real; + lai->primitive_type_vector [f_primitive_type_real_s8] +@@ -378,6 +369,11 @@ build_fortran_types (struct gdbarch *gdbarch) + gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "logical*2", (struct objfile *) NULL); + ++ builtin_f_type->builtin_logical_s8 = ++ init_type (TYPE_CODE_BOOL, ++ gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT, ++ TYPE_FLAG_UNSIGNED, "logical*8", (struct objfile *) NULL); ++ + builtin_f_type->builtin_integer = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, +@@ -451,395 +447,3 @@ _initialize_f_language (void) + + add_language (&f_language_defn); + } +- +-#if 0 +-static SAVED_BF_PTR +-allocate_saved_bf_node (void) +-{ +- SAVED_BF_PTR new; +- +- new = (SAVED_BF_PTR) xmalloc (sizeof (SAVED_BF)); +- return (new); +-} +- +-static SAVED_FUNCTION * +-allocate_saved_function_node (void) +-{ +- SAVED_FUNCTION *new; +- +- new = (SAVED_FUNCTION *) xmalloc (sizeof (SAVED_FUNCTION)); +- return (new); +-} +- +-static SAVED_F77_COMMON_PTR +-allocate_saved_f77_common_node (void) +-{ +- SAVED_F77_COMMON_PTR new; +- +- new = (SAVED_F77_COMMON_PTR) xmalloc (sizeof (SAVED_F77_COMMON)); +- return (new); +-} +- +-static COMMON_ENTRY_PTR +-allocate_common_entry_node (void) +-{ +- COMMON_ENTRY_PTR new; +- +- new = (COMMON_ENTRY_PTR) xmalloc (sizeof (COMMON_ENTRY)); +- return (new); +-} +-#endif +- +-SAVED_F77_COMMON_PTR head_common_list = NULL; /* Ptr to 1st saved COMMON */ +-SAVED_F77_COMMON_PTR tail_common_list = NULL; /* Ptr to last saved COMMON */ +-SAVED_F77_COMMON_PTR current_common = NULL; /* Ptr to current COMMON */ +- +-#if 0 +-static SAVED_BF_PTR saved_bf_list = NULL; /* Ptr to (.bf,function) +- list */ +-static SAVED_BF_PTR saved_bf_list_end = NULL; /* Ptr to above list's end */ +-static SAVED_BF_PTR current_head_bf_list = NULL; /* Current head of above list +- */ +- +-static SAVED_BF_PTR tmp_bf_ptr; /* Generic temporary for use +- in macros */ +- +-/* The following function simply enters a given common block onto +- the global common block chain */ +- +-static void +-add_common_block (char *name, CORE_ADDR offset, int secnum, char *func_stab) +-{ +- SAVED_F77_COMMON_PTR tmp; +- char *c, *local_copy_func_stab; +- +- /* If the COMMON block we are trying to add has a blank +- name (i.e. "#BLNK_COM") then we set it to __BLANK +- because the darn "#" character makes GDB's input +- parser have fits. */ +- +- +- if (strcmp (name, BLANK_COMMON_NAME_ORIGINAL) == 0 +- || strcmp (name, BLANK_COMMON_NAME_MF77) == 0) +- { +- +- xfree (name); +- name = alloca (strlen (BLANK_COMMON_NAME_LOCAL) + 1); +- strcpy (name, BLANK_COMMON_NAME_LOCAL); +- } +- +- tmp = allocate_saved_f77_common_node (); +- +- local_copy_func_stab = xmalloc (strlen (func_stab) + 1); +- strcpy (local_copy_func_stab, func_stab); +- +- tmp->name = xmalloc (strlen (name) + 1); +- +- /* local_copy_func_stab is a stabstring, let us first extract the +- function name from the stab by NULLing out the ':' character. */ +- +- +- c = NULL; +- c = strchr (local_copy_func_stab, ':'); +- +- if (c) +- *c = '\0'; +- else +- error (_("Malformed function STAB found in add_common_block()")); +- +- +- tmp->owning_function = xmalloc (strlen (local_copy_func_stab) + 1); +- +- strcpy (tmp->owning_function, local_copy_func_stab); +- +- strcpy (tmp->name, name); +- tmp->offset = offset; +- tmp->next = NULL; +- tmp->entries = NULL; +- tmp->secnum = secnum; +- +- current_common = tmp; +- +- if (head_common_list == NULL) +- { +- head_common_list = tail_common_list = tmp; +- } +- else +- { +- tail_common_list->next = tmp; +- tail_common_list = tmp; +- } +-} +-#endif +- +-/* The following function simply enters a given common entry onto +- the "current_common" block that has been saved away. */ +- +-#if 0 +-static void +-add_common_entry (struct symbol *entry_sym_ptr) +-{ +- COMMON_ENTRY_PTR tmp; +- +- +- +- /* The order of this list is important, since +- we expect the entries to appear in decl. +- order when we later issue "info common" calls */ +- +- tmp = allocate_common_entry_node (); +- +- tmp->next = NULL; +- tmp->symbol = entry_sym_ptr; +- +- if (current_common == NULL) +- error (_("Attempt to add COMMON entry with no block open!")); +- else +- { +- if (current_common->entries == NULL) +- { +- current_common->entries = tmp; +- current_common->end_of_entries = tmp; +- } +- else +- { +- current_common->end_of_entries->next = tmp; +- current_common->end_of_entries = tmp; +- } +- } +-} +-#endif +- +-/* This routine finds the first encountred COMMON block named "name" */ +- +-#if 0 +-static SAVED_F77_COMMON_PTR +-find_first_common_named (char *name) +-{ +- +- SAVED_F77_COMMON_PTR tmp; +- +- tmp = head_common_list; +- +- while (tmp != NULL) +- { +- if (strcmp (tmp->name, name) == 0) +- return (tmp); +- else +- tmp = tmp->next; +- } +- return (NULL); +-} +-#endif +- +-/* This routine finds the first encountred COMMON block named "name" +- that belongs to function funcname */ +- +-SAVED_F77_COMMON_PTR +-find_common_for_function (char *name, char *funcname) +-{ +- +- SAVED_F77_COMMON_PTR tmp; +- +- tmp = head_common_list; +- +- while (tmp != NULL) +- { +- if (strcmp (tmp->name, name) == 0 +- && strcmp (tmp->owning_function, funcname) == 0) +- return (tmp); +- else +- tmp = tmp->next; +- } +- return (NULL); +-} +- +- +-#if 0 +- +-/* The following function is called to patch up the offsets +- for the statics contained in the COMMON block named +- "name." */ +- +-static void +-patch_common_entries (SAVED_F77_COMMON_PTR blk, CORE_ADDR offset, int secnum) +-{ +- COMMON_ENTRY_PTR entry; +- +- blk->offset = offset; /* Keep this around for future use. */ +- +- entry = blk->entries; +- +- while (entry != NULL) +- { +- SYMBOL_VALUE (entry->symbol) += offset; +- SYMBOL_SECTION (entry->symbol) = secnum; +- +- entry = entry->next; +- } +- blk->secnum = secnum; +-} +- +-/* Patch all commons named "name" that need patching.Since COMMON +- blocks occur with relative infrequency, we simply do a linear scan on +- the name. Eventually, the best way to do this will be a +- hashed-lookup. Secnum is the section number for the .bss section +- (which is where common data lives). */ +- +-static void +-patch_all_commons_by_name (char *name, CORE_ADDR offset, int secnum) +-{ +- +- SAVED_F77_COMMON_PTR tmp; +- +- /* For blank common blocks, change the canonical reprsentation +- of a blank name */ +- +- if (strcmp (name, BLANK_COMMON_NAME_ORIGINAL) == 0 +- || strcmp (name, BLANK_COMMON_NAME_MF77) == 0) +- { +- xfree (name); +- name = alloca (strlen (BLANK_COMMON_NAME_LOCAL) + 1); +- strcpy (name, BLANK_COMMON_NAME_LOCAL); +- } +- +- tmp = head_common_list; +- +- while (tmp != NULL) +- { +- if (COMMON_NEEDS_PATCHING (tmp)) +- if (strcmp (tmp->name, name) == 0) +- patch_common_entries (tmp, offset, secnum); +- +- tmp = tmp->next; +- } +-} +-#endif +- +-/* This macro adds the symbol-number for the start of the function +- (the symbol number of the .bf) referenced by symnum_fcn to a +- list. This list, in reality should be a FIFO queue but since +- #line pragmas sometimes cause line ranges to get messed up +- we simply create a linear list. This list can then be searched +- first by a queueing algorithm and upon failure fall back to +- a linear scan. */ +- +-#if 0 +-#define ADD_BF_SYMNUM(bf_sym,fcn_sym) \ +- \ +- if (saved_bf_list == NULL) \ +-{ \ +- tmp_bf_ptr = allocate_saved_bf_node(); \ +- \ +- tmp_bf_ptr->symnum_bf = (bf_sym); \ +- tmp_bf_ptr->symnum_fcn = (fcn_sym); \ +- tmp_bf_ptr->next = NULL; \ +- \ +- current_head_bf_list = saved_bf_list = tmp_bf_ptr; \ +- saved_bf_list_end = tmp_bf_ptr; \ +- } \ +-else \ +-{ \ +- tmp_bf_ptr = allocate_saved_bf_node(); \ +- \ +- tmp_bf_ptr->symnum_bf = (bf_sym); \ +- tmp_bf_ptr->symnum_fcn = (fcn_sym); \ +- tmp_bf_ptr->next = NULL; \ +- \ +- saved_bf_list_end->next = tmp_bf_ptr; \ +- saved_bf_list_end = tmp_bf_ptr; \ +- } +-#endif +- +-/* This function frees the entire (.bf,function) list */ +- +-#if 0 +-static void +-clear_bf_list (void) +-{ +- +- SAVED_BF_PTR tmp = saved_bf_list; +- SAVED_BF_PTR next = NULL; +- +- while (tmp != NULL) +- { +- next = tmp->next; +- xfree (tmp); +- tmp = next; +- } +- saved_bf_list = NULL; +-} +-#endif +- +-int global_remote_debug; +- +-#if 0 +- +-static long +-get_bf_for_fcn (long the_function) +-{ +- SAVED_BF_PTR tmp; +- int nprobes = 0; +- +- /* First use a simple queuing algorithm (i.e. look and see if the +- item at the head of the queue is the one you want) */ +- +- if (saved_bf_list == NULL) +- internal_error (__FILE__, __LINE__, +- _("cannot get .bf node off empty list")); +- +- if (current_head_bf_list != NULL) +- if (current_head_bf_list->symnum_fcn == the_function) +- { +- if (global_remote_debug) +- fprintf_unfiltered (gdb_stderr, "*"); +- +- tmp = current_head_bf_list; +- current_head_bf_list = current_head_bf_list->next; +- return (tmp->symnum_bf); +- } +- +- /* If the above did not work (probably because #line directives were +- used in the sourcefile and they messed up our internal tables) we now do +- the ugly linear scan */ +- +- if (global_remote_debug) +- fprintf_unfiltered (gdb_stderr, "\ndefaulting to linear scan\n"); +- +- nprobes = 0; +- tmp = saved_bf_list; +- while (tmp != NULL) +- { +- nprobes++; +- if (tmp->symnum_fcn == the_function) +- { +- if (global_remote_debug) +- fprintf_unfiltered (gdb_stderr, "Found in %d probes\n", nprobes); +- current_head_bf_list = tmp->next; +- return (tmp->symnum_bf); +- } +- tmp = tmp->next; +- } +- +- return (-1); +-} +- +-static SAVED_FUNCTION_PTR saved_function_list = NULL; +-static SAVED_FUNCTION_PTR saved_function_list_end = NULL; +- +-static void +-clear_function_list (void) +-{ +- SAVED_FUNCTION_PTR tmp = saved_function_list; +- SAVED_FUNCTION_PTR next = NULL; +- +- while (tmp != NULL) +- { +- next = tmp->next; +- xfree (tmp); +- tmp = next; +- } +- +- saved_function_list = NULL; +-} +-#endif +diff --git a/gdb/f-lang.h b/gdb/f-lang.h +index 711bdba..cd2f804 100644 +--- a/gdb/f-lang.h ++++ b/gdb/f-lang.h +@@ -28,6 +28,10 @@ extern void f_error (char *); /* Defined in f-exp.y */ + extern void f_print_type (struct type *, char *, struct ui_file *, int, + int); + ++extern const char *f_object_address_data_valid_print_to_stream ++ (struct type *type, struct ui_file *stream); ++extern void f_object_address_data_valid_or_error (struct type *type); ++ + extern int f_val_print (struct type *, const gdb_byte *, int, CORE_ADDR, + struct ui_file *, int, + const struct value_print_options *); +@@ -47,41 +51,8 @@ enum f90_range_type + NONE_BOUND_DEFAULT /* "(low:high)" */ + }; + +-struct common_entry +- { +- struct symbol *symbol; /* The symbol node corresponding +- to this component */ +- struct common_entry *next; /* The next component */ +- }; +- +-struct saved_f77_common +- { +- char *name; /* Name of COMMON */ +- char *owning_function; /* Name of parent function */ +- int secnum; /* Section # of .bss */ +- CORE_ADDR offset; /* Offset from .bss for +- this block */ +- struct common_entry *entries; /* List of block's components */ +- struct common_entry *end_of_entries; /* ptr. to end of components */ +- struct saved_f77_common *next; /* Next saved COMMON block */ +- }; +- +-typedef struct saved_f77_common SAVED_F77_COMMON, *SAVED_F77_COMMON_PTR; +- +-typedef struct common_entry COMMON_ENTRY, *COMMON_ENTRY_PTR; +- +-extern SAVED_F77_COMMON_PTR head_common_list; /* Ptr to 1st saved COMMON */ +-extern SAVED_F77_COMMON_PTR tail_common_list; /* Ptr to last saved COMMON */ +-extern SAVED_F77_COMMON_PTR current_common; /* Ptr to current COMMON */ +- +-extern SAVED_F77_COMMON_PTR find_common_for_function (char *, char *); +- +-#define UNINITIALIZED_SECNUM -1 +-#define COMMON_NEEDS_PATCHING(blk) ((blk)->secnum == UNINITIALIZED_SECNUM) +- + #define BLANK_COMMON_NAME_ORIGINAL "#BLNK_COM" /* XLF assigned */ + #define BLANK_COMMON_NAME_MF77 "__BLNK__" /* MF77 assigned */ +-#define BLANK_COMMON_NAME_LOCAL "__BLANK" /* Local GDB */ + + /* When reasonable array bounds cannot be fetched, such as when + you ask to 'mt print symbols' and there is no stack frame and +@@ -113,6 +84,7 @@ struct builtin_f_type + struct type *builtin_logical; + struct type *builtin_logical_s1; + struct type *builtin_logical_s2; ++ struct type *builtin_logical_s8; + struct type *builtin_real; + struct type *builtin_real_s8; + struct type *builtin_real_s16; +diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c +index 6c9668f..852b9a8 100644 +--- a/gdb/f-typeprint.c ++++ b/gdb/f-typeprint.c +@@ -31,7 +31,7 @@ + #include "gdbcore.h" + #include "target.h" + #include "f-lang.h" +- ++#include "dwarf2loc.h" + #include "gdb_string.h" + #include + +@@ -48,6 +48,34 @@ void f_type_print_varspec_prefix (struct type *, struct ui_file *, + void f_type_print_base (struct type *, struct ui_file *, int, int); + + ++const char * ++f_object_address_data_valid_print_to_stream (struct type *type, ++ struct ui_file *stream) ++{ ++ const char *msg; ++ ++ msg = object_address_data_not_valid (type); ++ if (msg != NULL) ++ { ++ /* Assuming the content printed to STREAM should not be localized. */ ++ fprintf_filtered (stream, "<%s>", msg); ++ } ++ ++ return msg; ++} ++ ++void ++f_object_address_data_valid_or_error (struct type *type) ++{ ++ const char *msg; ++ ++ msg = object_address_data_not_valid (type); ++ if (msg != NULL) ++ { ++ error (_("Cannot access it because the %s."), _(msg)); ++ } ++} ++ + /* LEVEL is the depth to indent lines by. */ + + void +@@ -57,6 +85,9 @@ f_print_type (struct type *type, char *varstring, struct ui_file *stream, + enum type_code code; + int demangled_args; + ++ if (f_object_address_data_valid_print_to_stream (type, stream) != NULL) ++ return; ++ + f_type_print_base (type, stream, show, level); + code = TYPE_CODE (type); + if ((varstring != NULL && *varstring != '\0') +@@ -166,6 +197,9 @@ f_type_print_varspec_suffix (struct type *type, struct ui_file *stream, + + QUIT; + ++ if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF) ++ CHECK_TYPEDEF (type); ++ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: +diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c +index 5721041..2cff7bc 100644 +--- a/gdb/f-valprint.c ++++ b/gdb/f-valprint.c +@@ -34,10 +34,8 @@ + #include "gdbcore.h" + #include "command.h" + #include "block.h" +- +-#if 0 +-static int there_is_a_visible_common_named (char *); +-#endif ++#include "dictionary.h" ++#include "gdb_assert.h" + + extern void _initialize_f_valprint (void); + static void info_common_command (char *, int); +@@ -54,15 +52,17 @@ int f77_array_offset_tbl[MAX_FORTRAN_DIMS + 1][2]; + /* The following macro gives us the size of the nth dimension, Where + n is 1 based. */ + +-#define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1]) ++#define F77_DIM_COUNT(n) (f77_array_offset_tbl[n][1]) + +-/* The following gives us the offset for row n where n is 1-based. */ ++/* The following gives us the element size for row n where n is 1-based. */ + +-#define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0]) ++#define F77_DIM_BYTE_STRIDE(n) (f77_array_offset_tbl[n][0]) + + int + f77_get_lowerbound (struct type *type) + { ++ f_object_address_data_valid_or_error (type); ++ + if (TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED (type)) + error (_("Lower bound may not be '*' in F77")); + +@@ -72,14 +72,17 @@ f77_get_lowerbound (struct type *type) + int + f77_get_upperbound (struct type *type) + { ++ f_object_address_data_valid_or_error (type); ++ + if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) + { +- /* We have an assumed size array on our hands. Assume that +- upper_bound == lower_bound so that we show at least 1 element. +- If the user wants to see more elements, let him manually ask for 'em +- and we'll subscript the array and show him. */ ++ /* We have an assumed size array on our hands. As type_length_get ++ already assumes a length zero of arrays with underfined bounds VALADDR ++ passed to the Fortran functions does not contained the real inferior ++ memory content. User should request printing of specific array ++ elements instead. */ + +- return f77_get_lowerbound (type); ++ return f77_get_lowerbound (type) - 1; + } + + return TYPE_ARRAY_UPPER_BOUND_VALUE (type); +@@ -135,24 +138,29 @@ f77_create_arrayprint_offset_tbl (struct type *type, struct ui_file *stream) + upper = f77_get_upperbound (tmp_type); + lower = f77_get_lowerbound (tmp_type); + +- F77_DIM_SIZE (ndimen) = upper - lower + 1; ++ F77_DIM_COUNT (ndimen) = upper - lower + 1; ++ ++ F77_DIM_BYTE_STRIDE (ndimen) = ++ TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type); + + tmp_type = TYPE_TARGET_TYPE (tmp_type); + ndimen++; + } + +- /* Now we multiply eltlen by all the offsets, so that later we ++ /* Now we multiply eltlen by all the BYTE_STRIDEs, so that later we + can print out array elements correctly. Up till now we +- know an offset to apply to get the item but we also ++ know an eltlen to apply to get the item but we also + have to know how much to add to get to the next item */ + + ndimen--; + eltlen = TYPE_LENGTH (tmp_type); +- F77_DIM_OFFSET (ndimen) = eltlen; ++ if (F77_DIM_BYTE_STRIDE (ndimen) == 0) ++ F77_DIM_BYTE_STRIDE (ndimen) = eltlen; + while (--ndimen > 0) + { +- eltlen *= F77_DIM_SIZE (ndimen + 1); +- F77_DIM_OFFSET (ndimen) = eltlen; ++ eltlen *= F77_DIM_COUNT (ndimen + 1); ++ if (F77_DIM_BYTE_STRIDE (ndimen) == 0) ++ F77_DIM_BYTE_STRIDE (ndimen) = eltlen; + } + } + +@@ -172,34 +180,34 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type, + + if (nss != ndimensions) + { +- for (i = 0; (i < F77_DIM_SIZE (nss) && (*elts) < options->print_max); i++) ++ for (i = 0; (i < F77_DIM_COUNT (nss) && (*elts) < options->print_max); i++) + { + fprintf_filtered (stream, "( "); + f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type), +- valaddr + i * F77_DIM_OFFSET (nss), +- address + i * F77_DIM_OFFSET (nss), ++ valaddr + i * F77_DIM_BYTE_STRIDE (nss), ++ address + i * F77_DIM_BYTE_STRIDE (nss), + stream, recurse, options, elts); + fprintf_filtered (stream, ") "); + } +- if (*elts >= options->print_max && i < F77_DIM_SIZE (nss)) ++ if (*elts >= options->print_max && i < F77_DIM_COUNT (nss)) + fprintf_filtered (stream, "..."); + } + else + { +- for (i = 0; i < F77_DIM_SIZE (nss) && (*elts) < options->print_max; ++ for (i = 0; i < F77_DIM_COUNT (nss) && (*elts) < options->print_max; + i++, (*elts)++) + { + val_print (TYPE_TARGET_TYPE (type), +- valaddr + i * F77_DIM_OFFSET (ndimensions), ++ valaddr + i * F77_DIM_BYTE_STRIDE (ndimensions), + 0, +- address + i * F77_DIM_OFFSET (ndimensions), ++ address + i * F77_DIM_BYTE_STRIDE (ndimensions), + stream, recurse, options, current_language); + +- if (i != (F77_DIM_SIZE (nss) - 1)) ++ if (i != (F77_DIM_COUNT (nss) - 1)) + fprintf_filtered (stream, ", "); + + if ((*elts == options->print_max - 1) +- && (i != (F77_DIM_SIZE (nss) - 1))) ++ && (i != (F77_DIM_COUNT (nss) - 1))) + fprintf_filtered (stream, "..."); + } + } +@@ -251,12 +259,16 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + CORE_ADDR addr; + int index; + ++ if (f_object_address_data_valid_print_to_stream (type, stream) != NULL) ++ return 0; ++ + CHECK_TYPEDEF (type); + switch (TYPE_CODE (type)) + { + case TYPE_CODE_STRING: + f77_get_dynamic_length_of_aggregate (type); +- LA_PRINT_STRING (stream, valaddr, TYPE_LENGTH (type), 1, 0, options); ++ LA_PRINT_STRING (stream, builtin_type (current_gdbarch)->builtin_char, ++ valaddr, TYPE_LENGTH (type), 0, options); + break; + + case TYPE_CODE_ARRAY: +@@ -293,7 +305,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + && TYPE_CODE (elttype) == TYPE_CODE_INT + && (options->format == 0 || options->format == 's') + && addr != 0) +- i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream, ++ i = val_print_string (TYPE_TARGET_TYPE (type), addr, -1, stream, + options); + + /* Return number of characters printed, including the terminating +@@ -365,7 +377,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + { + fputs_filtered (" ", stream); + LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), +- stream); ++ type, stream); + } + } + break; +@@ -464,22 +476,54 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + return 0; + } + +-static void +-list_all_visible_commons (char *funname) ++static int ++info_common_command_for_block (struct block *block, struct frame_info *frame, ++ const char *comname) + { +- SAVED_F77_COMMON_PTR tmp; +- +- tmp = head_common_list; +- +- printf_filtered (_("All COMMON blocks visible at this level:\n\n")); +- +- while (tmp != NULL) +- { +- if (strcmp (tmp->owning_function, funname) == 0) +- printf_filtered ("%s\n", tmp->name); +- +- tmp = tmp->next; +- } ++ struct dict_iterator iter; ++ struct symbol *sym; ++ int values_printed = 0; ++ const char *name; ++ struct value_print_options opts; ++ ++ get_user_print_options (&opts); ++ ++ ALL_BLOCK_SYMBOLS (block, iter, sym) ++ if (SYMBOL_DOMAIN (sym) == COMMON_BLOCK_DOMAIN) ++ { ++ struct type *type = SYMBOL_TYPE (sym); ++ int index; ++ ++ gdb_assert (SYMBOL_CLASS (sym) == LOC_STATIC); ++ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT); ++ ++ if (comname && (!SYMBOL_LINKAGE_NAME (sym) ++ || strcmp (comname, SYMBOL_LINKAGE_NAME (sym)) != 0)) ++ continue; ++ ++ values_printed = 1; ++ if (SYMBOL_PRINT_NAME (sym)) ++ printf_filtered (_("Contents of F77 COMMON block '%s':\n"), ++ SYMBOL_PRINT_NAME (sym)); ++ else ++ printf_filtered (_("Contents of blank COMMON block:\n")); ++ ++ for (index = 0; index < TYPE_NFIELDS (type); index++) ++ { ++ struct value *val; ++ ++ gdb_assert (field_is_static (&TYPE_FIELD (type, index))); ++ val = value_static_field (type, index); ++ ++ printf_filtered ("%s = ", TYPE_FIELD_NAME (type, index)); ++ value_print (val, gdb_stdout, &opts); ++ putchar_filtered ('\n'); ++ } ++ ++ putchar_filtered ('\n'); ++ } ++ ++ return values_printed; + } + + /* This function is used to print out the values in a given COMMON +@@ -489,11 +533,9 @@ list_all_visible_commons (char *funname) + static void + info_common_command (char *comname, int from_tty) + { +- SAVED_F77_COMMON_PTR the_common; +- COMMON_ENTRY_PTR entry; + struct frame_info *fi; +- char *funname = 0; +- struct symbol *func; ++ struct block *block; ++ int values_printed = 0; + + /* We have been told to display the contents of F77 COMMON + block supposedly visible in this function. Let us +@@ -505,136 +547,32 @@ info_common_command (char *comname, int from_tty) + /* The following is generally ripped off from stack.c's routine + print_frame_info() */ + +- func = find_pc_function (get_frame_pc (fi)); +- if (func) +- { +- /* In certain pathological cases, the symtabs give the wrong +- function (when we are in the first function in a file which +- is compiled without debugging symbols, the previous function +- is compiled with debugging symbols, and the "foo.o" symbol +- that is supposed to tell us where the file with debugging symbols +- ends has been truncated by ar because it is longer than 15 +- characters). +- +- So look in the minimal symbol tables as well, and if it comes +- up with a larger address for the function use that instead. +- I don't think this can ever cause any problems; there shouldn't +- be any minimal symbols in the middle of a function. +- FIXME: (Not necessarily true. What about text labels) */ +- +- struct minimal_symbol *msymbol = +- lookup_minimal_symbol_by_pc (get_frame_pc (fi)); +- +- if (msymbol != NULL +- && (SYMBOL_VALUE_ADDRESS (msymbol) +- > BLOCK_START (SYMBOL_BLOCK_VALUE (func)))) +- funname = SYMBOL_LINKAGE_NAME (msymbol); +- else +- funname = SYMBOL_LINKAGE_NAME (func); +- } +- else +- { +- struct minimal_symbol *msymbol = +- lookup_minimal_symbol_by_pc (get_frame_pc (fi)); +- +- if (msymbol != NULL) +- funname = SYMBOL_LINKAGE_NAME (msymbol); +- else /* Got no 'funname', code below will fail. */ +- error (_("No function found for frame.")); +- } +- +- /* If comname is NULL, we assume the user wishes to see the +- which COMMON blocks are visible here and then return */ +- +- if (comname == 0) ++ block = get_frame_block (fi, 0); ++ if (block == NULL) + { +- list_all_visible_commons (funname); ++ printf_filtered (_("No symbol table info available.\n")); + return; + } + +- the_common = find_common_for_function (comname, funname); +- +- if (the_common) ++ while (block) + { +- if (strcmp (comname, BLANK_COMMON_NAME_LOCAL) == 0) +- printf_filtered (_("Contents of blank COMMON block:\n")); +- else +- printf_filtered (_("Contents of F77 COMMON block '%s':\n"), comname); +- +- printf_filtered ("\n"); +- entry = the_common->entries; +- +- while (entry != NULL) +- { +- print_variable_and_value (NULL, entry->symbol, fi, gdb_stdout, 0); +- entry = entry->next; +- } ++ if (info_common_command_for_block (block, fi, comname)) ++ values_printed = 1; ++ /* After handling the function's top-level block, stop. Don't ++ continue to its superblock, the block of per-file symbols. */ ++ if (BLOCK_FUNCTION (block)) ++ break; ++ block = BLOCK_SUPERBLOCK (block); + } +- else +- printf_filtered (_("Cannot locate the common block %s in function '%s'\n"), +- comname, funname); +-} +- +-/* This function is used to determine whether there is a +- F77 common block visible at the current scope called 'comname'. */ +- +-#if 0 +-static int +-there_is_a_visible_common_named (char *comname) +-{ +- SAVED_F77_COMMON_PTR the_common; +- struct frame_info *fi; +- char *funname = 0; +- struct symbol *func; +- +- if (comname == NULL) +- error (_("Cannot deal with NULL common name!")); + +- fi = get_selected_frame (_("No frame selected")); +- +- /* The following is generally ripped off from stack.c's routine +- print_frame_info() */ +- +- func = find_pc_function (fi->pc); +- if (func) ++ if (!values_printed) + { +- /* In certain pathological cases, the symtabs give the wrong +- function (when we are in the first function in a file which +- is compiled without debugging symbols, the previous function +- is compiled with debugging symbols, and the "foo.o" symbol +- that is supposed to tell us where the file with debugging symbols +- ends has been truncated by ar because it is longer than 15 +- characters). +- +- So look in the minimal symbol tables as well, and if it comes +- up with a larger address for the function use that instead. +- I don't think this can ever cause any problems; there shouldn't +- be any minimal symbols in the middle of a function. +- FIXME: (Not necessarily true. What about text labels) */ +- +- struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc); +- +- if (msymbol != NULL +- && (SYMBOL_VALUE_ADDRESS (msymbol) +- > BLOCK_START (SYMBOL_BLOCK_VALUE (func)))) +- funname = SYMBOL_LINKAGE_NAME (msymbol); ++ if (comname) ++ printf_filtered (_("No common block '%s'.\n"), comname); + else +- funname = SYMBOL_LINKAGE_NAME (func); ++ printf_filtered (_("No common blocks.\n")); + } +- else +- { +- struct minimal_symbol *msymbol = +- lookup_minimal_symbol_by_pc (fi->pc); +- +- if (msymbol != NULL) +- funname = SYMBOL_LINKAGE_NAME (msymbol); +- } +- +- the_common = find_common_for_function (comname, funname); +- +- return (the_common ? 1 : 0); + } +-#endif + + void + _initialize_f_valprint (void) +diff --git a/gdb/findcmd.c b/gdb/findcmd.c +index 7ae43e5..2894948 100644 +--- a/gdb/findcmd.c ++++ b/gdb/findcmd.c +@@ -26,7 +26,7 @@ + + /* Copied from bfd_put_bits. */ + +-static void ++void + put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p) + { + int i; +@@ -44,6 +44,41 @@ put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p) + } + } + ++/* Allocates a buffer in *PATTERN_BUF, with a hard-coded initial size which ++ will be returned in *PATTERN_BUF_SIZE. *PATTERN_BUF_END points to the same ++ place as *PATTERN_BUF, indicating that the buffer is initially empty. */ ++ ++void ++allocate_pattern_buffer (char **pattern_buf, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size) ++{ ++#define INITIAL_PATTERN_BUF_SIZE 100 ++ *pattern_buf_size = INITIAL_PATTERN_BUF_SIZE; ++ *pattern_buf = xmalloc (*pattern_buf_size); ++ *pattern_buf_end = *pattern_buf; ++} ++ ++/* Grows *PATTERN_BUF by a factor of two if it's not large enough to hold ++ VAL_BYTES more bytes or a 64-bit value, whichever is larger. ++ *PATTERN_BUF_END is updated as necessary. */ ++ ++void ++increase_pattern_buffer (char **pattern_buf, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size, int val_bytes) ++{ ++ /* Keep it simple and assume size == 'g' when watching for when we ++ need to grow the pattern buf. */ ++ if ((*pattern_buf_end - *pattern_buf + max (val_bytes, sizeof (int64_t))) ++ > *pattern_buf_size) ++ { ++ size_t current_offset = *pattern_buf_end - *pattern_buf; ++ ++ *pattern_buf_size *= 2; ++ *pattern_buf = xrealloc (*pattern_buf, *pattern_buf_size); ++ *pattern_buf_end = *pattern_buf + current_offset; ++ } ++} ++ + /* Subroutine of find_command to simplify it. + Parse the arguments of the "find" command. */ + +@@ -59,8 +94,7 @@ parse_find_args (char *args, ULONGEST *max_countp, + char *pattern_buf; + /* Current size of search pattern buffer. + We realloc space as needed. */ +-#define INITIAL_PATTERN_BUF_SIZE 100 +- ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE; ++ ULONGEST pattern_buf_size; + /* Pointer to one past the last in-use part of pattern_buf. */ + char *pattern_buf_end; + ULONGEST pattern_len; +@@ -74,8 +108,7 @@ parse_find_args (char *args, ULONGEST *max_countp, + if (args == NULL) + error (_("Missing search parameters.")); + +- pattern_buf = xmalloc (pattern_buf_size); +- pattern_buf_end = pattern_buf; ++ allocate_pattern_buffer (&pattern_buf, &pattern_buf_end, &pattern_buf_size); + old_cleanups = make_cleanup (free_current_contents, &pattern_buf); + + /* Get search granularity and/or max count if specified. +@@ -172,16 +205,8 @@ parse_find_args (char *args, ULONGEST *max_countp, + v = parse_to_comma_and_eval (&s); + val_bytes = TYPE_LENGTH (value_type (v)); + +- /* Keep it simple and assume size == 'g' when watching for when we +- need to grow the pattern buf. */ +- if ((pattern_buf_end - pattern_buf + max (val_bytes, sizeof (int64_t))) +- > pattern_buf_size) +- { +- size_t current_offset = pattern_buf_end - pattern_buf; +- pattern_buf_size *= 2; +- pattern_buf = xrealloc (pattern_buf, pattern_buf_size); +- pattern_buf_end = pattern_buf + current_offset; +- } ++ increase_pattern_buffer (&pattern_buf, &pattern_buf_end, ++ &pattern_buf_size, val_bytes); + + if (size != '\0') + { +@@ -236,6 +261,45 @@ parse_find_args (char *args, ULONGEST *max_countp, + discard_cleanups (old_cleanups); + } + ++/* Drives target_search_memory to sweep through the specified search space, ++ possibly in several iterations (with one call to this function for each ++ iteration). *START_ADDR is the address where the search starts, and is ++ updated to the next starting address to continue the search. ++ *SEARCH_SPACE_LEN is the amount of bytes which will be searched, and is ++ updated for the next iteration. PATTERN_BUF holds the pattern to be searched ++ for, PATTERN_LEN is the size of the pattern in bytes. If a match is found, ++ it's address is put in *FOUND_ADDR. ++ ++ Returns 1 if found, 0 if not found, and -1 if there was an error requiring ++ halting of the search (e.g. memory read error). */ ++ ++int ++search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len, ++ const char *pattern_buf, ULONGEST pattern_len, ++ CORE_ADDR *found_addr) ++{ ++ /* Offset from start of this iteration to the next iteration. */ ++ ULONGEST next_iter_incr; ++ int found; ++ ++ found = target_search_memory (*start_addr, *search_space_len, ++ pattern_buf, pattern_len, found_addr); ++ if (found <= 0) ++ return found; ++ ++ /* Begin next iteration at one byte past this match. */ ++ next_iter_incr = (*found_addr - *start_addr) + 1; ++ ++ /* For robustness, we don't let search_space_len go -ve here. */ ++ if (*search_space_len >= next_iter_incr) ++ *search_space_len -= next_iter_incr; ++ else ++ *search_space_len = 0; ++ *start_addr += next_iter_incr; ++ ++ return found; ++} ++ + static void + find_command (char *args, int from_tty) + { +@@ -264,12 +328,11 @@ find_command (char *args, int from_tty) + while (search_space_len >= pattern_len + && found_count < max_count) + { +- /* Offset from start of this iteration to the next iteration. */ +- ULONGEST next_iter_incr; + CORE_ADDR found_addr; +- int found = target_search_memory (start_addr, search_space_len, +- pattern_buf, pattern_len, &found_addr); ++ int found; + ++ found = search_memory (&start_addr, &search_space_len, pattern_buf, ++ pattern_len, &found_addr); + if (found <= 0) + break; + +@@ -277,16 +340,6 @@ find_command (char *args, int from_tty) + printf_filtered ("\n"); + ++found_count; + last_found_addr = found_addr; +- +- /* Begin next iteration at one byte past this match. */ +- next_iter_incr = (found_addr - start_addr) + 1; +- +- /* For robustness, we don't let search_space_len go -ve here. */ +- if (search_space_len >= next_iter_incr) +- search_space_len -= next_iter_incr; +- else +- search_space_len = 0; +- start_addr += next_iter_incr; + } + + /* Record and print the results. */ +diff --git a/gdb/findvar.c b/gdb/findvar.c +index 1048887..b958ec6 100644 +--- a/gdb/findvar.c ++++ b/gdb/findvar.c +@@ -35,6 +35,7 @@ + #include "user-regs.h" + #include "block.h" + #include "objfiles.h" ++#include "dwarf2loc.h" + + /* Basic byte-swapping routines. GDB has needed these for a long time... + All extract a target-format integer at ADDR which is LEN bytes long. */ +@@ -275,7 +276,7 @@ value_of_register (int regnum, struct frame_info *frame) + memcpy (value_contents_raw (reg_val), raw_buffer, + register_size (gdbarch, regnum)); + VALUE_LVAL (reg_val) = lval; +- VALUE_ADDRESS (reg_val) = addr; ++ set_value_address (reg_val, addr); + VALUE_REGNUM (reg_val) = regnum; + set_value_optimized_out (reg_val, optim); + VALUE_FRAME_ID (reg_val) = get_frame_id (frame); +@@ -382,27 +383,16 @@ symbol_read_needs_frame (struct symbol *sym) + /* Given a struct symbol for a variable, + and a stack frame id, read the value of the variable + and return a (pointer to a) struct value containing the value. +- If the variable cannot be found, return a zero pointer. */ ++ If the variable cannot be found, return a zero pointer. ++ We have to first find the address of the variable before allocating struct ++ value to return as its size may depend on DW_OP_PUSH_OBJECT_ADDRESS possibly ++ used by its type. */ + + struct value * + read_var_value (struct symbol *var, struct frame_info *frame) + { +- struct value *v; + struct type *type = SYMBOL_TYPE (var); + CORE_ADDR addr; +- int len; +- +- if (SYMBOL_CLASS (var) == LOC_COMPUTED +- || SYMBOL_CLASS (var) == LOC_REGISTER) +- /* These cases do not use V. */ +- v = NULL; +- else +- { +- v = allocate_value (type); +- VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */ +- } +- +- len = TYPE_LENGTH (type); + + if (symbol_read_needs_frame (var)) + gdb_assert (frame); +@@ -410,31 +400,39 @@ read_var_value (struct symbol *var, struct frame_info *frame) + switch (SYMBOL_CLASS (var)) + { + case LOC_CONST: +- /* Put the constant back in target format. */ +- store_signed_integer (value_contents_raw (v), len, +- (LONGEST) SYMBOL_VALUE (var)); +- VALUE_LVAL (v) = not_lval; +- return v; ++ { ++ /* Put the constant back in target format. */ ++ struct value *v = allocate_value (type); ++ VALUE_LVAL (v) = not_lval; ++ store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type), ++ (LONGEST) SYMBOL_VALUE (var)); ++ return v; ++ } + + case LOC_LABEL: +- /* Put the constant back in target format. */ +- if (overlay_debugging) +- { +- CORE_ADDR addr +- = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), +- SYMBOL_OBJ_SECTION (var)); +- store_typed_address (value_contents_raw (v), type, addr); +- } +- else +- store_typed_address (value_contents_raw (v), type, +- SYMBOL_VALUE_ADDRESS (var)); +- VALUE_LVAL (v) = not_lval; +- return v; ++ { ++ /* Put the constant back in target format. */ ++ struct value *v = allocate_value (type); ++ VALUE_LVAL (v) = not_lval; ++ if (overlay_debugging) ++ { ++ CORE_ADDR addr ++ = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), ++ SYMBOL_OBJ_SECTION (var)); ++ store_typed_address (value_contents_raw (v), type, addr); ++ } ++ else ++ store_typed_address (value_contents_raw (v), type, ++ SYMBOL_VALUE_ADDRESS (var)); ++ return v; ++ } + + case LOC_CONST_BYTES: + { +- memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), len); ++ struct value *v = allocate_value (type); + VALUE_LVAL (v) = not_lval; ++ memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), ++ TYPE_LENGTH (type)); + return v; + } + +@@ -476,12 +474,23 @@ read_var_value (struct symbol *var, struct frame_info *frame) + break; + + case LOC_BLOCK: +- if (overlay_debugging) +- VALUE_ADDRESS (v) = symbol_overlayed_address +- (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)); +- else +- VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); +- return v; ++ { ++ CORE_ADDR addr; ++ struct value *v; ++ ++ if (overlay_debugging) ++ addr = symbol_overlayed_address ++ (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)); ++ else ++ addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); ++ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for ++ DW_OP_push_object_address. */ ++ object_address_set (addr); ++ v = allocate_value (type); ++ VALUE_ADDRESS (v) = addr; ++ VALUE_LVAL (v) = lval_memory; ++ return v; ++ } + + case LOC_REGISTER: + case LOC_REGPARM_ADDR: +@@ -499,7 +508,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) + error (_("Value of register variable not available.")); + + addr = value_as_address (regval); +- VALUE_LVAL (v) = lval_memory; + } + else + { +@@ -542,18 +550,33 @@ read_var_value (struct symbol *var, struct frame_info *frame) + break; + + case LOC_OPTIMIZED_OUT: +- VALUE_LVAL (v) = not_lval; +- set_value_optimized_out (v, 1); +- return v; ++ { ++ struct value *v = allocate_value (type); ++ ++ VALUE_LVAL (v) = not_lval; ++ set_value_optimized_out (v, 1); ++ return v; ++ } + + default: + error (_("Cannot look up value of a botched symbol.")); + break; + } + +- VALUE_ADDRESS (v) = addr; +- set_value_lazy (v, 1); +- return v; ++ { ++ struct value *v; ++ ++ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for ++ DW_OP_PUSH_OBJECT_ADDRESS. */ ++ object_address_set (addr); ++ v = allocate_value (type); ++ VALUE_ADDRESS (v) = addr; ++ VALUE_LVAL (v) = lval_memory; ++ ++ set_value_lazy (v, 1); ++ ++ return v; ++ } + } + + /* Install default attributes for register values. */ +@@ -590,10 +613,11 @@ struct value * + value_from_register (struct type *type, int regnum, struct frame_info *frame) + { + struct gdbarch *gdbarch = get_frame_arch (frame); +- struct type *type1 = check_typedef (type); + struct value *v; + +- if (gdbarch_convert_register_p (gdbarch, regnum, type1)) ++ type = check_typedef (type); ++ ++ if (gdbarch_convert_register_p (gdbarch, regnum, type)) + { + /* The ISA/ABI need to something weird when obtaining the + specified value from this register. It might need to +@@ -607,7 +631,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame) + VALUE_FRAME_ID (v) = get_frame_id (frame); + VALUE_REGNUM (v) = regnum; + gdbarch_register_to_value (gdbarch, +- frame, regnum, type1, value_contents_raw (v)); ++ frame, regnum, type, value_contents_raw (v)); + } + else + { +diff --git a/gdb/frame.c b/gdb/frame.c +index dfd6b3d..2ea37c3 100644 +--- a/gdb/frame.c ++++ b/gdb/frame.c +@@ -596,7 +596,7 @@ frame_register_unwind (struct frame_info *frame, int regnum, + + *optimizedp = value_optimized_out (value); + *lvalp = VALUE_LVAL (value); +- *addrp = VALUE_ADDRESS (value); ++ *addrp = value_address (value); + *realnump = VALUE_REGNUM (value); + + if (bufferp) +@@ -682,7 +682,7 @@ frame_unwind_register_value (struct frame_info *frame, int regnum) + VALUE_REGNUM (value)); + else if (VALUE_LVAL (value) == lval_memory) + fprintf_unfiltered (gdb_stdlog, " address=0x%s", +- paddr_nz (VALUE_ADDRESS (value))); ++ paddr_nz (value_address (value))); + else + fprintf_unfiltered (gdb_stdlog, " computed"); + +diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c +index ff387db..452f70c 100644 +--- a/gdb/frv-tdep.c ++++ b/gdb/frv-tdep.c +@@ -1230,7 +1230,7 @@ frv_push_dummy_call (struct gdbarch *gdbarch, struct value *function, + + if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION) + { +- store_unsigned_integer (valbuf, 4, VALUE_ADDRESS (arg)); ++ store_unsigned_integer (valbuf, 4, value_address (arg)); + typecode = TYPE_CODE_PTR; + len = 4; + val = valbuf; +diff --git a/gdb/gdb_locale.h b/gdb/gdb_locale.h +index e8ba0ea..4fa4d3d 100644 +--- a/gdb/gdb_locale.h ++++ b/gdb/gdb_locale.h +@@ -41,4 +41,8 @@ + # define N_(String) (String) + #endif + ++#ifdef HAVE_LANGINFO_CODESET ++#include ++#endif ++ + #endif /* GDB_LOCALE_H */ +diff --git a/gdb/gdb_obstack.h b/gdb/gdb_obstack.h +index 48f49cd..cd1a1d7 100644 +--- a/gdb/gdb_obstack.h ++++ b/gdb/gdb_obstack.h +@@ -45,4 +45,7 @@ + #define obstack_grow_str0(OBSTACK,STRING) \ + obstack_grow0 (OBSTACK, STRING, strlen (STRING)) + ++#define obstack_grow_wstr(OBSTACK, WSTRING) \ ++ obstack_grow (OBSTACK, WSTRING, sizeof (wchar_t) * wcslen (WSTRING)) ++ + #endif +diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c +index 3273b34..d6c737b 100644 +--- a/gdb/gdbarch.c ++++ b/gdb/gdbarch.c +@@ -243,6 +243,11 @@ struct gdbarch + gdbarch_target_signal_to_host_ftype *target_signal_to_host; + gdbarch_get_siginfo_type_ftype *get_siginfo_type; + gdbarch_record_special_symbol_ftype *record_special_symbol; ++ gdbarch_get_syscall_number_ftype *get_syscall_number; ++ gdbarch_get_syscall_by_number_ftype *get_syscall_by_number; ++ gdbarch_get_syscall_by_name_ftype *get_syscall_by_name; ++ gdbarch_get_syscall_names_ftype *get_syscall_names; ++ const char * xml_syscall_filename; + int has_global_solist; + }; + +@@ -378,6 +383,11 @@ struct gdbarch startup_gdbarch = + default_target_signal_to_host, /* target_signal_to_host */ + 0, /* get_siginfo_type */ + 0, /* record_special_symbol */ ++ 0, /* get_syscall_number */ ++ 0, /* get_syscall_by_number */ ++ 0, /* get_syscall_by_name */ ++ 0, /* get_syscall_names */ ++ 0, /* xml_syscall_filename */ + 0, /* has_global_solist */ + /* startup_gdbarch() */ + }; +@@ -634,6 +644,11 @@ verify_gdbarch (struct gdbarch *gdbarch) + /* Skip verify of target_signal_to_host, invalid_p == 0 */ + /* Skip verify of get_siginfo_type, has predicate */ + /* Skip verify of record_special_symbol, has predicate */ ++ /* Skip verify of get_syscall_number, has predicate */ ++ /* Skip verify of get_syscall_by_number, has predicate */ ++ /* Skip verify of get_syscall_by_name, has predicate */ ++ /* Skip verify of get_syscall_names, has predicate */ ++ /* Skip verify of xml_syscall_filename, invalid_p == 0 */ + /* Skip verify of has_global_solist, invalid_p == 0 */ + buf = ui_file_xstrdup (log, &dummy); + make_cleanup (xfree, buf); +@@ -859,6 +874,30 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) + "gdbarch_dump: get_siginfo_type = <%s>\n", + host_address_to_string (gdbarch->get_siginfo_type)); + fprintf_unfiltered (file, ++ "gdbarch_dump: gdbarch_get_syscall_by_name_p() = %d\n", ++ gdbarch_get_syscall_by_name_p (gdbarch)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: get_syscall_by_name = <%s>\n", ++ host_address_to_string (gdbarch->get_syscall_by_name)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: gdbarch_get_syscall_by_number_p() = %d\n", ++ gdbarch_get_syscall_by_number_p (gdbarch)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: get_syscall_by_number = <%s>\n", ++ host_address_to_string (gdbarch->get_syscall_by_number)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: gdbarch_get_syscall_names_p() = %d\n", ++ gdbarch_get_syscall_names_p (gdbarch)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: get_syscall_names = <%s>\n", ++ host_address_to_string (gdbarch->get_syscall_names)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: gdbarch_get_syscall_number_p() = %d\n", ++ gdbarch_get_syscall_number_p (gdbarch)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: get_syscall_number = <%s>\n", ++ host_address_to_string (gdbarch->get_syscall_number)); ++ fprintf_unfiltered (file, + "gdbarch_dump: has_global_solist = %s\n", + plongest (gdbarch->has_global_solist)); + fprintf_unfiltered (file, +@@ -1122,6 +1161,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) + fprintf_unfiltered (file, + "gdbarch_dump: write_pc = <%s>\n", + host_address_to_string (gdbarch->write_pc)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: xml_syscall_filename = %s\n", ++ gdbarch->xml_syscall_filename); + if (gdbarch->dump_tdep != NULL) + gdbarch->dump_tdep (gdbarch, file); + } +@@ -3333,6 +3375,119 @@ set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, + } + + int ++gdbarch_get_syscall_number_p (struct gdbarch *gdbarch) ++{ ++ gdb_assert (gdbarch != NULL); ++ return gdbarch->get_syscall_number != NULL; ++} ++ ++LONGEST ++gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid) ++{ ++ gdb_assert (gdbarch != NULL); ++ gdb_assert (gdbarch->get_syscall_number != NULL); ++ if (gdbarch_debug >= 2) ++ fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_number called\n"); ++ return gdbarch->get_syscall_number (gdbarch, ptid); ++} ++ ++void ++set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, ++ gdbarch_get_syscall_number_ftype get_syscall_number) ++{ ++ gdbarch->get_syscall_number = get_syscall_number; ++} ++ ++int ++gdbarch_get_syscall_by_number_p (struct gdbarch *gdbarch) ++{ ++ gdb_assert (gdbarch != NULL); ++ return gdbarch->get_syscall_by_number != NULL; ++} ++ ++void ++gdbarch_get_syscall_by_number (struct gdbarch *gdbarch, int syscall_number, struct syscall *s) ++{ ++ gdb_assert (gdbarch != NULL); ++ gdb_assert (gdbarch->get_syscall_by_number != NULL); ++ if (gdbarch_debug >= 2) ++ fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_by_number called\n"); ++ gdbarch->get_syscall_by_number (gdbarch, syscall_number, s); ++} ++ ++void ++set_gdbarch_get_syscall_by_number (struct gdbarch *gdbarch, ++ gdbarch_get_syscall_by_number_ftype get_syscall_by_number) ++{ ++ gdbarch->get_syscall_by_number = get_syscall_by_number; ++} ++ ++int ++gdbarch_get_syscall_by_name_p (struct gdbarch *gdbarch) ++{ ++ gdb_assert (gdbarch != NULL); ++ return gdbarch->get_syscall_by_name != NULL; ++} ++ ++void ++gdbarch_get_syscall_by_name (struct gdbarch *gdbarch, const char *syscall_name, struct syscall *s) ++{ ++ gdb_assert (gdbarch != NULL); ++ gdb_assert (gdbarch->get_syscall_by_name != NULL); ++ if (gdbarch_debug >= 2) ++ fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_by_name called\n"); ++ gdbarch->get_syscall_by_name (gdbarch, syscall_name, s); ++} ++ ++void ++set_gdbarch_get_syscall_by_name (struct gdbarch *gdbarch, ++ gdbarch_get_syscall_by_name_ftype get_syscall_by_name) ++{ ++ gdbarch->get_syscall_by_name = get_syscall_by_name; ++} ++ ++int ++gdbarch_get_syscall_names_p (struct gdbarch *gdbarch) ++{ ++ gdb_assert (gdbarch != NULL); ++ return gdbarch->get_syscall_names != NULL; ++} ++ ++const char ** ++gdbarch_get_syscall_names (struct gdbarch *gdbarch) ++{ ++ gdb_assert (gdbarch != NULL); ++ gdb_assert (gdbarch->get_syscall_names != NULL); ++ if (gdbarch_debug >= 2) ++ fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_names called\n"); ++ return gdbarch->get_syscall_names (gdbarch); ++} ++ ++void ++set_gdbarch_get_syscall_names (struct gdbarch *gdbarch, ++ gdbarch_get_syscall_names_ftype get_syscall_names) ++{ ++ gdbarch->get_syscall_names = get_syscall_names; ++} ++ ++const char * ++gdbarch_xml_syscall_filename (struct gdbarch *gdbarch) ++{ ++ gdb_assert (gdbarch != NULL); ++ /* Skip verify of xml_syscall_filename, invalid_p == 0 */ ++ if (gdbarch_debug >= 2) ++ fprintf_unfiltered (gdb_stdlog, "gdbarch_xml_syscall_filename called\n"); ++ return gdbarch->xml_syscall_filename; ++} ++ ++void ++set_gdbarch_xml_syscall_filename (struct gdbarch *gdbarch, ++ const char * xml_syscall_filename) ++{ ++ gdbarch->xml_syscall_filename = xml_syscall_filename; ++} ++ ++int + gdbarch_has_global_solist (struct gdbarch *gdbarch) + { + gdb_assert (gdbarch != NULL); +diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h +index 04c8920..017b9df 100644 +--- a/gdb/gdbarch.h ++++ b/gdb/gdbarch.h +@@ -52,6 +52,7 @@ struct bp_target_info; + struct target_desc; + struct displaced_step_closure; + struct core_regset_section; ++struct syscall; + + extern struct gdbarch *current_gdbarch; + extern struct gdbarch *target_gdbarch; +@@ -839,6 +840,47 @@ typedef void (gdbarch_record_special_symbol_ftype) (struct gdbarch *gdbarch, str + extern void gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym); + extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_record_special_symbol_ftype *record_special_symbol); + ++/* Functions for the 'catch syscall' feature. ++ Get architecture-specific system calls information from registers. */ ++ ++extern int gdbarch_get_syscall_number_p (struct gdbarch *gdbarch); ++ ++typedef LONGEST (gdbarch_get_syscall_number_ftype) (struct gdbarch *gdbarch, ptid_t ptid); ++extern LONGEST gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid); ++extern void set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, gdbarch_get_syscall_number_ftype *get_syscall_number); ++ ++/* Fills the struct syscall (passed as argument) with the corresponding ++ system call represented by syscall_number. */ ++ ++extern int gdbarch_get_syscall_by_number_p (struct gdbarch *gdbarch); ++ ++typedef void (gdbarch_get_syscall_by_number_ftype) (struct gdbarch *gdbarch, int syscall_number, struct syscall *s); ++extern void gdbarch_get_syscall_by_number (struct gdbarch *gdbarch, int syscall_number, struct syscall *s); ++extern void set_gdbarch_get_syscall_by_number (struct gdbarch *gdbarch, gdbarch_get_syscall_by_number_ftype *get_syscall_by_number); ++ ++/* Fills the struct syscall (passed as argument) with the corresponding ++ system call represented by syscall_name. */ ++ ++extern int gdbarch_get_syscall_by_name_p (struct gdbarch *gdbarch); ++ ++typedef void (gdbarch_get_syscall_by_name_ftype) (struct gdbarch *gdbarch, const char *syscall_name, struct syscall *s); ++extern void gdbarch_get_syscall_by_name (struct gdbarch *gdbarch, const char *syscall_name, struct syscall *s); ++extern void set_gdbarch_get_syscall_by_name (struct gdbarch *gdbarch, gdbarch_get_syscall_by_name_ftype *get_syscall_by_name); ++ ++/* Returns the array containing the syscall names for the architecture. */ ++ ++extern int gdbarch_get_syscall_names_p (struct gdbarch *gdbarch); ++ ++typedef const char ** (gdbarch_get_syscall_names_ftype) (struct gdbarch *gdbarch); ++extern const char ** gdbarch_get_syscall_names (struct gdbarch *gdbarch); ++extern void set_gdbarch_get_syscall_names (struct gdbarch *gdbarch, gdbarch_get_syscall_names_ftype *get_syscall_names); ++ ++/* Stores the name of syscall's XML file. Contains NULL if the file ++ was not set. */ ++ ++extern const char * gdbarch_xml_syscall_filename (struct gdbarch *gdbarch); ++extern void set_gdbarch_xml_syscall_filename (struct gdbarch *gdbarch, const char * xml_syscall_filename); ++ + /* True if the list of shared libraries is one and only for all + processes, as opposed to a list of shared libraries per inferior. + When this property is true, GDB assumes that since shared libraries +@@ -848,6 +890,9 @@ extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_ + extern int gdbarch_has_global_solist (struct gdbarch *gdbarch); + extern void set_gdbarch_has_global_solist (struct gdbarch *gdbarch, int has_global_solist); + ++/* Definition for an unknown syscall, used basically in error-cases. */ ++#define UNKNOWN_SYSCALL (-1) ++ + extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); + + +diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh +index f93bfc1..66cbcd0 100755 +--- a/gdb/gdbarch.sh ++++ b/gdb/gdbarch.sh +@@ -724,6 +724,26 @@ M:struct type *:get_siginfo_type:void: + # Record architecture-specific information from the symbol table. + M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym + ++# Functions for the 'catch syscall' feature. ++ ++# Get architecture-specific system calls information from registers. ++M:LONGEST:get_syscall_number:ptid_t ptid:ptid ++ ++# Fills the struct syscall (passed as argument) with the corresponding ++# system call represented by syscall_number. ++M:void:get_syscall_by_number:int syscall_number, struct syscall *s:syscall_number, s ++ ++# Fills the struct syscall (passed as argument) with the corresponding ++# system call represented by syscall_name. ++M:void:get_syscall_by_name:const char *syscall_name, struct syscall *s:syscall_name, s ++ ++# Returns the array containing the syscall names for the architecture. ++M:const char **:get_syscall_names:void: ++ ++# Stores the name of syscall's XML file. Contains NULL if the file ++# was not set. ++v:const char *:xml_syscall_filename:::0:0::0:gdbarch->xml_syscall_filename ++ + # True if the list of shared libraries is one and only for all + # processes, as opposed to a list of shared libraries per inferior. + # When this property is true, GDB assumes that since shared libraries +@@ -842,6 +862,7 @@ struct bp_target_info; + struct target_desc; + struct displaced_step_closure; + struct core_regset_section; ++struct syscall; + + extern struct gdbarch *current_gdbarch; + extern struct gdbarch *target_gdbarch; +@@ -911,6 +932,9 @@ done + # close it off + cat <objfile_obstack, struct type); + TYPE_MAIN_TYPE (type) = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct main_type); + OBJSTAT (objfile, n_types++); ++ break; + } + + /* Initialize the fields that might not be zero. */ +@@ -180,6 +201,9 @@ alloc_type (struct objfile *objfile) + TYPE_VPTR_FIELDNO (type) = -1; + TYPE_CHAIN (type) = type; /* Chain back to itself. */ + ++ if (objfile == NULL) ++ type_init_refc (type, parent); ++ + return (type); + } + +@@ -194,16 +218,24 @@ alloc_type_instance (struct type *oldtype) + + /* Allocate the structure. */ + +- if (TYPE_OBJFILE (oldtype) == NULL) +- type = XZALLOC (struct type); +- else +- type = OBSTACK_ZALLOC (&TYPE_OBJFILE (oldtype)->objfile_obstack, +- struct type); +- ++ switch ((long) TYPE_OBJFILE (oldtype)) ++ { ++ case (long) OBJFILE_INTERNAL: ++ case (long) OBJFILE_MALLOC: ++ type = XZALLOC (struct type); ++ break; ++ default: ++ type = OBSTACK_ZALLOC (&TYPE_OBJFILE (oldtype)->objfile_obstack, ++ struct type); ++ break; ++ } + TYPE_MAIN_TYPE (type) = TYPE_MAIN_TYPE (oldtype); + + TYPE_CHAIN (type) = type; /* Chain back to itself for now. */ + ++ if (TYPE_OBJFILE (oldtype) == NULL) ++ type_init_refc (type, oldtype); ++ + return (type); + } + +@@ -248,7 +280,7 @@ make_pointer_type (struct type *type, struct type **typeptr) + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { +- ntype = alloc_type (TYPE_OBJFILE (type)); ++ ntype = alloc_type (TYPE_OBJFILE (type), type); + if (typeptr) + *typeptr = ntype; + } +@@ -260,6 +292,9 @@ make_pointer_type (struct type *type, struct type **typeptr) + smash_type (ntype); + TYPE_CHAIN (ntype) = chain; + TYPE_OBJFILE (ntype) = objfile; ++ ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (objfile); + } + + TYPE_TARGET_TYPE (ntype) = type; +@@ -328,7 +363,7 @@ make_reference_type (struct type *type, struct type **typeptr) + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { +- ntype = alloc_type (TYPE_OBJFILE (type)); ++ ntype = alloc_type (TYPE_OBJFILE (type), type); + if (typeptr) + *typeptr = ntype; + } +@@ -340,6 +375,9 @@ make_reference_type (struct type *type, struct type **typeptr) + smash_type (ntype); + TYPE_CHAIN (ntype) = chain; + TYPE_OBJFILE (ntype) = objfile; ++ ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (objfile); + } + + TYPE_TARGET_TYPE (ntype) = type; +@@ -388,7 +426,7 @@ make_function_type (struct type *type, struct type **typeptr) + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { +- ntype = alloc_type (TYPE_OBJFILE (type)); ++ ntype = alloc_type (TYPE_OBJFILE (type), type); + if (typeptr) + *typeptr = ntype; + } +@@ -398,6 +436,9 @@ make_function_type (struct type *type, struct type **typeptr) + objfile = TYPE_OBJFILE (ntype); + smash_type (ntype); + TYPE_OBJFILE (ntype) = objfile; ++ ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (objfile); + } + + TYPE_TARGET_TYPE (ntype) = type; +@@ -643,7 +684,7 @@ lookup_memberptr_type (struct type *type, struct type *domain) + { + struct type *mtype; + +- mtype = alloc_type (TYPE_OBJFILE (type)); ++ mtype = alloc_type (TYPE_OBJFILE (type), NULL); + smash_to_memberptr_type (mtype, domain, type); + return (mtype); + } +@@ -655,7 +696,7 @@ lookup_methodptr_type (struct type *to_type) + { + struct type *mtype; + +- mtype = alloc_type (TYPE_OBJFILE (to_type)); ++ mtype = alloc_type (TYPE_OBJFILE (to_type), NULL); + TYPE_TARGET_TYPE (mtype) = to_type; + TYPE_DOMAIN_TYPE (mtype) = TYPE_DOMAIN_TYPE (to_type); + TYPE_LENGTH (mtype) = cplus_method_ptr_size (to_type); +@@ -696,19 +737,20 @@ create_range_type (struct type *result_type, struct type *index_type, + int low_bound, int high_bound) + { + if (result_type == NULL) +- result_type = alloc_type (TYPE_OBJFILE (index_type)); ++ result_type = alloc_type (TYPE_OBJFILE (index_type), index_type); + TYPE_CODE (result_type) = TYPE_CODE_RANGE; + TYPE_TARGET_TYPE (result_type) = index_type; + if (TYPE_STUB (index_type)) + TYPE_TARGET_STUB (result_type) = 1; + else + TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type)); +- TYPE_NFIELDS (result_type) = 2; ++ TYPE_NFIELDS (result_type) = 3; + TYPE_FIELDS (result_type) = TYPE_ZALLOC (result_type, + TYPE_NFIELDS (result_type) + * sizeof (struct field)); + TYPE_LOW_BOUND (result_type) = low_bound; + TYPE_HIGH_BOUND (result_type) = high_bound; ++ TYPE_BYTE_STRIDE (result_type) = 0; + + if (low_bound >= 0) + TYPE_UNSIGNED (result_type) = 1; +@@ -727,6 +769,9 @@ get_discrete_bounds (struct type *type, LONGEST *lowp, LONGEST *highp) + switch (TYPE_CODE (type)) + { + case TYPE_CODE_RANGE: ++ if (TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (type) ++ || TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (type)) ++ return -1; + *lowp = TYPE_LOW_BOUND (type); + *highp = TYPE_HIGH_BOUND (type); + return 1; +@@ -805,30 +850,56 @@ create_array_type (struct type *result_type, + + if (result_type == NULL) + { +- result_type = alloc_type (TYPE_OBJFILE (range_type)); ++ result_type = alloc_type (TYPE_OBJFILE (range_type), range_type); + } ++ else ++ { ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (TYPE_OBJFILE (result_type)); ++ } ++ + TYPE_CODE (result_type) = TYPE_CODE_ARRAY; + TYPE_TARGET_TYPE (result_type) = element_type; +- if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) +- low_bound = high_bound = 0; +- CHECK_TYPEDEF (element_type); +- /* Be careful when setting the array length. Ada arrays can be +- empty arrays with the high_bound being smaller than the low_bound. +- In such cases, the array length should be zero. */ +- if (high_bound < low_bound) +- TYPE_LENGTH (result_type) = 0; +- else +- TYPE_LENGTH (result_type) = +- TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); + TYPE_NFIELDS (result_type) = 1; + TYPE_FIELDS (result_type) = + (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field)); ++ /* FIXME: type alloc. */ + TYPE_INDEX_TYPE (result_type) = range_type; + TYPE_VPTR_FIELDNO (result_type) = -1; + +- /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays */ ++ /* DWARF blocks may depend on runtime information like ++ DW_OP_PUSH_OBJECT_ADDRESS not being available during the ++ CREATE_ARRAY_TYPE time. */ ++ if (TYPE_RANGE_BOUND_IS_DWARF_BLOCK (range_type, 0) ++ || TYPE_RANGE_BOUND_IS_DWARF_BLOCK (range_type, 1) ++ || TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type) ++ || TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (range_type) ++ || get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) ++ { ++ low_bound = 0; ++ high_bound = -1; ++ } ++ ++ /* Be careful when setting the array length. Ada arrays can be ++ empty arrays with the high_bound being smaller than the low_bound. ++ In such cases, the array length should be zero. TYPE_TARGET_STUB needs to ++ be checked as it may have dependencies on DWARF blocks depending on ++ runtime information not available during the CREATE_ARRAY_TYPE time. */ ++ if (high_bound < low_bound || TYPE_TARGET_STUB (element_type)) ++ TYPE_LENGTH (result_type) = 0; ++ else ++ { ++ CHECK_TYPEDEF (element_type); ++ TYPE_LENGTH (result_type) = ++ TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); ++ } ++ + if (TYPE_LENGTH (result_type) == 0) +- TYPE_TARGET_STUB (result_type) = 1; ++ { ++ /* The real size will be computed for specific instances by ++ CHECK_TYPEDEF. */ ++ TYPE_TARGET_STUB (result_type) = 1; ++ } + + return (result_type); + } +@@ -865,7 +936,12 @@ create_set_type (struct type *result_type, struct type *domain_type) + { + if (result_type == NULL) + { +- result_type = alloc_type (TYPE_OBJFILE (domain_type)); ++ result_type = alloc_type (TYPE_OBJFILE (domain_type), domain_type); ++ } ++ else ++ { ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (TYPE_OBJFILE (result_type)); + } + TYPE_CODE (result_type) = TYPE_CODE_SET; + TYPE_NFIELDS (result_type) = 1; +@@ -1368,6 +1444,84 @@ stub_noname_complaint (void) + complaint (&symfile_complaints, _("stub type has NULL name")); + } + ++/* Calculate the memory length of array TYPE. ++ ++ TARGET_TYPE should be set to `check_typedef (TYPE_TARGET_TYPE (type))' as ++ a performance hint. Feel free to pass NULL. Set FULL_SPAN to return the ++ size incl. the possible padding of the last element - it may differ from the ++ cleared FULL_SPAN return value (the expected SIZEOF) for non-zero ++ TYPE_BYTE_STRIDE values. */ ++ ++static CORE_ADDR ++type_length_get (struct type *type, struct type *target_type, int full_span) ++{ ++ struct type *range_type; ++ int count; ++ CORE_ADDR byte_stride = 0; /* `= 0' for a false GCC warning. */ ++ CORE_ADDR element_size; ++ ++ if (TYPE_CODE (type) != TYPE_CODE_ARRAY ++ && TYPE_CODE (type) != TYPE_CODE_STRING) ++ return TYPE_LENGTH (type); ++ ++ /* Avoid executing TYPE_HIGH_BOUND for invalid (unallocated/unassociated) ++ Fortran arrays. The allocated data will never be used so they can be ++ zero-length. */ ++ if (object_address_data_not_valid (type)) ++ return 0; ++ ++ range_type = TYPE_INDEX_TYPE (type); ++ if (TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (range_type) ++ || TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type)) ++ return 0; ++ count = TYPE_HIGH_BOUND (range_type) - TYPE_LOW_BOUND (range_type) + 1; ++ /* It may happen for wrong DWARF annotations returning garbage data. */ ++ if (count < 0) ++ warning (_("Range for type %s has invalid bounds %d..%d"), ++ TYPE_NAME (type), TYPE_LOW_BOUND (range_type), ++ TYPE_HIGH_BOUND (range_type)); ++ /* The code below does not handle count == 0 right. */ ++ if (count <= 0) ++ return 0; ++ if (full_span || count > 1) ++ { ++ /* We do not use TYPE_ARRAY_BYTE_STRIDE_VALUE (type) here as we want to ++ force FULL_SPAN to 1. */ ++ byte_stride = TYPE_BYTE_STRIDE (range_type); ++ if (byte_stride == 0) ++ { ++ if (target_type == NULL) ++ target_type = check_typedef (TYPE_TARGET_TYPE (type)); ++ byte_stride = type_length_get (target_type, NULL, 1); ++ } ++ } ++ if (full_span) ++ return count * byte_stride; ++ if (target_type == NULL) ++ target_type = check_typedef (TYPE_TARGET_TYPE (type)); ++ element_size = type_length_get (target_type, NULL, 1); ++ return (count - 1) * byte_stride + element_size; ++} ++ ++/* Prepare TYPE after being read in by the backend. Currently this function ++ only propagates the TYPE_DYNAMIC flag. */ ++ ++void ++finalize_type (struct type *type) ++{ ++ int i; ++ ++ for (i = 0; i < TYPE_NFIELDS (type); ++i) ++ if (TYPE_FIELD_TYPE (type, i) && TYPE_DYNAMIC (TYPE_FIELD_TYPE (type, i))) ++ break; ++ ++ /* FIXME: cplus_stuff is ignored here. */ ++ if (i < TYPE_NFIELDS (type) ++ || (TYPE_VPTR_BASETYPE (type) && TYPE_DYNAMIC (TYPE_VPTR_BASETYPE (type))) ++ || (TYPE_TARGET_TYPE (type) && TYPE_DYNAMIC (TYPE_TARGET_TYPE (type)))) ++ TYPE_DYNAMIC (type) = 1; ++} ++ + /* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989. + + If this is a stubbed struct (i.e. declared as struct foo *), see if +@@ -1384,7 +1538,8 @@ stub_noname_complaint (void) + /* Find the real type of TYPE. This function returns the real type, + after removing all layers of typedefs and completing opaque or stub + types. Completion changes the TYPE argument, but stripping of +- typedefs does not. */ ++ typedefs does not. Still original passed TYPE will have TYPE_LENGTH ++ updated. FIXME: Remove this dependency (only ada_to_fixed_type?). */ + + struct type * + check_typedef (struct type *type) +@@ -1420,7 +1575,7 @@ check_typedef (struct type *type) + if (sym) + TYPE_TARGET_TYPE (type) = SYMBOL_TYPE (sym); + else /* TYPE_CODE_UNDEF */ +- TYPE_TARGET_TYPE (type) = alloc_type (NULL); ++ TYPE_TARGET_TYPE (type) = alloc_type (NULL, NULL); + } + type = TYPE_TARGET_TYPE (type); + } +@@ -1494,34 +1649,37 @@ check_typedef (struct type *type) + } + } + +- if (TYPE_TARGET_STUB (type)) ++ /* copy_type_recursive automatically makes the resulting type containing only ++ constant values expected by the callers of this function. */ ++ if (TYPE_DYNAMIC (type)) ++ { ++ htab_t copied_types; ++ struct type *type_old = type; ++ ++ copied_types = create_copied_types_hash (NULL); ++ type = copy_type_recursive (type, copied_types); ++ htab_delete (copied_types); ++ ++ gdb_assert (TYPE_DYNAMIC (type) == 0); ++ } ++ ++ if (!currently_reading_symtab ++ && (TYPE_TARGET_STUB (type) || TYPE_DYNAMIC (type))) + { +- struct type *range_type; + struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type)); + ++ if (TYPE_DYNAMIC (type)) ++ TYPE_TARGET_TYPE (type) = target_type; + if (TYPE_STUB (target_type) || TYPE_TARGET_STUB (target_type)) + { + /* Empty. */ + } + else if (TYPE_CODE (type) == TYPE_CODE_ARRAY +- && TYPE_NFIELDS (type) == 1 +- && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type)) +- == TYPE_CODE_RANGE)) ++ || TYPE_CODE (type) == TYPE_CODE_STRING) + { + /* Now recompute the length of the array type, based on its +- number of elements and the target type's length. +- Watch out for Ada null Ada arrays where the high bound +- is smaller than the low bound. */ +- const int low_bound = TYPE_LOW_BOUND (range_type); +- const int high_bound = TYPE_HIGH_BOUND (range_type); +- int nb_elements; +- +- if (high_bound < low_bound) +- nb_elements = 0; +- else +- nb_elements = high_bound - low_bound + 1; +- +- TYPE_LENGTH (type) = nb_elements * TYPE_LENGTH (target_type); ++ number of elements and the target type's length. */ ++ TYPE_LENGTH (type) = type_length_get (type, target_type, 0); + TYPE_TARGET_STUB (type) = 0; + } + else if (TYPE_CODE (type) == TYPE_CODE_RANGE) +@@ -1529,9 +1687,12 @@ check_typedef (struct type *type) + TYPE_LENGTH (type) = TYPE_LENGTH (target_type); + TYPE_TARGET_STUB (type) = 0; + } ++ TYPE_DYNAMIC (type) = 0; + } ++ + /* Cache TYPE_LENGTH for future use. */ + TYPE_LENGTH (orig_type) = TYPE_LENGTH (type); ++ + return type; + } + +@@ -1753,7 +1914,7 @@ init_type (enum type_code code, int length, int flags, + { + struct type *type; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + TYPE_CODE (type) = code; + TYPE_LENGTH (type) = length; + +@@ -1783,15 +1944,24 @@ init_type (enum type_code code, int length, int flags, + if (flags & TYPE_FLAG_FIXED_INSTANCE) + TYPE_FIXED_INSTANCE (type) = 1; + +- if ((name != NULL) && (objfile != NULL)) +- { +- TYPE_NAME (type) = obsavestring (name, strlen (name), +- &objfile->objfile_obstack); +- } +- else +- { +- TYPE_NAME (type) = name; +- } ++ if (name) ++ switch ((long) objfile) ++ { ++ case (long) OBJFILE_INTERNAL: ++ TYPE_NAME (type) = name; ++ break; ++ case (long) OBJFILE_MALLOC: ++ TYPE_NAME (type) = xstrdup (name); ++ break; ++#if 0 /* OBJFILE_MALLOC duplication now. */ ++ case (long) NULL: ++ internal_error (__FILE__, __LINE__, ++ _("OBJFILE pointer NULL should be OBJFILE_* instead")); ++#endif ++ default: ++ TYPE_NAME (type) = obsavestring (name, strlen (name), ++ &objfile->objfile_obstack); ++ } + + /* C++ fancies. */ + +@@ -1803,6 +1973,10 @@ init_type (enum type_code code, int length, int flags, + { + INIT_CPLUS_SPECIFIC (type); + } ++ ++ if (!objfile) ++ type_incref (type); ++ + return (type); + } + +@@ -2916,33 +3090,47 @@ type_pair_eq (const void *item_lhs, const void *item_rhs) + } + + /* Allocate the hash table used by copy_type_recursive to walk +- types without duplicates. We use OBJFILE's obstack, because +- OBJFILE is about to be deleted. */ ++ types without duplicates. */ + + htab_t + create_copied_types_hash (struct objfile *objfile) + { +- return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, +- NULL, &objfile->objfile_obstack, +- hashtab_obstack_allocate, +- dummy_obstack_deallocate); ++ if (objfile == NULL) ++ { ++ /* NULL OBJFILE is for TYPE_DYNAMIC types already contained in ++ OBJFILE_MALLOC memory, such as those from VALUE_HISTORY_CHAIN. Table ++ element entries get allocated by xmalloc - so use xfree. */ ++ return htab_create (1, type_pair_hash, type_pair_eq, xfree); ++ } ++ else ++ { ++ /* Use OBJFILE's obstack, because OBJFILE is about to be deleted. Table ++ element entries get allocated by xmalloc - so use xfree. */ ++ return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, ++ xfree, &objfile->objfile_obstack, ++ hashtab_obstack_allocate, ++ dummy_obstack_deallocate); ++ } + } + +-/* Recursively copy (deep copy) TYPE, if it is associated with +- OBJFILE. Return a new type allocated using malloc, a saved type if +- we have already visited TYPE (using COPIED_TYPES), or TYPE if it is +- not associated with OBJFILE. */ ++/* A helper for copy_type_recursive. This does all the work. ++ REPRESENTATIVE is a pointer to a type. This is used to register ++ newly-created types in the type_refc_table. Initially it pointer ++ to a NULL pointer, but it is filled in the first time a type is ++ copied. OBJFILE is used only for an assertion checking. */ + +-struct type * +-copy_type_recursive (struct objfile *objfile, +- struct type *type, +- htab_t copied_types) ++static struct type * ++copy_type_recursive_1 (struct objfile *objfile, ++ struct type *type, ++ htab_t copied_types, ++ struct type **representative) + { + struct type_pair *stored, pair; + void **slot; + struct type *new_type; + +- if (TYPE_OBJFILE (type) == NULL) ++ if (TYPE_OBJFILE (type) == OBJFILE_INTERNAL ++ || (objfile == OBJFILE_MALLOC && !TYPE_DYNAMIC (type))) + return type; + + /* This type shouldn't be pointing to any types in other objfiles; +@@ -2954,11 +3142,15 @@ copy_type_recursive (struct objfile *objfile, + if (*slot != NULL) + return ((struct type_pair *) *slot)->new; + +- new_type = alloc_type (NULL); ++ new_type = alloc_type (OBJFILE_MALLOC, *representative); ++ if (!*representative) ++ *representative = new_type; + + /* We must add the new type to the hash table immediately, in case +- we encounter this type again during a recursive call below. */ +- stored = obstack_alloc (&objfile->objfile_obstack, sizeof (struct type_pair)); ++ we encounter this type again during a recursive call below. Memory could ++ be allocated from OBJFILE in the case we will be removing OBJFILE, this ++ optimization is missed and xfree is called for it from COPIED_TYPES. */ ++ stored = xmalloc (sizeof (*stored)); + stored->old = type; + stored->new = new_type; + *slot = stored; +@@ -2968,6 +3160,13 @@ copy_type_recursive (struct objfile *objfile, + *TYPE_MAIN_TYPE (new_type) = *TYPE_MAIN_TYPE (type); + TYPE_OBJFILE (new_type) = NULL; + ++ /* Pre-clear the fields processed by delete_main_type. If DWARF block ++ evaluations below call error we would leave an unfreeable TYPE. */ ++ TYPE_TARGET_TYPE (new_type) = NULL; ++ TYPE_VPTR_BASETYPE (new_type) = NULL; ++ TYPE_NFIELDS (new_type) = 0; ++ TYPE_FIELDS (new_type) = NULL; ++ + if (TYPE_NAME (type)) + TYPE_NAME (new_type) = xstrdup (TYPE_NAME (type)); + if (TYPE_TAG_NAME (type)) +@@ -2976,12 +3175,45 @@ copy_type_recursive (struct objfile *objfile, + TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); + TYPE_LENGTH (new_type) = TYPE_LENGTH (type); + ++ if (TYPE_ALLOCATED (new_type)) ++ { ++ gdb_assert (!TYPE_NOT_ALLOCATED (new_type)); ++ ++ if (!dwarf_locexpr_baton_eval (TYPE_ALLOCATED (new_type))) ++ TYPE_NOT_ALLOCATED (new_type) = 1; ++ TYPE_ALLOCATED (new_type) = NULL; ++ } ++ ++ if (TYPE_ASSOCIATED (new_type)) ++ { ++ gdb_assert (!TYPE_NOT_ASSOCIATED (new_type)); ++ ++ if (!dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (new_type))) ++ TYPE_NOT_ASSOCIATED (new_type) = 1; ++ TYPE_ASSOCIATED (new_type) = NULL; ++ } ++ ++ if (!TYPE_DATA_LOCATION_IS_ADDR (new_type) ++ && TYPE_DATA_LOCATION_DWARF_BLOCK (new_type)) ++ { ++ if (TYPE_NOT_ALLOCATED (new_type) ++ || TYPE_NOT_ASSOCIATED (new_type)) ++ TYPE_DATA_LOCATION_DWARF_BLOCK (new_type) = NULL; ++ else ++ { ++ TYPE_DATA_LOCATION_IS_ADDR (new_type) = 1; ++ TYPE_DATA_LOCATION_ADDR (new_type) = dwarf_locexpr_baton_eval ++ (TYPE_DATA_LOCATION_DWARF_BLOCK (new_type)); ++ } ++ } ++ + /* Copy the fields. */ + if (TYPE_NFIELDS (type)) + { + int i, nfields; + + nfields = TYPE_NFIELDS (type); ++ TYPE_NFIELDS (new_type) = nfields; + TYPE_FIELDS (new_type) = XCALLOC (nfields, struct field); + for (i = 0; i < nfields; i++) + { +@@ -2990,8 +3222,8 @@ copy_type_recursive (struct objfile *objfile, + TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i); + if (TYPE_FIELD_TYPE (type, i)) + TYPE_FIELD_TYPE (new_type, i) +- = copy_type_recursive (objfile, TYPE_FIELD_TYPE (type, i), +- copied_types); ++ = copy_type_recursive_1 (objfile, TYPE_FIELD_TYPE (type, i), ++ copied_types, representative); + if (TYPE_FIELD_NAME (type, i)) + TYPE_FIELD_NAME (new_type, i) = + xstrdup (TYPE_FIELD_NAME (type, i)); +@@ -3010,6 +3242,16 @@ copy_type_recursive (struct objfile *objfile, + xstrdup (TYPE_FIELD_STATIC_PHYSNAME (type, + i))); + break; ++ case FIELD_LOC_KIND_DWARF_BLOCK: ++ /* `struct dwarf2_locexpr_baton' is too bound to its objfile so ++ it is expected to be made constant by CHECK_TYPEDEF. */ ++ if (TYPE_NOT_ALLOCATED (new_type) ++ || TYPE_NOT_ASSOCIATED (new_type)) ++ SET_FIELD_DWARF_BLOCK (TYPE_FIELD (new_type, i), NULL); ++ else ++ SET_FIELD_BITPOS (TYPE_FIELD (new_type, i), ++ dwarf_locexpr_baton_eval (TYPE_FIELD_DWARF_BLOCK (type, i))); ++ break; + default: + internal_error (__FILE__, __LINE__, + _("Unexpected type field location kind: %d"), +@@ -3018,17 +3260,32 @@ copy_type_recursive (struct objfile *objfile, + } + } + ++ /* Convert TYPE_RANGE_HIGH_BOUND_IS_COUNT into a regular bound. */ ++ if (TYPE_CODE (type) == TYPE_CODE_RANGE ++ && TYPE_RANGE_HIGH_BOUND_IS_COUNT (type)) ++ { ++ TYPE_RANGE_HIGH_BOUND_IS_COUNT (new_type) = 0; ++ TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (type) ++ + TYPE_HIGH_BOUND (type) - 1; ++ } ++ ++ /* Both FIELD_LOC_KIND_DWARF_BLOCK and TYPE_RANGE_HIGH_BOUND_IS_COUNT were ++ possibly converted. */ ++ TYPE_DYNAMIC (new_type) = 0; ++ + /* Copy pointers to other types. */ + if (TYPE_TARGET_TYPE (type)) + TYPE_TARGET_TYPE (new_type) = +- copy_type_recursive (objfile, +- TYPE_TARGET_TYPE (type), +- copied_types); ++ copy_type_recursive_1 (objfile, ++ TYPE_TARGET_TYPE (type), ++ copied_types, ++ representative); + if (TYPE_VPTR_BASETYPE (type)) + TYPE_VPTR_BASETYPE (new_type) = +- copy_type_recursive (objfile, +- TYPE_VPTR_BASETYPE (type), +- copied_types); ++ copy_type_recursive_1 (objfile, ++ TYPE_VPTR_BASETYPE (type), ++ copied_types, ++ representative); + /* Maybe copy the type_specific bits. + + NOTE drow/2005-12-09: We do not copy the C++-specific bits like +@@ -3046,6 +3303,20 @@ copy_type_recursive (struct objfile *objfile, + return new_type; + } + ++/* Recursively copy (deep copy) TYPE. Return a new type allocated using ++ malloc, a saved type if we have already visited TYPE (using COPIED_TYPES), ++ or TYPE if it is not associated with OBJFILE. */ ++ ++struct type * ++copy_type_recursive (struct type *type, ++ htab_t copied_types) ++{ ++ struct type *representative = NULL; ++ ++ return copy_type_recursive_1 (TYPE_OBJFILE (type), type, copied_types, ++ &representative); ++} ++ + /* Make a copy of the given TYPE, except that the pointer & reference + types are not preserved. + +@@ -3059,7 +3330,7 @@ copy_type (const struct type *type) + + gdb_assert (TYPE_OBJFILE (type) != NULL); + +- new_type = alloc_type (TYPE_OBJFILE (type)); ++ new_type = alloc_type (TYPE_OBJFILE (type), NULL); + TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); + TYPE_LENGTH (new_type) = TYPE_LENGTH (type); + memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type), +@@ -3068,6 +3339,232 @@ copy_type (const struct type *type) + return new_type; + } + ++static void delete_type (struct type *type); ++ ++/* A helper for delete_type which deletes a main_type and the things to which ++ it refers. TYPE is a type whose main_type we wish to destroy. */ ++ ++static void ++delete_main_type (struct main_type *main_type) ++{ ++ int i; ++ void **slot; ++ struct ++ { ++ struct main_type *main_type; ++ } type_local = { main_type }, *type = &type_local; ++ ++ gdb_assert (TYPE_OBJFILE (type) == OBJFILE_MALLOC); ++ ++ xfree (TYPE_NAME (type)); ++ xfree (TYPE_TAG_NAME (type)); ++ ++ for (i = 0; i < TYPE_NFIELDS (type); ++i) ++ { ++ xfree (TYPE_FIELD_NAME (type, i)); ++ ++ if (TYPE_FIELD_LOC_KIND (type, i) == FIELD_LOC_KIND_PHYSNAME) ++ xfree (TYPE_FIELD_STATIC_PHYSNAME (type, i)); ++ } ++ xfree (TYPE_FIELDS (type)); ++ ++ /* Strangely, HAVE_CPLUS_STRUCT will return true when there isn't ++ one at all. */ ++ gdb_assert (!HAVE_CPLUS_STRUCT (type) || !TYPE_CPLUS_SPECIFIC (type)); ++ ++ xfree (TYPE_MAIN_TYPE (type)); ++} ++ ++/* Store `struct main_type *' entries which got `struct type *' deleted. */ ++ ++static htab_t deleted_main_types_hash; ++ ++/* To be called before any call of delete_type. */ ++ ++static void ++delete_type_begin (void) ++{ ++ gdb_assert (deleted_main_types_hash == NULL); ++ ++ deleted_main_types_hash = htab_create_alloc (10, htab_hash_pointer, ++ htab_eq_pointer, NULL, xcalloc, xfree); ++} ++ ++/* Helper for delete_type_finish. */ ++ ++static int ++delete_type_finish_traverse (void **slot, void *unused) ++{ ++ struct main_type *main_type = *slot; ++ ++ delete_main_type (main_type); ++ ++ return 1; ++} ++ ++/* To be called after all the calls of delete_type. Each MAIN_TYPE must have ++ either none or all of its TYPE entries deleted. */ ++ ++static void ++delete_type_finish (void) ++{ ++ htab_traverse (deleted_main_types_hash, delete_type_finish_traverse, NULL); ++ ++ htab_delete (deleted_main_types_hash); ++ deleted_main_types_hash = NULL; ++} ++ ++/* Delete TYPE and remember MAIN_TYPE it references. TYPE must have been ++ allocated using xmalloc -- not using an objfile. You must wrap calls of ++ this function by delete_type_begin and delete_type_finish. */ ++ ++static void ++delete_type (struct type *type) ++{ ++ void **slot; ++ ++ if (!type) ++ return; ++ ++ if (TYPE_OBJFILE (type) == OBJFILE_INTERNAL) ++ return; ++ gdb_assert (TYPE_OBJFILE (type) == OBJFILE_MALLOC); ++ ++ slot = htab_find_slot (deleted_main_types_hash, TYPE_MAIN_TYPE (type), ++ INSERT); ++ gdb_assert (!*slot); ++ *slot = TYPE_MAIN_TYPE (type); ++ ++ xfree (type); ++} ++ ++/* Hash function for type_refc_table. */ ++ ++static hashval_t ++type_refc_hash (const void *p) ++{ ++ const struct type_refc_entry *entry = p; ++ return htab_hash_pointer (entry->type); ++} ++ ++/* Equality function for type_refc_table. */ ++ ++static int ++type_refc_equal (const void *a, const void *b) ++{ ++ const struct type_refc_entry *left = a; ++ const struct type_refc_entry *right = b; ++ return left->type == right->type; ++} ++ ++/* Insert the new type NEW_TYPE into the table. Does nothing if ++ NEW_TYPE has an objfile. If PARENT_TYPE is not NULL, then NEW_TYPE ++ will be inserted into the same hierarchy as PARENT_TYPE. In this ++ case, PARENT_TYPE must already exist in the reference count map. ++ If PARENT_TYPE is NULL, a new reference count is allocated and set ++ to one. */ ++ ++static void ++type_init_refc (struct type *new_type, struct type *parent_type) ++{ ++ int *refc; ++ void **slot; ++ struct type_refc_entry *new_entry; ++ ++ if (TYPE_OBJFILE (new_type)) ++ return; ++ ++ if (parent_type) ++ { ++ struct type_refc_entry entry, *found; ++ entry.type = parent_type; ++ found = htab_find (type_refc_table, &entry); ++ gdb_assert (found); ++ refc = found->refc; ++ } ++ else ++ { ++ refc = xmalloc (sizeof (int)); ++ *refc = 0; ++ } ++ ++ new_entry = XNEW (struct type_refc_entry); ++ new_entry->type = new_type; ++ new_entry->refc = refc; ++ ++ slot = htab_find_slot (type_refc_table, new_entry, INSERT); ++ gdb_assert (!*slot); ++ *slot = new_entry; ++} ++ ++/* Increment the reference count for TYPE. */ ++ ++void ++type_incref (struct type *type) ++{ ++ struct type_refc_entry entry, *found; ++ ++ if (TYPE_OBJFILE (type)) ++ return; ++ ++ entry.type = type; ++ found = htab_find (type_refc_table, &entry); ++ gdb_assert (found); ++ ++*(found->refc); ++} ++ ++/* A traverse callback for type_refc_table which removes any entry ++ whose reference count is zero (unused entry). */ ++ ++static int ++type_refc_remove (void **slot, void *unused) ++{ ++ struct type_refc_entry *entry = *slot; ++ ++ if (*entry->refc == 0) ++ { ++ delete_type (entry->type); ++ ++ xfree (entry); ++ htab_clear_slot (type_refc_table, slot); ++ } ++ ++ return 1; ++} ++ ++/* Decrement the reference count for TYPE. Even if TYPE has no more ++ references still do not delete it as callers may hold pointers to types ++ dynamically generated by check_typedef where type_incref is never called. ++ Always rely on the free_all_types garbage collector. */ ++ ++void ++type_decref (struct type *type) ++{ ++ struct type_refc_entry entry, *found; ++ ++ if (TYPE_OBJFILE (type)) ++ return; ++ ++ entry.type = type; ++ found = htab_find (type_refc_table, &entry); ++ gdb_assert (found); ++ gdb_assert (found->refc > 0); ++ --*(found->refc); ++} ++ ++/* Free all the types that have been allocated and that are not used according ++ to type_refc_entry->refc. Called after each command, successful or not. ++ Use this cleanup only in the GDB idle state as GDB code does not necessarily ++ use type_incref / type_decref during temporary use of types. */ ++ ++void ++free_all_types (void) ++{ ++ delete_type_begin (); ++ htab_traverse (type_refc_table, type_refc_remove, NULL); ++ delete_type_finish (); ++} ++ + static struct type * + build_flt (int bit, char *name, const struct floatformat **floatformats) + { +@@ -3105,7 +3602,7 @@ build_complex (int bit, char *name, struct type *target_type) + return builtin_type_error; + } + t = init_type (TYPE_CODE_COMPLEX, 2 * bit / TARGET_CHAR_BIT, +- 0, name, (struct objfile *) NULL); ++ 0, name, OBJFILE_INTERNAL); + TYPE_TARGET_TYPE (t) = target_type; + return t; + } +@@ -3119,56 +3616,56 @@ gdbtypes_post_init (struct gdbarch *gdbarch) + builtin_type->builtin_void = + init_type (TYPE_CODE_VOID, 1, + 0, +- "void", (struct objfile *) NULL); ++ "void", OBJFILE_INTERNAL); + builtin_type->builtin_char = + init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + (TYPE_FLAG_NOSIGN + | (gdbarch_char_signed (gdbarch) ? 0 : TYPE_FLAG_UNSIGNED)), +- "char", (struct objfile *) NULL); ++ "char", OBJFILE_INTERNAL); + builtin_type->builtin_signed_char = + init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "signed char", (struct objfile *) NULL); ++ "signed char", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_char = + init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, +- "unsigned char", (struct objfile *) NULL); ++ "unsigned char", OBJFILE_INTERNAL); + builtin_type->builtin_short = + init_type (TYPE_CODE_INT, + gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "short", (struct objfile *) NULL); ++ 0, "short", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_short = + init_type (TYPE_CODE_INT, + gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned short", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_int = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "int", (struct objfile *) NULL); ++ 0, "int", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_int = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned int", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_long = + init_type (TYPE_CODE_INT, + gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "long", (struct objfile *) NULL); ++ 0, "long", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_long = + init_type (TYPE_CODE_INT, + gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_long_long = + init_type (TYPE_CODE_INT, + gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "long long", (struct objfile *) NULL); ++ 0, "long long", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_long_long = + init_type (TYPE_CODE_INT, + gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long long", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_float + = build_flt (gdbarch_float_bit (gdbarch), "float", + gdbarch_float_format (gdbarch)); +@@ -3187,26 +3684,26 @@ gdbtypes_post_init (struct gdbarch *gdbarch) + builtin_type->builtin_string = + init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "string", (struct objfile *) NULL); ++ "string", OBJFILE_INTERNAL); + builtin_type->builtin_bool = + init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "bool", (struct objfile *) NULL); ++ "bool", OBJFILE_INTERNAL); + + /* The following three are about decimal floating point types, which + are 32-bits, 64-bits and 128-bits respectively. */ + builtin_type->builtin_decfloat + = init_type (TYPE_CODE_DECFLOAT, 32 / 8, + 0, +- "_Decimal32", (struct objfile *) NULL); ++ "_Decimal32", OBJFILE_INTERNAL); + builtin_type->builtin_decdouble + = init_type (TYPE_CODE_DECFLOAT, 64 / 8, + 0, +- "_Decimal64", (struct objfile *) NULL); ++ "_Decimal64", OBJFILE_INTERNAL); + builtin_type->builtin_declong + = init_type (TYPE_CODE_DECFLOAT, 128 / 8, + 0, +- "_Decimal128", (struct objfile *) NULL); ++ "_Decimal128", OBJFILE_INTERNAL); + + /* Pointer/Address types. */ + +@@ -3245,27 +3742,28 @@ gdbtypes_post_init (struct gdbarch *gdbarch) + init_type (TYPE_CODE_INT, + gdbarch_addr_bit (gdbarch) / 8, + TYPE_FLAG_UNSIGNED, +- "__CORE_ADDR", (struct objfile *) NULL); ++ "__CORE_ADDR", OBJFILE_INTERNAL); + + + /* The following set of types is used for symbols with no + debug information. */ + builtin_type->nodebug_text_symbol = + init_type (TYPE_CODE_FUNC, 1, 0, +- "", NULL); ++ "", OBJFILE_INTERNAL); + TYPE_TARGET_TYPE (builtin_type->nodebug_text_symbol) = + builtin_type->builtin_int; + builtin_type->nodebug_data_symbol = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, +- "", NULL); ++ "", OBJFILE_INTERNAL); + builtin_type->nodebug_unknown_symbol = + init_type (TYPE_CODE_INT, 1, 0, +- "", NULL); ++ "", ++ OBJFILE_INTERNAL); + builtin_type->nodebug_tls_symbol = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, +- "", NULL); ++ "", OBJFILE_INTERNAL); + + return builtin_type; + } +@@ -3276,6 +3774,9 @@ _initialize_gdbtypes (void) + { + gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init); + ++ type_refc_table = htab_create_alloc (20, type_refc_hash, type_refc_equal, ++ NULL, xcalloc, xfree); ++ + /* FIXME: The following types are architecture-neutral. However, + they contain pointer_type and reference_type fields potentially + caching pointer or reference types that *are* architecture +@@ -3284,47 +3785,47 @@ _initialize_gdbtypes (void) + builtin_type_int0 = + init_type (TYPE_CODE_INT, 0 / 8, + 0, +- "int0_t", (struct objfile *) NULL); ++ "int0_t", OBJFILE_INTERNAL); + builtin_type_int8 = + init_type (TYPE_CODE_INT, 8 / 8, + TYPE_FLAG_NOTTEXT, +- "int8_t", (struct objfile *) NULL); ++ "int8_t", OBJFILE_INTERNAL); + builtin_type_uint8 = + init_type (TYPE_CODE_INT, 8 / 8, + TYPE_FLAG_UNSIGNED | TYPE_FLAG_NOTTEXT, +- "uint8_t", (struct objfile *) NULL); ++ "uint8_t", OBJFILE_INTERNAL); + builtin_type_int16 = + init_type (TYPE_CODE_INT, 16 / 8, + 0, +- "int16_t", (struct objfile *) NULL); ++ "int16_t", OBJFILE_INTERNAL); + builtin_type_uint16 = + init_type (TYPE_CODE_INT, 16 / 8, + TYPE_FLAG_UNSIGNED, +- "uint16_t", (struct objfile *) NULL); ++ "uint16_t", OBJFILE_INTERNAL); + builtin_type_int32 = + init_type (TYPE_CODE_INT, 32 / 8, + 0, +- "int32_t", (struct objfile *) NULL); ++ "int32_t", OBJFILE_INTERNAL); + builtin_type_uint32 = + init_type (TYPE_CODE_INT, 32 / 8, + TYPE_FLAG_UNSIGNED, +- "uint32_t", (struct objfile *) NULL); ++ "uint32_t", OBJFILE_INTERNAL); + builtin_type_int64 = + init_type (TYPE_CODE_INT, 64 / 8, + 0, +- "int64_t", (struct objfile *) NULL); ++ "int64_t", OBJFILE_INTERNAL); + builtin_type_uint64 = + init_type (TYPE_CODE_INT, 64 / 8, + TYPE_FLAG_UNSIGNED, +- "uint64_t", (struct objfile *) NULL); ++ "uint64_t", OBJFILE_INTERNAL); + builtin_type_int128 = + init_type (TYPE_CODE_INT, 128 / 8, + 0, +- "int128_t", (struct objfile *) NULL); ++ "int128_t", OBJFILE_INTERNAL); + builtin_type_uint128 = + init_type (TYPE_CODE_INT, 128 / 8, + TYPE_FLAG_UNSIGNED, +- "uint128_t", (struct objfile *) NULL); ++ "uint128_t", OBJFILE_INTERNAL); + + builtin_type_ieee_single = + build_flt (-1, "builtin_type_ieee_single", floatformats_ieee_single); +@@ -3344,15 +3845,15 @@ _initialize_gdbtypes (void) + builtin_type_void = + init_type (TYPE_CODE_VOID, 1, + 0, +- "void", (struct objfile *) NULL); ++ "void", OBJFILE_INTERNAL); + builtin_type_true_char = + init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "true character", (struct objfile *) NULL); ++ "true character", OBJFILE_INTERNAL); + builtin_type_true_unsigned_char = + init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, +- "true character", (struct objfile *) NULL); ++ "true character", OBJFILE_INTERNAL); + + add_setshow_zinteger_cmd ("overload", no_class, &overload_debug, _("\ + Set debugging of C++ overloading."), _("\ +diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h +index c90b6d7..077b89c 100644 +--- a/gdb/gdbtypes.h ++++ b/gdb/gdbtypes.h +@@ -134,7 +134,10 @@ enum type_code + + TYPE_CODE_NAMESPACE, /* C++ namespace. */ + +- TYPE_CODE_DECFLOAT /* Decimal floating point. */ ++ TYPE_CODE_DECFLOAT, /* Decimal floating point. */ ++ ++ /* Internal function type. */ ++ TYPE_CODE_INTERNAL_FUNCTION + }; + + /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an +@@ -209,6 +212,11 @@ enum type_instance_flag_value + + #define TYPE_TARGET_STUB(t) (TYPE_MAIN_TYPE (t)->flag_target_stub) + ++/* Type needs to be evaluated on each CHECK_TYPEDEF and its results must not be ++ sticky. */ ++ ++#define TYPE_DYNAMIC(t) (TYPE_MAIN_TYPE (t)->flag_dynamic) ++ + /* Static type. If this is set, the corresponding type had + * a static modifier. + * Note: This may be unnecessary, since static data members +@@ -266,6 +274,36 @@ enum type_instance_flag_value + + #define TYPE_NOTTEXT(t) (TYPE_MAIN_TYPE (t)->flag_nottext) + ++/* Is HIGH_BOUND a low-bound relative count (1) or the high bound itself (0)? */ ++ ++#define TYPE_RANGE_HIGH_BOUND_IS_COUNT(range_type) \ ++ (TYPE_MAIN_TYPE (range_type)->flag_range_high_bound_is_count) ++ ++/* Not allocated. TYPE_ALLOCATED(t) must be NULL in such case. If this flag ++ is unset and TYPE_ALLOCATED(t) is NULL then the type is allocated. If this ++ flag is unset and TYPE_ALLOCATED(t) is not NULL then its DWARF block ++ determines the actual allocation state. */ ++ ++#define TYPE_NOT_ALLOCATED(t) (TYPE_MAIN_TYPE (t)->flag_not_allocated) ++ ++/* Not associated. TYPE_ASSOCIATED(t) must be NULL in such case. If this flag ++ is unset and TYPE_ASSOCIATED(t) is NULL then the type is associated. If ++ this flag is unset and TYPE_ASSOCIATED(t) is not NULL then its DWARF block ++ determines the actual association state. */ ++ ++#define TYPE_NOT_ASSOCIATED(t) (TYPE_MAIN_TYPE (t)->flag_not_associated) ++ ++/* Address of the actual data as for DW_AT_data_location. Its dwarf block must ++ not be evaluated unless both TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are ++ false. If TYPE_DATA_LOCATION_IS_ADDR set then TYPE_DATA_LOCATION_ADDR value ++ is the actual data address value. If unset and ++ TYPE_DATA_LOCATION_DWARF_BLOCK is NULL then the value is the normal ++ VALUE_ADDRESS copy. If unset and TYPE_DATA_LOCATION_DWARF_BLOCK is not NULL ++ then its DWARF block determines the actual data address. */ ++ ++#define TYPE_DATA_LOCATION_IS_ADDR(t) \ ++ (TYPE_MAIN_TYPE (t)->flag_data_location_is_addr) ++ + /* Constant type. If this is set, the corresponding type has a + * const modifier. + */ +@@ -352,6 +390,11 @@ struct main_type + unsigned int flag_stub_supported : 1; + unsigned int flag_nottext : 1; + unsigned int flag_fixed_instance : 1; ++ unsigned int flag_dynamic : 1; ++ unsigned int flag_range_high_bound_is_count : 1; ++ unsigned int flag_not_allocated : 1; ++ unsigned int flag_not_associated : 1; ++ unsigned int flag_data_location_is_addr : 1; + + /* Number of fields described for this type. This field appears at + this location because it packs nicely here. */ +@@ -414,6 +457,20 @@ struct main_type + + struct type *target_type; + ++ /* For DW_AT_data_location. */ ++ union ++ { ++ struct dwarf2_locexpr_baton *dwarf_block; ++ CORE_ADDR addr; ++ } ++ data_location; ++ ++ /* For DW_AT_allocated. */ ++ struct dwarf2_locexpr_baton *allocated; ++ ++ /* For DW_AT_associated. */ ++ struct dwarf2_locexpr_baton *associated; ++ + /* For structure and union types, a description of each field. + For set and pascal array types, there is one "field", + whose type is the domain type of the set or array. +@@ -795,9 +852,9 @@ extern void allocate_cplus_struct_type (struct type *); + #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type + #define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type + #define TYPE_CHAIN(thistype) (thistype)->chain +-/* Note that if thistype is a TYPEDEF type, you have to call check_typedef. +- But check_typedef does set the TYPE_LENGTH of the TYPEDEF type, +- so you only have to call check_typedef once. Since allocate_value ++/* Note that if thistype is a TYPEDEF, ARRAY or STRING type, you have to call ++ check_typedef. But check_typedef does set the TYPE_LENGTH of the TYPEDEF ++ type, so you only have to call check_typedef once. Since allocate_value + calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */ + #define TYPE_LENGTH(thistype) (thistype)->length + #define TYPE_OBJFILE(thistype) TYPE_MAIN_TYPE(thistype)->objfile +@@ -807,23 +864,44 @@ extern void allocate_cplus_struct_type (struct type *); + #define TYPE_NFIELDS(thistype) TYPE_MAIN_TYPE(thistype)->nfields + #define TYPE_FIELDS(thistype) TYPE_MAIN_TYPE(thistype)->fields + #define TYPE_TEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->template_args ++#define TYPE_DATA_LOCATION_DWARF_BLOCK(thistype) TYPE_MAIN_TYPE (thistype)->data_location.dwarf_block ++#define TYPE_DATA_LOCATION_ADDR(thistype) TYPE_MAIN_TYPE (thistype)->data_location.addr ++#define TYPE_ALLOCATED(thistype) TYPE_MAIN_TYPE (thistype)->allocated ++#define TYPE_ASSOCIATED(thistype) TYPE_MAIN_TYPE (thistype)->associated + + #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0) + #define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0) + #define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1) +- +-/* Moto-specific stuff for FORTRAN arrays */ +- +-#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \ +- (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),1)) ++#define TYPE_BYTE_STRIDE(range_type) TYPE_FIELD_BITPOS (range_type, 2) ++ ++/* Whether we should use TYPE_FIELD_DWARF_BLOCK (and not TYPE_FIELD_BITPOS). */ ++#define TYPE_RANGE_BOUND_IS_DWARF_BLOCK(range_type, fieldno) \ ++ (TYPE_FIELD_LOC_KIND (range_type, fieldno) == FIELD_LOC_KIND_DWARF_BLOCK) ++#define TYPE_RANGE_BOUND_SET_DWARF_BLOCK(range_type, fieldno) \ ++ (TYPE_FIELD_LOC_KIND (range_type, fieldno) = FIELD_LOC_KIND_DWARF_BLOCK) ++#define TYPE_ARRAY_BOUND_IS_DWARF_BLOCK(array_type, fieldno) \ ++ TYPE_RANGE_BOUND_IS_DWARF_BLOCK (TYPE_INDEX_TYPE (array_type), fieldno) ++ ++/* Unbound arrays, such as GCC array[]; at end of struct. */ ++#define TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED(rangetype) \ ++ TYPE_FIELD_ARTIFICIAL((rangetype),0) ++#define TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED(rangetype) \ ++ TYPE_FIELD_ARTIFICIAL((rangetype),1) + #define TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED(arraytype) \ +- (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),0)) +- +-#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \ +- (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE((arraytype)))) ++ TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype)) ++#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \ ++ TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype)) + + #define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \ +- (TYPE_LOW_BOUND(TYPE_INDEX_TYPE((arraytype)))) ++ TYPE_LOW_BOUND (TYPE_INDEX_TYPE (arraytype)) ++#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \ ++ TYPE_HIGH_BOUND (TYPE_INDEX_TYPE (arraytype)) ++/* TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) with a fallback to the ++ element size if no specific stride value is known. */ ++#define TYPE_ARRAY_BYTE_STRIDE_VALUE(arraytype) \ ++ (TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) == 0 \ ++ ? TYPE_LENGTH (TYPE_TARGET_TYPE (arraytype)) \ ++ : TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype))) + + /* C++ */ + +@@ -1078,6 +1156,16 @@ extern struct type *builtin_type_error; + (TYPE_UNSIGNED(t) ? UMIN_OF_SIZE(TYPE_LENGTH(t)) \ + : MIN_OF_SIZE(TYPE_LENGTH(t))) + ++/* Virtual OBJFILE used for builtin types. */ ++#define OBJFILE_INTERNAL ((struct objfile *) 1L) ++ ++/* Virtual OBJFILE used for types allocated by malloc. FIXME: Currently ++ backward compatible with the old NULL value; fix then also init_type. */ ++#define OBJFILE_MALLOC ((struct objfile *) 0L) ++ ++#define OBJFILE_IS_VIRTUAL(objfile) ((objfile) == OBJFILE_INTERNAL \ ++ || (objfile) == OBJFILE_MALLOC) ++ + /* Allocate space for storing data associated with a particular type. + We ensure that the space is allocated using the same mechanism that + was used to allocate the space for the type structure itself. I.E. +@@ -1087,18 +1175,18 @@ extern struct type *builtin_type_error; + builtin types), then the data space will be allocated with xmalloc, + the same as for the type structure. */ + +-#define TYPE_ALLOC(t,size) \ +- (TYPE_OBJFILE (t) != NULL \ +- ? obstack_alloc (&TYPE_OBJFILE (t) -> objfile_obstack, size) \ +- : xmalloc (size)) ++#define TYPE_ALLOC(t,size) \ ++ (OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (t)) \ ++ ? xmalloc (size) \ ++ : obstack_alloc (&TYPE_OBJFILE (t) -> objfile_obstack, size)) + +-#define TYPE_ZALLOC(t,size) \ +- (TYPE_OBJFILE (t) != NULL \ +- ? memset (obstack_alloc (&TYPE_OBJFILE (t)->objfile_obstack, size), \ +- 0, size) \ +- : xzalloc (size)) ++#define TYPE_ZALLOC(t,size) \ ++ (OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (t)) \ ++ ? xzalloc (size) \ ++ : memset (obstack_alloc (&TYPE_OBJFILE (t)->objfile_obstack, size), \ ++ 0, size)) + +-extern struct type *alloc_type (struct objfile *); ++extern struct type *alloc_type (struct objfile *, struct type *); + + extern struct type *init_type (enum type_code, int, int, char *, + struct objfile *); +@@ -1172,6 +1260,18 @@ extern struct type *create_range_type (struct type *, struct type *, int, + extern struct type *create_array_type (struct type *, struct type *, + struct type *); + ++extern CORE_ADDR type_range_any_field_internal (struct type *range_type, ++ int fieldno); ++ ++extern int type_range_high_bound_internal (struct type *range_type); ++ ++extern int type_range_count_bound_internal (struct type *range_type); ++ ++extern CORE_ADDR type_range_byte_stride_internal (struct type *range_type, ++ struct type *element_type); ++ ++extern void finalize_type (struct type *type); ++ + extern struct type *create_string_type (struct type *, struct type *); + + extern struct type *create_set_type (struct type *, struct type *); +@@ -1263,10 +1363,15 @@ extern void maintenance_print_type (char *, int); + + extern htab_t create_copied_types_hash (struct objfile *objfile); + +-extern struct type *copy_type_recursive (struct objfile *objfile, +- struct type *type, ++extern struct type *copy_type_recursive (struct type *type, + htab_t copied_types); + + extern struct type *copy_type (const struct type *type); + ++extern void type_incref (struct type *type); ++ ++extern void type_decref (struct type *type); ++ ++extern void free_all_types (void); ++ + #endif /* GDBTYPES_H */ +diff --git a/gdb/gnu-v2-abi.c b/gdb/gnu-v2-abi.c +index 7cacac1..a456228 100644 +--- a/gdb/gnu-v2-abi.c ++++ b/gdb/gnu-v2-abi.c +@@ -242,7 +242,7 @@ gnuv2_value_rtti_type (struct value *v, int *full, int *top, int *using_enc) + we'd waste a bunch of time figuring out we already know the type. + Besides, we don't care about the type, just the actual pointer + */ +- if (VALUE_ADDRESS (value_field (v, known_type_vptr_fieldno)) == 0) ++ if (value_address (value_field (v, known_type_vptr_fieldno)) == 0) + return NULL; + + vtbl = value_as_address (value_field (v, known_type_vptr_fieldno)); +diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c +index 3a52df3..6cdf716 100644 +--- a/gdb/gnu-v3-abi.c ++++ b/gdb/gnu-v3-abi.c +@@ -269,8 +269,7 @@ gnuv3_rtti_type (struct value *value, + + /* Find the linker symbol for this vtable. */ + vtable_symbol +- = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtable) +- + value_offset (vtable) ++ = lookup_minimal_symbol_by_pc (value_address (vtable) + + value_embedded_offset (vtable)); + if (! vtable_symbol) + return NULL; +@@ -487,10 +486,8 @@ gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset, + LONGEST adjustment) + { + int i; +- const char *physname; + + /* Search this class first. */ +- physname = NULL; + if (adjustment == 0) + { + int len; +@@ -615,13 +612,15 @@ gnuv3_print_method_ptr (const gdb_byte *contents, + { + char *demangled_name = cplus_demangle (physname, + DMGL_ANSI | DMGL_PARAMS); +- if (demangled_name != NULL) ++ fprintf_filtered (stream, "&virtual "); ++ if (demangled_name == NULL) ++ fputs_filtered (physname, stream); ++ else + { +- fprintf_filtered (stream, "&virtual "); + fputs_filtered (demangled_name, stream); + xfree (demangled_name); +- return; + } ++ return; + } + } + +diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c +index 2366474..f83de32 100644 +--- a/gdb/i386-linux-nat.c ++++ b/gdb/i386-linux-nat.c +@@ -751,7 +751,13 @@ i386_linux_resume (struct target_ops *ops, + { + int pid = PIDGET (ptid); + +- int request = PTRACE_CONT; ++ int request; ++ ++ if (target_passed_by_entrypoint () > 0 ++ && catch_syscall_enabled () > 0) ++ request = PTRACE_SYSCALL; ++ else ++ request = PTRACE_CONT; + + if (step) + { +diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c +index 1a2e4f0..973eced 100644 +--- a/gdb/i386-linux-tdep.c ++++ b/gdb/i386-linux-tdep.c +@@ -37,6 +37,10 @@ + #include "symtab.h" + #include "arch-utils.h" + #include "regset.h" ++#include "linux-tdep.h" ++ ++/* The syscall's XML filename for i386. */ ++#define XML_SYSCALL_FILENAME_I386 "syscalls/i386-linux.xml" + + /* Supported register note sections. */ + static struct core_regset_section i386_linux_regset_sections[] = +@@ -349,6 +353,26 @@ i386_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) + } + + ++static LONGEST ++i386_linux_get_syscall_number (struct gdbarch *gdbarch, ++ ptid_t ptid) ++{ ++ struct regcache *regcache = get_thread_regcache (ptid); ++ /* The content of a register. */ ++ gdb_byte buf[4]; ++ /* The result. */ ++ LONGEST ret; ++ ++ /* Getting the system call number from the register. ++ When dealing with x86 architecture, this information ++ is stored at %eax register. */ ++ regcache_cooked_read (regcache, I386_LINUX_ORIG_EAX_REGNUM, buf); ++ ++ ret = extract_signed_integer (buf, 4); ++ ++ return ret; ++} ++ + /* The register sets used in GNU/Linux ELF core-dumps are identical to + the register sets in `struct user' that are used for a.out + core-dumps. These are also used by ptrace(2). The corresponding +@@ -419,6 +443,9 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + ++ /* Initializing common functions. */ ++ linux_tdep_init (gdbarch); ++ + /* GNU/Linux uses ELF. */ + i386_elf_init_abi (info, gdbarch); + +@@ -472,6 +499,11 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + displaced_step_at_entry_point); + + set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); ++ ++ /* Functions for 'catch syscall'. */ ++ set_gdbarch_xml_syscall_filename (gdbarch, XML_SYSCALL_FILENAME_I386); ++ set_gdbarch_get_syscall_number (gdbarch, ++ i386_linux_get_syscall_number); + } + + /* Provide a prototype to silence -Wmissing-prototypes. */ +diff --git a/gdb/inf-child.c b/gdb/inf-child.c +index 38311f1..fc968cf 100644 +--- a/gdb/inf-child.c ++++ b/gdb/inf-child.c +@@ -148,6 +148,15 @@ inf_child_remove_exec_catchpoint (int pid) + } + + static int ++inf_child_set_syscall_catchpoint (int pid, int needed, int any_count, ++ int table_size, int *table) ++{ ++ /* This version of Unix doesn't support notification of syscall ++ events. */ ++ return 0; ++} ++ ++static int + inf_child_can_run (void) + { + return 1; +@@ -190,6 +199,7 @@ inf_child_target (void) + t->to_follow_fork = inf_child_follow_fork; + t->to_insert_exec_catchpoint = inf_child_insert_exec_catchpoint; + t->to_remove_exec_catchpoint = inf_child_remove_exec_catchpoint; ++ t->to_set_syscall_catchpoint = inf_child_set_syscall_catchpoint; + t->to_can_run = inf_child_can_run; + t->to_pid_to_exec_file = inf_child_pid_to_exec_file; + t->to_stratum = process_stratum; +diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c +index f40b6b7..ff429c4 100644 +--- a/gdb/inf-ptrace.c ++++ b/gdb/inf-ptrace.c +@@ -356,13 +356,19 @@ inf_ptrace_resume (struct target_ops *ops, + ptid_t ptid, int step, enum target_signal signal) + { + pid_t pid = ptid_get_pid (ptid); +- int request = PT_CONTINUE; ++ int request; + + if (pid == -1) + /* Resume all threads. Traditionally ptrace() only supports + single-threaded processes, so simply resume the inferior. */ + pid = ptid_get_pid (inferior_ptid); + ++ if (target_passed_by_entrypoint () > 0 ++ && catch_syscall_enabled () > 0) ++ request = PT_SYSCALL; ++ else ++ request = PT_CONTINUE; ++ + if (step) + { + /* If this system does not support PT_STEP, a higher level +diff --git a/gdb/infcall.c b/gdb/infcall.c +index d6da8b2..80168b3 100644 +--- a/gdb/infcall.c ++++ b/gdb/infcall.c +@@ -98,6 +98,28 @@ Unwinding of stack if a signal is received while in a call dummy is %s.\n"), + value); + } + ++/* This boolean tells what gdb should do if a std::terminate call is ++ made while in a function called from gdb (call dummy). ++ As the confines of a single dummy stack prohibit out-of-frame ++ handlers from handling a raised exception, and as out-of-frame ++ handlers are common in C++, this can lead to no handler being found ++ by the unwinder, and a std::terminate call. This is a false positive. ++ If set, gdb unwinds the stack and restores the context to what it ++ was before the call. ++ ++ The default is to unwind the frame if a std::terminate call is made.. */ ++ ++static int unwind_on_terminating_exception_p = 1; ++static void ++show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty, ++ struct cmd_list_element *c, ++ const char *value) ++ ++{ ++ fprintf_filtered (file, _("\ ++Unwind stack if a C++ exception is unhandled while in a call dummy is %s.\n"), ++ value); ++} + + /* Perform the standard coercions that are specified + for arguments to be passed to C or Ada functions. +@@ -217,7 +239,7 @@ find_function_addr (struct value *function, struct type **retval_type) + /* Determine address to call. */ + if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD) + { +- funaddr = VALUE_ADDRESS (function); ++ funaddr = value_address (function); + value_type = TYPE_TARGET_TYPE (ftype); + } + else if (code == TYPE_CODE_PTR) +@@ -419,6 +441,8 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) + struct cleanup *args_cleanup; + struct frame_info *frame; + struct gdbarch *gdbarch; ++ struct breakpoint *terminate_bp = 0; ++ struct minimal_symbol *tm; + ptid_t call_thread_ptid; + struct gdb_exception e; + const char *name; +@@ -718,6 +742,29 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) + bpt = set_momentary_breakpoint (sal, dummy_id, bp_call_dummy); + bpt->disposition = disp_del; + } ++ ++ /* Create a breakpoint in std::terminate. ++ If a C++ exception is raised in the dummy-frame, and the ++ exception handler is (normally, and expected to be) out-of-frame, ++ the default C++ handler will (wrongly) be called in an inferior ++ function call. This is wrong, as an exception can be normally ++ and legally handled out-of-frame. The confines of the dummy frame ++ prevent the unwinder from finding the correct handler (or any ++ handler, unless it is in-frame). The default handler calls ++ std::terminate. This will kill the inferior. Assert that ++ terminate should never be called in an inferior function ++ call. Place a momentary breakpoint in the std::terminate function ++ and if triggered in the call, rewind */ ++ if (unwind_on_terminating_exception_p) ++ { ++ tm = lookup_minimal_symbol ("std::terminate()", NULL, NULL); ++ if (tm != NULL) ++ { ++ terminate_bp = set_momentary_breakpoint_at_pc ++ (SYMBOL_VALUE_ADDRESS (tm), bp_breakpoint); ++ make_cleanup_delete_breakpoint (terminate_bp); ++ } ++ } + + /* Everything's ready, push all the info needed to restore the + caller (and identify the dummy-frame) onto the dummy-frame +@@ -828,6 +875,16 @@ When the function is done executing, GDB will silently stop."), + name); + } + ++ if (! target_has_execution) ++ { ++ /* If we try to restore the inferior status (via the cleanup), ++ we'll crash as the inferior is no longer running. */ ++ discard_cleanups (inf_status_cleanup); ++ discard_inferior_status (inf_status); ++ error (_("\ ++The program being debugged exited while in a function called from GDB.")); ++ } ++ + if (stopped_by_random_signal || !stop_stack_dummy) + { + const char *name = get_function_name (funaddr, +@@ -884,6 +941,38 @@ When the function is done executing, GDB will silently stop."), + + if (!stop_stack_dummy) + { ++ ++ /* Check if unwind on terminating exception behaviour is on */ ++ if (unwind_on_terminating_exception_p) ++ { ++ /* Check that the breakpoint is our special std::terminate ++ breakpoint. If it is, we do not want to kill the inferior ++ in an inferior function call. Rewind, and warn the user */ ++ ++ if ((terminate_bp != NULL) && ++ (inferior_thread()->stop_bpstat->breakpoint_at->address ++ == terminate_bp->loc->address)) ++ ++ ++ { ++ ++ /* We must get back to the frame we were before the ++ dummy call. */ ++ dummy_frame_pop (dummy_id); ++ ++ /* We also need to restore inferior status to that before the ++ dummy call. */ ++ restore_inferior_status (inf_status); ++ ++ error (_("\ ++The program being debugged entered a std::terminate call which would\n\ ++have terminated the program being debugged. GDB has restored the\n\ ++context to what it was before the call\n\ ++To change this behaviour use \"set unwind-on-terminating-exception off\"\n\ ++Evaluation of the expression containing the function (%s) will be abandoned."), ++ name); ++ } ++ } + /* We hit a breakpoint inside the FUNCTION. + Keep the dummy frame, the user may want to examine its state. + Discard inferior status, we're not at the same point +@@ -992,4 +1081,19 @@ The default is to stop in the frame where the signal was received."), + NULL, + show_unwind_on_signal_p, + &setlist, &showlist); ++ ++ add_setshow_boolean_cmd ("unwind-on-terminating-exception", no_class, ++ &unwind_on_terminating_exception_p, _("\ ++Set unwinding of stack if a std::terminate() call originates from\n\ ++the default C++ exception handler."), _("\ ++Show unwinding of stack if a std::terminate() call originates from\n\ ++the default C++ exception handler."), _("\ ++The unwind on terminating exception flag lets the user determine\n\ ++what gdb should do if a std::terminate() call is made from the\n\ ++default exception handler.\n\ ++The default is to unwind the frame."), ++ NULL, ++ show_unwind_on_terminating_exception_p, ++ &setlist, &showlist); ++ + } +diff --git a/gdb/infcmd.c b/gdb/infcmd.c +index 0a17dab..d48f4b1 100644 +--- a/gdb/infcmd.c ++++ b/gdb/infcmd.c +@@ -466,6 +466,11 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) + init_wait_for_inferior (); + clear_breakpoint_hit_counts (); + ++ /* If we already caught a syscall catchpoint, then reset its ++ syscall_number information because we are starting all over ++ again. */ ++ clear_syscall_catchpoints_info (); ++ + /* Clean up any leftovers from other runs. Some other things from + this function should probably be moved into target_pre_inferior. */ + target_pre_inferior (from_tty); +diff --git a/gdb/infrun.c b/gdb/infrun.c +index ee5f987..2f627ea 100644 +--- a/gdb/infrun.c ++++ b/gdb/infrun.c +@@ -1046,7 +1046,7 @@ a command like `return' or `jump' to continue execution.")); + } + } + +- /* If there were any forks/vforks/execs that were caught and are ++ /* If there were any forks/vforks/execs/syscalls that were caught and are + now to be followed, then do so. */ + switch (pending_follow.kind) + { +@@ -1069,6 +1069,11 @@ a command like `return' or `jump' to continue execution.")); + pending_follow.kind = TARGET_WAITKIND_SPURIOUS; + break; + ++ case TARGET_WAITKIND_SYSCALL_ENTRY: ++ case TARGET_WAITKIND_SYSCALL_RETURN: ++ pending_follow.kind = TARGET_WAITKIND_SPURIOUS; ++ break; ++ + default: + break; + } +@@ -1509,7 +1514,7 @@ init_wait_for_inferior (void) + + breakpoint_init_inferior (inf_starting); + +- /* The first resume is not following a fork/vfork/exec. */ ++ /* The first resume is not following a fork/vfork/exec/syscall. */ + pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */ + + clear_proceed_status (); +@@ -2155,6 +2160,50 @@ ensure_not_running (void) + error_is_running (); + } + ++/* Auxiliary function that handles syscall entry/return events. ++ It returns 1 if the inferior should keep going (and GDB ++ should ignore the event), or 0 if the event deserves to be ++ processed. */ ++static int ++deal_with_syscall_event (struct execution_control_state *ecs) ++{ ++ int syscall_number = gdbarch_get_syscall_number (current_gdbarch, ++ ecs->ptid); ++ if (catch_syscall_enabled () > 0 ++ && catching_syscall_number (syscall_number) > 0) ++ { ++ ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP; ++ pending_follow.kind = ecs->ws.kind; ++ ++ if (!ptid_equal (ecs->ptid, inferior_ptid)) ++ { ++ context_switch (ecs->ptid); ++ reinit_frame_cache (); ++ } ++ ++ stop_pc = read_pc (); ++ ++ ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid); ++ ++ ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat); ++ ++ /* If no catchpoint triggered for this, then keep going. */ ++ if (ecs->random_signal) ++ { ++ ecs->event_thread->stop_signal = TARGET_SIGNAL_0; ++ keep_going (ecs); ++ return 1; ++ } ++ return 0; ++ } ++ else ++ { ++ resume (0, TARGET_SIGNAL_0); ++ prepare_to_wait (ecs); ++ return 1; ++ } ++} ++ + /* Given an execution control state that has been freshly filled in + by an event from the inferior, figure out what it means and take + appropriate action. */ +@@ -2449,9 +2498,11 @@ handle_inferior_event (struct execution_control_state *ecs) + case TARGET_WAITKIND_SYSCALL_ENTRY: + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n"); +- resume (0, TARGET_SIGNAL_0); +- prepare_to_wait (ecs); +- return; ++ /* Getting the current syscall number */ ++ if (deal_with_syscall_event (ecs) != 0) ++ return; ++ goto process_event_stop_test; ++ break; + + /* Before examining the threads further, step this thread to + get it entirely out of the syscall. (We get notice of the +@@ -2461,9 +2512,10 @@ handle_inferior_event (struct execution_control_state *ecs) + case TARGET_WAITKIND_SYSCALL_RETURN: + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n"); +- target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); +- prepare_to_wait (ecs); +- return; ++ if (deal_with_syscall_event (ecs) != 0) ++ return; ++ goto process_event_stop_test; ++ break; + + case TARGET_WAITKIND_STOPPED: + if (debug_infrun) +@@ -5166,6 +5218,25 @@ inferior_has_execd (ptid_t pid, char **execd_pathname) + return 1; + } + ++int ++inferior_has_called_syscall (ptid_t pid, int *syscall_number) ++{ ++ struct target_waitstatus last; ++ ptid_t last_ptid; ++ ++ get_last_target_status (&last_ptid, &last); ++ ++ if (last.kind != TARGET_WAITKIND_SYSCALL_ENTRY && ++ last.kind != TARGET_WAITKIND_SYSCALL_RETURN) ++ return 0; ++ ++ if (!ptid_equal (last_ptid, pid)) ++ return 0; ++ ++ *syscall_number = last.value.syscall_number; ++ return 1; ++} ++ + /* Oft used ptids */ + ptid_t null_ptid; + ptid_t minus_one_ptid; +diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c +index b702ebf..a211adf 100644 +--- a/gdb/jv-lang.c ++++ b/gdb/jv-lang.c +@@ -61,7 +61,8 @@ static char *get_java_utf8_name (struct obstack *obstack, struct value *name); + static int java_class_is_primitive (struct value *clas); + static struct value *java_value_string (char *ptr, int len); + +-static void java_emit_char (int c, struct ui_file * stream, int quoter); ++static void java_emit_char (int c, struct type *type, ++ struct ui_file * stream, int quoter); + + static char *java_class_name_from_physname (const char *physname); + +@@ -210,8 +211,7 @@ get_java_utf8_name (struct obstack *obstack, struct value *name) + CORE_ADDR data_addr; + temp = value_struct_elt (&temp, NULL, "length", NULL, "structure"); + name_length = (int) value_as_long (temp); +- data_addr = VALUE_ADDRESS (temp) + value_offset (temp) +- + TYPE_LENGTH (value_type (temp)); ++ data_addr = value_address (temp) + TYPE_LENGTH (value_type (temp)); + chrs = obstack_alloc (obstack, name_length + 1); + chrs[name_length] = '\0'; + read_memory (data_addr, (gdb_byte *) chrs, name_length); +@@ -266,7 +266,7 @@ type_from_class (struct value *clas) + return NULL; + clas = value_ind (clas); + } +- addr = VALUE_ADDRESS (clas) + value_offset (clas); ++ addr = value_address (clas); + + #if 0 + get_java_class_symtab (); +@@ -302,7 +302,7 @@ type_from_class (struct value *clas) + if (type != NULL) + return type; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (type); + +@@ -422,7 +422,7 @@ java_link_class_type (struct type *type, struct value *clas) + fields = NULL; + nfields--; /* First set up dummy "class" field. */ + SET_FIELD_PHYSADDR (TYPE_FIELD (type, nfields), +- VALUE_ADDRESS (clas) + value_offset (clas)); ++ value_address (clas)); + TYPE_FIELD_NAME (type, nfields) = "class"; + TYPE_FIELD_TYPE (type, nfields) = value_type (clas); + SET_TYPE_FIELD_PRIVATE (type, nfields); +@@ -439,7 +439,9 @@ java_link_class_type (struct type *type, struct value *clas) + } + else + { /* Re-use field value for next field. */ +- VALUE_ADDRESS (field) += TYPE_LENGTH (value_type (field)); ++ CORE_ADDR addr ++ = value_address (field) + TYPE_LENGTH (value_type (field)); ++ set_value_address (field, addr); + set_value_lazy (field, 1); + } + temp = field; +@@ -509,7 +511,9 @@ java_link_class_type (struct type *type, struct value *clas) + } + else + { /* Re-use method value for next method. */ +- VALUE_ADDRESS (method) += TYPE_LENGTH (value_type (method)); ++ CORE_ADDR addr ++ = value_address (method) + TYPE_LENGTH (value_type (method)); ++ set_value_address (method, addr); + set_value_lazy (method, 1); + } + +@@ -796,7 +800,7 @@ java_value_string (char *ptr, int len) + characters and strings is language specific. */ + + static void +-java_emit_char (int c, struct ui_file *stream, int quoter) ++java_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) + { + switch (c) + { +diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c +index d3606fd..cdcb440 100644 +--- a/gdb/jv-valprint.c ++++ b/gdb/jv-valprint.c +@@ -45,7 +45,7 @@ java_value_print (struct value *val, struct ui_file *stream, + struct value_print_options opts; + + type = value_type (val); +- address = VALUE_ADDRESS (val) + value_offset (val); ++ address = value_address (val); + + if (is_object_type (type)) + { +@@ -143,8 +143,8 @@ java_value_print (struct value *val, struct ui_file *stream, + struct value *v = allocate_value (el_type); + struct value *next_v = allocate_value (el_type); + +- VALUE_ADDRESS (v) = address + JAVA_OBJECT_SIZE + 4; +- VALUE_ADDRESS (next_v) = VALUE_ADDRESS (v); ++ set_value_address (v, address + JAVA_OBJECT_SIZE + 4); ++ set_value_address (next_v, value_raw_address (v)); + + while (i < length && things_printed < options->print_max) + { +@@ -230,7 +230,7 @@ java_value_print (struct value *val, struct ui_file *stream, + + value_free_to_mark (mark); /* Release unnecessary values */ + +- val_print_string (data + boffset, count, 2, stream, options); ++ val_print_string (java_char_type, data + boffset, count, stream, options); + + return 0; + } +@@ -520,7 +520,7 @@ java_val_print (struct type *type, const gdb_byte *valaddr, + || (TYPE_CODE (type) == TYPE_CODE_INT + && TYPE_LENGTH (type) == 2 + && strcmp (TYPE_NAME (type), "char") == 0)) +- LA_PRINT_CHAR ((int) unpack_long (type, valaddr), stream); ++ LA_PRINT_CHAR ((int) unpack_long (type, valaddr), type, stream); + else + val_print_type_code_int (type, valaddr, stream); + break; +diff --git a/gdb/language.c b/gdb/language.c +index 3c37a64..6209d7f 100644 +--- a/gdb/language.c ++++ b/gdb/language.c +@@ -65,9 +65,11 @@ static void set_check (char *, int); + + static void set_type_range_case (void); + +-static void unk_lang_emit_char (int c, struct ui_file *stream, int quoter); ++static void unk_lang_emit_char (int c, struct type *type, ++ struct ui_file *stream, int quoter); + +-static void unk_lang_printchar (int c, struct ui_file *stream); ++static void unk_lang_printchar (int c, struct type *type, ++ struct ui_file *stream); + + static void unk_lang_print_type (struct type *, char *, struct ui_file *, + int, int); +@@ -1065,20 +1067,22 @@ unk_lang_error (char *msg) + } + + static void +-unk_lang_emit_char (int c, struct ui_file *stream, int quoter) ++unk_lang_emit_char (int c, struct type *type, struct ui_file *stream, ++ int quoter) + { + error (_("internal error - unimplemented function unk_lang_emit_char called.")); + } + + static void +-unk_lang_printchar (int c, struct ui_file *stream) ++unk_lang_printchar (int c, struct type *type, struct ui_file *stream) + { + error (_("internal error - unimplemented function unk_lang_printchar called.")); + } + + static void +-unk_lang_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++unk_lang_printstr (struct ui_file *stream, struct type *type, ++ const gdb_byte *string, unsigned int length, ++ int force_ellipses, + const struct value_print_options *options) + { + error (_("internal error - unimplemented function unk_lang_printstr called.")); +diff --git a/gdb/language.h b/gdb/language.h +index 85826fd..e5f80ab 100644 +--- a/gdb/language.h ++++ b/gdb/language.h +@@ -186,14 +186,15 @@ struct language_defn + + void (*la_post_parser) (struct expression ** expp, int void_context_p); + +- void (*la_printchar) (int ch, struct ui_file * stream); ++ void (*la_printchar) (int ch, struct type *chtype, struct ui_file * stream); + +- void (*la_printstr) (struct ui_file * stream, const gdb_byte *string, +- unsigned int length, int width, ++ void (*la_printstr) (struct ui_file * stream, struct type *elttype, ++ const gdb_byte *string, unsigned int length, + int force_ellipses, + const struct value_print_options *); + +- void (*la_emitchar) (int ch, struct ui_file * stream, int quoter); ++ void (*la_emitchar) (int ch, struct type *chtype, ++ struct ui_file * stream, int quoter); + + /* Print a type using syntax appropriate for this language. */ + +@@ -381,13 +382,13 @@ extern enum language set_language (enum language); + #define LA_VALUE_PRINT(val,stream,options) \ + (current_language->la_value_print(val,stream,options)) + +-#define LA_PRINT_CHAR(ch, stream) \ +- (current_language->la_printchar(ch, stream)) +-#define LA_PRINT_STRING(stream, string, length, width, force_ellipses,options) \ +- (current_language->la_printstr(stream, string, length, width, \ ++#define LA_PRINT_CHAR(ch, type, stream) \ ++ (current_language->la_printchar(ch, type, stream)) ++#define LA_PRINT_STRING(stream, elttype, string, length, force_ellipses,options) \ ++ (current_language->la_printstr(stream, elttype, string, length, \ + force_ellipses,options)) +-#define LA_EMIT_CHAR(ch, stream, quoter) \ +- (current_language->la_emitchar(ch, stream, quoter)) ++#define LA_EMIT_CHAR(ch, type, stream, quoter) \ ++ (current_language->la_emitchar(ch, type, stream, quoter)) + #define LA_GET_STRING(value, buffer, length, encoding) \ + (current_language->la_get_string(value, buffer, length, encoding)) + +diff --git a/gdb/linespec.c b/gdb/linespec.c +index 6579d42..b3ae6c0 100644 +--- a/gdb/linespec.c ++++ b/gdb/linespec.c +@@ -842,13 +842,33 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab, + } + else if (paren_pointer != NULL) + { +- p = paren_pointer + 1; ++ /* We need to deal with method and function overloads ++ with no parameters. Gdb and gcc (and who knows about other ++ compilers) are very inconsistent with the keyword "void". ++ Canonicalizing C++ types is insufficient in this case, since ++ we still need to enforce the presence (or lack thereof) of ++ "void". For simplicity, omit the keyword "void" if present. */ ++ if (strncmp (paren_pointer - 5, "(void)", 6) == 0) ++ { ++ char *a, *b; ++ a = paren_pointer - 4; ++ b = paren_pointer; ++ while ((*(a++) = *(b++)) != '\0') ; ++ *a = '\0'; ++ p = paren_pointer - 3; ++ } ++ else ++ p = paren_pointer + 1; + } + else + { + p = skip_quoted (*argptr); + } + ++ /* Make sure we keep important kewords like "const" */ ++ if (strncmp (p, " const", 6) == 0) ++ p += 6; ++ + copy = (char *) alloca (p - *argptr + 1); + memcpy (copy, *argptr, p - *argptr); + copy[p - *argptr] = '\0'; +diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c +index 12b786e..e30bf9a 100644 +--- a/gdb/linux-nat.c ++++ b/gdb/linux-nat.c +@@ -61,6 +61,10 @@ + # endif + #endif /* HAVE_PERSONALITY */ + ++/* To be used when one needs to know wether a ++ WSTOPSIG (status) is a syscall */ ++#define TRAP_IS_SYSCALL (SIGTRAP | 0x80) ++ + /* This comment documents high-level logic of this file. + + Waiting for events in sync mode +@@ -281,17 +285,29 @@ struct simple_pid_list *stopped_pids; + + static int linux_supports_tracefork_flag = -1; + ++/* This variable is a tri-state flag: -1 for unknown, 0 if PTRACE_O_TRACESYSGOOD ++ can not be used, 1 if it can. */ ++ ++static int linux_supports_tracesysgood_flag = -1; ++ + /* If we have PTRACE_O_TRACEFORK, this flag indicates whether we also have + PTRACE_O_TRACEVFORKDONE. */ + + static int linux_supports_tracevforkdone_flag = -1; + ++/* If the inferior have passed through its entrypoint (AT_ENTRY), ++ then this flag is set to 1. Otherwise, its value is 0. */ ++static int linux_passed_by_entrypoint_flag = 0; ++ + /* Async mode support */ + + /* Zero if the async mode, although enabled, is masked, which means + linux_nat_wait should behave as if async mode was off. */ + static int linux_nat_async_mask_value = 1; + ++/* Stores the current used ptrace() options. */ ++static int current_ptrace_options = 0; ++ + /* The read/write ends of the pipe registered as waitable file in the + event loop. */ + static int linux_nat_event_pipe[2] = { -1, -1 }; +@@ -636,6 +652,41 @@ linux_test_for_tracefork (int original_pid) + linux_nat_async_events (async_events_original_state); + } + ++/* Determine if PTRACE_O_TRACESYSGOOD can be used to follow syscalls. ++ ++ We try to enable syscall tracing on ORIGINAL_PID. If this fails, ++ we know that the feature is not available. This may change the tracing ++ options for ORIGINAL_PID, but we'll be setting them shortly anyway. */ ++ ++static void ++linux_test_for_tracesysgood (int original_pid) ++{ ++ int ret; ++ enum sigchld_state async_events_original_state; ++ ++ async_events_original_state = linux_nat_async_events (sigchld_sync); ++ ++ linux_supports_tracesysgood_flag = 0; ++ ++ ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD); ++ if (ret != 0) ++ return; ++ ++ linux_supports_tracesysgood_flag = 1; ++ linux_nat_async_events (async_events_original_state); ++} ++ ++/* Determine wether we support PTRACE_O_TRACESYSGOOD option available. ++ This function also sets linux_supports_tracesysgood_flag. */ ++ ++static int ++linux_supports_tracesysgood (int pid) ++{ ++ if (linux_supports_tracesysgood_flag == -1) ++ linux_test_for_tracesysgood (pid); ++ return linux_supports_tracesysgood_flag; ++} ++ + /* Return non-zero iff we have tracefork functionality available. + This function also sets linux_supports_tracefork_flag. */ + +@@ -655,12 +706,34 @@ linux_supports_tracevforkdone (int pid) + return linux_supports_tracevforkdone_flag; + } + ++static void ++linux_enable_tracesysgood (ptid_t ptid) ++{ ++ int pid = ptid_get_lwp (ptid); ++ ++ if (pid == 0) ++ pid = ptid_get_pid (ptid); ++ ++ if (linux_supports_tracesysgood (pid) == 0) ++ return; ++ ++ current_ptrace_options |= PTRACE_O_TRACESYSGOOD; ++ linux_passed_by_entrypoint_flag = 1; ++ ++ ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options); ++} ++ ++static int ++linux_passed_by_entrypoint (void) ++{ ++ return linux_passed_by_entrypoint_flag; ++} ++ + + void + linux_enable_event_reporting (ptid_t ptid) + { + int pid = ptid_get_lwp (ptid); +- int options; + + if (pid == 0) + pid = ptid_get_pid (ptid); +@@ -668,15 +741,16 @@ linux_enable_event_reporting (ptid_t ptid) + if (! linux_supports_tracefork (pid)) + return; + +- options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC +- | PTRACE_O_TRACECLONE; ++ current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK ++ | PTRACE_O_TRACEEXEC | PTRACE_O_TRACECLONE; ++ + if (linux_supports_tracevforkdone (pid)) +- options |= PTRACE_O_TRACEVFORKDONE; ++ current_ptrace_options |= PTRACE_O_TRACEVFORKDONE; + + /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support + read-only process state. */ + +- ptrace (PTRACE_SETOPTIONS, pid, 0, options); ++ ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options); + } + + static void +@@ -684,6 +758,7 @@ linux_child_post_attach (int pid) + { + linux_enable_event_reporting (pid_to_ptid (pid)); + check_for_thread_db (); ++ linux_enable_tracesysgood (pid_to_ptid (pid)); + } + + static void +@@ -691,6 +766,7 @@ linux_child_post_startup_inferior (ptid_t ptid) + { + linux_enable_event_reporting (ptid); + check_for_thread_db (); ++ linux_enable_tracesysgood (ptid); + } + + static int +@@ -931,6 +1007,16 @@ linux_child_insert_exec_catchpoint (int pid) + error (_("Your system does not support exec catchpoints.")); + } + ++static int ++linux_child_set_syscall_catchpoint (int pid, int needed, int any_count, ++ int table_size, int *table) ++{ ++ if (! linux_supports_tracesysgood (pid)) ++ error (_("Your system does not support syscall catchpoints.")); ++ /* We ignore the arguments. */ ++ return 0; ++} ++ + /* On GNU/Linux there are no real LWP's. The closest thing to LWP's + are processes sharing the same VM space. A multi-threaded process + is basically a group of such processes. However, such a grouping +@@ -1352,6 +1438,9 @@ linux_nat_create_inferior (struct target_ops *ops, + int personality_orig = 0, personality_set = 0; + #endif /* HAVE_PERSONALITY */ + ++ /* We are sarting, so we still have not passed through our entrypoint. */ ++ linux_passed_by_entrypoint_flag = 0; ++ + /* The fork_child mechanism is synchronous and calls target_wait, so + we have to mask the async mode. */ + +@@ -1996,6 +2085,26 @@ linux_handle_extended_wait (struct lwp_info *lp, int status, + return 0; + } + ++ /* Used for 'catch syscall' feature. */ ++ if (WSTOPSIG (status) == TRAP_IS_SYSCALL) ++ { ++ if (catch_syscall_enabled () == 0) ++ ourstatus->kind = TARGET_WAITKIND_IGNORE; ++ else ++ { ++ struct regcache *regcache = get_thread_regcache (lp->ptid); ++ struct gdbarch *gdbarch = get_regcache_arch (regcache); ++ ++ ourstatus->kind = ++ (lp->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY) ? ++ TARGET_WAITKIND_SYSCALL_RETURN : TARGET_WAITKIND_SYSCALL_ENTRY; ++ lp->syscall_state = ourstatus->kind; ++ ourstatus->value.syscall_number = ++ (int) gdbarch_get_syscall_number (gdbarch, lp->ptid); ++ } ++ return 0; ++ } ++ + internal_error (__FILE__, __LINE__, + _("unknown ptrace event %d"), event); + } +@@ -2606,11 +2715,16 @@ linux_nat_filter_event (int lwpid, int status, int options) + } + + /* Save the trap's siginfo in case we need it later. */ +- if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP) ++ if (WIFSTOPPED (status) ++ && (WSTOPSIG (status) == SIGTRAP || WSTOPSIG (status) == TRAP_IS_SYSCALL)) + save_siginfo (lp); + +- /* Handle GNU/Linux's extended waitstatus for trace events. */ +- if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0) ++ /* Handle GNU/Linux's extended waitstatus for trace events. ++ It is necessary to check if WSTOPSIG is signaling a that ++ the inferior is entering/exiting a system call. */ ++ if (WIFSTOPPED (status) ++ && ((WSTOPSIG (status) == TRAP_IS_SYSCALL) ++ || (WSTOPSIG (status) == SIGTRAP && status >> 16 != 0))) + { + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, +@@ -4262,12 +4376,14 @@ linux_target_install_ops (struct target_ops *t) + t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint; + t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint; + t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint; ++ t->to_set_syscall_catchpoint = linux_child_set_syscall_catchpoint; + t->to_pid_to_exec_file = linux_child_pid_to_exec_file; + t->to_post_startup_inferior = linux_child_post_startup_inferior; + t->to_post_attach = linux_child_post_attach; + t->to_follow_fork = linux_child_follow_fork; + t->to_find_memory_regions = linux_nat_find_memory_regions; + t->to_make_corefile_notes = linux_nat_make_corefile_notes; ++ t->to_passed_by_entrypoint = linux_passed_by_entrypoint; + + super_xfer_partial = t->to_xfer_partial; + t->to_xfer_partial = linux_xfer_partial; +diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h +index fec5139..36d2439 100644 +--- a/gdb/linux-nat.h ++++ b/gdb/linux-nat.h +@@ -70,6 +70,13 @@ struct lwp_info + or to a local variable in lin_lwp_wait. */ + struct target_waitstatus waitstatus; + ++ /* Signal wether we are in a SYSCALL_ENTRY or ++ in a SYSCALL_RETURN event. ++ Values: ++ - TARGET_WAITKIND_SYSCALL_ENTRY ++ - TARGET_WAITKIND_SYSCALL_RETURN */ ++ int syscall_state; ++ + /* Next LWP in list. */ + struct lwp_info *next; + }; +diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c +index e18e134..d44b505 100644 +--- a/gdb/linux-tdep.c ++++ b/gdb/linux-tdep.c +@@ -20,6 +20,8 @@ + #include "defs.h" + #include "gdbtypes.h" + #include "linux-tdep.h" ++#include "xml-syscall.h" ++#include "target.h" + + /* This function is suitable for architectures that don't + extend/override the standard siginfo structure. */ +@@ -137,3 +139,81 @@ linux_get_siginfo_type (struct gdbarch *gdbarch) + + return siginfo_type; + } ++ ++/* Structure used to store information about the available syscalls in ++ the system. */ ++static const struct syscalls_info *sysinfo = NULL; ++ ++/* A flag to tell if we already initialized the structure above. */ ++static int have_initialized_sysinfo = 0; ++ ++/* The filename of the syscall's XML. */ ++static const char *xml_syscall_file = NULL; ++ ++/* Initializes the syscalls_info structure according to the ++ architecture. */ ++static void ++init_sysinfo (struct gdbarch *gdbarch) ++{ ++ /* Did we already try to initialize the structure? */ ++ if (have_initialized_sysinfo) ++ return; ++ ++ if (xml_syscall_file == NULL) ++ xml_syscall_file = gdbarch_xml_syscall_filename (gdbarch); ++ ++ sysinfo = xml_init_syscalls_info (xml_syscall_file); ++ ++ have_initialized_sysinfo = 1; ++ ++ if (sysinfo == NULL) ++ { ++ if (xml_syscall_file) ++ /* The initialization failed. Let's show a warning ++ message to the user (just this time) and leave. */ ++ warning (_("Could not load the syscall XML file '%s'.\n\ ++GDB will not be able to display syscall names."), xml_syscall_file); ++ else ++ /* There's no file to open. Let's warn the user. */ ++ warning (_("There is no XML file to open.\n\ ++GDB will not be able to display syscall names.")); ++ } ++} ++ ++static void ++linux_get_syscall_by_number (struct gdbarch *gdbarch, ++ int syscall_number, ++ struct syscall *s) ++{ ++ init_sysinfo (gdbarch); ++ ++ s->number = syscall_number; ++ s->name = xml_get_syscall_name (sysinfo, syscall_number); ++} ++ ++static void ++linux_get_syscall_by_name (struct gdbarch *gdbarch, ++ const char *syscall_name, ++ struct syscall *s) ++{ ++ init_sysinfo (gdbarch); ++ ++ s->number = xml_get_syscall_number (sysinfo, syscall_name); ++ s->name = syscall_name; ++} ++ ++static const char ** ++linux_get_syscall_names (struct gdbarch *gdbarch) ++{ ++ init_sysinfo (gdbarch); ++ ++ return xml_list_of_syscalls (sysinfo); ++} ++ ++void ++linux_tdep_init (struct gdbarch *gdbarch) ++{ ++ set_gdbarch_get_syscall_by_number (gdbarch, linux_get_syscall_by_number); ++ set_gdbarch_get_syscall_by_name (gdbarch, linux_get_syscall_by_name); ++ set_gdbarch_get_syscall_names (gdbarch, linux_get_syscall_names); ++} +diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h +index 50af511..1e1e541 100644 +--- a/gdb/linux-tdep.h ++++ b/gdb/linux-tdep.h +@@ -22,4 +22,6 @@ + + struct type *linux_get_siginfo_type (struct gdbarch *); + ++extern void linux_tdep_init (struct gdbarch *gdbarch); ++ + #endif /* linux-tdep.h */ +diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c +index 9e4bb1b..9ca3ae1 100644 +--- a/gdb/m2-lang.c ++++ b/gdb/m2-lang.c +@@ -29,8 +29,8 @@ + #include "valprint.h" + + extern void _initialize_m2_language (void); +-static void m2_printchar (int, struct ui_file *); +-static void m2_emit_char (int, struct ui_file *, int); ++static void m2_printchar (int, struct type *, struct ui_file *); ++static void m2_emit_char (int, struct type *, struct ui_file *, int); + + /* Print the character C on STREAM as part of the contents of a literal + string whose delimiter is QUOTER. Note that that format for printing +@@ -39,7 +39,7 @@ static void m2_emit_char (int, struct ui_file *, int); + be replaced with a true Modula version. */ + + static void +-m2_emit_char (int c, struct ui_file *stream, int quoter) ++m2_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) + { + + c &= 0xFF; /* Avoid sign bit follies */ +@@ -88,10 +88,10 @@ m2_emit_char (int c, struct ui_file *stream, int quoter) + be replaced with a true Modula version. */ + + static void +-m2_printchar (int c, struct ui_file *stream) ++m2_printchar (int c, struct type *type, struct ui_file *stream) + { + fputs_filtered ("'", stream); +- LA_EMIT_CHAR (c, stream, '\''); ++ LA_EMIT_CHAR (c, type, stream, '\''); + fputs_filtered ("'", stream); + } + +@@ -103,14 +103,15 @@ m2_printchar (int c, struct ui_file *stream) + be replaced with a true Modula version. */ + + static void +-m2_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++m2_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, ++ unsigned int length, int force_ellipses, + const struct value_print_options *options) + { + unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; ++ int width = TYPE_LENGTH (type); + + if (length == 0) + { +@@ -152,7 +153,7 @@ m2_printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("\", ", stream); + in_quotes = 0; + } +- m2_printchar (string[i], stream); ++ m2_printchar (string[i], type, stream); + fprintf_filtered (stream, " ", reps); + i = rep1 - 1; + things_printed += options->repeat_count_threshold; +@@ -168,7 +169,7 @@ m2_printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("\"", stream); + in_quotes = 1; + } +- LA_EMIT_CHAR (string[i], stream, '"'); ++ LA_EMIT_CHAR (string[i], type, stream, '"'); + ++things_printed; + } + } +diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c +index 71c410c..41fb8fe 100644 +--- a/gdb/m2-valprint.c ++++ b/gdb/m2-valprint.c +@@ -237,7 +237,8 @@ print_unpacked_pointer (struct type *type, + && TYPE_CODE (elttype) == TYPE_CODE_INT + && (options->format == 0 || options->format == 's') + && addr != 0) +- return val_print_string (addr, -1, TYPE_LENGTH (elttype), stream, options); ++ return val_print_string (TYPE_TARGET_TYPE (type), addr, -1, ++ stream, options); + + return 0; + } +@@ -294,7 +295,7 @@ m2_print_array_contents (struct type *type, const gdb_byte *valaddr, + || ((current_language->la_language == language_m2) + && (TYPE_CODE (type) == TYPE_CODE_CHAR))) + && (options->format == 0 || options->format == 's')) +- val_print_string (address, len+1, eltlen, stream, options); ++ val_print_string (type, address, len+1, stream, options); + else + { + fprintf_filtered (stream, "{"); +@@ -359,7 +360,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + len = temp_len; + } + +- LA_PRINT_STRING (stream, valaddr + embedded_offset, len, 1, 0, ++ LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type), ++ valaddr + embedded_offset, len, 0, + options); + i = len; + } +@@ -547,7 +549,7 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + else + fprintf_filtered (stream, "%d", (int) val); + fputs_filtered (" ", stream); +- LA_PRINT_CHAR ((unsigned char) val, stream); ++ LA_PRINT_CHAR ((unsigned char) val, type, stream); + } + break; + +diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c +index 5f4b9a6..eccfe31 100644 +--- a/gdb/m32r-tdep.c ++++ b/gdb/m32r-tdep.c +@@ -713,7 +713,7 @@ m32r_push_dummy_call (struct gdbarch *gdbarch, struct value *function, + if (len > 8 + && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) + { +- store_unsigned_integer (valbuf, 4, VALUE_ADDRESS (args[argnum])); ++ store_unsigned_integer (valbuf, 4, value_address (args[argnum])); + typecode = TYPE_CODE_PTR; + len = 4; + val = valbuf; +diff --git a/gdb/macroexp.c b/gdb/macroexp.c +index f0a8c1f..752a939 100644 +--- a/gdb/macroexp.c ++++ b/gdb/macroexp.c +@@ -23,6 +23,7 @@ + #include "macrotab.h" + #include "macroexp.h" + #include "gdb_assert.h" ++#include "c-lang.h" + + + +@@ -320,14 +321,17 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end) + way GDB's C/C++ lexer does. So we call parse_escape in utils.c + to handle escape sequences. */ + if ((p + 1 <= end && *p == '\'') +- || (p + 2 <= end && p[0] == 'L' && p[1] == '\'')) ++ || (p + 2 <= end ++ && (p[0] == 'L' || p[0] == 'u' || p[0] == 'U') ++ && p[1] == '\'')) + { + char *tok_start = p; + char *body_start; ++ int char_count = 0; + + if (*p == '\'') + p++; +- else if (*p == 'L') ++ else if (*p == 'L' || *p == 'u' || *p == 'U') + p += 2; + else + gdb_assert (0); +@@ -339,7 +343,7 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end) + error (_("Unmatched single quote.")); + else if (*p == '\'') + { +- if (p == body_start) ++ if (!char_count) + error (_("A character constant must contain at least one " + "character.")); + p++; +@@ -348,10 +352,13 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end) + else if (*p == '\\') + { + p++; +- parse_escape (&p); ++ char_count += c_parse_escape (&p, NULL); + } + else +- p++; ++ { ++ p++; ++ char_count++; ++ } + } + + set_token (tok, tok_start, p); +@@ -370,16 +377,16 @@ static int + get_string_literal (struct macro_buffer *tok, char *p, char *end) + { + if ((p + 1 <= end +- && *p == '\"') ++ && *p == '"') + || (p + 2 <= end +- && p[0] == 'L' +- && p[1] == '\"')) ++ && (p[0] == 'L' || p[0] == 'u' || p[0] == 'U') ++ && p[1] == '"')) + { + char *tok_start = p; + +- if (*p == '\"') ++ if (*p == '"') + p++; +- else if (*p == 'L') ++ else if (*p == 'L' || *p == 'u' || *p == 'U') + p += 2; + else + gdb_assert (0); +@@ -388,7 +395,7 @@ get_string_literal (struct macro_buffer *tok, char *p, char *end) + { + if (p >= end) + error (_("Unterminated string in expression.")); +- else if (*p == '\"') ++ else if (*p == '"') + { + p++; + break; +@@ -399,7 +406,7 @@ get_string_literal (struct macro_buffer *tok, char *p, char *end) + else if (*p == '\\') + { + p++; +- parse_escape (&p); ++ c_parse_escape (&p, NULL); + } + else + p++; +diff --git a/gdb/main.c b/gdb/main.c +index 5d4640b..6f9e61b 100644 +--- a/gdb/main.c ++++ b/gdb/main.c +@@ -40,6 +40,8 @@ + #include "interps.h" + #include "main.h" + ++#include "python/python.h" ++ + /* If nonzero, display time usage both at startup and for each command. */ + + int display_time; +@@ -62,6 +64,9 @@ int dbx_commands = 0; + /* System root path, used to find libraries etc. */ + char *gdb_sysroot = 0; + ++/* GDB datadir, used to store data files. */ ++char *gdb_datadir = 0; ++ + struct ui_file *gdb_stdout; + struct ui_file *gdb_stderr; + struct ui_file *gdb_stdlog; +@@ -211,6 +216,8 @@ captured_main (void *data) + char *cdarg = NULL; + char *ttyarg = NULL; + ++ int python_script = 0; ++ + /* These are static so that we can take their address in an initializer. */ + static int print_help; + static int print_version; +@@ -357,6 +364,40 @@ captured_main (void *data) + } + } + ++#ifdef GDB_DATADIR_RELOCATABLE ++ gdb_datadir = make_relative_prefix (argv[0], BINDIR, GDB_DATADIR); ++ if (gdb_datadir) ++ { ++ struct stat s; ++ int res = 0; ++ ++ if (stat (gdb_datadir, &s) == 0) ++ if (S_ISDIR (s.st_mode)) ++ res = 1; ++ ++ if (res == 0) ++ { ++ xfree (gdb_datadir); ++ gdb_datadir = xstrdup (GDB_DATADIR); ++ } ++ } ++ else ++ gdb_datadir = xstrdup (GDB_DATADIR); ++#else ++ gdb_datadir = xstrdup (GDB_DATADIR); ++#endif /* GDB_DATADIR_RELOCATABLE */ ++ ++ /* Canonicalize the GDB's datadir path. */ ++ if (*gdb_datadir) ++ { ++ char *canon_debug = lrealpath (gdb_datadir); ++ if (canon_debug) ++ { ++ xfree (gdb_datadir); ++ gdb_datadir = canon_debug; ++ } ++ } ++ + get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit); + + /* There will always be an interpreter. Either the one passed into +@@ -441,10 +482,14 @@ captured_main (void *data) + {"args", no_argument, &set_args, 1}, + {"l", required_argument, 0, 'l'}, + {"return-child-result", no_argument, &return_child_result, 1}, ++#if HAVE_PYTHON ++ {"python", no_argument, 0, 'P'}, ++ {"P", no_argument, 0, 'P'}, ++#endif + {0, no_argument, 0, 0} + }; + +- while (1) ++ while (!python_script) + { + int option_index; + +@@ -462,6 +507,9 @@ captured_main (void *data) + case 0: + /* Long option that just sets a flag. */ + break; ++ case 'P': ++ python_script = 1; ++ break; + case OPT_SE: + symarg = optarg; + execarg = optarg; +@@ -638,7 +686,31 @@ extern int gdbtk_test (char *); + use_windows = 0; + } + +- if (set_args) ++ if (python_script) ++ { ++ /* The first argument is a python script to evaluate, and ++ subsequent arguments are passed to the script for ++ processing there. */ ++ if (optind >= argc) ++ { ++ fprintf_unfiltered (gdb_stderr, ++ _("%s: Python script file name required\n"), ++ argv[0]); ++ exit (1); ++ } ++ ++ /* FIXME: should handle inferior I/O intelligently here. ++ E.g., should be possible to run gdb in pipeline and have ++ Python (and gdb) output go to stderr or file; and if a ++ prompt is needed, open the tty. */ ++ quiet = 1; ++ /* FIXME: should read .gdbinit if, and only if, a prompt is ++ requested by the script. Though... maybe this is not ++ ideal? */ ++ /* FIXME: likewise, reading in history. */ ++ inhibit_gdbinit = 1; ++ } ++ else if (set_args) + { + /* The remaining options are the command-line options for the + inferior. The first one is the sym/exec file, and the rest +@@ -866,7 +938,8 @@ Can't attach to process and specify a core file at the same time.")); + xfree (cmdarg); + + /* Read in the old history after all the command files have been read. */ +- init_history (); ++ if (!python_script) ++ init_history (); + + if (batch) + { +@@ -895,13 +968,25 @@ Can't attach to process and specify a core file at the same time.")); + #endif + } + +- /* NOTE: cagney/1999-11-07: There is probably no reason for not +- moving this loop and the code found in captured_command_loop() +- into the command_loop() proper. The main thing holding back that +- change - SET_TOP_LEVEL() - has been eliminated. */ +- while (1) ++#if HAVE_PYTHON ++ if (python_script) + { +- catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); ++ extern int pagination_enabled; ++ pagination_enabled = 0; ++ run_python_script (argc - optind, &argv[optind]); ++ return 1; ++ } ++ else ++#endif ++ { ++ /* NOTE: cagney/1999-11-07: There is probably no reason for not ++ moving this loop and the code found in captured_command_loop() ++ into the command_loop() proper. The main thing holding back that ++ change - SET_TOP_LEVEL() - has been eliminated. */ ++ while (1) ++ { ++ catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL); ++ } + } + /* No exit -- exit is through quit_command. */ + } +@@ -933,7 +1018,12 @@ print_gdb_help (struct ui_file *stream) + fputs_unfiltered (_("\ + This is the GNU debugger. Usage:\n\n\ + gdb [options] [executable-file [core-file or process-id]]\n\ +- gdb [options] --args executable-file [inferior-arguments ...]\n\n\ ++ gdb [options] --args executable-file [inferior-arguments ...]\n"), stream); ++#if HAVE_PYTHON ++ fputs_unfiltered (_("\ ++ gdb [options] [--python|-P] script-file [script-arguments ...]\n"), stream); ++#endif ++ fputs_unfiltered (_("\n\ + Options:\n\n\ + "), stream); + fputs_unfiltered (_("\ +@@ -971,7 +1061,13 @@ Options:\n\n\ + --nw Do not use a window interface.\n\ + --nx Do not read "), stream); + fputs_unfiltered (gdbinit, stream); +- fputs_unfiltered (_(" file.\n\ ++ fputs_unfiltered (_(" file.\n"), stream); ++#if HAVE_PYTHON ++ fputs_unfiltered (_("\ ++ --python, -P Following argument is Python script file; remaining\n\ ++ arguments are passed to script.\n"), stream); ++#endif ++ fputs_unfiltered (_("\ + --quiet Do not print version number on startup.\n\ + --readnow Fully read symbol files on first access.\n\ + "), stream); +diff --git a/gdb/maint.c b/gdb/maint.c +index 56cafe9..1b57ff5 100644 +--- a/gdb/maint.c ++++ b/gdb/maint.c +@@ -906,4 +906,12 @@ When enabled GDB is profiled."), + show_maintenance_profile_p, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); ++ add_setshow_filename_cmd ("gdb_datadir", class_maintenance, ++ &gdb_datadir, _("Set GDB's datadir path."), ++ _("Show GDB's datadir path."), ++ _("\ ++When set, GDB uses the specified path to search for data files."), ++ NULL, NULL, ++ &maintenance_set_cmdlist, ++ &maintenance_show_cmdlist); + } +diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c +index 7cbcc59..e507c3b 100644 +--- a/gdb/mdebugread.c ++++ b/gdb/mdebugread.c +@@ -4696,7 +4696,7 @@ new_type (char *name) + { + struct type *t; + +- t = alloc_type (current_objfile); ++ t = alloc_type (current_objfile, NULL); + TYPE_NAME (t) = name; + TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default; + return t; +diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c +index 143074b..0f4efba 100644 +--- a/gdb/mi/mi-cmd-var.c ++++ b/gdb/mi/mi-cmd-var.c +@@ -249,6 +249,41 @@ mi_cmd_var_set_format (char *command, char **argv, int argc) + } + + void ++mi_cmd_var_set_visualizer (char *command, char **argv, int argc) ++{ ++ struct varobj *var; ++ ++ if (argc != 2) ++ error ("Usage: NAME VISUALIZER_FUNCTION."); ++ ++ var = varobj_get_handle (argv[0]); ++ ++ if (var == NULL) ++ error ("Variable object not found"); ++ ++ varobj_set_visualizer (var, argv[1]); ++} ++ ++void ++mi_cmd_var_set_child_range (char *command, char **argv, int argc) ++{ ++ struct varobj *var; ++ int from, to; ++ ++ if (argc != 3) ++ error (_("-var-set-child-range: NAME FROM TO")); ++ ++ var = varobj_get_handle (argv[0]); ++ if (var == NULL) ++ error (_("Variable object not found")); ++ ++ from = atoi (argv[1]); ++ to = atoi (argv[2]); ++ ++ varobj_set_child_range (var, from, to); ++} ++ ++void + mi_cmd_var_set_frozen (char *command, char **argv, int argc) + { + struct varobj *var; +@@ -369,6 +404,8 @@ mi_cmd_var_list_children (char *command, char **argv, int argc) + int numchild; + enum print_values print_values; + int ix; ++ int from, to; ++ char *display_hint; + + if (argc != 1 && argc != 2) + error (_("mi_cmd_var_list_children: Usage: [PRINT_VALUES] NAME")); +@@ -388,14 +425,22 @@ mi_cmd_var_list_children (char *command, char **argv, int argc) + else + print_values = PRINT_NO_VALUES; + +- if (VEC_length (varobj_p, children) == 0) ++ varobj_get_child_range (var, children, &from, &to); ++ if (from >= to) + return; + ++ display_hint = varobj_get_display_hint (var); ++ if (display_hint) ++ { ++ ui_out_field_string (uiout, "displayhint", display_hint); ++ xfree (display_hint); ++ } ++ + if (mi_version (uiout) == 1) + cleanup_children = make_cleanup_ui_out_tuple_begin_end (uiout, "children"); + else + cleanup_children = make_cleanup_ui_out_list_begin_end (uiout, "children"); +- for (ix = 0; VEC_iterate (varobj_p, children, ix, child); ++ix) ++ for (ix = from; ix < to && VEC_iterate (varobj_p, children, ix, child); ++ix) + { + struct cleanup *cleanup_child; + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, "child"); +@@ -662,6 +707,8 @@ varobj_update_one (struct varobj *var, enum print_values print_values, + + for (i = 0; VEC_iterate (varobj_update_result, changes, i, r); ++i) + { ++ char *display_hint; ++ + if (mi_version (uiout) > 1) + cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_string (uiout, "name", varobj_get_objname (r->varobj)); +@@ -695,6 +742,36 @@ varobj_update_one (struct varobj *var, enum print_values print_values, + ui_out_field_int (uiout, "new_num_children", + varobj_get_num_children (r->varobj)); + } ++ ++ display_hint = varobj_get_display_hint (var); ++ if (display_hint) ++ { ++ ui_out_field_string (uiout, "displayhint", display_hint); ++ xfree (display_hint); ++ } ++ ++ if (r->children_changed) ++ { ++ int ix, from, to; ++ struct varobj *child; ++ struct cleanup *cleanup = ++ make_cleanup_ui_out_list_begin_end (uiout, "children"); ++ ++ VEC (varobj_p)* children = varobj_list_children (r->varobj); ++ varobj_get_child_range (r->varobj, children, &from, &to); ++ ++ for (ix = from; ++ ix < to && VEC_iterate (varobj_p, children, ix, child); ++ ++ix) ++ { ++ struct cleanup *cleanup_child; ++ cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ++ print_varobj (child, print_values, 1 /* print expression */); ++ do_cleanups (cleanup_child); ++ } ++ ++ do_cleanups (cleanup); ++ } + + if (mi_version (uiout) > 1) + do_cleanups (cleanup); +diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c +index 2610b6a..f31233b 100644 +--- a/gdb/mi/mi-cmds.c ++++ b/gdb/mi/mi-cmds.c +@@ -160,7 +160,9 @@ struct mi_cmd mi_cmds[] = + { "var-info-num-children", { NULL, 0 }, mi_cmd_var_info_num_children}, + { "var-info-type", { NULL, 0 }, mi_cmd_var_info_type}, + { "var-list-children", { NULL, 0 }, mi_cmd_var_list_children}, ++ { "var-set-child-range", { NULL, 0 }, mi_cmd_var_set_child_range }, + { "var-set-format", { NULL, 0 }, mi_cmd_var_set_format}, ++ { "var-set-visualizer", { NULL, 0 }, mi_cmd_var_set_visualizer}, + { "var-set-frozen", { NULL, 0 }, mi_cmd_var_set_frozen}, + { "var-show-attributes", { NULL, 0 }, mi_cmd_var_show_attributes}, + { "var-show-format", { NULL, 0 }, mi_cmd_var_show_format}, +diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h +index 39f16fb..291a07f 100644 +--- a/gdb/mi/mi-cmds.h ++++ b/gdb/mi/mi-cmds.h +@@ -92,7 +92,9 @@ extern mi_cmd_argv_ftype mi_cmd_var_info_num_children; + extern mi_cmd_argv_ftype mi_cmd_var_info_type; + extern mi_cmd_argv_ftype mi_cmd_var_list_children; + extern mi_cmd_argv_ftype mi_cmd_var_set_format; ++extern mi_cmd_argv_ftype mi_cmd_var_set_child_range; + extern mi_cmd_argv_ftype mi_cmd_var_set_frozen; ++extern mi_cmd_argv_ftype mi_cmd_var_set_visualizer; + extern mi_cmd_argv_ftype mi_cmd_var_show_attributes; + extern mi_cmd_argv_ftype mi_cmd_var_show_format; + extern mi_cmd_argv_ftype mi_cmd_var_update; +diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c +index b905a9e..eaa5f12 100644 +--- a/gdb/mi/mi-main.c ++++ b/gdb/mi/mi-main.c +@@ -777,7 +777,7 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc) + get_user_print_options (&opts); + opts.deref_ref = 0; + val_print (value_type (val), value_contents (val), +- value_embedded_offset (val), VALUE_ADDRESS (val), ++ value_embedded_offset (val), value_address (val), + stb->stream, 0, &opts, current_language); + + ui_out_field_stream (uiout, "value", stb); +@@ -1101,6 +1101,10 @@ mi_cmd_list_features (char *command, char **argv, int argc) + ui_out_field_string (uiout, NULL, "frozen-varobjs"); + ui_out_field_string (uiout, NULL, "pending-breakpoints"); + ui_out_field_string (uiout, NULL, "thread-info"); ++ ++#if HAVE_PYTHON ++ ui_out_field_string (uiout, NULL, "python"); ++#endif + + do_cleanups (cleanup); + return; +@@ -1317,6 +1321,7 @@ mi_cmd_execute (struct mi_parse *parse) + struct cleanup *cleanup; + int i; + free_all_values (); ++ free_all_types (); + + current_token = xstrdup (parse->token); + cleanup = make_cleanup (free_current_contents, ¤t_token); +diff --git a/gdb/minsyms.c b/gdb/minsyms.c +index bf776b3..e4b0f31 100644 +--- a/gdb/minsyms.c ++++ b/gdb/minsyms.c +@@ -48,6 +48,8 @@ + #include "value.h" + #include "cp-abi.h" + #include "target.h" ++#include "cp-support.h" ++#include "language.h" + + /* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE. + At the end, copy them all into one newly allocated location on an objfile's +@@ -187,6 +189,9 @@ lookup_minimal_symbol (const char *name, const char *sfile, + unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE; + unsigned int dem_hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE; + ++ int needtofreename = 0; ++ const char *modified_name; ++ + if (sfile != NULL) + { + char *p = strrchr (sfile, '/'); +@@ -194,6 +199,18 @@ lookup_minimal_symbol (const char *name, const char *sfile, + sfile = p + 1; + } + ++ /* For C++, canonicalize the input name. */ ++ modified_name = name; ++ if (current_language->la_language == language_cplus) ++ { ++ char *cname = cp_canonicalize_string (name); ++ if (cname) ++ { ++ modified_name = cname; ++ needtofreename = 1; ++ } ++ } ++ + for (objfile = object_files; + objfile != NULL && found_symbol == NULL; + objfile = objfile->next) +@@ -218,9 +235,16 @@ lookup_minimal_symbol (const char *name, const char *sfile, + int match; + + if (pass == 1) +- match = strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0; ++ { ++ match = strcmp (SYMBOL_LINKAGE_NAME (msymbol), ++ modified_name) == 0; ++ } + else +- match = SYMBOL_MATCHES_SEARCH_NAME (msymbol, name); ++ { ++ match = SYMBOL_MATCHES_SEARCH_NAME (msymbol, ++ modified_name); ++ } ++ + if (match) + { + switch (MSYMBOL_TYPE (msymbol)) +@@ -259,6 +283,10 @@ lookup_minimal_symbol (const char *name, const char *sfile, + } + } + } ++ ++ if (needtofreename) ++ xfree ((void *) modified_name); ++ + /* External symbols are best. */ + if (found_symbol) + return found_symbol; +diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c +index 6c8c4c0..7d283a4 100644 +--- a/gdb/mips-tdep.c ++++ b/gdb/mips-tdep.c +@@ -2757,7 +2757,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, + if (len > regsize + && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) + { +- store_unsigned_integer (valbuf, regsize, VALUE_ADDRESS (arg)); ++ store_unsigned_integer (valbuf, regsize, value_address (arg)); + typecode = TYPE_CODE_PTR; + len = regsize; + val = valbuf; +diff --git a/gdb/mipsread.c b/gdb/mipsread.c +index a84003f..924c1c5 100644 +--- a/gdb/mipsread.c ++++ b/gdb/mipsread.c +@@ -394,6 +394,7 @@ static struct sym_fns ecoff_sym_fns = + mipscoff_new_init, /* sym_new_init: init anything gbl to entire symtab */ + mipscoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + mipscoff_symfile_read, /* sym_read: read a symbol file into symtab */ ++ NULL, /* sym_read_psymbols */ + mipscoff_symfile_finish, /* sym_finish: finished with file, cleanup */ + default_symfile_offsets, /* sym_offsets: dummy FIXME til implem sym reloc */ + default_symfile_segments, /* sym_segments: Get segment information from +diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c +index f0cea27..02be43a 100644 +--- a/gdb/mn10300-tdep.c ++++ b/gdb/mn10300-tdep.c +@@ -1027,7 +1027,7 @@ mn10300_push_dummy_call (struct gdbarch *gdbarch, + /* Change to pointer-to-type. */ + arg_len = push_size; + store_unsigned_integer (valbuf, push_size, +- VALUE_ADDRESS (*args)); ++ value_address (*args)); + val = &valbuf[0]; + } + else +diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c +index a6c74a3..9b8d801 100644 +--- a/gdb/objc-lang.c ++++ b/gdb/objc-lang.c +@@ -280,7 +280,7 @@ objc_demangle (const char *mangled, int options) + for printing characters and strings is language specific. */ + + static void +-objc_emit_char (int c, struct ui_file *stream, int quoter) ++objc_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) + { + + c &= 0xFF; /* Avoid sign bit follies. */ +@@ -326,10 +326,10 @@ objc_emit_char (int c, struct ui_file *stream, int quoter) + } + + static void +-objc_printchar (int c, struct ui_file *stream) ++objc_printchar (int c, struct type *type, struct ui_file *stream) + { + fputs_filtered ("'", stream); +- objc_emit_char (c, stream, '\''); ++ objc_emit_char (c, type, stream, '\''); + fputs_filtered ("'", stream); + } + +@@ -340,14 +340,16 @@ objc_printchar (int c, struct ui_file *stream) + FORCE_ELLIPSES. */ + + static void +-objc_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++objc_printstr (struct ui_file *stream, struct type *type, ++ const gdb_byte *string, unsigned int length, ++ int force_ellipses, + const struct value_print_options *options) + { + unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; ++ int width = TYPE_LENGTH (type); + + /* If the string was not truncated due to `set print elements', and + the last byte of it is a null, we don't print that, in +@@ -395,7 +397,7 @@ objc_printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("\", ", stream); + in_quotes = 0; + } +- objc_printchar (string[i], stream); ++ objc_printchar (string[i], type, stream); + fprintf_filtered (stream, " ", reps); + i = rep1 - 1; + things_printed += options->repeat_count_threshold; +@@ -411,7 +413,7 @@ objc_printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("\"", stream); + in_quotes = 1; + } +- objc_emit_char (string[i], stream, '"'); ++ objc_emit_char (string[i], type, stream, '"'); + ++things_printed; + } + } +diff --git a/gdb/objfiles.c b/gdb/objfiles.c +index bc77de8..079ebcf 100644 +--- a/gdb/objfiles.c ++++ b/gdb/objfiles.c +@@ -691,6 +691,20 @@ have_partial_symbols (void) + return 1; + } + } ++ ++ /* Try again, after reading partial symbols. We do this in two ++ passes because objfiles are always added to the head of the list, ++ and there might be a later objfile for which we've already read ++ partial symbols. */ ++ ALL_OBJFILES (ofp) ++ { ++ require_partial_symbols (ofp); ++ if (ofp->psymtabs != NULL) ++ { ++ return 1; ++ } ++ } ++ + return 0; + } + +diff --git a/gdb/objfiles.h b/gdb/objfiles.h +index 60d3143..b6fdd92 100644 +--- a/gdb/objfiles.h ++++ b/gdb/objfiles.h +@@ -212,6 +212,11 @@ struct objfile + + struct partial_symtab *psymtabs; + ++ /* An address map that can be used to quickly determine if an ++ address comes from this objfile. This can be NULL. */ ++ ++ struct addrmap *quick_addrmap; ++ + /* Map addresses to the entries of PSYMTABS. It would be more efficient to + have a map per the whole process but ADDRMAP cannot selectively remove + its items during FREE_OBJFILE. This mapping is already present even for +@@ -420,6 +425,15 @@ struct objfile + #define OBJF_KEEPBFD (1 << 4) /* Do not delete bfd */ + + ++/* Set if we have tried to read partial symtabs for this objfile. ++ This is used to allow lazy reading of partial symtabs. */ ++ ++#define OBJF_SYMTABS_READ (1 << 6) ++ ++/* This flag is set for the main objfile. */ ++ ++#define OBJF_MAIN (1 << 7) ++ + /* The object file that the main symbol table was loaded from (e.g. the + argument to the "symbol-file" or "file" command). */ + +@@ -556,6 +570,13 @@ extern void *objfile_data (struct objfile *objfile, + ALL_OBJFILES (objfile) \ + ALL_OBJFILE_PSYMTABS (objfile, p) + ++/* Like ALL_PSYMTABS, but ensure that partial symbols have been read ++ before examining the objfile. */ ++ ++#define ALL_PSYMTABS_REQUIRED(objfile, p) \ ++ ALL_OBJFILES (objfile) \ ++ ALL_OBJFILE_PSYMTABS (require_partial_symbols (objfile), p) ++ + /* Traverse all minimal symbols in all objfiles. */ + + #define ALL_MSYMBOLS(objfile, m) \ +diff --git a/gdb/p-lang.c b/gdb/p-lang.c +index 41da3e0..e743a6f 100644 +--- a/gdb/p-lang.c ++++ b/gdb/p-lang.c +@@ -97,7 +97,8 @@ pascal_main_name (void) + but this does not happen for Free Pascal nor for GPC. */ + int + is_pascal_string_type (struct type *type,int *length_pos, +- int *length_size, int *string_pos, int *char_size, ++ int *length_size, int *string_pos, ++ struct type **char_type, + char **arrayname) + { + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) +@@ -114,8 +115,8 @@ is_pascal_string_type (struct type *type,int *length_pos, + *length_size = TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)); + if (string_pos) + *string_pos = TYPE_FIELD_BITPOS (type, 1) / TARGET_CHAR_BIT; +- if (char_size) +- *char_size = 1; ++ if (char_type) ++ *char_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 1)); + if (arrayname) + *arrayname = TYPE_FIELDS (type)[1].name; + return 2; +@@ -126,7 +127,6 @@ is_pascal_string_type (struct type *type,int *length_pos, + && strcmp (TYPE_FIELDS (type)[0].name, "Capacity") == 0 + && strcmp (TYPE_FIELDS (type)[1].name, "length") == 0) + { +- struct type *char_type; + if (length_pos) + *length_pos = TYPE_FIELD_BITPOS (type, 1) / TARGET_CHAR_BIT; + if (length_size) +@@ -134,13 +134,12 @@ is_pascal_string_type (struct type *type,int *length_pos, + if (string_pos) + *string_pos = TYPE_FIELD_BITPOS (type, 2) / TARGET_CHAR_BIT; + /* FIXME: how can I detect wide chars in GPC ?? */ +- char_type = TYPE_FIELD_TYPE (type,2); +- if (char_size && TYPE_CODE (char_type) == TYPE_CODE_ARRAY) ++ if (char_type) + { +- *char_size = TYPE_LENGTH (TYPE_TARGET_TYPE (char_type)); ++ *char_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 2)); ++ if (TYPE_CODE (*char_type) == TYPE_CODE_ARRAY) ++ *char_type = TYPE_TARGET_TYPE (*char_type); + } +- else if (char_size) +- *char_size = 1; + if (arrayname) + *arrayname = TYPE_FIELDS (type)[2].name; + return 3; +@@ -182,14 +181,15 @@ pascal_one_char (int c, struct ui_file *stream, int *in_quotes) + } + } + +-static void pascal_emit_char (int c, struct ui_file *stream, int quoter); ++static void pascal_emit_char (int c, struct type *type, ++ struct ui_file *stream, int quoter); + + /* Print the character C on STREAM as part of the contents of a literal + string whose delimiter is QUOTER. Note that that format for printing + characters and strings is language specific. */ + + static void +-pascal_emit_char (int c, struct ui_file *stream, int quoter) ++pascal_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) + { + int in_quotes = 0; + pascal_one_char (c, stream, &in_quotes); +@@ -198,7 +198,7 @@ pascal_emit_char (int c, struct ui_file *stream, int quoter) + } + + void +-pascal_printchar (int c, struct ui_file *stream) ++pascal_printchar (int c, struct type *type, struct ui_file *stream) + { + int in_quotes = 0; + pascal_one_char (c, stream, &in_quotes); +@@ -212,14 +212,16 @@ pascal_printchar (int c, struct ui_file *stream) + had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. */ + + void +-pascal_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++pascal_printstr (struct ui_file *stream, struct type *type, ++ const gdb_byte *string, unsigned int length, ++ int force_ellipses, + const struct value_print_options *options) + { + unsigned int i; + unsigned int things_printed = 0; + int in_quotes = 0; + int need_comma = 0; ++ int width = TYPE_LENGTH (type); + + /* If the string was not truncated due to `set print elements', and + the last byte of it is a null, we don't print that, in traditional C +@@ -273,7 +275,7 @@ pascal_printstr (struct ui_file *stream, const gdb_byte *string, + fputs_filtered ("', ", stream); + in_quotes = 0; + } +- pascal_printchar (current_char, stream); ++ pascal_printchar (current_char, type, stream); + fprintf_filtered (stream, " ", reps); + i = rep1 - 1; + things_printed += options->repeat_count_threshold; +diff --git a/gdb/p-lang.h b/gdb/p-lang.h +index 09a4569..2b2eb2d 100644 +--- a/gdb/p-lang.h ++++ b/gdb/p-lang.h +@@ -48,12 +48,13 @@ extern void pascal_type_print_method_args (char *, char *, + /* These are in p-lang.c: */ + + extern int +- is_pascal_string_type (struct type *, int *, int *, int *, int *, char **); ++ is_pascal_string_type (struct type *, int *, int *, int *, ++ struct type **, char **); + +-extern void pascal_printchar (int, struct ui_file *); ++extern void pascal_printchar (int, struct type *, struct ui_file *); + +-extern void pascal_printstr (struct ui_file *, const gdb_byte *, +- unsigned int, int, int, ++extern void pascal_printstr (struct ui_file *, struct type *, const gdb_byte *, ++ unsigned int, int, + const struct value_print_options *); + + extern struct type **const (pascal_builtin_types[]); +diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c +index 27ae619..29f0e6d 100644 +--- a/gdb/p-valprint.c ++++ b/gdb/p-valprint.c +@@ -61,7 +61,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, + struct type *elttype; + unsigned eltlen; + int length_pos, length_size, string_pos; +- int char_size; ++ struct type *char_type; + LONGEST val; + CORE_ADDR addr; + +@@ -100,8 +100,9 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, + len = temp_len; + } + +- LA_PRINT_STRING (stream, valaddr + embedded_offset, len, +- eltlen, 0, options); ++ LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type), ++ valaddr + embedded_offset, len, 0, ++ options); + i = len; + } + else +@@ -175,8 +176,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, + && addr != 0) + { + /* no wide string yet */ +- i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream, +- options); ++ i = val_print_string (elttype, addr, -1, stream, options); + } + /* also for pointers to pascal strings */ + /* Note: this is Free Pascal specific: +@@ -184,7 +184,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, + Pascal strings are mapped to records + with lowercase names PM */ + if (is_pascal_string_type (elttype, &length_pos, &length_size, +- &string_pos, &char_size, NULL) ++ &string_pos, &char_type, NULL) + && addr != 0) + { + ULONGEST string_length; +@@ -193,7 +193,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, + read_memory (addr + length_pos, buffer, length_size); + string_length = extract_unsigned_integer (buffer, length_size); + xfree (buffer); +- i = val_print_string (addr + string_pos, string_length, char_size, stream, options); ++ i = val_print_string (char_type ,addr + string_pos, string_length, stream, options); + } + else if (pascal_object_is_vtbl_member (type)) + { +@@ -298,10 +298,10 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, + else + { + if (is_pascal_string_type (type, &length_pos, &length_size, +- &string_pos, &char_size, NULL)) ++ &string_pos, &char_type, NULL)) + { + len = extract_unsigned_integer (valaddr + embedded_offset + length_pos, length_size); +- LA_PRINT_STRING (stream, valaddr + embedded_offset + string_pos, len, char_size, 0, options); ++ LA_PRINT_STRING (stream, char_type, valaddr + embedded_offset + string_pos, len, 0, options); + } + else + pascal_object_print_value_fields (type, valaddr + embedded_offset, address, stream, +@@ -426,7 +426,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, + else + fprintf_filtered (stream, "%d", (int) val); + fputs_filtered (" ", stream); +- LA_PRINT_CHAR ((unsigned char) val, stream); ++ LA_PRINT_CHAR ((unsigned char) val, type, stream); + } + break; + +@@ -931,7 +931,7 @@ pascal_object_print_static_field (struct value *val, + + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + { +- CORE_ADDR *first_dont_print; ++ CORE_ADDR *first_dont_print, addr; + int i; + + first_dont_print +@@ -941,7 +941,7 @@ pascal_object_print_static_field (struct value *val, + + while (--i >= 0) + { +- if (VALUE_ADDRESS (val) == first_dont_print[i]) ++ if (value_address (val) == first_dont_print[i]) + { + fputs_filtered ("", + stream); +@@ -949,11 +949,12 @@ pascal_object_print_static_field (struct value *val, + } + } + +- obstack_grow (&dont_print_statmem_obstack, (char *) &VALUE_ADDRESS (val), ++ addr = value_address (val); ++ obstack_grow (&dont_print_statmem_obstack, (char *) &addr, + sizeof (CORE_ADDR)); + + CHECK_TYPEDEF (type); +- pascal_object_print_value_fields (type, value_contents (val), VALUE_ADDRESS (val), ++ pascal_object_print_value_fields (type, value_contents (val), value_address (val), + stream, recurse, options, NULL, 1); + return; + } +diff --git a/gdb/parse.c b/gdb/parse.c +index eee1f8e..66aaf6a 100644 +--- a/gdb/parse.c ++++ b/gdb/parse.c +@@ -306,7 +306,7 @@ write_exp_elt_intern (struct internalvar *expelt) + strings with embedded null bytes, as is required for some languages. + + Don't be fooled by the fact that the string is null byte terminated, +- this is strictly for the convenience of debugging gdb itself. Gdb ++ this is strictly for the convenience of debugging gdb itself. + Gdb does not depend up the string being null terminated, since the + actual length is recorded in expression elements at each end of the + string. The null byte is taken into consideration when computing how +@@ -352,6 +352,65 @@ write_exp_string (struct stoken str) + write_exp_elt_longcst ((LONGEST) len); + } + ++/* Add a vector of string constants to the end of the expression. ++ ++ This adds an OP_STRING operation, but encodes the contents ++ differently from write_exp_string. The language is expected to ++ handle evaluation of this expression itself. ++ ++ After the usual OP_STRING header, TYPE is written into the ++ expression as a long constant. The interpretation of this field is ++ up to the language evaluator. ++ ++ Next, each string in VEC is written. The length is written as a ++ long constant, followed by the contents of the string. */ ++ ++void ++write_exp_string_vector (int type, struct stoken_vector *vec) ++{ ++ int i, n_slots, len; ++ ++ /* Compute the size. We compute the size in number of slots to ++ avoid issues with string padding. */ ++ n_slots = 0; ++ for (i = 0; i < vec->len; ++i) ++ { ++ /* One slot for the length of this element, plus the number of ++ slots needed for this string. */ ++ n_slots += 1 + BYTES_TO_EXP_ELEM (vec->tokens[i].length); ++ } ++ ++ /* One more slot for the type of the string. */ ++ ++n_slots; ++ ++ /* Now compute a phony string length. */ ++ len = EXP_ELEM_TO_BYTES (n_slots) - 1; ++ ++ n_slots += 4; ++ if ((expout_ptr + n_slots) >= expout_size) ++ { ++ expout_size = max (expout_size * 2, expout_ptr + n_slots + 10); ++ expout = (struct expression *) ++ xrealloc ((char *) expout, (sizeof (struct expression) ++ + EXP_ELEM_TO_BYTES (expout_size))); ++ } ++ ++ write_exp_elt_opcode (OP_STRING); ++ write_exp_elt_longcst (len); ++ write_exp_elt_longcst (type); ++ ++ for (i = 0; i < vec->len; ++i) ++ { ++ write_exp_elt_longcst (vec->tokens[i].length); ++ memcpy (&expout->elts[expout_ptr], vec->tokens[i].ptr, ++ vec->tokens[i].length); ++ expout_ptr += BYTES_TO_EXP_ELEM (vec->tokens[i].length); ++ } ++ ++ write_exp_elt_longcst (len); ++ write_exp_elt_opcode (OP_STRING); ++} ++ + /* Add a bitstring constant to the end of the expression. + + Bitstring constants are stored by first writing an expression element +@@ -777,6 +836,15 @@ operator_length_standard (struct expression *expr, int endpos, + args = 1 + longest_to_int (expr->elts[endpos - 2].longconst); + break; + ++ case TYPE_INSTANCE: ++ oplen = 4 + longest_to_int (expr->elts[endpos - 2].longconst); ++ args = 1; ++ break; ++ ++ case TYPE_INSTANCE_LOOKUP: ++ oplen = 3; ++ break; ++ + case OP_OBJC_MSGCALL: /* Objective C message (method) call */ + oplen = 4; + args = 1 + longest_to_int (expr->elts[endpos - 2].longconst); +diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h +index 2c4b755..cbda9c3 100644 +--- a/gdb/parser-defs.h ++++ b/gdb/parser-defs.h +@@ -69,6 +69,22 @@ struct stoken + int length; + }; + ++struct typed_stoken ++ { ++ /* A language-specific type field. */ ++ int type; ++ /* Pointer to first byte of char-string or first bit of bit-string */ ++ char *ptr; ++ /* Length of string in bytes for char-string or bits for bit-string */ ++ int length; ++ }; ++ ++struct stoken_vector ++ { ++ int len; ++ struct typed_stoken *tokens; ++ }; ++ + struct ttype + { + struct stoken stoken; +@@ -130,6 +146,8 @@ extern void write_exp_elt_intern (struct internalvar *); + + extern void write_exp_string (struct stoken); + ++void write_exp_string_vector (int type, struct stoken_vector *vec); ++ + extern void write_exp_bitstring (struct stoken); + + extern void write_exp_elt_block (struct block *); +diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c +index d08d4fc..c2bbdf9 100644 +--- a/gdb/ppc-linux-tdep.c ++++ b/gdb/ppc-linux-tdep.c +@@ -38,6 +38,7 @@ + #include "trad-frame.h" + #include "frame-unwind.h" + #include "tramp-frame.h" ++#include "linux-tdep.h" + + #include "features/rs6000/powerpc-32l.c" + #include "features/rs6000/powerpc-altivec32l.c" +@@ -53,6 +54,9 @@ + #include "features/rs6000/powerpc-isa205-vsx64l.c" + #include "features/rs6000/powerpc-e500l.c" + ++/* The syscall's XML filename for PPC and PPC64. */ ++#define XML_SYSCALL_FILENAME_PPC "syscalls/ppc-linux.xml" ++#define XML_SYSCALL_FILENAME_PPC64 "syscalls/ppc64-linux.xml" + + /* ppc_linux_memory_remove_breakpoints attempts to remove a breakpoint + in much the same fashion as memory_remove_breakpoint in mem-break.c, +@@ -1009,6 +1013,38 @@ ppc_linux_trap_reg_p (struct gdbarch *gdbarch) + && register_size (gdbarch, PPC_TRAP_REGNUM) > 0; + } + ++/* Return the current system call's number present in the ++ r0 register. When the function fails, it returns -1. */ ++static LONGEST ++ppc_linux_get_syscall_number (struct gdbarch *gdbarch, ++ ptid_t ptid) ++{ ++ struct regcache *regcache = get_thread_regcache (ptid); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ struct cleanup *cleanbuf; ++ /* The content of a register */ ++ gdb_byte *buf; ++ /* The result */ ++ LONGEST ret; ++ ++ /* Make sure we're in a 32- or 64-bit machine */ ++ gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8); ++ ++ buf = (gdb_byte *) xmalloc (tdep->wordsize * sizeof (gdb_byte)); ++ ++ cleanbuf = make_cleanup (xfree, buf); ++ ++ /* Getting the system call number from the register. ++ When dealing with PowerPC architecture, this information ++ is stored at 0th register. */ ++ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum, buf); ++ ++ ret = extract_signed_integer (buf, tdep->wordsize); ++ do_cleanups (cleanbuf); ++ ++ return ret; ++} ++ + static void + ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) + { +@@ -1069,6 +1105,9 @@ ppc_linux_init_abi (struct gdbarch_info info, + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info; + ++ /* Initializing common methods. */ ++ linux_tdep_init (gdbarch); ++ + /* PPC GNU/Linux uses either 64-bit or 128-bit long doubles; where + 128-bit, they are IBM long double, not IEEE quad long double as + in the System V ABI PowerPC Processor Supplement. We can safely +@@ -1080,6 +1119,9 @@ ppc_linux_init_abi (struct gdbarch_info info, + /* Handle inferior calls during interrupted system calls. */ + set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc); + ++ /* Get the syscall number from the arch's register. */ ++ set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number); ++ + if (tdep->wordsize == 4) + { + /* Until November 2001, gcc did not comply with the 32 bit SysV +@@ -1099,6 +1141,9 @@ ppc_linux_init_abi (struct gdbarch_info info, + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + ++ /* Setting the correct XML syscall filename. */ ++ set_gdbarch_xml_syscall_filename (gdbarch, XML_SYSCALL_FILENAME_PPC); ++ + /* Trampolines. */ + tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sigaction_tramp_frame); + tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sighandler_tramp_frame); +@@ -1116,6 +1161,9 @@ ppc_linux_init_abi (struct gdbarch_info info, + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); + ++ /* Setting the correct XML syscall filename. */ ++ set_gdbarch_xml_syscall_filename (gdbarch, XML_SYSCALL_FILENAME_PPC64); ++ + /* Trampolines. */ + tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sigaction_tramp_frame); + tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame); +diff --git a/gdb/printcmd.c b/gdb/printcmd.c +index 375f82e..8c3f476 100644 +--- a/gdb/printcmd.c ++++ b/gdb/printcmd.c +@@ -43,6 +43,7 @@ + #include "disasm.h" + #include "dfp.h" + #include "valprint.h" ++#include "charset.h" + + #ifdef TUI + #include "tui/tui.h" /* For tui_active et.al. */ +@@ -62,11 +63,15 @@ struct format_data + int count; + char format; + char size; ++ ++ /* True if the value should be printed raw -- that is, bypassing ++ python-based formatters. */ ++ unsigned char raw; + }; + + /* Last specified output format. */ + +-static char last_format = 'x'; ++static char last_format = 0; + + /* Last specified examination size. 'b', 'h', 'w' or `q'. */ + +@@ -175,6 +180,7 @@ decode_format (char **string_ptr, int oformat, int osize) + val.format = '?'; + val.size = '?'; + val.count = 1; ++ val.raw = 0; + + if (*p >= '0' && *p <= '9') + val.count = atoi (p); +@@ -187,6 +193,11 @@ decode_format (char **string_ptr, int oformat, int osize) + { + if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g') + val.size = *p++; ++ else if (*p == 'r') ++ { ++ val.raw = 1; ++ p++; ++ } + else if (*p >= 'a' && *p <= 'z') + val.format = *p++; + else +@@ -264,24 +275,27 @@ print_formatted (struct value *val, int size, + int len = TYPE_LENGTH (type); + + if (VALUE_LVAL (val) == lval_memory) +- next_address = VALUE_ADDRESS (val) + len; ++ next_address = value_address (val) + len; + + if (size) + { + switch (options->format) + { + case 's': +- /* FIXME: Need to handle wchar_t's here... */ +- next_address = VALUE_ADDRESS (val) +- + val_print_string (VALUE_ADDRESS (val), -1, 1, stream, +- options); ++ { ++ struct type *elttype = value_type (val); ++ next_address = (value_address (val) ++ + val_print_string (elttype, ++ value_address (val), -1, ++ stream, options)); ++ } + return; + + case 'i': + /* We often wrap here if there are long symbolic names. */ + wrap_here (" "); +- next_address = (VALUE_ADDRESS (val) +- + gdb_print_insn (VALUE_ADDRESS (val), stream, ++ next_address = (value_address (val) ++ + gdb_print_insn (value_address (val), stream, + &branch_delay_insns)); + return; + } +@@ -369,7 +383,7 @@ print_scalar_formatted (const void *valaddr, struct type *type, + print_hex_chars (stream, valaddr, len, byte_order); + return; + case 'c': +- print_char_chars (stream, valaddr, len, byte_order); ++ print_char_chars (stream, type, valaddr, len, byte_order); + return; + default: + break; +@@ -865,6 +879,7 @@ print_command_1 (char *exp, int inspect, int voidprint) + fmt.count = 1; + fmt.format = 0; + fmt.size = 0; ++ fmt.raw = 0; + } + + if (exp && *exp) +@@ -878,6 +893,11 @@ print_command_1 (char *exp, int inspect, int voidprint) + else + val = access_value_history (0); + ++ /* Do not try to OBJECT_ADDRESS_SET here anything. We are interested in the ++ source variable base addresses as found by READ_VAR_VALUE. The value here ++ can be already a calculated expression address inappropriate for ++ DW_OP_push_object_address. */ ++ + if (voidprint || (val && value_type (val) && + TYPE_CODE (value_type (val)) != TYPE_CODE_VOID)) + { +@@ -900,6 +920,7 @@ print_command_1 (char *exp, int inspect, int voidprint) + + get_formatted_print_options (&opts, format); + opts.inspect_it = inspect; ++ opts.raw = fmt.raw; + + print_formatted (val, fmt.size, &opts, gdb_stdout); + printf_filtered ("\n"); +@@ -950,6 +971,7 @@ output_command (char *exp, int from_tty) + struct value_print_options opts; + + fmt.size = 0; ++ fmt.raw = 0; + + if (exp && *exp == '/') + { +@@ -967,6 +989,7 @@ output_command (char *exp, int from_tty) + annotate_value_begin (value_type (val)); + + get_formatted_print_options (&opts, format); ++ opts.raw = fmt.raw; + print_formatted (val, fmt.size, &opts, gdb_stdout); + + annotate_value_end (); +@@ -1287,9 +1310,10 @@ x_command (char *exp, int from_tty) + struct cleanup *old_chain; + struct value *val; + +- fmt.format = last_format; ++ fmt.format = last_format ? last_format : 'x'; + fmt.size = last_size; + fmt.count = 1; ++ fmt.raw = 0; + + if (exp && *exp == '/') + { +@@ -1316,7 +1340,7 @@ x_command (char *exp, int from_tty) + if (/* last_format == 'i' && */ + TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC + && VALUE_LVAL (val) == lval_memory) +- next_address = VALUE_ADDRESS (val); ++ next_address = value_address (val); + else + next_address = value_as_address (val); + do_cleanups (old_chain); +@@ -1393,6 +1417,7 @@ display_command (char *exp, int from_tty) + fmt.format = 0; + fmt.size = 0; + fmt.count = 0; ++ fmt.raw = 0; + } + + innermost_block = 0; +@@ -1585,6 +1610,7 @@ do_one_display (struct display *d) + annotate_display_expression (); + + get_formatted_print_options (&opts, d->format.format); ++ opts.raw = d->format.raw; + print_formatted (evaluate_expression (d->exp), + d->format.size, &opts, gdb_stdout); + printf_filtered ("\n"); +@@ -1865,7 +1891,8 @@ printf_command (char *arg, int from_tty) + + enum argclass + { +- int_arg, long_arg, long_long_arg, ptr_arg, string_arg, ++ int_arg, long_arg, long_long_arg, ptr_arg, ++ string_arg, wide_string_arg, wide_char_arg, + double_arg, long_double_arg, decfloat_arg + }; + enum argclass *argclass; +@@ -1997,8 +2024,8 @@ printf_command (char *arg, int from_tty) + break; + + case 'c': +- this_argclass = int_arg; +- if (lcount || seen_h || seen_big_l) ++ this_argclass = lcount == 0 ? int_arg : wide_char_arg; ++ if (lcount > 1 || seen_h || seen_big_l) + bad = 1; + if (seen_prec || seen_zero || seen_space || seen_plus) + bad = 1; +@@ -2013,8 +2040,8 @@ printf_command (char *arg, int from_tty) + break; + + case 's': +- this_argclass = string_arg; +- if (lcount || seen_h || seen_big_l) ++ this_argclass = lcount == 0 ? string_arg : wide_string_arg; ++ if (lcount > 1 || seen_h || seen_big_l) + bad = 1; + if (seen_zero || seen_space || seen_plus) + bad = 1; +@@ -2066,6 +2093,15 @@ printf_command (char *arg, int from_tty) + last_arg[length_before_ll + lcount]; + current_substring += length_before_ll + 4; + } ++ else if (this_argclass == wide_string_arg ++ || this_argclass == wide_char_arg) ++ { ++ /* Convert %ls or %lc to %s. */ ++ int length_before_ls = f - last_arg - 2; ++ strncpy (current_substring, last_arg, length_before_ls); ++ strcpy (current_substring + length_before_ls, "s"); ++ current_substring += length_before_ls + 2; ++ } + else + { + strncpy (current_substring, last_arg, f - last_arg); +@@ -2130,6 +2166,76 @@ printf_command (char *arg, int from_tty) + printf_filtered (current_substring, (char *) str); + } + break; ++ case wide_string_arg: ++ { ++ gdb_byte *str; ++ CORE_ADDR tem; ++ int j; ++ struct type *wctype = lookup_typename ("wchar_t", NULL, 0); ++ int wcwidth = TYPE_LENGTH (wctype); ++ gdb_byte *buf = alloca (wcwidth); ++ struct obstack output; ++ struct cleanup *inner_cleanup; ++ ++ tem = value_as_address (val_args[i]); ++ ++ /* This is a %s argument. Find the length of the string. */ ++ for (j = 0;; j += wcwidth) ++ { ++ QUIT; ++ read_memory (tem + j, buf, wcwidth); ++ if (extract_unsigned_integer (buf, wcwidth) == 0) ++ break; ++ } ++ ++ /* Copy the string contents into a string inside GDB. */ ++ str = (gdb_byte *) alloca (j + wcwidth); ++ if (j != 0) ++ read_memory (tem, str, j); ++ memset (&str[j], 0, wcwidth); ++ ++ obstack_init (&output); ++ inner_cleanup = make_cleanup_obstack_free (&output); ++ ++ convert_between_encodings (target_wide_charset (), ++ host_charset (), ++ str, j, wcwidth, ++ &output, translit_char); ++ obstack_grow_str0 (&output, ""); ++ ++ printf_filtered (current_substring, obstack_base (&output)); ++ do_cleanups (inner_cleanup); ++ } ++ break; ++ case wide_char_arg: ++ { ++ struct type *wctype = lookup_typename ("wchar_t", NULL, 0); ++ struct type *valtype; ++ struct obstack output; ++ struct cleanup *inner_cleanup; ++ const gdb_byte *bytes; ++ ++ valtype = value_type (val_args[i]); ++ if (TYPE_LENGTH (valtype) != TYPE_LENGTH (wctype) ++ || TYPE_CODE (valtype) != TYPE_CODE_INT) ++ error (_("expected wchar_t argument for %%lc")); ++ ++ bytes = value_contents (val_args[i]); ++ ++ obstack_init (&output); ++ inner_cleanup = make_cleanup_obstack_free (&output); ++ ++ convert_between_encodings (target_wide_charset (), ++ host_charset (), ++ bytes, TYPE_LENGTH (valtype), ++ TYPE_LENGTH (valtype), ++ &output, translit_char); ++ obstack_grow_str0 (&output, ""); ++ ++ printf_filtered (current_substring, obstack_base (&output)); ++ do_cleanups (inner_cleanup); ++ } ++ break; + case double_arg: + { + struct type *type = value_type (val_args[i]); +diff --git a/gdb/python/lib/gdb/FrameIterator.py b/gdb/python/lib/gdb/FrameIterator.py +new file mode 100644 +index 0000000..5654546 +--- /dev/null ++++ b/gdb/python/lib/gdb/FrameIterator.py +@@ -0,0 +1,33 @@ ++# Iterator over frames. ++ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++class FrameIterator: ++ """An iterator that iterates over frames.""" ++ ++ def __init__ (self, frame): ++ "Initialize a FrameIterator. FRAME is the starting frame." ++ self.frame = frame ++ ++ def __iter__ (self): ++ return self ++ ++ def next (self): ++ result = self.frame ++ if result is None: ++ raise StopIteration ++ self.frame = result.older () ++ return result +diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py +new file mode 100644 +index 0000000..b375c68 +--- /dev/null ++++ b/gdb/python/lib/gdb/__init__.py +@@ -0,0 +1,19 @@ ++# Startup code. ++ ++# Copyright (C) 2008 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 3 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, see . ++ ++# Load the require command by default. ++import gdb.command.require +diff --git a/gdb/python/lib/gdb/backtrace.py b/gdb/python/lib/gdb/backtrace.py +new file mode 100644 +index 0000000..2baab5f +--- /dev/null ++++ b/gdb/python/lib/gdb/backtrace.py +@@ -0,0 +1,42 @@ ++# Filtering backtrace. ++ ++# Copyright (C) 2008 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 3 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, see . ++ ++import gdb ++import itertools ++ ++# Our only exports. ++__all__ = ['push_frame_filter', 'create_frame_filter'] ++ ++frame_filter = None ++ ++def push_frame_filter (constructor): ++ """Register a new backtrace filter class with the 'backtrace' command. ++The filter will be passed an iterator as an argument. The iterator ++will return gdb.Frame-like objects. The filter should in turn act as ++an iterator returning such objects.""" ++ global frame_filter ++ if frame_filter == None: ++ frame_filter = constructor ++ else: ++ frame_filter = lambda iterator: constructor (frame_filter (iterator)) ++ ++def create_frame_filter (iter): ++ global frame_filter ++ if frame_filter is None: ++ return iter ++ return frame_filter (iter) ++ +diff --git a/gdb/python/lib/gdb/command/__init__.py b/gdb/python/lib/gdb/command/__init__.py +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/__init__.py +@@ -0,0 +1 @@ ++ +diff --git a/gdb/python/lib/gdb/command/alias.py b/gdb/python/lib/gdb/command/alias.py +new file mode 100644 +index 0000000..96b6618 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/alias.py +@@ -0,0 +1,59 @@ ++# Alias command. ++ ++# Copyright (C) 2008 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 3 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, see . ++ ++import gdb ++ ++class AliasImplementation (gdb.Command): ++ def __init__ (self, name, real, doc): ++ # Have to set __doc__ before the super init call. ++ # It would be nice if gdb's help looked up __doc__ dynamically. ++ self.__doc__ = doc ++ # Note: no good way to complete :( ++ super (AliasImplementation, self).__init__ (name, gdb.COMMAND_NONE) ++ self.real = real ++ ++ def invoke(self, arg, from_tty): ++ gdb.execute (self.real + ' ' + arg, from_tty) ++ ++class AliasCommand (gdb.Command): ++ """Alias one command to another. ++In the simplest form, the first word is the name of the alias, and ++the remaining words are the the expansion. ++An '=' by itself can be used to define a multi-word alias; words ++before the '=' are the name of the new command.""" ++ ++ def __init__ (self): ++ # Completion is not quite right here. ++ super (AliasCommand, self).__init__ ("alias", gdb.COMMAND_NONE, ++ gdb.COMPLETE_COMMAND) ++ ++ def invoke (self, arg, from_tty): ++ self.dont_repeat () ++ # Without some form of quoting we can't alias a multi-word ++ # command to another command. ++ args = arg.split() ++ try: ++ start = args.index ('=') ++ end = start + 1 ++ except ValueError: ++ start = 1 ++ end = 1 ++ target = " ".join(args[end:]) ++ AliasImplementation (" ".join (args[0:start]), target, ++ "This command is an alias for '%s'." % target) ++ ++AliasCommand() +diff --git a/gdb/python/lib/gdb/command/backtrace.py b/gdb/python/lib/gdb/command/backtrace.py +new file mode 100644 +index 0000000..f07696e +--- /dev/null ++++ b/gdb/python/lib/gdb/command/backtrace.py +@@ -0,0 +1,197 @@ ++# New backtrace command. ++ ++# Copyright (C) 2008 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 3 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, see . ++ ++import gdb ++import gdb.backtrace ++import itertools ++from gdb.FrameIterator import FrameIterator ++import sys ++ ++class FrameWrapper: ++ def __init__ (self, frame): ++ self.frame = frame; ++ ++ def write_symbol (self, stream, sym, block): ++ if len (sym.linkage_name): ++ nsym, is_field_of_this = gdb.lookup_symbol (sym.linkage_name, block) ++ if nsym.addr_class != gdb.SYMBOL_LOC_REGISTER: ++ sym = nsym ++ ++ stream.write (sym.print_name + "=") ++ try: ++ val = self.frame.read_var (sym) ++ if val != None: ++ val = str (val) ++ # FIXME: would be nice to have a more precise exception here. ++ except RuntimeError, text: ++ val = text ++ if val == None: ++ stream.write ("???") ++ else: ++ stream.write (str (val)) ++ ++ def print_frame_locals (self, stream, func): ++ if not func: ++ return ++ ++ first = True ++ block = func.value ++ ++ for sym in block: ++ if sym.is_argument: ++ continue; ++ ++ self.write_symbol (stream, sym, block) ++ stream.write ('\n') ++ ++ def print_frame_args (self, stream, func): ++ if not func: ++ return ++ ++ first = True ++ block = func.value ++ ++ for sym in block: ++ if not sym.is_argument: ++ continue; ++ ++ if not first: ++ stream.write (", ") ++ ++ self.write_symbol (stream, sym, block) ++ first = False ++ ++ # FIXME: this should probably just be a method on gdb.Frame. ++ # But then we need stream wrappers. ++ def describe (self, stream, full): ++ if self.frame.type () == gdb.DUMMY_FRAME: ++ stream.write (" \n") ++ elif self.frame.type () == gdb.SIGTRAMP_FRAME: ++ stream.write (" \n") ++ else: ++ sal = self.frame.find_sal () ++ pc = self.frame.pc () ++ name = self.frame.name () ++ if not name: ++ name = "??" ++ if pc != sal.pc or not sal.symtab: ++ stream.write (" 0x%08x in" % pc) ++ stream.write (" " + name + " (") ++ ++ func = gdb.find_pc_function (self.frame.addr_in_block ()) ++ self.print_frame_args (stream, func) ++ ++ stream.write (")") ++ ++ if sal.symtab and sal.symtab.filename: ++ stream.write (" at " + sal.symtab.filename) ++ stream.write (":" + str (sal.line)) ++ ++ if not self.frame.name () or (not sal.symtab or not sal.symtab.filename): ++ lib = gdb.solib_address (pc) ++ if lib: ++ stream.write (" from " + lib) ++ ++ stream.write ("\n") ++ ++ if full: ++ self.print_frame_locals (stream, func) ++ ++ def __getattr__ (self, name): ++ return getattr (self.frame, name) ++ ++class ReverseBacktraceParameter (gdb.Parameter): ++ """The new-backtrace command can show backtraces in 'reverse' order. ++This means that the innermost frame will be printed last. ++Note that reverse backtraces are more expensive to compute.""" ++ ++ set_doc = "Enable or disable reverse backtraces." ++ show_doc = "Show whether backtraces will be printed in reverse order." ++ ++ def __init__(self): ++ gdb.Parameter.__init__ (self, "reverse-backtrace", ++ gdb.COMMAND_STACK, gdb.PARAM_BOOLEAN) ++ # Default to compatibility with gdb. ++ self.value = False ++ ++class FilteringBacktrace (gdb.Command): ++ """Print backtrace of all stack frames, or innermost COUNT frames. ++With a negative argument, print outermost -COUNT frames. ++Use of the 'full' qualifier also prints the values of the local variables. ++Use of the 'raw' qualifier avoids any filtering by loadable modules. ++""" ++ ++ def __init__ (self): ++ # FIXME: this is not working quite well enough to replace ++ # "backtrace" yet. ++ gdb.Command.__init__ (self, "new-backtrace", gdb.COMMAND_STACK) ++ self.reverse = ReverseBacktraceParameter() ++ ++ def reverse_iter (self, iter): ++ result = [] ++ for item in iter: ++ result.append (item) ++ result.reverse() ++ return result ++ ++ def final_n (self, iter, x): ++ result = [] ++ for item in iter: ++ result.append (item) ++ return result[x:] ++ ++ def invoke (self, arg, from_tty): ++ i = 0 ++ count = 0 ++ filter = True ++ full = False ++ ++ for word in arg.split (" "): ++ if word == '': ++ continue ++ elif word == 'raw': ++ filter = False ++ elif word == 'full': ++ full = True ++ else: ++ count = int (word) ++ ++ # FIXME: provide option to start at selected frame ++ # However, should still number as if starting from newest ++ iter = itertools.imap (FrameWrapper, ++ FrameIterator (gdb.newest_frame ())) ++ if filter: ++ iter = gdb.backtrace.create_frame_filter (iter) ++ ++ # Now wrap in an iterator that numbers the frames. ++ iter = itertools.izip (itertools.count (0), iter) ++ ++ # Reverse if the user wanted that. ++ if self.reverse.value: ++ iter = self.reverse_iter (iter) ++ ++ # Extract sub-range user wants. ++ if count < 0: ++ iter = self.final_n (iter, count) ++ elif count > 0: ++ iter = itertools.islice (iter, 0, count) ++ ++ for pair in iter: ++ sys.stdout.write ("#%-2d" % pair[0]) ++ pair[1].describe (sys.stdout, full) ++ ++FilteringBacktrace() +diff --git a/gdb/python/lib/gdb/command/ignore_errors.py b/gdb/python/lib/gdb/command/ignore_errors.py +new file mode 100644 +index 0000000..6fa48ff +--- /dev/null ++++ b/gdb/python/lib/gdb/command/ignore_errors.py +@@ -0,0 +1,37 @@ ++# Ignore errors in user commands. ++ ++# Copyright (C) 2008 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 3 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, see . ++ ++import gdb ++ ++class IgnoreErrorsCommand (gdb.Command): ++ """Execute a single command, ignoring all errors. ++Only one-line commands are supported. ++This is primarily useful in scripts.""" ++ ++ def __init__ (self): ++ super (IgnoreErrorsCommand, self).__init__ ("ignore-errors", ++ gdb.COMMAND_OBSCURE, ++ # FIXME... ++ gdb.COMPLETE_COMMAND) ++ ++ def invoke (self, arg, from_tty): ++ try: ++ gdb.execute (arg, from_tty) ++ except: ++ pass ++ ++IgnoreErrorsCommand () +diff --git a/gdb/python/lib/gdb/command/pahole.py b/gdb/python/lib/gdb/command/pahole.py +new file mode 100644 +index 0000000..21a0bf0 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/pahole.py +@@ -0,0 +1,75 @@ ++# pahole command for gdb ++ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++import gdb ++ ++class Pahole (gdb.Command): ++ """Show the holes in a structure. ++This command takes a single argument, a type name. ++It prints the type and displays comments showing where holes are.""" ++ ++ def __init__ (self): ++ super (Pahole, self).__init__ ("pahole", gdb.COMMAND_NONE, ++ gdb.COMPLETE_SYMBOL) ++ ++ def pahole (self, type, level, name): ++ if name is None: ++ name = '' ++ tag = type.tag ++ if tag is None: ++ tag = '' ++ print '%sstruct %s {' % (' ' * (2 * level), tag) ++ bitpos = 0 ++ for field in type.fields (): ++ # Skip static fields. ++ if not hasattr (field, ('bitpos')): ++ continue ++ ++ ftype = field.type.strip_typedefs() ++ ++ if bitpos != field.bitpos: ++ hole = field.bitpos - bitpos ++ print ' /* XXX %d bit hole, try to pack */' % hole ++ bitpos = field.bitpos ++ if field.bitsize > 0: ++ fieldsize = field.bitsize ++ else: ++ # TARGET_CHAR_BIT here... ++ fieldsize = 8 * ftype.sizeof ++ ++ # TARGET_CHAR_BIT ++ print ' /* %3d %3d */' % (int (bitpos / 8), int (fieldsize / 8)), ++ bitpos = bitpos + fieldsize ++ ++ if ftype.code == gdb.TYPE_CODE_STRUCT: ++ self.pahole (ftype, level + 1, field.name) ++ else: ++ print ' ' * (2 + 2 * level), ++ print '%s %s' % (str (ftype), field.name) ++ ++ print ' ' * (14 + 2 * level), ++ print '} %s' % name ++ ++ def invoke (self, arg, from_tty): ++ type = gdb.lookup_type (arg) ++ type = type.strip_typedefs () ++ if type.code != gdb.TYPE_CODE_STRUCT: ++ raise TypeError, '%s is not a struct type' % arg ++ print ' ' * 14, ++ self.pahole (type, 0, '') ++ ++Pahole() +diff --git a/gdb/python/lib/gdb/command/require.py b/gdb/python/lib/gdb/command/require.py +new file mode 100644 +index 0000000..1fbc1e8 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/require.py +@@ -0,0 +1,57 @@ ++# Demand-loading commands. ++ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++import gdb ++import os ++ ++class RequireCommand (gdb.Command): ++ """Prefix command for requiring features.""" ++ ++ def __init__ (self): ++ super (RequireCommand, self).__init__ ("require", ++ gdb.COMMAND_SUPPORT, ++ gdb.COMPLETE_NONE, ++ True) ++ ++class RequireSubcommand (gdb.Command): ++ """Demand-load a command by name.""" ++ ++ def __init__ (self, name): ++ self.__doc__ = "Demand-load a %s by name." % name ++ super (RequireSubcommand, self).__init__ ("require %s" % name, ++ gdb.COMMAND_SUPPORT) ++ self.name = name ++ ++ def invoke (self, arg, from_tty): ++ for cmd in arg.split(): ++ exec ('import gdb.' + self.name + '.' + cmd, globals ()) ++ ++ def complete (self, text, word): ++ dir = gdb.pythondir + '/gdb/' + self.name ++ result = [] ++ for file in os.listdir(dir): ++ if not file.startswith (word) or not file.endswith ('.py'): ++ continue ++ feature = file[0:-3] ++ if feature == 'require' or feature == '__init__': ++ continue ++ result.append (feature) ++ return result ++ ++RequireCommand() ++RequireSubcommand("command") ++RequireSubcommand("function") +diff --git a/gdb/python/lib/gdb/command/save_breakpoints.py b/gdb/python/lib/gdb/command/save_breakpoints.py +new file mode 100644 +index 0000000..90e07db +--- /dev/null ++++ b/gdb/python/lib/gdb/command/save_breakpoints.py +@@ -0,0 +1,65 @@ ++# Save breakpoints. ++ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++from __future__ import with_statement ++import gdb ++ ++class SavePrefixCommand (gdb.Command): ++ "Prefix command for saving things." ++ ++ def __init__ (self): ++ super (SavePrefixCommand, self).__init__ ("save", ++ gdb.COMMAND_SUPPORT, ++ gdb.COMPLETE_NONE, True) ++ ++class SaveBreakpointsCommand (gdb.Command): ++ """Save the current breakpoints to a file. ++This command takes a single argument, a file name. ++The breakpoints can be restored using the 'source' command.""" ++ ++ def __init__ (self): ++ super (SaveBreakpointsCommand, self).__init__ ("save breakpoints", ++ gdb.COMMAND_SUPPORT, ++ gdb.COMPLETE_FILENAME) ++ ++ def invoke (self, arg, from_tty): ++ self.dont_repeat () ++ bps = gdb.breakpoints () ++ if bps is None: ++ raise RuntimeError, 'No breakpoints to save' ++ with open (arg.strip (), 'w') as f: ++ for bp in bps: ++ print >> f, "break", bp.location, ++ if bp.thread is not None: ++ print >> f, " thread", bp.thread, ++ if bp.condition is not None: ++ print >> f, " if", bp.condition, ++ print >> f ++ if not bp.enabled: ++ print >> f, "disable %d" % bp.number ++ # Note: we don't save the ignore count; there doesn't ++ # seem to be much point. ++ commands = bp.commands ++ if commands is not None: ++ print >> f, "commands" ++ # Note that COMMANDS has a trailing newline. ++ print >> f, commands, ++ print >> f, "end" ++ print >> f ++ ++SavePrefixCommand () ++SaveBreakpointsCommand () +diff --git a/gdb/python/lib/gdb/function/__init__.py b/gdb/python/lib/gdb/function/__init__.py +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/gdb/python/lib/gdb/function/__init__.py +@@ -0,0 +1 @@ ++ +diff --git a/gdb/python/lib/gdb/function/caller_is.py b/gdb/python/lib/gdb/function/caller_is.py +new file mode 100644 +index 0000000..2b9c5c7 +--- /dev/null ++++ b/gdb/python/lib/gdb/function/caller_is.py +@@ -0,0 +1,58 @@ ++# Caller-is functions. ++ ++# Copyright (C) 2008 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 3 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, see . ++ ++import gdb ++import re ++ ++class CallerIs (gdb.Function): ++ """Return True if the calling function's name is equal to a string. ++This function takes one or two arguments. ++The first argument is the name of a function; if the calling function's ++name is equal to this argument, this function returns True. ++The optional second argument tells this function how many stack frames ++to traverse to find the calling function. The default is 1.""" ++ ++ def __init__ (self): ++ super (CallerIs, self).__init__ ("caller_is") ++ ++ def invoke (self, name, nframes = 1): ++ frame = gdb.selected_frame () ++ while nframes > 0: ++ frame = frame.older () ++ nframes = nframes - 1 ++ return frame.name () == name.string () ++ ++class CallerMatches (gdb.Function): ++ """Return True if the calling function's name matches a string. ++This function takes one or two arguments. ++The first argument is a regular expression; if the calling function's ++name is matched by this argument, this function returns True. ++The optional second argument tells this function how many stack frames ++to traverse to find the calling function. The default is 1.""" ++ ++ def __init__ (self): ++ super (CallerMatches, self).__init__ ("caller_matches") ++ ++ def invoke (self, name, nframes = 1): ++ frame = gdb.selected_frame () ++ while nframes > 0: ++ frame = frame.older () ++ nframes = nframes - 1 ++ return re.match (name.string (), frame.name ()) is not None ++ ++CallerIs() ++CallerMatches() +diff --git a/gdb/python/lib/gdb/function/in_scope.py b/gdb/python/lib/gdb/function/in_scope.py +new file mode 100644 +index 0000000..debb3bb +--- /dev/null ++++ b/gdb/python/lib/gdb/function/in_scope.py +@@ -0,0 +1,47 @@ ++# In-scope function. ++ ++# Copyright (C) 2008 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 3 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, see . ++ ++import gdb ++ ++class InScope (gdb.Function): ++ """Return True if all the given variables or macros are in scope. ++Takes one argument for each variable name to be checked.""" ++ ++ def __init__ (self): ++ super (InScope, self).__init__ ("in_scope") ++ ++ def invoke (self, *vars): ++ if len (vars) == 0: ++ raise TypeError, "in_scope takes at least one argument" ++ ++ # gdb.Value isn't hashable so it can't be put in a map. ++ # Convert to string first. ++ wanted = set (map (lambda x: x.string (), vars)) ++ found = set () ++ block = gdb.selected_frame ().block () ++ while block: ++ for sym in block: ++ if (sym.is_argument or sym.is_constant ++ or sym.is_function or sym.is_variable): ++ if sym.name in wanted: ++ found.add (sym.name) ++ ++ block = block.superblock ++ ++ return wanted == found ++ ++InScope () +diff --git a/gdb/python/lib/gdb/libstdcxx/__init__.py b/gdb/python/lib/gdb/libstdcxx/__init__.py +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/gdb/python/lib/gdb/libstdcxx/__init__.py +@@ -0,0 +1 @@ ++ +diff --git a/gdb/python/lib/gdb/libstdcxx/v6/__init__.py b/gdb/python/lib/gdb/libstdcxx/v6/__init__.py +new file mode 100644 +index 0000000..8b13789 +--- /dev/null ++++ b/gdb/python/lib/gdb/libstdcxx/v6/__init__.py +@@ -0,0 +1 @@ ++ +diff --git a/gdb/python/lib/gdb/libstdcxx/v6/hook.in b/gdb/python/lib/gdb/libstdcxx/v6/hook.in +new file mode 100644 +index 0000000..fe7c072 +--- /dev/null ++++ b/gdb/python/lib/gdb/libstdcxx/v6/hook.in +@@ -0,0 +1,27 @@ ++# -*- python -*- ++# Copyright (C) 2009 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 3 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, see . ++ ++import sys ++import gdb ++ ++# Update module path. ++dir = '@dir@' ++if not dir in sys.path: ++ sys.path.insert(0, dir) ++ ++# Load the pretty-printers. ++from libstdcxx.v6.printers import register_libstdcxx_printers ++register_libstdcxx_printers (gdb.current_objfile ()) +diff --git a/gdb/python/lib/gdb/libstdcxx/v6/printers.py b/gdb/python/lib/gdb/libstdcxx/v6/printers.py +new file mode 100644 +index 0000000..58fd91c +--- /dev/null ++++ b/gdb/python/lib/gdb/libstdcxx/v6/printers.py +@@ -0,0 +1,629 @@ ++# Pretty-printers for libstc++. ++ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++import gdb ++import itertools ++import re ++ ++class StdPointerPrinter: ++ "Print a smart pointer of some kind" ++ ++ def __init__ (self, typename, val): ++ self.typename = typename ++ self.val = val ++ ++ def to_string (self): ++ return '%s (count %d) %s' % (self.typename, ++ self.val['_M_refcount']['_M_pi']['_M_use_count'], ++ self.val['_M_ptr']) ++ ++class UniquePointerPrinter: ++ "Print a unique_ptr" ++ ++ def __init__ (self, val): ++ self.val = val ++ ++ def to_string (self): ++ return self.val['_M_t'] ++ ++class StdListPrinter: ++ "Print a std::list" ++ ++ class _iterator: ++ def __init__(self, nodetype, head): ++ self.nodetype = nodetype ++ self.base = head['_M_next'] ++ self.head = head.address ++ self.count = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.base == self.head: ++ raise StopIteration ++ elt = self.base.cast(self.nodetype).dereference() ++ self.base = elt['_M_next'] ++ count = self.count ++ self.count = self.count + 1 ++ return ('[%d]' % count, elt['_M_data']) ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def children(self): ++ itype = self.val.type.template_argument(0) ++ nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer() ++ return self._iterator(nodetype, self.val['_M_impl']['_M_node']) ++ ++ def to_string(self): ++ if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']: ++ return 'empty std::list' ++ return 'std::list' ++ ++class StdListIteratorPrinter: ++ "Print std::list::iterator" ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ itype = self.val.type.template_argument(0) ++ nodetype = gdb.lookup_type('std::_List_node<%s>' % itype).pointer() ++ return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] ++ ++class StdSlistPrinter: ++ "Print a __gnu_cxx::slist" ++ ++ class _iterator: ++ def __init__(self, nodetype, head): ++ self.nodetype = nodetype ++ self.base = head['_M_head']['_M_next'] ++ self.count = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.base == 0: ++ raise StopIteration ++ elt = self.base.cast(self.nodetype).dereference() ++ self.base = elt['_M_next'] ++ count = self.count ++ self.count = self.count + 1 ++ return ('[%d]' % count, elt['_M_data']) ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def children(self): ++ itype = self.val.type.template_argument(0) ++ nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer() ++ return self._iterator(nodetype, self.val) ++ ++ def to_string(self): ++ if self.val['_M_head']['_M_next'] == 0: ++ return 'empty __gnu_cxx::slist' ++ return '__gnu_cxx::slist' ++ ++class StdSlistIteratorPrinter: ++ "Print __gnu_cxx::slist::iterator" ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ itype = self.val.type.template_argument(0) ++ nodetype = gdb.lookup_type('__gnu_cxx::_Slist_node<%s>' % itype).pointer() ++ return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] ++ ++class StdVectorPrinter: ++ "Print a std::vector" ++ ++ class _iterator: ++ def __init__ (self, start, finish): ++ self.item = start ++ self.finish = finish ++ self.count = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.item == self.finish: ++ raise StopIteration ++ count = self.count ++ self.count = self.count + 1 ++ elt = self.item.dereference() ++ self.item = self.item + 1 ++ return ('[%d]' % count, elt) ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def children(self): ++ return self._iterator(self.val['_M_impl']['_M_start'], ++ self.val['_M_impl']['_M_finish']) ++ ++ def to_string(self): ++ start = self.val['_M_impl']['_M_start'] ++ finish = self.val['_M_impl']['_M_finish'] ++ end = self.val['_M_impl']['_M_end_of_storage'] ++ return ('std::vector of length %d, capacity %d' ++ % (int (finish - start), int (end - start))) ++ ++ def display_hint(self): ++ return 'array' ++ ++class StdVectorIteratorPrinter: ++ "Print std::vector::iterator" ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ return self.val['_M_current'].dereference() ++ ++class StdStackOrQueuePrinter: ++ "Print a std::stack or std::queue" ++ ++ def __init__ (self, typename, val): ++ self.typename = typename ++ self.visualizer = gdb.default_visualizer(val['c']) ++ ++ def children (self): ++ return self.visualizer.children() ++ ++ def to_string (self): ++ return '%s wrapping: %s' % (self.typename, ++ self.visualizer.to_string()) ++ ++ def display_hint (self): ++ if hasattr (self.visualizer, 'display_hint'): ++ return self.visualizer.display_hint () ++ return None ++ ++class RbtreeIterator: ++ def __init__(self, rbtree): ++ self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] ++ self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] ++ self.count = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def __len__(self): ++ return int (self.size) ++ ++ def next(self): ++ if self.count == self.size: ++ raise StopIteration ++ result = self.node ++ self.count = self.count + 1 ++ if self.count < self.size: ++ # Compute the next node. ++ node = self.node ++ if node.dereference()['_M_right']: ++ node = node.dereference()['_M_right'] ++ while node.dereference()['_M_left']: ++ node = node.dereference()['_M_left'] ++ else: ++ parent = node.dereference()['_M_parent'] ++ while node == parent.dereference()['_M_right']: ++ node = parent ++ parent = parent.dereference()['_M_parent'] ++ if node.dereference()['_M_right'] != parent: ++ node = parent ++ self.node = node ++ return result ++ ++# This is a pretty printer for std::_Rb_tree_iterator (which is ++# std::map::iterator), and has nothing to do with the RbtreeIterator ++# class above. ++class StdRbtreeIteratorPrinter: ++ "Print std::map::iterator" ++ ++ def __init__ (self, val): ++ self.val = val ++ ++ def to_string (self): ++ valuetype = self.val.type.template_argument(0) ++ nodetype = gdb.lookup_type('std::_Rb_tree_node < %s >' % valuetype) ++ nodetype = nodetype.pointer() ++ return self.val.cast(nodetype).dereference()['_M_value_field'] ++ ++ ++class StdMapPrinter: ++ "Print a std::map or std::multimap" ++ ++ # Turn an RbtreeIterator into a pretty-print iterator. ++ class _iter: ++ def __init__(self, rbiter, type): ++ self.rbiter = rbiter ++ self.count = 0 ++ self.type = type ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.count % 2 == 0: ++ n = self.rbiter.next() ++ n = n.cast(self.type).dereference()['_M_value_field'] ++ self.pair = n ++ item = n['first'] ++ else: ++ item = self.pair['second'] ++ result = ('[%d]' % self.count, item) ++ self.count = self.count + 1 ++ return result ++ ++ def __init__ (self, typename, val): ++ self.typename = typename ++ self.val = val ++ self.iter = RbtreeIterator (val) ++ ++ def to_string (self): ++ return '%s with %d elements' % (self.typename, len (self.iter)) ++ ++ def children (self): ++ keytype = self.val.type.template_argument(0).const() ++ valuetype = self.val.type.template_argument(1) ++ nodetype = gdb.lookup_type('std::_Rb_tree_node< std::pair< %s, %s > >' % (keytype, valuetype)) ++ nodetype = nodetype.pointer() ++ return self._iter (self.iter, nodetype) ++ ++ def display_hint (self): ++ return 'map' ++ ++class StdSetPrinter: ++ "Print a std::set or std::multiset" ++ ++ # Turn an RbtreeIterator into a pretty-print iterator. ++ class _iter: ++ def __init__(self, rbiter, type): ++ self.rbiter = rbiter ++ self.count = 0 ++ self.type = type ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ item = self.rbiter.next() ++ item = item.cast(self.type).dereference()['_M_value_field'] ++ # FIXME: this is weird ... what to do? ++ # Maybe a 'set' display hint? ++ result = ('[%d]' % self.count, item) ++ self.count = self.count + 1 ++ return result ++ ++ def __init__ (self, typename, val): ++ self.typename = typename ++ self.val = val ++ self.iter = RbtreeIterator (val) ++ ++ def to_string (self): ++ return '%s with %d elements' % (self.typename, len (self.iter)) ++ ++ def children (self): ++ keytype = self.val.type.template_argument(0) ++ nodetype = gdb.lookup_type('std::_Rb_tree_node< %s >' % keytype).pointer() ++ return self._iter (self.iter, nodetype) ++ ++class StdBitsetPrinter: ++ "Print a std::bitset" ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string (self): ++ # If template_argument handled values, we could print the ++ # size. Or we could use a regexp on the type. ++ return 'std::bitset' ++ ++ def children (self): ++ words = self.val['_M_w'] ++ wtype = words.type ++ ++ # The _M_w member can be either an unsigned long, or an ++ # array. This depends on the template specialization used. ++ # If it is a single long, convert to a single element list. ++ if wtype.code == gdb.TYPE_CODE_ARRAY: ++ tsize = wtype.target ().sizeof ++ else: ++ words = [words] ++ tsize = wtype.sizeof ++ ++ nwords = wtype.sizeof / tsize ++ result = [] ++ byte = 0 ++ while byte < nwords: ++ w = words[byte] ++ bit = 0 ++ while w != 0: ++ if (w & 1) != 0: ++ # Another spot where we could use 'set'? ++ result.append(('[%d]' % (byte * tsize * 8 + bit), 1)) ++ bit = bit + 1 ++ w = w >> 1 ++ byte = byte + 1 ++ return result ++ ++class StdDequePrinter: ++ "Print a std::deque" ++ ++ class _iter: ++ def __init__(self, node, start, end, last, buffer_size): ++ self.node = node ++ self.p = start ++ self.end = end ++ self.last = last ++ self.buffer_size = buffer_size ++ self.count = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.p == self.last: ++ raise StopIteration ++ ++ result = ('[%d]' % self.count, self.p.dereference()) ++ self.count = self.count + 1 ++ ++ # Advance the 'cur' pointer. ++ self.p = self.p + 1 ++ if self.p == self.end: ++ # If we got to the end of this bucket, move to the ++ # next bucket. ++ self.node = self.node + 1 ++ self.p = self.node[0] ++ self.end = self.p + self.buffer_size ++ ++ return result ++ ++ def __init__(self, val): ++ self.val = val ++ self.elttype = val.type.template_argument(0) ++ size = self.elttype.sizeof ++ if size < 512: ++ self.buffer_size = int (512 / size) ++ else: ++ self.buffer_size = 1 ++ ++ def to_string(self): ++ start = self.val['_M_impl']['_M_start'] ++ end = self.val['_M_impl']['_M_finish'] ++ ++ delta_n = end['_M_node'] - start['_M_node'] - 1 ++ delta_s = start['_M_last'] - start['_M_cur'] ++ delta_e = end['_M_cur'] - end['_M_first'] ++ ++ size = self.buffer_size * delta_n + delta_s + delta_e ++ ++ return 'std::deque with %d elements' % long (size) ++ ++ def children(self): ++ start = self.val['_M_impl']['_M_start'] ++ end = self.val['_M_impl']['_M_finish'] ++ return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'], ++ end['_M_cur'], self.buffer_size) ++ ++ def display_hint (self): ++ return 'array' ++ ++class StdDequeIteratorPrinter: ++ "Print std::deque::iterator" ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ return self.val['_M_cur'].dereference() ++ ++class StdStringPrinter: ++ "Print a std::basic_string of some kind" ++ ++ def __init__(self, encoding, val): ++ self.encoding = encoding ++ self.val = val ++ ++ def to_string(self): ++ # Look up the target encoding as late as possible. ++ encoding = self.encoding ++ if encoding[0] is '@': ++ encoding = gdb.parameter(encoding[1:]) ++ return self.val['_M_dataplus']['_M_p'].string(encoding) ++ ++ def display_hint (self): ++ return 'string' ++ ++class Tr1HashtableIterator: ++ def __init__ (self, hash): ++ self.count = 0 ++ self.n_buckets = hash['_M_element_count'] ++ if self.n_buckets == 0: ++ self.node = False ++ else: ++ self.bucket = hash['_M_buckets'] ++ self.node = self.bucket[0] ++ self.update () ++ ++ def __iter__ (self): ++ return self ++ ++ def update (self): ++ # If we advanced off the end of the chain, move to the next ++ # bucket. ++ while self.node == 0: ++ self.bucket = self.bucket + 1 ++ self.node = self.bucket[0] ++ ++ # If we advanced off the end of the bucket array, then ++ # we're done. ++ if self.count == self.n_buckets: ++ self.node = False ++ else: ++ self.count = self.count + 1 ++ ++ def next (self): ++ if not self.node: ++ raise StopIteration ++ result = self.node.dereference()['_M_v'] ++ self.node = self.node.dereference()['_M_next'] ++ self.update () ++ return result ++ ++class Tr1UnorderedSetPrinter: ++ "Print a tr1::unordered_set" ++ ++ def __init__ (self, typename, val): ++ self.typename = typename ++ self.val = val ++ ++ def to_string (self): ++ return '%s with %d elements' % (self.typename, self.val['_M_element_count']) ++ ++ @staticmethod ++ def format_count (i): ++ return '[%d]' % i ++ ++ def children (self): ++ counter = itertools.imap (self.format_count, itertools.count()) ++ return itertools.izip (counter, Tr1HashtableIterator (self.val)) ++ ++class Tr1UnorderedMapPrinter: ++ "Print a tr1::unordered_map" ++ ++ def __init__ (self, typename, val): ++ self.typename = typename ++ self.val = val ++ ++ def to_string (self): ++ return '%s with %d elements' % (self.typename, self.val['_M_element_count']) ++ ++ @staticmethod ++ def flatten (list): ++ for elt in list: ++ for i in elt: ++ yield i ++ ++ @staticmethod ++ def format_one (elt): ++ return (elt['first'], elt['second']) ++ ++ @staticmethod ++ def format_count (i): ++ return '[%d]' % i ++ ++ def children (self): ++ counter = itertools.imap (self.format_count, itertools.count()) ++ # Map over the hash table and flatten the result. ++ data = self.flatten (itertools.imap (self.format_one, Tr1HashtableIterator (self.val))) ++ # Zip the two iterators together. ++ return itertools.izip (counter, data) ++ ++ def display_hint (self): ++ return 'map' ++ ++def register_libstdcxx_printers (obj): ++ "Register libstdc++ pretty-printers with objfile Obj." ++ ++ if obj == None: ++ obj = gdb ++ ++ obj.pretty_printers.append (lookup_function) ++ ++def lookup_function (val): ++ "Look-up and return a pretty-printer that can print val." ++ ++ # Get the type. ++ type = val.type; ++ ++ # If it points to a reference, get the reference. ++ if type.code == gdb.TYPE_CODE_REF: ++ type = type.target () ++ ++ # Get the unqualified type, stripped of typedefs. ++ type = type.unqualified ().strip_typedefs () ++ ++ # Get the type name. ++ typename = type.tag ++ if typename == None: ++ return None ++ ++ # Iterate over local dictionary of types to determine ++ # if a printer is registered for that type. Return an ++ # instantiation of the printer if found. ++ for function in pretty_printers_dict: ++ if function.search (typename): ++ return pretty_printers_dict[function] (val) ++ ++ # Cannot find a pretty printer. Return None. ++ return None ++ ++def build_libstdcxx_dictionary (): ++ # libstdc++ objects requiring pretty-printing. ++ # In order from: ++ # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html ++ pretty_printers_dict[re.compile('^std::basic_string$')] = lambda val: StdStringPrinter('@target-charset', val) ++ pretty_printers_dict[re.compile('^std::basic_string$')] = lambda val: StdStringPrinter('@target-wide-charset', val) ++ pretty_printers_dict[re.compile('^std::basic_string$')] = lambda val: StdStringPrinter('UTF-16', val) ++ pretty_printers_dict[re.compile('^std::basic_string$')] = lambda val: StdStringPrinter('UTF-32', val) ++ pretty_printers_dict[re.compile('^std::bitset<.*>$')] = StdBitsetPrinter ++ pretty_printers_dict[re.compile('^std::deque<.*>$')] = StdDequePrinter ++ pretty_printers_dict[re.compile('^std::list<.*>$')] = StdListPrinter ++ pretty_printers_dict[re.compile('^std::map<.*>$')] = lambda val: StdMapPrinter("std::map", val) ++ pretty_printers_dict[re.compile('^std::multimap<.*>$')] = lambda val: StdMapPrinter("std::multimap", val) ++ pretty_printers_dict[re.compile('^std::multiset<.*>$')] = lambda val: StdSetPrinter("std::multiset", val) ++ pretty_printers_dict[re.compile('^std::priority_queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::priority_queue", val) ++ pretty_printers_dict[re.compile('^std::queue<.*>$')] = lambda val: StdStackOrQueuePrinter("std::queue", val) ++ pretty_printers_dict[re.compile('^std::set<.*>$')] = lambda val: StdSetPrinter("std::set", val) ++ pretty_printers_dict[re.compile('^std::stack<.*>$')] = lambda val: StdStackOrQueuePrinter("std::stack", val) ++ pretty_printers_dict[re.compile('^std::unique_ptr<.*>$')] = UniquePointerPrinter ++ pretty_printers_dict[re.compile('^std::vector<.*>$')] = StdVectorPrinter ++ # vector ++ ++ # These are the C++0x printers. They also exist in the standard namespace. ++ # For array - the default GDB pretty-printer seems reasonable. ++ pretty_printers_dict[re.compile('^std::(tr1::)?shared_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::shared_ptr', val) ++ pretty_printers_dict[re.compile('^std::(tr1::)?weak_ptr<.*>$')] = lambda val: StdPointerPrinter ('std::weak_ptr', val) ++ pretty_printers_dict[re.compile('^std::(tr1::)?unordered_map<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::tr1::unordered_map', val) ++ pretty_printers_dict[re.compile('^std::(tr1::)?unordered_set<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::tr1::unordered_set', val) ++ pretty_printers_dict[re.compile('^std::(tr1::)?unordered_multimap<.*>$')] = lambda val: Tr1UnorderedMapPrinter ('std::tr1::unordered_multimap', val) ++ pretty_printers_dict[re.compile('^std::(tr1::)?unordered_multiset<.*>$')] = lambda val: Tr1UnorderedSetPrinter ('std::tr1::unordered_multiset', val) ++ ++ ++ # Extensions. ++ pretty_printers_dict[re.compile('^__gnu_cxx::slist<.*>$')] = StdSlistPrinter ++ ++ if True: ++ # These shouldn't be necessary, if GDB "print *i" worked. ++ # But it often doesn't, so here they are. ++ pretty_printers_dict[re.compile('^std::_List_iterator<.*>$')] = lambda val: StdListIteratorPrinter(val) ++ pretty_printers_dict[re.compile('^std::_List_const_iterator<.*>$')] = lambda val: StdListIteratorPrinter(val) ++ pretty_printers_dict[re.compile('^std::_Rb_tree_iterator<.*>$')] = lambda val: StdRbtreeIteratorPrinter(val) ++ pretty_printers_dict[re.compile('^std::_Rb_tree_const_iterator<.*>$')] = lambda val: StdRbtreeIteratorPrinter(val) ++ pretty_printers_dict[re.compile('^std::_Deque_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) ++ pretty_printers_dict[re.compile('^std::_Deque_const_iterator<.*>$')] = lambda val: StdDequeIteratorPrinter(val) ++ pretty_printers_dict[re.compile('^__gnu_cxx::__normal_iterator<.*>$')] = lambda val: StdVectorIteratorPrinter(val) ++ pretty_printers_dict[re.compile('^__gnu_cxx::_Slist_iterator<.*>$')] = lambda val: StdSlistIteratorPrinter(val) ++ ++pretty_printers_dict = {} ++ ++build_libstdcxx_dictionary () +diff --git a/gdb/python/python-block.c b/gdb/python/python-block.c +new file mode 100644 +index 0000000..8019e9d +--- /dev/null ++++ b/gdb/python/python-block.c +@@ -0,0 +1,265 @@ ++/* Python interface to blocks. ++ ++ Copyright (C) 2008 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 3 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, see . */ ++ ++#include "defs.h" ++#include "block.h" ++#include "dictionary.h" ++#include "symtab.h" ++#include "python-internal.h" ++ ++typedef struct { ++ PyObject_HEAD ++ struct block *block; ++} block_object; ++ ++typedef struct { ++ PyObject_HEAD ++ struct dictionary *dict; ++ struct dict_iterator iter; ++ int initialized_p; ++} block_syms_iterator_object; ++ ++static PyTypeObject block_syms_iterator_object_type; ++ ++static PyObject * ++blpy_iter (PyObject *self) ++{ ++ block_syms_iterator_object *block_iter_obj; ++ ++ block_iter_obj = PyObject_New (block_syms_iterator_object, ++ &block_syms_iterator_object_type); ++ if (block_iter_obj == NULL) ++ { ++ PyErr_SetString (PyExc_MemoryError, ++ "Could not allocate iterator object."); ++ return NULL; ++ } ++ ++ block_iter_obj->dict = BLOCK_DICT (((block_object *) self)->block); ++ block_iter_obj->initialized_p = 0; ++ ++ return (PyObject *) block_iter_obj; ++} ++ ++static PyObject * ++blpy_get_start (PyObject *self, void *closure) ++{ ++ block_object *self_block = (block_object *) self; ++ ++ return PyLong_FromUnsignedLongLong (BLOCK_START (self_block->block)); ++} ++ ++static PyObject * ++blpy_get_end (PyObject *self, void *closure) ++{ ++ block_object *self_block = (block_object *) self; ++ ++ return PyLong_FromUnsignedLongLong (BLOCK_END (self_block->block)); ++} ++ ++static PyObject * ++blpy_get_function (PyObject *self, void *closure) ++{ ++ block_object *self_block = (block_object *) self; ++ struct symbol *sym; ++ ++ sym = BLOCK_FUNCTION (self_block->block); ++ if (sym) ++ return symbol_to_symbol_object (sym); ++ ++ Py_RETURN_NONE; ++} ++ ++static PyObject * ++blpy_get_superblock (PyObject *self, void *closure) ++{ ++ block_object *self_block = (block_object *) self; ++ struct block *block; ++ ++ block = BLOCK_SUPERBLOCK (self_block->block); ++ if (block) ++ return block_to_block_object (block); ++ ++ Py_RETURN_NONE; ++} ++ ++PyObject * ++block_to_block_object (struct block *block) ++{ ++ block_object *block_obj; ++ ++ block_obj = PyObject_New (block_object, &block_object_type); ++ if (block_obj == NULL) ++ { ++ PyErr_SetString (PyExc_MemoryError, "Could not allocate block object."); ++ return NULL; ++ } ++ ++ block_obj->block = block; ++ ++ return (PyObject *) block_obj; ++} ++ ++struct block * ++block_object_to_block (PyObject *obj) ++{ ++ if (! PyObject_TypeCheck (obj, &block_object_type)) ++ return NULL; ++ return ((block_object *) obj)->block; ++} ++ ++static PyObject * ++blpy_block_syms_iter (PyObject *self) ++{ ++ return self; ++} ++ ++static PyObject * ++blpy_block_syms_iternext (PyObject *self) ++{ ++ block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self; ++ struct symbol *sym; ++ ++ if (!iter_obj->initialized_p) ++ { ++ sym = dict_iterator_first (iter_obj->dict, &(iter_obj->iter)); ++ iter_obj->initialized_p = 1; ++ } ++ else ++ sym = dict_iterator_next (&(iter_obj->iter)); ++ ++ return (sym == NULL)? NULL : symbol_to_symbol_object (sym); ++} ++ ++/* Return the innermost lexical block containing the specified pc value, ++ or 0 if there is none. */ ++ ++PyObject * ++gdbpy_block_for_pc (PyObject *self, PyObject *args) ++{ ++ unsigned PY_LONG_LONG pc; ++ struct block *block; ++ PyObject *sym_obj; ++ ++ if (!PyArg_ParseTuple (args, "K", &pc)) ++ return NULL; ++ ++ block = block_for_pc (pc); ++ if (block) ++ return block_to_block_object (block); ++ ++ Py_RETURN_NONE; ++} ++ ++void ++gdbpy_initialize_blocks (void) ++{ ++ block_object_type.tp_new = PyType_GenericNew; ++ if (PyType_Ready (&block_object_type) < 0) ++ return; ++ ++ block_syms_iterator_object_type.tp_new = PyType_GenericNew; ++ if (PyType_Ready (&block_syms_iterator_object_type) < 0) ++ return; ++ ++ Py_INCREF (&block_object_type); ++ PyModule_AddObject (gdb_module, "Block", (PyObject *) &block_object_type); ++ ++ Py_INCREF (&block_syms_iterator_object_type); ++ PyModule_AddObject (gdb_module, "BlockIterator", ++ (PyObject *) &block_syms_iterator_object_type); ++} ++ ++ ++ ++static PyGetSetDef block_object_getset[] = { ++ { "start", blpy_get_start, NULL, "Start address of the block.", NULL }, ++ { "end", blpy_get_end, NULL, "End address of the block.", NULL }, ++ { "function", blpy_get_function, NULL, ++ "Symbol that names the block, or None.", NULL }, ++ { "superblock", blpy_get_superblock, NULL, ++ "Block containing the block, or None.", NULL }, ++ { NULL } /* Sentinel */ ++}; ++ ++PyTypeObject block_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Block", /*tp_name*/ ++ sizeof (block_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ 0, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ 0, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ ++ "GDB block object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ blpy_iter, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ block_object_getset /* tp_getset */ ++}; ++ ++static PyTypeObject block_syms_iterator_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.BlockIterator", /*tp_name*/ ++ sizeof (block_syms_iterator_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ 0, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ 0, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ ++ "GDB block syms iterator object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ blpy_block_syms_iter, /* tp_iter */ ++ blpy_block_syms_iternext, /* tp_iternext */ ++ 0 /* tp_methods */ ++}; +diff --git a/gdb/python/python-breakpoint.c b/gdb/python/python-breakpoint.c +new file mode 100644 +index 0000000..ec80419 +--- /dev/null ++++ b/gdb/python/python-breakpoint.c +@@ -0,0 +1,665 @@ ++/* Python interface to breakpoints ++ ++ Copyright (C) 2008, 2009 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 3 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, see . */ ++ ++#include "defs.h" ++#include "value.h" ++#include "exceptions.h" ++#include "python-internal.h" ++#include "charset.h" ++#include "breakpoint.h" ++#include "gdbcmd.h" ++#include "gdbthread.h" ++#include "observer.h" ++ ++ ++/* From breakpoint.c. */ ++extern struct breakpoint *breakpoint_chain; ++ ++ ++typedef struct breakpoint_object breakpoint_object; ++ ++static PyTypeObject breakpoint_object_type; ++ ++/* A dynamically allocated vector of breakpoint objects. Each ++ breakpoint has a number. A breakpoint is valid if its slot in this ++ vector is non-null. When a breakpoint is deleted, we drop our ++ reference to it and zero its slot; this is how we let the Python ++ object have a lifetime which is independent from that of the gdb ++ breakpoint. */ ++static breakpoint_object **bppy_breakpoints; ++ ++/* Number of slots in bppy_breakpoints. */ ++static int bppy_slots; ++ ++/* Number of live breakpoints. */ ++static int bppy_live; ++ ++/* Variables used to pass information between the Breakpoint ++ constructor and the breakpoint-created hook function. */ ++static breakpoint_object *bppy_pending_object; ++ ++struct breakpoint_object ++{ ++ PyObject_HEAD ++ ++ /* The breakpoint number according to gdb. */ ++ int number; ++ ++ /* The gdb breakpoint object, or NULL if the breakpoint has been ++ deleted. */ ++ struct breakpoint *bp; ++}; ++ ++/* Evaluate to true if the breakpoint NUM is valid, false otherwise. */ ++#define BPPY_VALID_P(Num) \ ++ ((Num) >= 0 \ ++ && (Num) < bppy_slots \ ++ && bppy_breakpoints[Num] != NULL) ++ ++/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python ++ exception if it is invalid. */ ++#define BPPY_REQUIRE_VALID(Breakpoint) \ ++ do { \ ++ if (! BPPY_VALID_P ((Breakpoint)->number)) \ ++ return PyErr_Format (PyExc_RuntimeError, "breakpoint %d is invalid", \ ++ (Breakpoint)->number); \ ++ } while (0) ++ ++/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python ++ exception if it is invalid. This macro is for use in setter functions. */ ++#define BPPY_SET_REQUIRE_VALID(Breakpoint) \ ++ do { \ ++ if (! BPPY_VALID_P ((Breakpoint)->number)) \ ++ { \ ++ PyErr_Format (PyExc_RuntimeError, "breakpoint %d is invalid", \ ++ (Breakpoint)->number); \ ++ return -1; \ ++ } \ ++ } while (0) ++ ++/* Python function which checks the validity of a breakpoint object. */ ++static PyObject * ++bppy_is_valid (PyObject *self, PyObject *args) ++{ ++ if (((breakpoint_object *) self)->bp) ++ Py_RETURN_TRUE; ++ Py_RETURN_FALSE; ++} ++ ++/* Python function to test whether or not the breakpoint is enabled. */ ++static PyObject * ++bppy_get_enabled (PyObject *self, void *closure) ++{ ++ if (! ((breakpoint_object *) self)->bp) ++ Py_RETURN_FALSE; ++ /* Not clear what we really want here. */ ++ if (((breakpoint_object *) self)->bp->enable_state == bp_enabled) ++ Py_RETURN_TRUE; ++ Py_RETURN_FALSE; ++} ++ ++/* Python function to test whether or not the breakpoint is silent. */ ++static PyObject * ++bppy_get_silent (PyObject *self, void *closure) ++{ ++ BPPY_REQUIRE_VALID ((breakpoint_object *) self); ++ if (((breakpoint_object *) self)->bp->silent) ++ Py_RETURN_TRUE; ++ Py_RETURN_FALSE; ++} ++ ++/* Python function to set the enabled state of a breakpoint. */ ++static int ++bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ int cmp; ++ ++ BPPY_SET_REQUIRE_VALID (self_bp); ++ ++ if (newvalue == NULL) ++ { ++ PyErr_SetString (PyExc_TypeError, "cannot delete `enabled' attribute"); ++ return -1; ++ } ++ else if (! PyBool_Check (newvalue)) ++ { ++ PyErr_SetString (PyExc_TypeError, ++ "the value of `enabled' must be a boolean"); ++ return -1; ++ } ++ ++ cmp = PyObject_IsTrue (newvalue); ++ if (cmp < 0) ++ return -1; ++ else if (cmp == 1) ++ enable_breakpoint (self_bp->bp); ++ else ++ disable_breakpoint (self_bp->bp); ++ return 0; ++} ++ ++/* Python function to set the 'silent' state of a breakpoint. */ ++static int ++bppy_set_silent (PyObject *self, PyObject *newvalue, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ int cmp; ++ ++ BPPY_SET_REQUIRE_VALID (self_bp); ++ ++ if (newvalue == NULL) ++ { ++ PyErr_SetString (PyExc_TypeError, "cannot delete `silent' attribute"); ++ return -1; ++ } ++ else if (! PyBool_Check (newvalue)) ++ { ++ PyErr_SetString (PyExc_TypeError, ++ "the value of `silent' must be a boolean"); ++ return -1; ++ } ++ ++ cmp = PyObject_IsTrue (newvalue); ++ if (cmp < 0) ++ return -1; ++ else ++ self_bp->bp->silent = cmp; ++ ++ return 0; ++} ++ ++/* Python function to set the thread of a breakpoint. */ ++static int ++bppy_set_thread (PyObject *self, PyObject *newvalue, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ int id; ++ ++ BPPY_SET_REQUIRE_VALID (self_bp); ++ ++ if (newvalue == NULL) ++ { ++ PyErr_SetString (PyExc_TypeError, "cannot delete `thread' attribute"); ++ return -1; ++ } ++ else if (PyInt_Check (newvalue)) ++ { ++ id = (int) PyInt_AsLong (newvalue); ++ if (! valid_thread_id (id)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "invalid thread id"); ++ return -1; ++ } ++ } ++ else if (newvalue == Py_None) ++ id = -1; ++ else ++ { ++ PyErr_SetString (PyExc_TypeError, ++ "the value of `thread' must be an integer or None"); ++ return -1; ++ } ++ ++ self_bp->bp->thread = id; ++ ++ return 0; ++} ++ ++/* Python function to set the ignore count of a breakpoint. */ ++static int ++bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ long value; ++ ++ BPPY_SET_REQUIRE_VALID (self_bp); ++ ++ if (newvalue == NULL) ++ { ++ PyErr_SetString (PyExc_TypeError, ++ "cannot delete `ignore_count' attribute"); ++ return -1; ++ } ++ else if (! PyInt_Check (newvalue)) ++ { ++ PyErr_SetString (PyExc_TypeError, ++ "the value of `ignore_count' must be an integer"); ++ return -1; ++ } ++ ++ value = PyInt_AsLong (newvalue); ++ if (value < 0) ++ value = 0; ++ set_ignore_count (self_bp->number, (int) value, 0); ++ ++ return 0; ++} ++ ++/* Python function to set the hit count of a breakpoint. */ ++static int ++bppy_set_hit_count (PyObject *self, PyObject *newvalue, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ ++ BPPY_SET_REQUIRE_VALID (self_bp); ++ ++ if (newvalue == NULL) ++ { ++ PyErr_SetString (PyExc_TypeError, "cannot delete `hit_count' attribute"); ++ return -1; ++ } ++ else if (! PyInt_Check (newvalue) || PyInt_AsLong (newvalue) != 0) ++ { ++ PyErr_SetString (PyExc_AttributeError, ++ "the value of `hit_count' must be zero"); ++ return -1; ++ } ++ ++ self_bp->bp->hit_count = 0; ++ ++ return 0; ++} ++ ++/* Python function to get the location of a breakpoint. */ ++static PyObject * ++bppy_get_location (PyObject *self, void *closure) ++{ ++ char *str; ++ ++ BPPY_REQUIRE_VALID ((breakpoint_object *) self); ++ str = ((breakpoint_object *) self)->bp->addr_string; ++ /* FIXME: watchpoints? tracepoints? */ ++ if (! str) ++ str = ""; ++ return PyString_Decode (str, strlen (str), host_charset (), NULL); ++} ++ ++/* Python function to get the condition expression of a breakpoint. */ ++static PyObject * ++bppy_get_condition (PyObject *self, void *closure) ++{ ++ char *str; ++ BPPY_REQUIRE_VALID ((breakpoint_object *) self); ++ ++ str = ((breakpoint_object *) self)->bp->cond_string; ++ if (! str) ++ Py_RETURN_NONE; ++ return PyString_Decode (str, strlen (str), host_charset (), NULL); ++} ++ ++static int ++bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure) ++{ ++ char *exp; ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ volatile struct gdb_exception except; ++ ++ BPPY_SET_REQUIRE_VALID (self_bp); ++ ++ if (newvalue == NULL) ++ { ++ PyErr_SetString (PyExc_TypeError, "cannot delete `condition' attribute"); ++ return -1; ++ } ++ else if (newvalue == Py_None) ++ exp = ""; ++ else ++ { ++ exp = python_string_to_host_string (newvalue); ++ if (exp == NULL) ++ return -1; ++ } ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ set_breakpoint_condition (self_bp->bp, exp, 0); ++ } ++ GDB_PY_SET_HANDLE_EXCEPTION (except); ++ ++ return 0; ++} ++ ++/* Python function to get the commands attached to a breakpoint. */ ++static PyObject * ++bppy_get_commands (PyObject *self, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ long length; ++ volatile struct gdb_exception except; ++ struct ui_file *string_file; ++ struct cleanup *chain; ++ PyObject *result; ++ char *cmdstr; ++ ++ BPPY_REQUIRE_VALID (self_bp); ++ ++ if (! self_bp->bp->commands) ++ Py_RETURN_NONE; ++ ++ string_file = mem_fileopen (); ++ chain = make_cleanup_ui_file_delete (string_file); ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ /* FIXME: this can fail. Maybe we need to be making a new ++ ui_out object here? */ ++ ui_out_redirect (uiout, string_file); ++ print_command_lines (uiout, self_bp->bp->commands, 0); ++ ui_out_redirect (uiout, NULL); ++ } ++ cmdstr = ui_file_xstrdup (string_file, &length); ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ result = PyString_Decode (cmdstr, strlen (cmdstr), host_charset (), NULL); ++ do_cleanups (chain); ++ xfree (cmdstr); ++ return result; ++} ++ ++/* Python function to get the breakpoint's number. */ ++static PyObject * ++bppy_get_number (PyObject *self, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ ++ BPPY_REQUIRE_VALID (self_bp); ++ ++ return PyInt_FromLong (self_bp->number); ++} ++ ++/* Python function to get the breakpoint's thread ID. */ ++static PyObject * ++bppy_get_thread (PyObject *self, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ ++ BPPY_REQUIRE_VALID (self_bp); ++ ++ if (self_bp->bp->thread == -1) ++ Py_RETURN_NONE; ++ ++ return PyInt_FromLong (self_bp->bp->thread); ++} ++ ++/* Python function to get the breakpoint's hit count. */ ++static PyObject * ++bppy_get_hit_count (PyObject *self, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ ++ BPPY_REQUIRE_VALID (self_bp); ++ ++ return PyInt_FromLong (self_bp->bp->hit_count); ++} ++ ++/* Python function to get the breakpoint's ignore count. */ ++static PyObject * ++bppy_get_ignore_count (PyObject *self, void *closure) ++{ ++ breakpoint_object *self_bp = (breakpoint_object *) self; ++ ++ BPPY_REQUIRE_VALID (self_bp); ++ ++ return PyInt_FromLong (self_bp->bp->ignore_count); ++} ++ ++/* Python function to create a new breakpoint. */ ++static PyObject * ++bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs) ++{ ++ PyObject *result; ++ char *spec; ++ volatile struct gdb_exception except; ++ ++ /* FIXME: allow condition, thread, temporary, ... ? */ ++ if (! PyArg_ParseTuple (args, "s", &spec)) ++ return NULL; ++ result = subtype->tp_alloc (subtype, 0); ++ if (! result) ++ return NULL; ++ bppy_pending_object = (breakpoint_object *) result; ++ bppy_pending_object->number = -1; ++ bppy_pending_object->bp = NULL; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ set_breakpoint (spec, NULL, 0, 0, -1, 0, AUTO_BOOLEAN_TRUE, ++ 1 /*enabled*/); ++ } ++ if (except.reason < 0) ++ { ++ subtype->tp_free (result); ++ return PyErr_Format (except.reason == RETURN_QUIT ++ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, ++ "%s", except.message); ++ } ++ ++ BPPY_REQUIRE_VALID ((breakpoint_object *) result); ++ return result; ++} ++ ++ ++ ++/* Static function to return a tuple holding all breakpoints. */ ++ ++PyObject * ++gdbpy_breakpoints (PyObject *self, PyObject *args) ++{ ++ PyObject *result; ++ ++ if (bppy_live == 0) ++ Py_RETURN_NONE; ++ ++ result = PyTuple_New (bppy_live); ++ if (result) ++ { ++ int i, out = 0; ++ for (i = 0; out < bppy_live; ++i) ++ { ++ if (! bppy_breakpoints[i]) ++ continue; ++ Py_INCREF (bppy_breakpoints[i]); ++ PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]); ++ ++out; ++ } ++ } ++ return result; ++} ++ ++ ++ ++/* Event callback functions. */ ++ ++/* Callback that is used when a breakpoint is created. This function ++ will create a new Python breakpoint object. */ ++static void ++gdbpy_breakpoint_created (int num) ++{ ++ breakpoint_object *newbp; ++ struct breakpoint *bp; ++ PyGILState_STATE state; ++ ++ if (num < 0) ++ return; ++ ++ for (bp = breakpoint_chain; bp; bp = bp->next) ++ if (bp->number == num) ++ break; ++ if (! bp) ++ return; ++ ++ if (num >= bppy_slots) ++ { ++ int old = bppy_slots; ++ bppy_slots = bppy_slots * 2 + 10; ++ bppy_breakpoints ++ = (breakpoint_object **) xrealloc (bppy_breakpoints, ++ (bppy_slots ++ * sizeof (breakpoint_object *))); ++ memset (&bppy_breakpoints[old], 0, ++ (bppy_slots - old) * sizeof (PyObject *)); ++ } ++ ++ ++bppy_live; ++ ++ state = PyGILState_Ensure (); ++ ++ if (bppy_pending_object) ++ { ++ newbp = bppy_pending_object; ++ bppy_pending_object = NULL; ++ } ++ else ++ newbp = PyObject_New (breakpoint_object, &breakpoint_object_type); ++ if (newbp) ++ { ++ PyObject *hookfn; ++ ++ newbp->number = num; ++ newbp->bp = bp; ++ bppy_breakpoints[num] = newbp; ++ ++ hookfn = gdbpy_get_hook_function ("new_breakpoint"); ++ if (hookfn) ++ { ++ PyObject *result; ++ result = PyObject_CallFunctionObjArgs (hookfn, newbp, NULL); ++ if (result) ++ { ++ Py_DECREF (result); ++ } ++ Py_DECREF (hookfn); ++ } ++ } ++ ++ /* Just ignore errors here. */ ++ PyErr_Clear (); ++ ++ PyGILState_Release (state); ++} ++ ++/* Callback that is used when a breakpoint is deleted. This will ++ invalidate the corresponding Python object. */ ++static void ++gdbpy_breakpoint_deleted (int num) ++{ ++ PyGILState_STATE state; ++ ++ state = PyGILState_Ensure (); ++ if (BPPY_VALID_P (num)) ++ { ++ bppy_breakpoints[num]->bp = NULL; ++ Py_DECREF (bppy_breakpoints[num]); ++ bppy_breakpoints[num] = NULL; ++ --bppy_live; ++ } ++ PyGILState_Release (state); ++} ++ ++ ++ ++/* Initialize the Python breakpoint code. */ ++void ++gdbpy_initialize_breakpoints (void) ++{ ++ breakpoint_object_type.tp_new = bppy_new; ++ if (PyType_Ready (&breakpoint_object_type) < 0) ++ return; ++ ++ Py_INCREF (&breakpoint_object_type); ++ PyModule_AddObject (gdb_module, "Breakpoint", ++ (PyObject *) &breakpoint_object_type); ++ ++ observer_attach_breakpoint_created (gdbpy_breakpoint_created); ++ observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted); ++} ++ ++ ++ ++static PyGetSetDef breakpoint_object_getset[] = { ++ { "enabled", bppy_get_enabled, bppy_set_enabled, ++ "Boolean telling whether the breakpoint is enabled.", NULL }, ++ { "silent", bppy_get_silent, bppy_set_silent, ++ "Boolean telling whether the breakpoint is silent.", NULL }, ++ { "thread", bppy_get_thread, bppy_set_thread, ++ "Thread ID for the breakpoint.\n\ ++If the value is a thread ID (integer), then this is a thread-specific breakpoint.\n\ ++If the value is None, then this breakpoint not thread-specific.\n\ ++No other type of value can be used.", NULL }, ++ { "ignore_count", bppy_get_ignore_count, bppy_set_ignore_count, ++ "Number of times this breakpoint should be automatically continued.", ++ NULL }, ++ { "number", bppy_get_number, NULL, ++ "Breakpoint's number assigned by GDB.", NULL }, ++ { "hit_count", bppy_get_hit_count, bppy_set_hit_count, ++ "Number of times the breakpoint has been hit.\n\ ++Can be set to zero to clear the count. No other value is valid\n\ ++when setting this property.", NULL }, ++ { "location", bppy_get_location, NULL, ++ "Location of the breakpoint, as specified by the user.", NULL}, ++ { "condition", bppy_get_condition, bppy_set_condition, ++ "Condition of the breakpoint, as specified by the user,\ ++or None if no condition set."}, ++ { "commands", bppy_get_commands, NULL, ++ "Commands of the breakpoint, as specified by the user."}, ++ { NULL } /* Sentinel. */ ++}; ++ ++static PyMethodDef breakpoint_object_methods[] = ++{ ++ { "is_valid", bppy_is_valid, METH_NOARGS, ++ "Return true if this breakpoint is valid, false if not." }, ++ { NULL } /* Sentinel. */ ++}; ++ ++static PyTypeObject breakpoint_object_type = ++{ ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Breakpoint", /*tp_name*/ ++ sizeof (breakpoint_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ 0, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ 0, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT, /*tp_flags*/ ++ "GDB breakpoint object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ breakpoint_object_methods, /* tp_methods */ ++ 0, /* tp_members */ ++ breakpoint_object_getset /* tp_getset */ ++}; +diff --git a/gdb/python/python-cmd.c b/gdb/python/python-cmd.c +index 36cde34..e6e3ac0 100644 +--- a/gdb/python/python-cmd.c ++++ b/gdb/python/python-cmd.c +@@ -47,8 +47,7 @@ static struct cmdpy_completer completers[] = + + #define N_COMPLETERS (sizeof (completers) / sizeof (completers[0])) + +-/* A gdb command. For the time being only ordinary commands (not +- set/show commands) are allowed. */ ++/* A gdb command. */ + struct cmdpy_object + { + PyObject_HEAD +@@ -68,7 +67,6 @@ typedef struct cmdpy_object cmdpy_object; + + static PyTypeObject cmdpy_object_type; + +- + /* Constants used by this module. */ + static PyObject *invoke_cst; + static PyObject *complete_cst; +@@ -265,10 +263,13 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word) + *BASE_LIST is set to the final prefix command's list of + *sub-commands. + ++ START_LIST is the list in which the search starts. ++ + This function returns the xmalloc()d name of the new command. On + error sets the Python error and returns NULL. */ +-static char * +-parse_command_name (char *text, struct cmd_list_element ***base_list) ++char * ++gdbpy_parse_command_name (char *text, struct cmd_list_element ***base_list, ++ struct cmd_list_element **start_list) + { + struct cmd_list_element *elt; + int len = strlen (text); +@@ -301,7 +302,7 @@ parse_command_name (char *text, struct cmd_list_element ***base_list) + ; + if (i < 0) + { +- *base_list = &cmdlist; ++ *base_list = start_list; + return result; + } + +@@ -310,7 +311,7 @@ parse_command_name (char *text, struct cmd_list_element ***base_list) + prefix_text[i + 1] = '\0'; + + text = prefix_text; +- elt = lookup_cmd_1 (&text, cmdlist, NULL, 1); ++ elt = lookup_cmd_1 (&text, *start_list, NULL, 1); + if (!elt || elt == (struct cmd_list_element *) -1) + { + PyErr_Format (PyExc_RuntimeError, _("could not find command prefix %s"), +@@ -336,16 +337,16 @@ parse_command_name (char *text, struct cmd_list_element ***base_list) + + /* Object initializer; sets up gdb-side structures for command. + +- Use: __init__(NAME, CMDCLASS, [COMPLETERCLASS, [PREFIX]]). ++ Use: __init__(NAME, COMMAND_CLASS, [COMPLETER_CLASS, [PREFIX]]). + + NAME is the name of the command. It may consist of multiple words, + in which case the final word is the name of the new command, and + earlier words must be prefix commands. + +- CMDCLASS is the kind of command. It should be one of the COMMAND_* ++ COMMAND_CLASS is the kind of command. It should be one of the COMMAND_* + constants defined in the gdb module. + +- COMPLETERCLASS is the kind of completer. If not given, the ++ COMPLETER_CLASS is the kind of completer. If not given, the + "complete" method will be used. Otherwise, it should be one of the + COMPLETE_* constants defined in the gdb module. + +@@ -356,7 +357,7 @@ parse_command_name (char *text, struct cmd_list_element ***base_list) + + */ + static int +-cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) ++cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) + { + cmdpy_object *obj = (cmdpy_object *) self; + char *name; +@@ -366,6 +367,8 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) + volatile struct gdb_exception except; + struct cmd_list_element **cmd_list; + char *cmd_name, *pfx_name; ++ static char *keywords[] = { "name", "command_class", "completer_class", ++ "prefix", NULL }; + PyObject *is_prefix = NULL; + int cmp; + +@@ -378,7 +381,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) + return -1; + } + +- if (! PyArg_ParseTuple (args, "si|iO", &name, &cmdtype, ++ if (! PyArg_ParseTupleAndKeywords (args, kw, "si|iO", keywords, &name, &cmdtype, + &completetype, &is_prefix)) + return -1; + +@@ -399,7 +402,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) + return -1; + } + +- cmd_name = parse_command_name (name, &cmd_list); ++ cmd_name = gdbpy_parse_command_name (name, &cmd_list, &cmdlist); + if (! cmd_name) + return -1; + +diff --git a/gdb/python/python-frame.c b/gdb/python/python-frame.c +new file mode 100644 +index 0000000..dafe69a +--- /dev/null ++++ b/gdb/python/python-frame.c +@@ -0,0 +1,713 @@ ++/* Python interface to stack frames ++ ++ Copyright (C) 2008, 2009 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 3 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, see . */ ++ ++#include "defs.h" ++#include "charset.h" ++#include "block.h" ++#include "frame.h" ++#include "exceptions.h" ++#include "symtab.h" ++#include "stack.h" ++#include "value.h" ++#include "python-internal.h" ++ ++typedef struct { ++ PyObject_HEAD ++ struct frame_id frame_id; ++ struct gdbarch *gdbarch; ++ ++ /* Marks that the FRAME_ID member actually holds the ID of the frame next ++ to this, and not this frames' ID itself. This is a hack to permit Python ++ frame objects which represent invalid frames (i.e., the last frame_info ++ in a corrupt stack). The problem arises from the fact that this code ++ relies on FRAME_ID to uniquely identify a frame, which is not always true ++ for the last "frame" in a corrupt stack (it can have a null ID, or the same ++ ID as the previous frame). Whenever get_prev_frame returns NULL, we ++ record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */ ++ int frame_id_is_next; ++} frame_object; ++ ++/* Require a valid frame. This must be called inside a TRY_CATCH, or ++ another context in which a gdb exception is allowed. */ ++#define FRAPY_REQUIRE_VALID(frame_obj, frame) \ ++ do { \ ++ frame = frame_object_to_frame_info (frame_obj); \ ++ if (frame == NULL) \ ++ error ("Frame is invalid."); \ ++ } while (0) ++ ++static PyTypeObject frame_object_type; ++ ++/* Returns the frame_info object corresponding to the given Python Frame ++ object. If the frame doesn't exist anymore (the frame id doesn't ++ correspond to any frame in the inferior), returns NULL. */ ++ ++static struct frame_info * ++frame_object_to_frame_info (frame_object *frame_obj) ++{ ++ struct frame_info *frame; ++ ++ frame = frame_find_by_id (frame_obj->frame_id); ++ if (frame == NULL) ++ return NULL; ++ ++ if (frame_obj->frame_id_is_next) ++ frame = get_prev_frame (frame); ++ ++ return frame; ++} ++ ++/* Called by the Python interpreter to obtain string representation ++ of the object. */ ++ ++static PyObject * ++frapy_str (PyObject *self) ++{ ++ char *s; ++ long len; ++ PyObject *result; ++ struct ui_file *strfile; ++ ++ strfile = mem_fileopen (); ++ fprint_frame_id (strfile, ((frame_object *) self)->frame_id); ++ s = ui_file_xstrdup (strfile, &len); ++ result = PyString_FromString (s); ++ xfree (s); ++ ++ return result; ++} ++ ++/* Implementation of gdb.Frame.is_valid (self) -> Boolean. ++ Returns True if the frame corresponding to the frame_id of this ++ object still exists in the inferior. */ ++ ++static PyObject * ++frapy_is_valid (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ ++ frame = frame_object_to_frame_info ((frame_object *) self); ++ if (frame == NULL) ++ Py_RETURN_FALSE; ++ ++ Py_RETURN_TRUE; ++} ++ ++/* Implementation of gdb.Frame.equals (self, other) -> Boolean. */ ++ ++static PyObject * ++frapy_equal_p (PyObject *self, PyObject *args) ++{ ++ int equalp = 0; /* Initialize to appease gcc warning. */ ++ frame_object *self_frame = (frame_object *) self; ++ frame_object *other; ++ volatile struct gdb_exception except; ++ ++ if (!PyArg_ParseTuple (args, "O!", &frame_object_type, &other)) ++ return NULL; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ equalp = frame_id_eq (self_frame->frame_id, other->frame_id); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ if (equalp) ++ Py_RETURN_TRUE; ++ ++ Py_RETURN_FALSE; ++} ++ ++/* Implementation of gdb.Frame.name (self) -> String. ++ Returns the name of the function corresponding to this frame. */ ++ ++static PyObject * ++frapy_name (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ char *name; ++ enum language lang; ++ PyObject *result; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ find_frame_funname (frame, &name, &lang); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ if (name) ++ result = target_string_to_unicode (name, strlen (name)); ++ else ++ { ++ result = Py_None; ++ Py_INCREF (Py_None); ++ } ++ ++ return result; ++} ++ ++/* Implementation of gdb.Frame.type (self) -> Integer. ++ Returns the frame type, namely one of the gdb.*_FRAME constants. */ ++ ++static PyObject * ++frapy_type (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning. */ ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ type = get_frame_type (frame); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return PyInt_FromLong (type); ++} ++ ++/* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer. ++ Returns one of the gdb.FRAME_UNWIND_* constants. */ ++ ++static PyObject * ++frapy_unwind_stop_reason (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */ ++ volatile struct gdb_exception except; ++ enum unwind_stop_reason stop_reason; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ stop_reason = get_frame_unwind_stop_reason (frame); ++ ++ return PyInt_FromLong (stop_reason); ++} ++ ++/* Implementation of gdb.Frame.pc (self) -> Long. ++ Returns the frame's resume address. */ ++ ++static PyObject * ++frapy_pc (PyObject *self, PyObject *args) ++{ ++ CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */ ++ struct frame_info *frame; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ pc = get_frame_pc (frame); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return PyLong_FromUnsignedLongLong (pc); ++} ++ ++/* Implementation of gdb.Frame.block (self) -> gdb.Block. ++ Returns the frame's code block. */ ++ ++static PyObject * ++frapy_block (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ struct block *block = NULL; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ block = block_for_pc (get_frame_address_in_block (frame)); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ if (block) ++ return block_to_block_object (block); ++ ++ Py_RETURN_NONE; ++} ++ ++ ++/* Implementation of gdb.Frame.addr_in_block (self) -> Long. ++ Returns an address which falls within the frame's code block. */ ++ ++static PyObject * ++frapy_addr_in_block (PyObject *self, PyObject *args) ++{ ++ CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */ ++ struct frame_info *frame; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ pc = get_frame_address_in_block (frame); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return PyLong_FromUnsignedLongLong (pc); ++} ++ ++/* Convert a frame_info struct to a Python Frame object. ++ Sets a Python exception and returns NULL on error. */ ++ ++static frame_object * ++frame_info_to_frame_object (struct frame_info *frame) ++{ ++ frame_object *frame_obj; ++ ++ frame_obj = PyObject_New (frame_object, &frame_object_type); ++ if (frame_obj == NULL) ++ { ++ PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object."); ++ return NULL; ++ } ++ ++ /* Try to get the previous frame, to determine if this is the last frame ++ in a corrupt stack. If so, we need to store the frame_id of the next ++ frame and not of this one (which is possibly invalid). */ ++ if (get_prev_frame (frame) == NULL ++ && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON ++ && get_next_frame (frame) != NULL) ++ { ++ frame_obj->frame_id = get_frame_id (get_next_frame (frame)); ++ frame_obj->frame_id_is_next = 1; ++ } ++ else ++ { ++ frame_obj->frame_id = get_frame_id (frame); ++ frame_obj->frame_id_is_next = 0; ++ } ++ ++ frame_obj->gdbarch = get_frame_arch (frame); ++ ++ return frame_obj; ++} ++ ++/* Implementation of gdb.Frame.older (self) -> gdb.Frame. ++ Returns the frame immediately older (outer) to this frame, or None if ++ there isn't one. */ ++ ++static PyObject * ++frapy_older (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame, *prev; ++ volatile struct gdb_exception except; ++ PyObject *prev_obj = NULL; /* Initialize to appease gcc warning. */ ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ prev = get_prev_frame (frame); ++ if (prev) ++ prev_obj = (PyObject *) frame_info_to_frame_object (prev); ++ else ++ { ++ Py_INCREF (Py_None); ++ prev_obj = Py_None; ++ } ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return prev_obj; ++} ++ ++/* Implementation of gdb.Frame.newer (self) -> gdb.Frame. ++ Returns the frame immediately newer (inner) to this frame, or None if ++ there isn't one. */ ++ ++static PyObject * ++frapy_newer (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame, *next; ++ volatile struct gdb_exception except; ++ PyObject *next_obj = NULL; /* Initialize to appease gcc warning. */ ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ next = get_next_frame (frame); ++ if (next) ++ next_obj = (PyObject *) frame_info_to_frame_object (next); ++ else ++ { ++ Py_INCREF (Py_None); ++ next_obj = Py_None; ++ } ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return next_obj; ++} ++ ++/* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line. ++ Returns the frame's symtab and line. */ ++ ++static PyObject * ++frapy_find_sal (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ struct symtab_and_line sal; ++ volatile struct gdb_exception except; ++ PyObject *sal_obj = NULL; /* Initialize to appease gcc warning. */ ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ find_frame_sal (frame, &sal); ++ sal_obj = symtab_and_line_to_sal_object (sal); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return sal_obj; ++} ++ ++/* Implementation of gdb.Frame.read_var (self, variable) -> gdb.Value. ++ Returns the value of the given variable in this frame. The argument can be ++ either a gdb.Symbol or a string. Returns None if GDB can't find the ++ specified variable. */ ++ ++static PyObject * ++frapy_read_var (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ PyObject *sym_obj; ++ struct symbol *var = NULL; /* gcc-4.3.2 false warning. */ ++ struct value *val = NULL; ++ volatile struct gdb_exception except; ++ ++ if (!PyArg_ParseTuple (args, "O", &sym_obj)) ++ return NULL; ++ ++ if (PyObject_TypeCheck (sym_obj, &symbol_object_type)) ++ var = symbol_object_to_symbol (sym_obj); ++ else if (gdbpy_is_string (sym_obj)) ++ { ++ char *var_name; ++ struct block *block = NULL; ++ struct cleanup *cleanup; ++ volatile struct gdb_exception except; ++ ++ var_name = python_string_to_target_string (sym_obj); ++ if (!var_name) ++ return NULL; ++ cleanup = make_cleanup (xfree, var_name); ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ block = block_for_pc (get_frame_address_in_block (frame)); ++ var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ if (!var) ++ { ++ PyErr_Format (PyExc_ValueError, ++ _("variable '%s' not found"), var_name); ++ do_cleanups (cleanup); ++ ++ return NULL; ++ } ++ ++ do_cleanups (cleanup); ++ } ++ else ++ { ++ PyErr_SetString (PyExc_TypeError, ++ _("argument must be a symbol or string")); ++ return NULL; ++ } ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ FRAPY_REQUIRE_VALID ((frame_object *) self, frame); ++ ++ val = read_var_value (var, frame); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ if (val) ++ return value_to_value_object (val); ++ ++ Py_RETURN_NONE; ++} ++ ++/* Implementation of gdb.frames () -> (gdb.Frame, ...). ++ Returns a tuple of all frame objects. */ ++ ++PyObject * ++gdbpy_frames (PyObject *self, PyObject *args) ++{ ++ int result = 0; ++ struct frame_info *frame; ++ frame_object *frame_obj; ++ PyObject *list, *tuple; ++ volatile struct gdb_exception except; ++ ++ list = PyList_New (0); ++ if (list == NULL) ++ { ++ PyErr_SetString (PyExc_MemoryError, "Could not allocate frames list."); ++ return NULL; ++ } ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ for (frame = get_current_frame (); frame; frame = get_prev_frame (frame)) ++ { ++ frame_obj = frame_info_to_frame_object (frame); ++ if (frame_obj == NULL) ++ { ++ Py_DECREF (list); ++ list = NULL; ++ break; ++ } ++ ++ PyList_Append (list, (PyObject *) frame_obj); ++ } ++ } ++ if (except.reason < 0) ++ { ++ Py_DECREF (list); ++ return PyErr_Format (except.reason == RETURN_QUIT ++ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, ++ "%s", except.message); ++ } ++ ++ if (list) ++ { ++ tuple = PyList_AsTuple (list); ++ Py_DECREF (list); ++ } ++ else ++ tuple = NULL; ++ ++ return tuple; ++} ++ ++/* Implementation of gdb.newest_frame () -> gdb.Frame. ++ Returns the newest frame object. */ ++ ++PyObject * ++gdbpy_newest_frame (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */ ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ frame = get_current_frame (); ++ frame_obj = frame_info_to_frame_object (frame); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return (PyObject *) frame_obj; ++} ++ ++/* Implementation of gdb.selected_frame () -> gdb.Frame. ++ Returns the selected frame object. */ ++ ++PyObject * ++gdbpy_selected_frame (PyObject *self, PyObject *args) ++{ ++ struct frame_info *frame; ++ frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */ ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ frame = get_selected_frame ("No frame is currently selected."); ++ frame_obj = frame_info_to_frame_object (frame); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return (PyObject *) frame_obj; ++} ++ ++/* Implementation of gdb.stop_reason_string (Integer) -> String. ++ Return a string explaining the unwind stop reason. */ ++ ++PyObject * ++gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args) ++{ ++ int reason; ++ const char *str; ++ ++ if (!PyArg_ParseTuple (args, "i", &reason)) ++ return NULL; ++ ++ if (reason < 0 || reason > UNWIND_NO_SAVED_PC) ++ { ++ PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason."); ++ return NULL; ++ } ++ ++ str = frame_stop_reason_string (reason); ++ return PyUnicode_Decode (str, strlen (str), host_charset (), NULL); ++} ++ ++/* Implements the equality comparison for Frame objects. ++ All other comparison operators will throw a TypeError Python exception, ++ as they aren't valid for frames. */ ++ ++static PyObject * ++frapy_richcompare (PyObject *self, PyObject *other, int op) ++{ ++ int result; ++ ++ if (!PyObject_TypeCheck (other, &frame_object_type) ++ || (op != Py_EQ && op != Py_NE)) ++ { ++ Py_INCREF (Py_NotImplemented); ++ return Py_NotImplemented; ++ } ++ ++ if (frame_id_eq (((frame_object *) self)->frame_id, ++ ((frame_object *) other)->frame_id)) ++ result = Py_EQ; ++ else ++ result = Py_NE; ++ ++ if (op == result) ++ Py_RETURN_TRUE; ++ Py_RETURN_FALSE; ++} ++ ++/* Sets up the Frame API in the gdb module. */ ++ ++void ++gdbpy_initialize_frames (void) ++{ ++ frame_object_type.tp_new = PyType_GenericNew; ++ if (PyType_Ready (&frame_object_type) < 0) ++ return; ++ ++ /* Note: These would probably be best exposed as class attributes of Frame, ++ but I don't know how to do it except by messing with the type's dictionary. ++ That seems too messy. */ ++ PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME); ++ PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME); ++ PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME); ++ PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME); ++ PyModule_AddIntConstant (gdb_module, ++ "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON); ++ PyModule_AddIntConstant (gdb_module, ++ "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID); ++ PyModule_AddIntConstant (gdb_module, ++ "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR); ++ PyModule_AddIntConstant (gdb_module, ++ "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID); ++ PyModule_AddIntConstant (gdb_module, ++ "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID); ++ PyModule_AddIntConstant (gdb_module, ++ "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC); ++ ++ Py_INCREF (&frame_object_type); ++ PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type); ++} ++ ++ ++ ++static PyMethodDef frame_object_methods[] = { ++ { "equals", frapy_equal_p, METH_VARARGS, ++ "equals (frame) -> Boolean.\n\ ++Compare this frame to the given frame." }, ++ { "is_valid", frapy_is_valid, METH_NOARGS, ++ "is_valid () -> Boolean.\n\ ++Return true if this frame is valid, false if not." }, ++ { "name", frapy_name, METH_NOARGS, ++ "name () -> String.\n\ ++Return the function name of the frame, or None if it can't be determined." }, ++ { "type", frapy_type, METH_NOARGS, ++ "type () -> Integer.\n\ ++Return the type of the frame." }, ++ { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS, ++ "unwind_stop_reason () -> Integer.\n\ ++Return the reason why it's not possible to find frames older than this." }, ++ { "pc", frapy_pc, METH_NOARGS, ++ "pc () -> Long.\n\ ++Return the frame's resume address." }, ++ { "block", frapy_block, METH_NOARGS, ++ "block () -> gdb.Block.\n\ ++Return the frame's code block." }, ++ { "addr_in_block", frapy_addr_in_block, METH_NOARGS, ++ "addr_in_block () -> Long.\n\ ++Return an address which falls within the frame's code block." }, ++ { "older", frapy_older, METH_NOARGS, ++ "older () -> gdb.Frame.\n\ ++Return the frame immediately older (outer) to this frame." }, ++ { "newer", frapy_newer, METH_NOARGS, ++ "newer () -> gdb.Frame.\n\ ++Return the frame immetidaely newer (inner) to this frame." }, ++ { "find_sal", frapy_find_sal, METH_NOARGS, ++ "find_sal () -> gdb.Symtab_and_line.\n\ ++Return the frame's symtab and line." }, ++ { "read_var", frapy_read_var, METH_VARARGS, ++ "read_var (variable) -> gdb.Value.\n\ ++Return the value of the variable in this frame." }, ++ {NULL} /* Sentinel */ ++}; ++ ++static PyTypeObject frame_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /* ob_size */ ++ "gdb.Frame", /* tp_name */ ++ sizeof (frame_object), /* tp_basicsize */ ++ 0, /* tp_itemsize */ ++ 0, /* tp_dealloc */ ++ 0, /* tp_print */ ++ 0, /* tp_getattr */ ++ 0, /* tp_setattr */ ++ 0, /* tp_compare */ ++ 0, /* tp_repr */ ++ 0, /* tp_as_number */ ++ 0, /* tp_as_sequence */ ++ 0, /* tp_as_mapping */ ++ 0, /* tp_hash */ ++ 0, /* tp_call */ ++ frapy_str, /* tp_str */ ++ 0, /* tp_getattro */ ++ 0, /* tp_setattro */ ++ 0, /* tp_as_buffer */ ++ Py_TPFLAGS_DEFAULT, /* tp_flags */ ++ "GDB frame object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ frame_object_methods /* tp_methods */ ++}; +diff --git a/gdb/python/python-function.c b/gdb/python/python-function.c +new file mode 100644 +index 0000000..4a85a33 +--- /dev/null ++++ b/gdb/python/python-function.c +@@ -0,0 +1,180 @@ ++/* Convenience functions implemented in Python. ++ ++ Copyright (C) 2008, 2009 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 3 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, see . */ ++ ++ ++#include "defs.h" ++#include "value.h" ++#include "exceptions.h" ++#include "python-internal.h" ++#include "charset.h" ++#include "gdbcmd.h" ++#include "cli/cli-decode.h" ++#include "completer.h" ++#include "expression.h" ++ ++static PyTypeObject fnpy_object_type; ++ ++ ++ ++static PyObject * ++convert_values_to_python (int argc, struct value **argv) ++{ ++ int i; ++ PyObject *result = PyTuple_New (argc); ++ for (i = 0; i < argc; ++i) ++ { ++ PyObject *elt = value_to_value_object (argv[i]); ++ if (! elt) ++ { ++ Py_DECREF (result); ++ error (_("Could not convert value to Python object.")); ++ } ++ PyTuple_SetItem (result, i, elt); ++ } ++ return result; ++} ++ ++/* Call a Python function object's invoke method. */ ++ ++static struct value * ++fnpy_call (void *cookie, int argc, struct value **argv) ++{ ++ int i; ++ struct value *value = NULL; ++ PyObject *result, *callable, *args; ++ struct cleanup *cleanup; ++ PyGILState_STATE state; ++ ++ state = PyGILState_Ensure (); ++ cleanup = make_cleanup_py_restore_gil (&state); ++ ++ args = convert_values_to_python (argc, argv); ++ ++ callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke"); ++ if (! callable) ++ { ++ Py_DECREF (args); ++ error (_("No method named 'invoke' in object.")); ++ } ++ ++ result = PyObject_Call (callable, args, NULL); ++ Py_DECREF (callable); ++ Py_DECREF (args); ++ ++ if (!result) ++ { ++ gdbpy_print_stack (); ++ error (_("Error while executing Python code.")); ++ } ++ ++ value = convert_value_from_python (result); ++ if (value == NULL) ++ { ++ Py_DECREF (result); ++ gdbpy_print_stack (); ++ error (_("Error while executing Python code.")); ++ } ++ ++ Py_DECREF (result); ++ do_cleanups (cleanup); ++ ++ return value; ++} ++ ++/* Initializer for a Function object. It takes one argument, the name ++ of the function. */ ++ ++static int ++fnpy_init (PyObject *self, PyObject *args, PyObject *kwds) ++{ ++ char *name, *docstring = NULL; ++ if (! PyArg_ParseTuple (args, "s", &name)) ++ return -1; ++ Py_INCREF (self); ++ ++ if (PyObject_HasAttrString (self, "__doc__")) ++ { ++ PyObject *ds_obj = PyObject_GetAttrString (self, "__doc__"); ++ if (ds_obj && gdbpy_is_string (ds_obj)) ++ /* Nothing ever frees this. */ ++ docstring = python_string_to_host_string (ds_obj); ++ } ++ if (! docstring) ++ docstring = _("This function is not documented."); ++ ++ add_internal_function (name, docstring, fnpy_call, self); ++ return 0; ++} ++ ++/* Initialize internal function support. */ ++ ++void ++gdbpy_initialize_functions (void) ++{ ++ if (PyType_Ready (&fnpy_object_type) < 0) ++ return; ++ ++ Py_INCREF (&fnpy_object_type); ++ PyModule_AddObject (gdb_module, "Function", (PyObject *) &fnpy_object_type); ++} ++ ++ ++ ++static PyTypeObject fnpy_object_type = ++{ ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Function", /*tp_name*/ ++ sizeof (PyObject), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ 0, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ 0, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ ++ "GDB function object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ 0, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ 0, /* tp_dictoffset */ ++ fnpy_init, /* tp_init */ ++ 0, /* tp_alloc */ ++ PyType_GenericNew /* tp_new */ ++}; +diff --git a/gdb/python/python-hooks.c b/gdb/python/python-hooks.c +new file mode 100644 +index 0000000..a3140bc +--- /dev/null ++++ b/gdb/python/python-hooks.c +@@ -0,0 +1,50 @@ ++/* Notifications from gdb to Python ++ ++ Copyright (C) 2008 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 3 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, see . */ ++ ++#include "defs.h" ++#include "cli/cli-decode.h" ++#include "charset.h" ++#include "python.h" ++#include "python-internal.h" ++#include "observer.h" ++ ++PyObject * ++gdbpy_get_hook_function (const char *name) ++{ ++ PyObject *hooks; ++ PyObject *result; ++ ++ if (! PyObject_HasAttrString (gdb_module, "hooks")) ++ return NULL; ++ hooks = PyObject_GetAttrString (gdb_module, "hooks"); ++ if (! hooks) ++ return NULL; ++ /* The cast is because the Python function doesn't declare const argument. ++ This is a problem in Python version 2.4, but not in 2.5. */ ++ if (! PyObject_HasAttrString (hooks, (char *) name)) ++ { ++ Py_DECREF (hooks); ++ return NULL; ++ } ++ /* The cast is because the Python function doesn't declare const argument. ++ This is a problem in Python version 2.4, but not in 2.5. */ ++ result = PyObject_GetAttrString (hooks, (char *) name); ++ Py_DECREF (hooks); ++ return result; ++} +diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h +index 02dbfc4..5e43267 100644 +--- a/gdb/python/python-internal.h ++++ b/gdb/python/python-internal.h +@@ -33,6 +33,7 @@ + + #if HAVE_LIBPYTHON2_4 + #include "python2.4/Python.h" ++#include "python2.4/frameobject.h" + /* Py_ssize_t is not defined until 2.5. + Logical type for Py_ssize_t is Py_intptr_t, but that fails in 64-bit + compilation due to several apparent mistakes in python2.4 API, so we +@@ -40,8 +41,10 @@ + typedef int Py_ssize_t; + #elif HAVE_LIBPYTHON2_5 + #include "python2.5/Python.h" ++#include "python2.5/frameobject.h" + #elif HAVE_LIBPYTHON2_6 + #include "python2.6/Python.h" ++#include "python2.6/frameobject.h" + #else + #error "Unable to find usable Python.h" + #endif +@@ -58,23 +61,70 @@ typedef int Py_ssize_t; + #define PyEval_ReleaseLock() 0 + #endif + ++#include "command.h" ++ ++struct block; ++struct symbol; ++struct symtab_and_line; + struct value; + + extern PyObject *gdb_module; ++extern PyTypeObject block_object_type; + extern PyTypeObject value_object_type; ++extern PyTypeObject symbol_object_type; + + PyObject *gdbpy_history (PyObject *self, PyObject *args); +- ++PyObject *gdbpy_breakpoints (PyObject *, PyObject *); ++PyObject *gdbpy_frames (PyObject *, PyObject *); ++PyObject *gdbpy_newest_frame (PyObject *, PyObject *); ++PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); ++PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw); ++PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args); ++PyObject *gdbpy_block_for_pc (PyObject *self, PyObject *args); ++PyObject *gdbpy_read_memory (PyObject *self, PyObject *args); ++PyObject *gdbpy_write_memory (PyObject *self, PyObject *args); ++PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw); ++ ++PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal); ++PyObject *symtab_to_symtab_object (struct symtab *symtab); ++PyObject *symbol_to_symbol_object (struct symbol *sym); ++PyObject *block_to_block_object (struct block *block); + PyObject *value_to_value_object (struct value *v); ++PyObject *type_to_type_object (struct type *); ++PyObject *objfile_to_objfile_object (struct objfile *); + ++PyObject *objfpy_get_printers (PyObject *, void *); ++ ++struct block *block_object_to_block (PyObject *obj); ++struct symbol *symbol_object_to_symbol (PyObject *obj); ++struct value *value_object_to_value (PyObject *self); + struct value *convert_value_from_python (PyObject *obj); ++struct type *type_object_to_type (PyObject *obj); ++ ++PyObject *gdbpy_get_hook_function (const char *); + + void gdbpy_initialize_values (void); ++void gdbpy_initialize_breakpoints (void); ++void gdbpy_initialize_frames (void); ++void gdbpy_initialize_symtabs (void); + void gdbpy_initialize_commands (void); ++void gdbpy_initialize_symbols (void); ++void gdbpy_initialize_types (void); ++void gdbpy_initialize_blocks (void); ++void gdbpy_initialize_functions (void); ++void gdbpy_initialize_objfile (void); ++void gdbpy_initialize_parameters (void); ++void gdbpy_initialize_membuf (void); + + struct cleanup *make_cleanup_py_decref (PyObject *py); + struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state); + ++char *gdbpy_parse_command_name (char *text, ++ struct cmd_list_element ***base_list, ++ struct cmd_list_element **start_list); ++ ++PyObject *gdbpy_parameter_value (enum var_types, void *); ++ + /* Use this after a TRY_EXCEPT to throw the appropriate Python + exception. */ + #define GDB_PY_HANDLE_EXCEPTION(Exception) \ +@@ -85,6 +135,19 @@ struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state); + "%s", Exception.message); \ + } while (0) + ++/* Use this after a TRY_EXCEPT to throw the appropriate Python ++ exception. This macro is for use inside setter functions. */ ++#define GDB_PY_SET_HANDLE_EXCEPTION(Exception) \ ++ do { \ ++ if (Exception.reason < 0) \ ++ { \ ++ PyErr_Format (Exception.reason == RETURN_QUIT \ ++ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \ ++ "%s", Exception.message); \ ++ return -1; \ ++ } \ ++ } while (0) ++ + + void gdbpy_print_stack (void); + +@@ -95,6 +158,21 @@ char *python_string_to_host_string (PyObject *obj); + PyObject *target_string_to_unicode (const gdb_byte *str, int length); + int gdbpy_is_string (PyObject *obj); + ++int gdbpy_is_value_object (PyObject *obj); ++ ++/* Note that these are declared here, and not in python.h with the ++ other pretty-printer functions, because they refer to PyObject. */ ++char *apply_varobj_pretty_printer (PyObject *print_obj, ++ struct value **replacement); ++PyObject *gdbpy_get_varobj_pretty_printer (struct value *value); ++PyObject *gdbpy_instantiate_printer (PyObject *cons, PyObject *value); ++char *gdbpy_get_display_hint (PyObject *printer); ++ ++extern PyObject *gdbpy_children_cst; ++extern PyObject *gdbpy_to_string_cst; ++extern PyObject *gdbpy_display_hint_cst; + extern PyObject *gdbpy_doc_cst; + ++int get_addr_from_python (PyObject *obj, CORE_ADDR *addr); ++ + #endif /* GDB_PYTHON_INTERNAL_H */ +diff --git a/gdb/python/python-membuf.c b/gdb/python/python-membuf.c +new file mode 100644 +index 0000000..a4c7d74 +--- /dev/null ++++ b/gdb/python/python-membuf.c +@@ -0,0 +1,243 @@ ++/* Python interface to the inferior memory. ++ ++ Copyright (C) 2008, 2009 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 3 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, see . */ ++ ++#include "defs.h" ++#include "exceptions.h" ++#include "gdbcore.h" ++#include "python-internal.h" ++ ++typedef struct { ++ PyObject_HEAD ++ void *buffer; ++ ++ /* These are kept just for mbpy_str. */ ++ CORE_ADDR addr; ++ CORE_ADDR length; ++} membuf_object; ++ ++static PyTypeObject membuf_object_type; ++ ++/* Implementation of gdb.read_memory (address, length). ++ Returns a Python buffer object with LENGTH bytes of the inferior's memory ++ at ADDRESS. Both arguments are integers. */ ++ ++PyObject * ++gdbpy_read_memory (PyObject *self, PyObject *args) ++{ ++ CORE_ADDR addr, length; ++ void *buffer; ++ membuf_object *membuf_obj; ++ struct cleanup *cleanups; ++ volatile struct gdb_exception except; ++ ++ /* Assume CORE_ADDR corresponds to unsigned long. */ ++ if (! PyArg_ParseTuple (args, "kk", &addr, &length)) ++ return NULL; ++ ++ buffer = xmalloc (length); ++ cleanups = make_cleanup (xfree, buffer); ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ read_memory (addr, buffer, length); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ discard_cleanups (cleanups); ++ ++ membuf_obj = PyObject_New (membuf_object, &membuf_object_type); ++ if (membuf_obj == NULL) ++ { ++ xfree (buffer); ++ PyErr_SetString (PyExc_MemoryError, ++ "Could not allocate memory buffer object."); ++ return NULL; ++ } ++ ++ membuf_obj->buffer = buffer; ++ ++ membuf_obj->addr = addr; ++ membuf_obj->length = length; ++ ++ return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0, Py_END_OF_BUFFER); ++} ++ ++/* Implementation of gdb.write_memory (address, buffer [, length]). ++ Writes the contents of BUFFER (a Python object supporting the read buffer ++ protocol) at ADDRESS in the inferior's memory. Write LENGTH bytes from ++ BUFFER, or its entire contents if the argument is not provided. The ++ function returns nothing. */ ++ ++PyObject * ++gdbpy_write_memory (PyObject *self, PyObject *args) ++{ ++ int buf_len; ++ const char *buffer; ++ long length = -1; ++ CORE_ADDR addr; ++ volatile struct gdb_exception except; ++ ++ /* Assume CORE_ADDR corresponds to unsigned long. */ ++ if (! PyArg_ParseTuple (args, "ks#|l", &addr, &buffer, &buf_len, &length)) ++ return NULL; ++ ++ if (length == -1) ++ length = buf_len; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ write_memory (addr, buffer, length); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ Py_RETURN_NONE; ++} ++ ++/* Destructor of Membuf objects. */ ++ ++static void ++mbpy_dealloc (PyObject *self) ++{ ++ xfree (((membuf_object *) self)->buffer); ++ self->ob_type->tp_free (self); ++} ++ ++/* Return a description of the Membuf object. */ ++ ++static PyObject * ++mbpy_str (PyObject *self) ++{ ++ membuf_object *membuf_obj = (membuf_object *) self; ++ ++ return PyString_FromFormat ("memory buffer for address %s, %s bytes long", ++ paddress (membuf_obj->addr), ++ pulongest (membuf_obj->length)); ++} ++ ++static Py_ssize_t ++get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) ++{ ++ membuf_object *membuf_obj = (membuf_object *) self; ++ ++ if (segment) ++ { ++ PyErr_SetString (PyExc_SystemError, ++ "The memory buffer supports only one segment."); ++ return -1; ++ } ++ ++ *ptrptr = membuf_obj->buffer; ++ ++ return membuf_obj->length; ++} ++ ++static Py_ssize_t ++get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr) ++{ ++ return get_read_buffer (self, segment, ptrptr); ++} ++ ++static Py_ssize_t ++get_seg_count (PyObject *self, Py_ssize_t *lenp) ++{ ++ if (lenp) ++ *lenp = ((membuf_object *) self)->length; ++ ++ return 1; ++} ++ ++static Py_ssize_t ++get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr) ++{ ++ void *ptr = NULL; ++ Py_ssize_t ret; ++ ++ ret = get_read_buffer (self, segment, &ptr); ++ *ptrptr = (char *) ptr; ++ ++ return ret; ++} ++ ++/* Python doesn't provide a decent way to get compatibility here. */ ++#if HAVE_LIBPYTHON2_4 ++#define CHARBUFFERPROC_NAME getcharbufferproc ++#else ++#define CHARBUFFERPROC_NAME charbufferproc ++#endif ++ ++static PyBufferProcs buffer_procs = { ++ get_read_buffer, ++ get_write_buffer, ++ get_seg_count, ++ /* The cast here works around a difference between Python 2.4 and ++ Python 2.5. */ ++ (CHARBUFFERPROC_NAME) get_char_buffer ++}; ++ ++static PyTypeObject membuf_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Membuf", /*tp_name*/ ++ sizeof (membuf_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ mbpy_dealloc, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ mbpy_str, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ &buffer_procs, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT, /*tp_flags*/ ++ "GDB memory buffer object", /*tp_doc*/ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ 0, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ 0, /* tp_dictoffset */ ++ 0, /* tp_init */ ++ 0, /* tp_alloc */ ++ PyType_GenericNew /* tp_new */ ++}; ++ ++void ++gdbpy_initialize_membuf (void) ++{ ++ if (PyType_Ready (&membuf_object_type) < 0) ++ return; ++ ++ Py_INCREF (&membuf_object_type); ++ PyModule_AddObject (gdb_module, "Membuf", (PyObject *) &membuf_object_type); ++} +diff --git a/gdb/python/python-objfile.c b/gdb/python/python-objfile.c +new file mode 100644 +index 0000000..f5db084 +--- /dev/null ++++ b/gdb/python/python-objfile.c +@@ -0,0 +1,225 @@ ++/* Python interface to objfiles. ++ ++ Copyright (C) 2008, 2009 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 3 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, see . */ ++ ++#include "defs.h" ++#include "python-internal.h" ++#include "charset.h" ++#include "objfiles.h" ++ ++typedef struct ++{ ++ PyObject_HEAD ++ ++ /* The corresponding objfile. */ ++ struct objfile *objfile; ++ ++ /* The pretty-printer list of functions. */ ++ PyObject *printers; ++} objfile_object; ++ ++static PyTypeObject objfile_object_type; ++ ++static const struct objfile_data *objfpy_objfile_data_key; ++ ++ ++ ++/* An Objfile method which returns the objfile's file name, or None. */ ++static PyObject * ++objfpy_get_filename (PyObject *self, void *closure) ++{ ++ objfile_object *obj = (objfile_object *) self; ++ if (obj->objfile && obj->objfile->name) ++ return PyString_Decode (obj->objfile->name, strlen (obj->objfile->name), ++ host_charset (), NULL); ++ Py_RETURN_NONE; ++} ++ ++static void ++objfpy_dealloc (PyObject *o) ++{ ++ objfile_object *self = (objfile_object *) o; ++ Py_XDECREF (self->printers); ++ self->ob_type->tp_free ((PyObject *) self); ++} ++ ++static PyObject * ++objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) ++{ ++ objfile_object *self = (objfile_object *) type->tp_alloc (type, 0); ++ if (self) ++ { ++ self->objfile = NULL; ++ ++ self->printers = PyList_New (0); ++ if (!self->printers) ++ { ++ Py_DECREF (self); ++ return NULL; ++ } ++ } ++ return (PyObject *) self; ++} ++ ++PyObject * ++objfpy_get_printers (PyObject *o, void *ignore) ++{ ++ objfile_object *self = (objfile_object *) o; ++ Py_INCREF (self->printers); ++ return self->printers; ++} ++ ++static int ++objfpy_set_printers (PyObject *o, PyObject *value, void *ignore) ++{ ++ objfile_object *self = (objfile_object *) o; ++ if (! value) ++ { ++ PyErr_SetString (PyExc_TypeError, ++ "cannot delete the pretty_printers attribute"); ++ return -1; ++ } ++ ++ if (! PyList_Check (value)) ++ { ++ PyErr_SetString (PyExc_TypeError, ++ "the pretty_printers attribute must be a list"); ++ return -1; ++ } ++ ++ Py_XDECREF (self->printers); ++ Py_INCREF (value); ++ self->printers = value; ++ ++ return 0; ++} ++ ++ ++ ++/* Clear the OBJFILE pointer in an Objfile object and remove the ++ reference. */ ++static void ++clean_up_objfile (struct objfile *objfile, void *datum) ++{ ++ PyGILState_STATE state; ++ objfile_object *object = datum; ++ ++ state = PyGILState_Ensure (); ++ object->objfile = NULL; ++ Py_DECREF ((PyObject *) object); ++ PyGILState_Release (state); ++} ++ ++/* Return the Python object of type Objfile representing OBJFILE. If ++ the object has already been created, return it. Otherwise, create ++ it. Return NULL and set the Python error on failure. */ ++PyObject * ++objfile_to_objfile_object (struct objfile *objfile) ++{ ++ objfile_object *object; ++ ++ object = objfile_data (objfile, objfpy_objfile_data_key); ++ if (!object) ++ { ++ object = PyObject_New (objfile_object, &objfile_object_type); ++ if (object) ++ { ++ PyObject *dict; ++ ++ object->objfile = objfile; ++ ++ object->printers = PyList_New (0); ++ if (!object->printers) ++ { ++ Py_DECREF (object); ++ return NULL; ++ } ++ ++ set_objfile_data (objfile, objfpy_objfile_data_key, object); ++ } ++ } ++ ++ return (PyObject *) object; ++} ++ ++void ++gdbpy_initialize_objfile (void) ++{ ++ objfpy_objfile_data_key ++ = register_objfile_data_with_cleanup (clean_up_objfile); ++ ++ if (PyType_Ready (&objfile_object_type) < 0) ++ return; ++ ++ Py_INCREF (&objfile_object_type); ++ PyModule_AddObject (gdb_module, "Objfile", (PyObject *) &objfile_object_type); ++} ++ ++ ++ ++static PyGetSetDef objfile_getset[] = ++{ ++ { "filename", objfpy_get_filename, NULL, ++ "The objfile's filename, or None.", NULL }, ++ { "pretty_printers", objfpy_get_printers, objfpy_set_printers, ++ "Pretty printers.", NULL }, ++ { NULL } ++}; ++ ++static PyTypeObject objfile_object_type = ++{ ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Objfile", /*tp_name*/ ++ sizeof (objfile_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ objfpy_dealloc, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ 0, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT, /*tp_flags*/ ++ "GDB objfile object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ objfile_getset, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ 0, /* tp_dictoffset */ ++ 0, /* tp_init */ ++ 0, /* tp_alloc */ ++ objfpy_new, /* tp_new */ ++}; +diff --git a/gdb/python/python-param.c b/gdb/python/python-param.c +new file mode 100644 +index 0000000..1f591a8 +--- /dev/null ++++ b/gdb/python/python-param.c +@@ -0,0 +1,606 @@ ++/* gdb parameters implemented in Python ++ ++ Copyright (C) 2008, 2009 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 3 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, see . */ ++ ++ ++#include "defs.h" ++#include "value.h" ++#include "exceptions.h" ++#include "python-internal.h" ++#include "charset.h" ++#include "gdbcmd.h" ++#include "cli/cli-decode.h" ++#include "completer.h" ++ ++/* Parameter constants and their values. */ ++struct parm_constant ++{ ++ char *name; ++ int value; ++}; ++ ++struct parm_constant parm_constants[] = ++{ ++ { "PARAM_BOOLEAN", var_boolean }, ++ { "PARAM_AUTO_BOOLEAN", var_auto_boolean }, ++ { "PARAM_UINTEGER", var_uinteger }, ++ { "PARAM_INTEGER", var_integer }, ++ { "PARAM_STRING", var_string }, ++ { "PARAM_STRING_NOESCAPE", var_string_noescape }, ++ { "PARAM_OPTIONAL_FILENAME", var_optional_filename }, ++ { "PARAM_FILENAME", var_filename }, ++ { "PARAM_ZINTEGER", var_zinteger }, ++ { "PARAM_ENUM", var_enum }, ++ { NULL, 0 } ++}; ++ ++/* A union that can hold anything described by enum var_types. */ ++union parmpy_variable ++{ ++ /* Hold an integer value, for boolean and integer types. */ ++ int intval; ++ ++ /* Hold an auto_boolean. */ ++ enum auto_boolean autoboolval; ++ ++ /* Hold an unsigned integer value, for uinteger. */ ++ unsigned int uintval; ++ ++ /* Hold a string, for the various string types. */ ++ char *stringval; ++ ++ /* Hold a string, for enums. */ ++ const char *cstringval; ++}; ++ ++/* A gdb parameter. */ ++struct parmpy_object ++{ ++ PyObject_HEAD ++ ++ /* The type of the parameter. */ ++ enum var_types type; ++ ++ /* The value of the parameter. */ ++ union parmpy_variable value; ++ ++ /* For an enum command, the possible values. The vector is ++ allocated with xmalloc, as is each element. It is ++ NULL-terminated. */ ++ const char **enumeration; ++}; ++ ++typedef struct parmpy_object parmpy_object; ++ ++static PyTypeObject parmpy_object_type; ++ ++/* Some handy string constants. */ ++static PyObject *set_doc_cst; ++static PyObject *show_doc_cst; ++ ++ ++ ++/* Get an attribute. */ ++static PyObject * ++get_attr (PyObject *obj, PyObject *attr_name) ++{ ++ if (PyString_Check (attr_name) ++ && ! strcmp (PyString_AsString (attr_name), "value")) ++ { ++ parmpy_object *self = (parmpy_object *) obj; ++ return gdbpy_parameter_value (self->type, &self->value); ++ } ++ ++ return PyObject_GenericGetAttr (obj, attr_name); ++} ++ ++/* Set a parameter value from a Python value. Return 0 on success, -1 ++ on failure. */ ++static int ++set_parameter_value (parmpy_object *self, PyObject *value) ++{ ++ int cmp; ++ ++ switch (self->type) ++ { ++ case var_string: ++ case var_string_noescape: ++ case var_optional_filename: ++ case var_filename: ++ if (! gdbpy_is_string (value) ++ && (self->type == var_filename ++ || value != Py_None)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "string required"); ++ return -1; ++ } ++ if (self->value.stringval) ++ xfree (self->value.stringval); ++ if (value == Py_None) ++ { ++ if (self->type == var_optional_filename) ++ self->value.stringval = xstrdup (""); ++ else ++ self->value.stringval = NULL; ++ } ++ else ++ self->value.stringval = python_string_to_host_string (value); ++ break; ++ ++ case var_enum: ++ { ++ int i; ++ char *str; ++ ++ if (! gdbpy_is_string (value)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "string required"); ++ return -1; ++ } ++ ++ str = python_string_to_host_string (value); ++ for (i = 0; self->enumeration[i]; ++i) ++ if (! strcmp (self->enumeration[i], str)) ++ break; ++ xfree (str); ++ if (! self->enumeration[i]) ++ { ++ PyErr_SetString (PyExc_RuntimeError, ++ "value must be member of enumeration"); ++ return -1; ++ } ++ self->value.cstringval = self->enumeration[i]; ++ break; ++ } ++ ++ case var_boolean: ++ if (! PyBool_Check (value)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "boolean required"); ++ return -1; ++ } ++ cmp = PyObject_IsTrue (value); ++ if (cmp < 0) ++ return -1; ++ self->value.intval = cmp; ++ break; ++ ++ case var_auto_boolean: ++ if (! PyBool_Check (value) && value != Py_None) ++ { ++ PyErr_SetString (PyExc_RuntimeError, ++ "boolean or None required"); ++ return -1; ++ } ++ ++ if (value == Py_None) ++ self->value.autoboolval = AUTO_BOOLEAN_AUTO; ++ else ++ { ++ cmp = PyObject_IsTrue (value); ++ if (cmp < 0 ) ++ return -1; ++ if (cmp == 1) ++ self->value.autoboolval = AUTO_BOOLEAN_TRUE; ++ else ++ self->value.autoboolval = AUTO_BOOLEAN_FALSE; ++ ++ break; ++ } ++ ++ case var_integer: ++ case var_zinteger: ++ case var_uinteger: ++ { ++ long l; ++ int ok; ++ ++ if (! PyInt_Check (value)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "value must be integer"); ++ return -1; ++ } ++ ++ l = PyInt_AsLong (value); ++ if (self->type == var_uinteger) ++ { ++ ok = (l >= 0 && l <= UINT_MAX); ++ if (l == 0) ++ l = UINT_MAX; ++ } ++ else if (self->type == var_integer) ++ { ++ ok = (l >= INT_MIN && l <= INT_MAX); ++ if (l == 0) ++ l = INT_MAX; ++ } ++ else ++ ok = (l >= INT_MIN && l <= INT_MAX); ++ ++ if (! ok) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "range exceeded"); ++ return -1; ++ } ++ ++ self->value.intval = (int) l; ++ break; ++ } ++ ++ default: ++ PyErr_SetString (PyExc_RuntimeError, "programmer error: unhandled type"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/* Set an attribute. */ ++static int ++set_attr (PyObject *obj, PyObject *attr_name, PyObject *val) ++{ ++ if (PyString_Check (attr_name) ++ && ! strcmp (PyString_AsString (attr_name), "value")) ++ { ++ if (!val) ++ { ++ PyErr_SetString (PyExc_RuntimeError, ++ "cannot delete a parameter's value"); ++ return -1; ++ } ++ return set_parameter_value ((parmpy_object *) obj, val); ++ } ++ ++ return PyObject_GenericSetAttr (obj, attr_name, val); ++} ++ ++ ++ ++/* A helper function that dispatches to the appropriate add_setshow ++ function. */ ++static void ++add_setshow_generic (int parmclass, enum command_class cmdclass, ++ char *cmd_name, parmpy_object *self, ++ char *set_doc, char *show_doc, char *help_doc, ++ struct cmd_list_element **set_list, ++ struct cmd_list_element **show_list) ++{ ++ switch (parmclass) ++ { ++ case var_boolean: ++ add_setshow_boolean_cmd (cmd_name, cmdclass, &self->value.intval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_auto_boolean: ++ add_setshow_auto_boolean_cmd (cmd_name, cmdclass, ++ &self->value.autoboolval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_uinteger: ++ add_setshow_uinteger_cmd (cmd_name, cmdclass, &self->value.uintval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_integer: ++ add_setshow_integer_cmd (cmd_name, cmdclass, &self->value.intval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_string: ++ add_setshow_string_cmd (cmd_name, cmdclass, &self->value.stringval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_string_noescape: ++ add_setshow_string_noescape_cmd (cmd_name, cmdclass, ++ &self->value.stringval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_optional_filename: ++ add_setshow_optional_filename_cmd (cmd_name, cmdclass, ++ &self->value.stringval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_filename: ++ add_setshow_filename_cmd (cmd_name, cmdclass, &self->value.stringval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_zinteger: ++ add_setshow_zinteger_cmd (cmd_name, cmdclass, &self->value.intval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ break; ++ ++ case var_enum: ++ add_setshow_enum_cmd (cmd_name, cmdclass, self->enumeration, ++ &self->value.cstringval, ++ set_doc, show_doc, help_doc, ++ NULL, NULL, set_list, show_list); ++ /* Initialize the value, just in case. */ ++ self->value.cstringval = self->enumeration[0]; ++ break; ++ } ++} ++ ++/* A helper which computes enum values. Returns 1 on success, 0 on ++ error. */ ++static int ++compute_enum_values (parmpy_object *self, PyObject *enum_values) ++{ ++ Py_ssize_t size, i; ++ ++ if (! enum_values) ++ { ++ PyErr_SetString (PyExc_RuntimeError, ++ "enumeration required for PARAM_ENUM"); ++ return 0; ++ } ++ ++ if (! PySequence_Check (enum_values)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "enumeration is not a sequence"); ++ return 0; ++ } ++ ++ size = PySequence_Size (enum_values); ++ if (size < 0) ++ return 0; ++ if (size == 0) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "empty enumeration"); ++ return 0; ++ } ++ ++ self->enumeration = xmalloc ((size + 1) * sizeof (char *)); ++ memset (self->enumeration, 0, (size + 1) * sizeof (char *)); ++ ++ for (i = 0; i < size; ++i) ++ { ++ PyObject *item = PySequence_GetItem (enum_values, i); ++ if (! item) ++ return 0; ++ if (! gdbpy_is_string (item)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "enumeration item not a string"); ++ return 0; ++ } ++ self->enumeration[i] = python_string_to_host_string (item); ++ } ++ ++ return 1; ++} ++ ++/* A helper function which returns a documentation string for an ++ object. */ ++static char * ++get_doc_string (PyObject *object, PyObject *attr) ++{ ++ char *result = NULL; ++ if (PyObject_HasAttr (object, attr)) ++ { ++ PyObject *ds_obj = PyObject_GetAttr (object, attr); ++ if (ds_obj && gdbpy_is_string (ds_obj)) ++ result = python_string_to_host_string (ds_obj); ++ } ++ if (! result) ++ result = xstrdup ("This command is not documented."); ++ return result; ++} ++ ++/* Object initializer; sets up gdb-side structures for command. ++ ++ Use: __init__(NAME, CMDCLASS, PARMCLASS, [ENUM]) ++ ++ NAME is the name of the parameter. It may consist of multiple ++ words, in which case the final word is the name of the new command, ++ and earlier words must be prefix commands. ++ ++ CMDCLASS is the kind of command. It should be one of the COMMAND_* ++ constants defined in the gdb module. ++ ++ PARMCLASS is the type of the parameter. It should be one of the ++ PARAM_* constants defined in the gdb module. ++ ++ If PARMCLASS is PARAM_ENUM, then the final argument should be a ++ collection of strings. These strings are the valid values for this ++ parameter. ++ ++ The documentation for the parameter is taken from the doc string ++ for the python class. ++ ++*/ ++static int ++parmpy_init (PyObject *self, PyObject *args, PyObject *kwds) ++{ ++ parmpy_object *obj = (parmpy_object *) self; ++ char *name; ++ char *set_doc, *show_doc, *doc; ++ char *cmd_name; ++ int parmclass, cmdtype; ++ PyObject *enum_values = NULL; ++ struct cmd_list_element *cmd_list; ++ struct cmd_list_element **set_list, **show_list; ++ volatile struct gdb_exception except; ++ ++ if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass, ++ &enum_values)) ++ return -1; ++ ++ if (cmdtype != no_class && cmdtype != class_run ++ && cmdtype != class_vars && cmdtype != class_stack ++ && cmdtype != class_files && cmdtype != class_support ++ && cmdtype != class_info && cmdtype != class_breakpoint ++ && cmdtype != class_trace && cmdtype != class_obscure ++ && cmdtype != class_maintenance) ++ { ++ PyErr_Format (PyExc_RuntimeError, "invalid command class argument"); ++ return -1; ++ } ++ ++ if (parmclass != var_boolean && parmclass != var_auto_boolean ++ && parmclass != var_uinteger && parmclass != var_integer ++ && parmclass != var_string && parmclass != var_string_noescape ++ && parmclass != var_optional_filename && parmclass != var_filename ++ && parmclass != var_zinteger && parmclass != var_enum) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "invalid parameter class argument"); ++ return -1; ++ } ++ ++ if (enum_values && parmclass != var_enum) ++ { ++ PyErr_SetString (PyExc_RuntimeError, ++ "only PARAM_ENUM accepts a fourth argument"); ++ return -1; ++ } ++ if (parmclass == var_enum) ++ { ++ if (! compute_enum_values (obj, enum_values)) ++ return -1; ++ } ++ ++ obj->type = (enum var_types) parmclass; ++ memset (&obj->value, 0, sizeof (obj->value)); ++ obj->enumeration = NULL; ++ ++ cmd_name = gdbpy_parse_command_name (name, &set_list, &setlist); ++ if (! cmd_name) ++ return -1; ++ xfree (cmd_name); ++ cmd_name = gdbpy_parse_command_name (name, &show_list, &showlist); ++ if (! cmd_name) ++ return -1; ++ ++ /* FIXME: there is no way to register a destructor function for ++ set/show commands. So, these are leaked. */ ++ set_doc = get_doc_string (self, set_doc_cst); ++ show_doc = get_doc_string (self, show_doc_cst); ++ doc = get_doc_string (self, gdbpy_doc_cst); ++ ++ Py_INCREF (self); ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ add_setshow_generic (parmclass, (enum command_class) cmdtype, ++ cmd_name, obj, ++ set_doc, show_doc, ++ doc, set_list, show_list); ++ } ++ if (except.reason < 0) ++ { ++ xfree (cmd_name); ++ xfree (set_doc); ++ xfree (show_doc); ++ xfree (doc); ++ Py_DECREF (self); ++ PyErr_Format (except.reason == RETURN_QUIT ++ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, ++ "%s", except.message); ++ return -1; ++ } ++ return 0; ++} ++ ++ ++ ++/* Initialize the 'parameters' module. */ ++void ++gdbpy_initialize_parameters (void) ++{ ++ int i; ++ ++ if (PyType_Ready (&parmpy_object_type) < 0) ++ return; ++ ++ set_doc_cst = PyString_FromString ("set_doc"); ++ if (! set_doc_cst) ++ return; ++ show_doc_cst = PyString_FromString ("show_doc"); ++ if (! show_doc_cst) ++ return; ++ ++ for (i = 0; parm_constants[i].name; ++i) ++ { ++ if (PyModule_AddIntConstant (gdb_module, ++ parm_constants[i].name, ++ parm_constants[i].value) < 0) ++ return; ++ } ++ ++ Py_INCREF (&parmpy_object_type); ++ PyModule_AddObject (gdb_module, "Parameter", ++ (PyObject *) &parmpy_object_type); ++} ++ ++ ++ ++static PyTypeObject parmpy_object_type = ++{ ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Parameter", /*tp_name*/ ++ sizeof (parmpy_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ 0, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ 0, /*tp_str*/ ++ get_attr, /*tp_getattro*/ ++ set_attr, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ ++ "GDB parameter object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ 0, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ 0, /* tp_dictoffset */ ++ parmpy_init, /* tp_init */ ++ 0, /* tp_alloc */ ++ PyType_GenericNew /* tp_new */ ++}; +diff --git a/gdb/python/python-symbol.c b/gdb/python/python-symbol.c +new file mode 100644 +index 0000000..c7fda5c +--- /dev/null ++++ b/gdb/python/python-symbol.c +@@ -0,0 +1,337 @@ ++/* Python interface to symbols. ++ ++ Copyright (C) 2008 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 3 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, see . */ ++ ++#include "defs.h" ++#include "block.h" ++#include "exceptions.h" ++#include "frame.h" ++#include "symtab.h" ++#include "python-internal.h" ++ ++typedef struct { ++ PyObject_HEAD ++ struct symbol *symbol; ++} symbol_object; ++ ++ ++static PyObject * ++sympy_str (PyObject *self) ++{ ++ int ret; ++ char *s; ++ PyObject *result; ++ ++ ret = asprintf (&s, "symbol for %s", ++ SYMBOL_PRINT_NAME (((symbol_object *) self)->symbol)); ++ if (ret < 0) ++ Py_RETURN_NONE; ++ ++ result = PyString_FromString (s); ++ xfree (s); ++ ++ return result; ++} ++ ++static PyObject * ++sympy_get_value (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ ++ switch (SYMBOL_CLASS (self_sym->symbol)) ++ { ++ case LOC_BLOCK: ++ return block_to_block_object (SYMBOL_BLOCK_VALUE (self_sym->symbol)); ++ } ++ ++ PyErr_SetString (PyExc_NotImplementedError, ++ "Symbol type not yet supported in Python scripts."); ++ return NULL; ++} ++ ++static PyObject * ++sympy_get_symtab (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ ++ return symtab_to_symtab_object (SYMBOL_SYMTAB (self_sym->symbol)); ++} ++ ++static PyObject * ++sympy_get_name (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ ++ return PyString_FromString (SYMBOL_NATURAL_NAME (self_sym->symbol)); ++} ++ ++static PyObject * ++sympy_get_linkage_name (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ ++ return PyString_FromString (SYMBOL_LINKAGE_NAME (self_sym->symbol)); ++} ++ ++static PyObject * ++sympy_get_print_name (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ ++ return PyString_FromString (SYMBOL_PRINT_NAME (self_sym->symbol)); ++} ++ ++static PyObject * ++sympy_get_addr_class (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ ++ return PyInt_FromLong (SYMBOL_CLASS (self_sym->symbol)); ++} ++ ++static PyObject * ++sympy_is_argument (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ ++ return PyBool_FromLong (SYMBOL_IS_ARGUMENT (self_sym->symbol)); ++} ++ ++static PyObject * ++sympy_is_constant (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ enum address_class class = SYMBOL_CLASS (self_sym->symbol); ++ ++ return PyBool_FromLong (class == LOC_CONST || class == LOC_CONST_BYTES); ++} ++ ++static PyObject * ++sympy_is_function (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ enum address_class class = SYMBOL_CLASS (self_sym->symbol); ++ ++ return PyBool_FromLong (class == LOC_BLOCK); ++} ++ ++static PyObject * ++sympy_is_variable (PyObject *self, void *closure) ++{ ++ symbol_object *self_sym = (symbol_object *) self; ++ enum address_class class = SYMBOL_CLASS (self_sym->symbol); ++ ++ return PyBool_FromLong (!SYMBOL_IS_ARGUMENT (self_sym->symbol) ++ && (class == LOC_LOCAL || class == LOC_REGISTER || class == LOC_STATIC ++ || class == LOC_COMPUTED || class == LOC_OPTIMIZED_OUT)); ++} ++ ++PyObject * ++symbol_to_symbol_object (struct symbol *sym) ++{ ++ symbol_object *sym_obj; ++ ++ sym_obj = PyObject_New (symbol_object, &symbol_object_type); ++ if (sym_obj == NULL) ++ { ++ PyErr_SetString (PyExc_MemoryError, "Could not allocate symbol object."); ++ return NULL; ++ } ++ ++ sym_obj->symbol = sym; ++ ++ return (PyObject *) sym_obj; ++} ++ ++struct symbol * ++symbol_object_to_symbol (PyObject *obj) ++{ ++ if (! PyObject_TypeCheck (obj, &symbol_object_type)) ++ return NULL; ++ return ((symbol_object *) obj)->symbol; ++} ++ ++/* Implementation of ++ gdb.lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this) ++ A tuple with 2 elements is always returned. The first is the symbol ++ object or None, the second is a boolean with the value of ++ is_a_field_of_this (see comment in lookup_symbol_in_language). */ ++ ++PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw) ++{ ++ int domain = VAR_DOMAIN, is_a_field_of_this = 0; ++ const char *name; ++ static char *keywords[] = { "name", "block", "domain", NULL }; ++ struct symbol *symbol; ++ PyObject *block_obj = NULL, *ret_tuple, *sym_obj, *bool_obj; ++ struct block *block = NULL; ++ ++ if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!i", keywords, &name, ++ &block_object_type, &block_obj, &domain)) ++ return NULL; ++ ++ if (block_obj) ++ block = block_object_to_block (block_obj); ++ else ++ { ++ struct frame_info *selected_frame; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ selected_frame = get_selected_frame (_("No frame selected.")); ++ block = block_for_pc (get_frame_address_in_block (selected_frame)); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ } ++ ++ symbol = lookup_symbol (name, block, domain, &is_a_field_of_this); ++ ++ ret_tuple = PyTuple_New (2); ++ if (!ret_tuple) ++ { ++ PyErr_SetString (PyExc_MemoryError, "Could not allocate tuple object."); ++ return NULL; ++ } ++ ++ if (symbol) ++ { ++ sym_obj = symbol_to_symbol_object (symbol); ++ if (!sym_obj) ++ { ++ Py_DECREF (ret_tuple); ++ return NULL; ++ } ++ } ++ else ++ { ++ sym_obj = Py_None; ++ Py_INCREF (Py_None); ++ } ++ PyTuple_SET_ITEM (ret_tuple, 0, sym_obj); ++ ++ bool_obj = is_a_field_of_this? Py_True : Py_False; ++ Py_INCREF (bool_obj); ++ PyTuple_SET_ITEM (ret_tuple, 1, bool_obj); ++ ++ return ret_tuple; ++} ++ ++void ++gdbpy_initialize_symbols (void) ++{ ++ symbol_object_type.tp_new = PyType_GenericNew; ++ if (PyType_Ready (&symbol_object_type) < 0) ++ return; ++ ++ /* FIXME: These would probably be best exposed as class attributes of Symbol, ++ but I don't know how to do it except by messing with the type's dictionary. ++ That seems too messy. */ ++ /* FIXME 2: Some of these were removed from GDB since I first wrote this code, ++ so it's probably a good idea not to expose them to Python. */ ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNDEF", LOC_UNDEF); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST", LOC_CONST); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_STATIC", LOC_STATIC); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGISTER", LOC_REGISTER); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_ARG", LOC_ARG); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REF_ARG", LOC_REF_ARG); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LOCAL", LOC_LOCAL); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_TYPEDEF", LOC_TYPEDEF); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LABEL", LOC_LABEL); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_BLOCK", LOC_BLOCK); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST_BYTES", ++ LOC_CONST_BYTES); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNRESOLVED", LOC_UNRESOLVED); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_OPTIMIZED_OUT", ++ LOC_OPTIMIZED_OUT); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_COMPUTED", LOC_COMPUTED); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGPARM_ADDR", ++ LOC_REGPARM_ADDR); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_UNDEF_DOMAIN", UNDEF_DOMAIN); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_VAR_DOMAIN", VAR_DOMAIN); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_STRUCT_DOMAIN", STRUCT_DOMAIN); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_LABEL_DOMAIN", LABEL_DOMAIN); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_VARIABLES_DOMAIN", ++ VARIABLES_DOMAIN); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_FUNCTIONS_DOMAIN", ++ FUNCTIONS_DOMAIN); ++ PyModule_AddIntConstant (gdb_module, "SYMBOL_TYPES_DOMAIN", TYPES_DOMAIN); ++ ++ Py_INCREF (&symbol_object_type); ++ PyModule_AddObject (gdb_module, "Symbol", (PyObject *) &symbol_object_type); ++} ++ ++ ++ ++static PyGetSetDef symbol_object_getset[] = { ++ { "value", sympy_get_value, NULL, "Value of the symbol.", NULL }, ++ { "symtab", sympy_get_symtab, NULL, ++ "Symbol table in which the symbol appears.", NULL }, ++ { "name", sympy_get_name, NULL, ++ "Name of the symbol, as it appears in the source code.", NULL }, ++ { "linkage_name", sympy_get_linkage_name, NULL, ++ "Name of the symbol, as used by the linker (i.e., may be mangled).", NULL }, ++ { "print_name", sympy_get_print_name, NULL, ++ "Name of the symbol in a form suitable for output.\n\ ++This is either name or linkage_name, depending on whether the user asked GDB\n\ ++to display demangled or mangled names.", NULL }, ++ { "addr_class", sympy_get_addr_class, NULL, "Address class of the symbol." }, ++ { "is_argument", sympy_is_argument, NULL, ++ "True if the symbol is an argument of a function." }, ++ { "is_constant", sympy_is_constant, NULL, ++ "True if the symbol is a constant." }, ++ { "is_function", sympy_is_function, NULL, ++ "True if the symbol is a function or method." }, ++ { "is_variable", sympy_is_variable, NULL, ++ "True if the symbol is a variable." }, ++ { NULL } /* Sentinel */ ++}; ++ ++PyTypeObject symbol_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Symbol", /*tp_name*/ ++ sizeof (symbol_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ 0, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ sympy_str, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT, /*tp_flags*/ ++ "GDB symbol object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ symbol_object_getset /* tp_getset */ ++}; +diff --git a/gdb/python/python-symtab.c b/gdb/python/python-symtab.c +new file mode 100644 +index 0000000..a48c38c +--- /dev/null ++++ b/gdb/python/python-symtab.c +@@ -0,0 +1,311 @@ ++/* Python interface to symbol tables. ++ ++ Copyright (C) 2008 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 3 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, see . */ ++ ++#include "defs.h" ++#include "charset.h" ++#include "symtab.h" ++#include "source.h" ++#include "python-internal.h" ++ ++typedef struct { ++ PyObject_HEAD ++ struct symtab *symtab; ++} symtab_object; ++ ++static PyTypeObject symtab_object_type; ++ ++typedef struct { ++ PyObject_HEAD ++ symtab_object *symtab; ++ struct symtab_and_line *sal; ++} sal_object; ++ ++static PyTypeObject sal_object_type; ++ ++ ++static PyObject * ++stpy_str (PyObject *self) ++{ ++ int ret; ++ char *s; ++ PyObject *result; ++ ++ ret = asprintf (&s, "symbol table for %s", ++ ((symtab_object *) self)->symtab->filename); ++ if (ret < 0) ++ Py_RETURN_NONE; ++ ++ result = PyString_FromString (s); ++ xfree (s); ++ ++ return result; ++} ++ ++static PyObject * ++stpy_get_filename (PyObject *self, void *closure) ++{ ++ symtab_object *self_symtab = (symtab_object *) self; ++ PyObject *str_obj; ++ ++ /* FIXME: Can symtab->filename really be NULL? */ ++ if (self_symtab->symtab->filename) ++ str_obj = PyString_Decode (self_symtab->symtab->filename, ++ strlen (self_symtab->symtab->filename), ++ host_charset (), NULL); ++ else ++ { ++ str_obj = Py_None; ++ Py_INCREF (Py_None); ++ } ++ ++ return str_obj; ++} ++ ++static PyObject * ++stpy_fullname (PyObject *self, PyObject *args) ++{ ++ char *fullname; ++ ++ fullname = symtab_to_fullname (((symtab_object *) self)->symtab); ++ if (fullname) ++ return PyString_Decode (fullname, strlen (fullname), host_charset (), NULL); ++ ++ Py_RETURN_NONE; ++} ++ ++static PyObject * ++salpy_str (PyObject *self) ++{ ++ int ret; ++ char *s, *filename; ++ sal_object *sal_obj; ++ PyObject *result; ++ ++ sal_obj = (sal_object *) self; ++ filename = (sal_obj->symtab == (symtab_object *) Py_None)? "" : ++ sal_obj->symtab->symtab->filename; ++ ret = asprintf (&s, "symbol and line for %s, line %d", filename, ++ sal_obj->sal->line); ++ if (ret < 0) ++ Py_RETURN_NONE; ++ ++ result = PyString_FromString (s); ++ xfree (s); ++ ++ return result; ++} ++ ++static PyObject * ++salpy_get_pc (PyObject *self, void *closure) ++{ ++ return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->pc); ++} ++ ++static PyObject * ++salpy_get_line (PyObject *self, void *closure) ++{ ++ return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->line); ++} ++ ++static PyObject * ++salpy_get_symtab (PyObject *self, void *closure) ++{ ++ sal_object *self_sal = (sal_object *) self; ++ ++ Py_INCREF (self_sal->symtab); ++ ++ return (PyObject *) self_sal->symtab; ++} ++ ++static void ++salpy_dealloc (PyObject *self) ++{ ++ sal_object *self_sal = (sal_object *) self; ++ ++ Py_DECREF (self_sal->symtab); ++ xfree (self_sal->sal); ++ self_sal->ob_type->tp_free (self); ++} ++ ++PyObject * ++symtab_and_line_to_sal_object (struct symtab_and_line sal) ++{ ++ sal_object *sal_obj; ++ symtab_object *symtab_obj; ++ ++ sal_obj = PyObject_New (sal_object, &sal_object_type); ++ if (sal_obj == NULL) ++ { ++ PyErr_SetString (PyExc_MemoryError, ++ "Could not allocate Symtab_and_line object."); ++ return NULL; ++ } ++ ++ if (sal.symtab) ++ { ++ symtab_obj = (symtab_object *) symtab_to_symtab_object (sal.symtab); ++ if (symtab_obj == NULL) ++ { ++ Py_DECREF (sal_obj); ++ return NULL; ++ } ++ ++ symtab_obj->symtab = sal.symtab; ++ } ++ else ++ { ++ symtab_obj = (symtab_object *) Py_None; ++ Py_INCREF (Py_None); ++ } ++ ++ sal_obj->sal = (struct symtab_and_line *) ++ xmalloc (sizeof (struct symtab_and_line)); ++ *(sal_obj->sal) = sal; ++ sal_obj->symtab = symtab_obj; ++ ++ return (PyObject *) sal_obj; ++} ++ ++PyObject * ++symtab_to_symtab_object (struct symtab *symtab) ++{ ++ symtab_object *symtab_obj; ++ ++ symtab_obj = PyObject_New (symtab_object, &symtab_object_type); ++ if (symtab_obj == NULL) ++ { ++ PyErr_SetString (PyExc_MemoryError, ++ "Could not allocate Symtab object."); ++ ++ return NULL; ++ } ++ ++ symtab_obj->symtab = symtab; ++ ++ return (PyObject *) symtab_obj; ++} ++ ++void ++gdbpy_initialize_symtabs (void) ++{ ++ symtab_object_type.tp_new = PyType_GenericNew; ++ if (PyType_Ready (&symtab_object_type) < 0) ++ return; ++ ++ sal_object_type.tp_new = PyType_GenericNew; ++ if (PyType_Ready (&sal_object_type) < 0) ++ return; ++ ++ Py_INCREF (&symtab_object_type); ++ PyModule_AddObject (gdb_module, "Symtab", (PyObject *) &symtab_object_type); ++ ++ Py_INCREF (&sal_object_type); ++ PyModule_AddObject (gdb_module, "Symtab_and_line", ++ (PyObject *) &sal_object_type); ++} ++ ++ ++ ++static PyGetSetDef symtab_object_getset[] = { ++ { "filename", stpy_get_filename, NULL, ++ "The symbol table's source filename.", NULL }, ++ {NULL} /* Sentinel */ ++}; ++ ++static PyMethodDef symtab_object_methods[] = { ++ { "fullname", stpy_fullname, METH_NOARGS, ++ "Return the symtab's full source filename." }, ++ {NULL} /* Sentinel */ ++}; ++ ++static PyTypeObject symtab_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Symtab", /*tp_name*/ ++ sizeof (symtab_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ 0, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ stpy_str, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT, /*tp_flags*/ ++ "GDB symtab object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ symtab_object_methods, /* tp_methods */ ++ 0, /* tp_members */ ++ symtab_object_getset /* tp_getset */ ++}; ++ ++static PyGetSetDef sal_object_getset[] = { ++ { "symtab", salpy_get_symtab, NULL, "Symtab object.", NULL }, ++ { "pc", salpy_get_pc, NULL, "Return the symtab_and_line's pc.", NULL }, ++ { "line", salpy_get_line, NULL, ++ "Return the symtab_and_line's line.", NULL }, ++ {NULL} /* Sentinel */ ++}; ++ ++static PyTypeObject sal_object_type = { ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Symtab_and_line", /*tp_name*/ ++ sizeof (sal_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ salpy_dealloc, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ salpy_str, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT, /*tp_flags*/ ++ "GDB symtab_and_line object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ sal_object_getset /* tp_getset */ ++}; +diff --git a/gdb/python/python-type.c b/gdb/python/python-type.c +new file mode 100644 +index 0000000..fcf6b82 +--- /dev/null ++++ b/gdb/python/python-type.c +@@ -0,0 +1,836 @@ ++/* Python interface to types. ++ ++ Copyright (C) 2008, 2009 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 3 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, see . */ ++ ++#include "defs.h" ++#include "value.h" ++#include "exceptions.h" ++#include "python-internal.h" ++#include "charset.h" ++#include "gdbtypes.h" ++#include "cp-support.h" ++#include "demangle.h" ++#include "objfiles.h" ++#include "gdb_assert.h" ++ ++typedef struct pyty_type_object ++{ ++ PyObject_HEAD ++ struct type *type; ++ ++ /* If a Type object is associated with an objfile, it is kept on a ++ doubly-linked list, rooted in the objfile. This lets us copy the ++ underlying struct type when the objfile is deleted. */ ++ struct pyty_type_object *prev; ++ struct pyty_type_object *next; ++} type_object; ++ ++static PyTypeObject type_object_type; ++ ++/* A Field object. */ ++typedef struct pyty_field_object ++{ ++ PyObject_HEAD ++ ++ /* Dictionary holding our attributes. */ ++ PyObject *dict; ++} field_object; ++ ++static PyTypeObject field_object_type; ++ ++/* This is used to initialize various gdb.TYPE_ constants. */ ++struct pyty_code ++{ ++ /* The code. */ ++ enum type_code code; ++ /* The name. */ ++ const char *name; ++}; ++ ++#define ENTRY(X) { X, #X } ++ ++static struct pyty_code pyty_codes[] = ++{ ++ ENTRY (TYPE_CODE_PTR), ++ ENTRY (TYPE_CODE_ARRAY), ++ ENTRY (TYPE_CODE_STRUCT), ++ ENTRY (TYPE_CODE_UNION), ++ ENTRY (TYPE_CODE_ENUM), ++ ENTRY (TYPE_CODE_FLAGS), ++ ENTRY (TYPE_CODE_FUNC), ++ ENTRY (TYPE_CODE_INT), ++ ENTRY (TYPE_CODE_FLT), ++ ENTRY (TYPE_CODE_VOID), ++ ENTRY (TYPE_CODE_SET), ++ ENTRY (TYPE_CODE_RANGE), ++ ENTRY (TYPE_CODE_STRING), ++ ENTRY (TYPE_CODE_BITSTRING), ++ ENTRY (TYPE_CODE_ERROR), ++ ENTRY (TYPE_CODE_METHOD), ++ ENTRY (TYPE_CODE_METHODPTR), ++ ENTRY (TYPE_CODE_MEMBERPTR), ++ ENTRY (TYPE_CODE_REF), ++ ENTRY (TYPE_CODE_CHAR), ++ ENTRY (TYPE_CODE_BOOL), ++ ENTRY (TYPE_CODE_COMPLEX), ++ ENTRY (TYPE_CODE_TYPEDEF), ++ ENTRY (TYPE_CODE_NAMESPACE), ++ ENTRY (TYPE_CODE_DECFLOAT), ++ ENTRY (TYPE_CODE_INTERNAL_FUNCTION), ++ { TYPE_CODE_UNDEF, NULL } ++}; ++ ++ ++ ++static void ++field_dealloc (PyObject *obj) ++{ ++ field_object *f = (field_object *) obj; ++ Py_XDECREF (f->dict); ++ f->ob_type->tp_free (obj); ++} ++ ++static PyObject * ++field_new (void) ++{ ++ field_object *result = PyObject_New (field_object, &field_object_type); ++ if (result) ++ { ++ result->dict = PyDict_New (); ++ if (!result->dict) ++ { ++ Py_DECREF (result); ++ result = NULL; ++ } ++ } ++ return (PyObject *) result; ++} ++ ++ ++ ++/* Return the code for this type. */ ++static PyObject * ++typy_get_code (PyObject *self, void *closure) ++{ ++ struct type *type = ((type_object *) self)->type; ++ return PyInt_FromLong (TYPE_CODE (type)); ++} ++ ++/* Helper function for typy_fields which converts a single field to a ++ dictionary. Returns NULL on error. */ ++static PyObject * ++convert_field (struct type *type, int field) ++{ ++ PyObject *result = field_new (); ++ PyObject *arg; ++ ++ if (!result) ++ return NULL; ++ ++ if (!field_is_static (&TYPE_FIELD (type, field))) ++ { ++ arg = PyLong_FromLong (TYPE_FIELD_BITPOS (type, field)); ++ if (!arg) ++ goto fail; ++ ++ if (PyObject_SetAttrString (result, "bitpos", arg) < 0) ++ goto failarg; ++ } ++ ++ if (TYPE_FIELD_NAME (type, field)) ++ arg = PyString_FromString (TYPE_FIELD_NAME (type, field)); ++ else ++ { ++ arg = Py_None; ++ Py_INCREF (arg); ++ } ++ if (!arg) ++ goto fail; ++ if (PyObject_SetAttrString (result, "name", arg) < 0) ++ goto failarg; ++ ++ arg = TYPE_FIELD_ARTIFICIAL (type, field) ? Py_True : Py_False; ++ Py_INCREF (arg); ++ if (PyObject_SetAttrString (result, "artificial", arg) < 0) ++ goto failarg; ++ ++ arg = PyLong_FromLong (TYPE_FIELD_BITSIZE (type, field)); ++ if (!arg) ++ goto fail; ++ if (PyObject_SetAttrString (result, "bitsize", arg) < 0) ++ goto failarg; ++ ++ /* A field can have a NULL type in some situations. */ ++ if (TYPE_FIELD_TYPE (type, field) == NULL) ++ { ++ arg = Py_None; ++ Py_INCREF (arg); ++ } ++ else ++ arg = type_to_type_object (TYPE_FIELD_TYPE (type, field)); ++ if (!arg) ++ goto fail; ++ if (PyObject_SetAttrString (result, "type", arg) < 0) ++ goto failarg; ++ ++ return result; ++ ++ failarg: ++ Py_DECREF (arg); ++ fail: ++ Py_DECREF (result); ++ return NULL; ++} ++ ++/* Return a sequence of all fields. Each field is a dictionary with ++ some pre-defined keys. */ ++static PyObject * ++typy_fields (PyObject *self, PyObject *args) ++{ ++ PyObject *result; ++ int i; ++ struct type *type = ((type_object *) self)->type; ++ ++ /* We would like to make a tuple here, make fields immutable, and ++ then memoize the result (and perhaps make Field.type() lazy). ++ However, that can lead to cycles. */ ++ result = PyList_New (0); ++ ++ for (i = 0; i < TYPE_NFIELDS (type); ++i) ++ { ++ PyObject *dict = convert_field (type, i); ++ if (!dict) ++ { ++ Py_DECREF (result); ++ return NULL; ++ } ++ if (PyList_Append (result, dict)) ++ { ++ Py_DECREF (dict); ++ Py_DECREF (result); ++ return NULL; ++ } ++ } ++ ++ return result; ++} ++ ++/* Return the type's tag, or None. */ ++static PyObject * ++typy_get_tag (PyObject *self, void *closure) ++{ ++ struct type *type = ((type_object *) self)->type; ++ if (!TYPE_TAG_NAME (type)) ++ Py_RETURN_NONE; ++ return PyString_FromString (TYPE_TAG_NAME (type)); ++} ++ ++/* Return the type, stripped of typedefs. */ ++static PyObject * ++typy_strip_typedefs (PyObject *self, PyObject *args) ++{ ++ struct type *type = ((type_object *) self)->type; ++ ++ return type_to_type_object (check_typedef (type)); ++} ++ ++/* Return a Type object which represents a pointer to SELF. */ ++static PyObject * ++typy_pointer (PyObject *self, PyObject *args) ++{ ++ struct type *type = ((type_object *) self)->type; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ type = lookup_pointer_type (type); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return type_to_type_object (type); ++} ++ ++/* Return a Type object which represents a reference to SELF. */ ++static PyObject * ++typy_reference (PyObject *self, PyObject *args) ++{ ++ struct type *type = ((type_object *) self)->type; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ type = lookup_reference_type (type); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return type_to_type_object (type); ++} ++ ++/* Return a Type object which represents the target type of SELF. */ ++static PyObject * ++typy_target (PyObject *self, PyObject *args) ++{ ++ struct type *type = ((type_object *) self)->type; ++ ++ if (!TYPE_TARGET_TYPE (type)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "type does not have a target"); ++ return NULL; ++ } ++ ++ return type_to_type_object (TYPE_TARGET_TYPE (type)); ++} ++ ++/* Return a const-qualified type variant. */ ++static PyObject * ++typy_const (PyObject *self, PyObject *args) ++{ ++ struct type *type = ((type_object *) self)->type; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ type = make_cv_type (1, 0, type, NULL); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return type_to_type_object (type); ++} ++ ++/* Return a volatile-qualified type variant. */ ++static PyObject * ++typy_volatile (PyObject *self, PyObject *args) ++{ ++ struct type *type = ((type_object *) self)->type; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ type = make_cv_type (0, 1, type, NULL); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return type_to_type_object (type); ++} ++ ++/* Return an unqualified type variant. */ ++static PyObject * ++typy_unqualified (PyObject *self, PyObject *args) ++{ ++ struct type *type = ((type_object *) self)->type; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ type = make_cv_type (0, 0, type, NULL); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return type_to_type_object (type); ++} ++ ++/* Return the size of the type represented by SELF, in bytes. */ ++static PyObject * ++typy_get_sizeof (PyObject *self, void *closure) ++{ ++ struct type *type = ((type_object *) self)->type; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ check_typedef (type); ++ } ++ /* Ignore exceptions. */ ++ ++ return PyLong_FromLong (TYPE_LENGTH (type)); ++} ++ ++static struct type * ++typy_lookup_typename (char *type_name, struct block *block) ++{ ++ struct type *type = NULL; ++ volatile struct gdb_exception except; ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ if (!strncmp (type_name, "struct ", 7)) ++ type = lookup_struct (type_name + 7, block); ++ else if (!strncmp (type_name, "union ", 6)) ++ type = lookup_union (type_name + 6, block); ++ else if (!strncmp (type_name, "enum ", 5)) ++ type = lookup_enum (type_name + 5, block); ++ else ++ type = lookup_typename (type_name, block, 0); ++ } ++ if (except.reason < 0) ++ { ++ PyErr_Format (except.reason == RETURN_QUIT ++ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, ++ "%s", except.message); ++ return NULL; ++ } ++ ++ return type; ++} ++ ++static struct type * ++typy_lookup_type (struct demangle_component *demangled, ++ struct block *block) ++{ ++ struct type *type; ++ char *type_name; ++ enum demangle_component_type demangled_type; ++ ++ /* Save the type: typy_lookup_type() may (indirectly) overwrite ++ memory pointed by demangled. */ ++ demangled_type = demangled->type; ++ ++ if (demangled_type == DEMANGLE_COMPONENT_POINTER ++ || demangled_type == DEMANGLE_COMPONENT_REFERENCE ++ || demangled_type == DEMANGLE_COMPONENT_CONST ++ || demangled_type == DEMANGLE_COMPONENT_VOLATILE) ++ { ++ type = typy_lookup_type (demangled->u.s_binary.left, block); ++ if (! type) ++ return NULL; ++ ++ switch (demangled_type) ++ { ++ case DEMANGLE_COMPONENT_REFERENCE: ++ return lookup_reference_type (type); ++ case DEMANGLE_COMPONENT_POINTER: ++ return lookup_pointer_type (type); ++ case DEMANGLE_COMPONENT_CONST: ++ return make_cv_type (1, 0, type, NULL); ++ case DEMANGLE_COMPONENT_VOLATILE: ++ return make_cv_type (0, 1, type, NULL); ++ } ++ } ++ ++ type_name = cp_comp_to_string (demangled, 10); ++ type = typy_lookup_typename (type_name, block); ++ xfree (type_name); ++ ++ return type; ++} ++ ++static PyObject * ++typy_template_argument (PyObject *self, PyObject *args) ++{ ++ int i, argno, n_pointers; ++ struct type *type = ((type_object *) self)->type; ++ struct demangle_component *demangled; ++ const char *err; ++ struct type *argtype; ++ struct block *block = NULL; ++ PyObject *block_obj = NULL; ++ ++ if (! PyArg_ParseTuple (args, "i|O", &argno, &block_obj)) ++ return NULL; ++ ++ if (block_obj) ++ { ++ block = block_object_to_block (block_obj); ++ if (! block) ++ { ++ PyErr_SetString (PyExc_RuntimeError, ++ "second argument must be block"); ++ return NULL; ++ } ++ } ++ ++ type = check_typedef (type); ++ if (TYPE_CODE (type) == TYPE_CODE_REF) ++ type = check_typedef (TYPE_TARGET_TYPE (type)); ++ ++ if (TYPE_NAME (type) == NULL) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "null type name"); ++ return NULL; ++ } ++ ++ /* Note -- this is not thread-safe. */ ++ demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err); ++ if (! demangled) ++ { ++ PyErr_SetString (PyExc_RuntimeError, err); ++ return NULL; ++ } ++ ++ /* Strip off component names. */ ++ while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME ++ || demangled->type == DEMANGLE_COMPONENT_LOCAL_NAME) ++ demangled = demangled->u.s_binary.right; ++ ++ if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "type is not a template"); ++ return NULL; ++ } ++ ++ /* Skip from the template to the arguments. */ ++ demangled = demangled->u.s_binary.right; ++ ++ for (i = 0; demangled && i < argno; ++i) ++ demangled = demangled->u.s_binary.right; ++ ++ if (! demangled) ++ { ++ PyErr_Format (PyExc_RuntimeError, "no argument %d in template", ++ argno); ++ return NULL; ++ } ++ ++ argtype = typy_lookup_type (demangled->u.s_binary.left, block); ++ if (! argtype) ++ return NULL; ++ ++ return type_to_type_object (argtype); ++} ++ ++static PyObject * ++typy_str (PyObject *self) ++{ ++ volatile struct gdb_exception except; ++ char *thetype = NULL; ++ PyObject *result; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ struct cleanup *old_chain; ++ struct ui_file *stb; ++ long length; ++ ++ stb = mem_fileopen (); ++ old_chain = make_cleanup_ui_file_delete (stb); ++ ++ type_print (type_object_to_type (self), "", stb, -1); ++ ++ thetype = ui_file_xstrdup (stb, &length); ++ do_cleanups (old_chain); ++ } ++ if (except.reason < 0) ++ { ++ xfree (thetype); ++ GDB_PY_HANDLE_EXCEPTION (except); ++ } ++ ++ result = PyUnicode_Decode (thetype, strlen (thetype), host_charset (), NULL); ++ xfree (thetype); ++ ++ return result; ++} ++ ++ ++ ++static const struct objfile_data *typy_objfile_data_key; ++ ++static void ++clean_up_objfile_types (struct objfile *objfile, void *datum) ++{ ++ type_object *obj = datum; ++ htab_t copied_types; ++ struct cleanup *cleanup; ++ PyGILState_STATE state; ++ ++ /* This prevents another thread from freeing the objects we're ++ operating on. */ ++ state = PyGILState_Ensure (); ++ cleanup = make_cleanup_py_restore_gil (&state); ++ ++ copied_types = create_copied_types_hash (objfile); ++ ++ while (obj) ++ { ++ type_object *next = obj->next; ++ ++ htab_empty (copied_types); ++ ++ /* No need to decref the old type here, since we know it has no ++ reference count. */ ++ gdb_assert (objfile == TYPE_OBJFILE (obj->type)); ++ obj->type = copy_type_recursive (obj->type, copied_types); ++ type_incref (obj->type); ++ ++ obj->next = NULL; ++ obj->prev = NULL; ++ ++ obj = next; ++ } ++ ++ htab_delete (copied_types); ++ ++ do_cleanups (cleanup); ++} ++ ++static void ++set_type (type_object *obj, struct type *type) ++{ ++ obj->type = type; ++ type_incref (type); ++ obj->prev = NULL; ++ if (type && !OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (type))) ++ { ++ struct objfile *objfile = TYPE_OBJFILE (type); ++ ++ obj->next = objfile_data (objfile, typy_objfile_data_key); ++ if (obj->next) ++ obj->next->prev = obj; ++ set_objfile_data (objfile, typy_objfile_data_key, obj); ++ } ++ else ++ obj->next = NULL; ++} ++ ++static void ++typy_dealloc (PyObject *obj) ++{ ++ type_object *type = (type_object *) obj; ++ ++ if (type->type) ++ type_decref (type->type); ++ ++ if (type->prev) ++ type->prev->next = type->next; ++ else if (type->type && !OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (type->type))) ++ { ++ /* Must reset head of list. */ ++ struct objfile *objfile = TYPE_OBJFILE (type->type); ++ if (objfile) ++ set_objfile_data (objfile, typy_objfile_data_key, type->next); ++ } ++ if (type->next) ++ type->next->prev = type->prev; ++ ++ type->ob_type->tp_free (type); ++} ++ ++/* Create a new Type referring to TYPE. */ ++PyObject * ++type_to_type_object (struct type *type) ++{ ++ type_object *type_obj; ++ ++ type_obj = PyObject_New (type_object, &type_object_type); ++ if (type_obj) ++ set_type (type_obj, type); ++ ++ return (PyObject *) type_obj; ++} ++ ++struct type * ++type_object_to_type (PyObject *obj) ++{ ++ if (! PyObject_TypeCheck (obj, &type_object_type)) ++ return NULL; ++ return ((type_object *) obj)->type; ++} ++ ++ ++ ++/* Implementation of gdb.lookup_type. */ ++PyObject * ++gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw) ++{ ++ static char *keywords[] = { "name", "block", NULL }; ++ char *type_name = NULL; ++ struct type *type = NULL; ++ PyObject *block_obj = NULL; ++ struct block *block = NULL; ++ ++ if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O", keywords, ++ &type_name, &block_obj)) ++ return NULL; ++ ++ if (block_obj) ++ { ++ block = block_object_to_block (block_obj); ++ if (! block) ++ { ++ PyErr_SetString (PyExc_RuntimeError, ++ "'block' argument must be a Block"); ++ return NULL; ++ } ++ } ++ ++ type = typy_lookup_typename (type_name, block); ++ if (! type) ++ return NULL; ++ ++ return (PyObject *) type_to_type_object (type); ++} ++ ++void ++gdbpy_initialize_types (void) ++{ ++ int i; ++ ++ typy_objfile_data_key ++ = register_objfile_data_with_cleanup (clean_up_objfile_types); ++ ++ if (PyType_Ready (&type_object_type) < 0) ++ return; ++ if (PyType_Ready (&field_object_type) < 0) ++ return; ++ ++ for (i = 0; pyty_codes[i].name; ++i) ++ { ++ if (PyModule_AddIntConstant (gdb_module, ++ /* Cast needed for Python 2.4. */ ++ (char *) pyty_codes[i].name, ++ pyty_codes[i].code) < 0) ++ return; ++ } ++ ++ Py_INCREF (&type_object_type); ++ PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type); ++ ++ Py_INCREF (&field_object_type); ++ PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type); ++} ++ ++ ++ ++static PyGetSetDef type_object_getset[] = ++{ ++ { "code", typy_get_code, NULL, ++ "The code for this type.", NULL }, ++ { "sizeof", typy_get_sizeof, NULL, ++ "The size of this type, in bytes.", NULL }, ++ { "tag", typy_get_tag, NULL, ++ "The tag name for this type, or None.", NULL }, ++ { NULL } ++}; ++ ++static PyMethodDef type_object_methods[] = ++{ ++ { "const", typy_const, METH_NOARGS, ++ "const () -> Type\n\ ++Return a const variant of this type." }, ++ { "fields", typy_fields, METH_NOARGS, ++ "field () -> list\n\ ++Return a sequence holding all the fields of this type.\n\ ++Each field is a dictionary." }, ++ { "pointer", typy_pointer, METH_NOARGS, ++ "pointer () -> Type\n\ ++Return a type of pointer to this type." }, ++ { "reference", typy_reference, METH_NOARGS, ++ "reference () -> Type\n\ ++Return a type of reference to this type." }, ++ { "strip_typedefs", typy_strip_typedefs, METH_NOARGS, ++ "strip_typedefs () -> Type\n\ ++Return a type formed by stripping this type of all typedefs."}, ++ { "target", typy_target, METH_NOARGS, ++ "target () -> Type\n\ ++Return the target type of this type." }, ++ { "template_argument", typy_template_argument, METH_VARARGS, ++ "template_argument (arg) -> Type\n\ ++Return the type of a template argument." }, ++ { "unqualified", typy_unqualified, METH_NOARGS, ++ "unqualified () -> Type\n\ ++Return a variant of this type without const or volatile attributes." }, ++ { "volatile", typy_volatile, METH_NOARGS, ++ "volatile () -> Type\n\ ++Return a volatile variant of this type" }, ++ { NULL } ++}; ++ ++static PyTypeObject type_object_type = ++{ ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Type", /*tp_name*/ ++ sizeof (type_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ typy_dealloc, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ typy_str, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ ++ "GDB type object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ type_object_methods, /* tp_methods */ ++ 0, /* tp_members */ ++ type_object_getset, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ 0, /* tp_dictoffset */ ++ 0, /* tp_init */ ++ 0, /* tp_alloc */ ++ 0, /* tp_new */ ++}; ++ ++static PyTypeObject field_object_type = ++{ ++ PyObject_HEAD_INIT (NULL) ++ 0, /*ob_size*/ ++ "gdb.Field", /*tp_name*/ ++ sizeof (field_object), /*tp_basicsize*/ ++ 0, /*tp_itemsize*/ ++ field_dealloc, /*tp_dealloc*/ ++ 0, /*tp_print*/ ++ 0, /*tp_getattr*/ ++ 0, /*tp_setattr*/ ++ 0, /*tp_compare*/ ++ 0, /*tp_repr*/ ++ 0, /*tp_as_number*/ ++ 0, /*tp_as_sequence*/ ++ 0, /*tp_as_mapping*/ ++ 0, /*tp_hash */ ++ 0, /*tp_call*/ ++ 0, /*tp_str*/ ++ 0, /*tp_getattro*/ ++ 0, /*tp_setattro*/ ++ 0, /*tp_as_buffer*/ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ ++ "GDB field object", /* tp_doc */ ++ 0, /* tp_traverse */ ++ 0, /* tp_clear */ ++ 0, /* tp_richcompare */ ++ 0, /* tp_weaklistoffset */ ++ 0, /* tp_iter */ ++ 0, /* tp_iternext */ ++ 0, /* tp_methods */ ++ 0, /* tp_members */ ++ 0, /* tp_getset */ ++ 0, /* tp_base */ ++ 0, /* tp_dict */ ++ 0, /* tp_descr_get */ ++ 0, /* tp_descr_set */ ++ offsetof (field_object, dict), /* tp_dictoffset */ ++ 0, /* tp_init */ ++ 0, /* tp_alloc */ ++ 0, /* tp_new */ ++}; +diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c +index ddac2f5..f9c9486 100644 +--- a/gdb/python/python-utils.c ++++ b/gdb/python/python-utils.c +@@ -19,6 +19,7 @@ + + #include "defs.h" + #include "charset.h" ++#include "value.h" + #include "python-internal.h" + + +@@ -99,8 +100,8 @@ python_string_to_unicode (PyObject *obj) + } + + /* Returns a newly allocated string with the contents of the given unicode +- string object converted to CHARSET. If an error occurs during the +- conversion, NULL will be returned and a python exception will be set. ++ string object converted to a named charset. If an error occurs during ++ the conversion, NULL will be returned and a python exception will be set. + + The caller is responsible for xfree'ing the string. */ + static char * +@@ -191,3 +192,48 @@ gdbpy_is_string (PyObject *obj) + { + return PyString_Check (obj) || PyUnicode_Check (obj); + } ++ ++/* Converts OBJ to a CORE_ADDR value. ++ ++ Returns 1 on success or 0 on failure, with a Python exception set. This ++ function can also throw GDB exceptions. */ ++ ++int ++get_addr_from_python (PyObject *obj, CORE_ADDR *addr) ++{ ++ if (gdbpy_is_value_object (obj)) ++ *addr = value_as_address (value_object_to_value (obj)); ++ else if (PyLong_Check (obj)) ++ { ++ /* Assume CORE_ADDR corresponds to unsigned long. */ ++ *addr = PyLong_AsUnsignedLong (obj); ++ if (PyErr_Occurred () != NULL) ++ return 0; ++ } ++ else if (PyInt_Check (obj)) ++ { ++ long val; ++ ++ /* Assume CORE_ADDR corresponds to unsigned long. */ ++ val = PyInt_AsLong (obj); ++ ++ if (val >= 0) ++ *addr = val; ++ else ++ { ++ /* If no error ocurred, VAL is indeed negative. */ ++ if (PyErr_Occurred () != NULL) ++ return 0; ++ ++ PyErr_SetString (PyExc_ValueError, "negative address"); ++ return 0; ++ } ++ } ++ else ++ { ++ PyErr_SetString (PyExc_TypeError, "invalid type for address"); ++ return 0; ++ } ++ ++ return 1; ++} +diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c +index bc077b6..e26880a 100644 +--- a/gdb/python/python-value.c ++++ b/gdb/python/python-value.c +@@ -52,6 +52,10 @@ struct value *values_in_python = NULL; + /* Python's long type corresponds to C's long long type. */ + #define builtin_type_pylong builtin_type (current_gdbarch)->builtin_long_long + ++/* Python's long type corresponds to C's long long type. Unsigned version. */ ++#define builtin_type_upylong builtin_type \ ++ (current_gdbarch)->builtin_unsigned_long_long ++ + #define builtin_type_pybool \ + language_bool_type (current_language, current_gdbarch) + +@@ -59,6 +63,8 @@ typedef struct { + PyObject_HEAD + struct value *value; + int owned_by_gdb; ++ PyObject *address; ++ PyObject *type; + } value_object; + + /* Called by the Python interpreter when deallocating a value object. */ +@@ -71,6 +77,18 @@ valpy_dealloc (PyObject *obj) + + if (!self->owned_by_gdb) + value_free (self->value); ++ ++ if (self->address) ++ /* Use braces to appease gcc warning. *sigh* */ ++ { ++ Py_DECREF (self->address); ++ } ++ ++ if (self->type) ++ { ++ Py_DECREF (self->type); ++ } ++ + self->ob_type->tp_free (self); + } + +@@ -105,6 +123,8 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) + + value_obj->value = value; + value_obj->owned_by_gdb = 0; ++ value_obj->address = NULL; ++ value_obj->type = NULL; + release_value (value); + value_prepend_to_list (&values_in_python, value); + +@@ -129,24 +149,55 @@ valpy_dereference (PyObject *self, PyObject *args) + + /* Return "&value". */ + static PyObject * +-valpy_address (PyObject *self, PyObject *args) ++valpy_get_address (PyObject *self, void *closure) + { + struct value *res_val = NULL; /* Initialize to appease gcc warning. */ ++ value_object *val_obj = (value_object *) self; + volatile struct gdb_exception except; + +- TRY_CATCH (except, RETURN_MASK_ALL) ++ if (!val_obj->address) + { +- res_val = value_addr (((value_object *) self)->value); ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ res_val = value_addr (val_obj->value); ++ } ++ if (except.reason < 0) ++ { ++ val_obj->address = Py_None; ++ Py_INCREF (Py_None); ++ } ++ else ++ val_obj->address = value_to_value_object (res_val); + } +- GDB_PY_HANDLE_EXCEPTION (except); + +- return value_to_value_object (res_val); ++ Py_INCREF (val_obj->address); ++ ++ return val_obj->address; + } + +-/* Return Unicode string with value contents (assumed to be encoded in the +- target's charset). */ ++/* Return type of the value. */ + static PyObject * +-valpy_string (PyObject *self, PyObject *args) ++valpy_get_type (PyObject *self, void *closure) ++{ ++ value_object *obj = (value_object *) self; ++ if (!obj->type) ++ { ++ obj->type = type_to_type_object (value_type (obj->value)); ++ if (!obj->type) ++ { ++ obj->type = Py_None; ++ Py_INCREF (obj->type); ++ } ++ } ++ Py_INCREF (obj->type); ++ return obj->type; ++} ++ ++/* Implementation of gdb.Value.string ([encoding] [, errors]) -> string ++ Return Unicode string with value contents. If ENCODING is not given, ++ the string is assumed to be encoded in the target's charset. */ ++static PyObject * ++valpy_string (PyObject *self, PyObject *args, PyObject *kw) + { + int length, ret = 0; + gdb_byte *buffer; +@@ -157,8 +208,10 @@ valpy_string (PyObject *self, PyObject *args) + const char *errors = NULL; + const char *user_encoding = NULL; + const char *la_encoding = NULL; ++ static char *keywords[] = { "encoding", "errors" }; + +- if (!PyArg_ParseTuple (args, "|ss", &user_encoding, &errors)) ++ if (!PyArg_ParseTupleAndKeywords (args, kw, "|ss", keywords, ++ &user_encoding, &errors)) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) +@@ -174,6 +227,34 @@ valpy_string (PyObject *self, PyObject *args) + return unicode; + } + ++/* Cast a value to a given type. */ ++static PyObject * ++valpy_cast (PyObject *self, PyObject *args) ++{ ++ PyObject *type_obj; ++ struct type *type; ++ struct value *res_val = NULL; /* Initialize to appease gcc warning. */ ++ volatile struct gdb_exception except; ++ ++ if (! PyArg_ParseTuple (args, "O", &type_obj)) ++ return NULL; ++ ++ type = type_object_to_type (type_obj); ++ if (! type) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "argument must be a Type"); ++ return NULL; ++ } ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ res_val = value_cast (type, ((value_object *) self)->value); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return value_to_value_object (res_val); ++} ++ + static Py_ssize_t + valpy_length (PyObject *self) + { +@@ -269,6 +350,18 @@ valpy_str (PyObject *self) + return result; + } + ++/* Implements gdb.Value.is_optimized_out. */ ++static PyObject * ++valpy_get_is_optimized_out (PyObject *self, void *closure) ++{ ++ struct value *value = ((value_object *) self)->value; ++ ++ if (value_optimized_out (value)) ++ Py_RETURN_TRUE; ++ ++ Py_RETURN_FALSE; ++} ++ + enum valpy_opcode + { + VALPY_ADD, +@@ -306,11 +399,11 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) + a gdb.Value object and need to convert it from python as well. */ + arg1 = convert_value_from_python (self); + if (arg1 == NULL) +- return NULL; ++ break; + + arg2 = convert_value_from_python (other); + if (arg2 == NULL) +- return NULL; ++ break; + + switch (opcode) + { +@@ -387,7 +480,7 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) + } + GDB_PY_HANDLE_EXCEPTION (except); + +- return value_to_value_object (res_val); ++ return res_val ? value_to_value_object (res_val) : NULL; + } + + static PyObject * +@@ -711,6 +804,8 @@ value_to_value_object (struct value *val) + { + val_obj->value = val; + val_obj->owned_by_gdb = 0; ++ val_obj->address = NULL; ++ val_obj->type = NULL; + release_value (val); + value_prepend_to_list (&values_in_python, val); + } +@@ -718,6 +813,17 @@ value_to_value_object (struct value *val) + return (PyObject *) val_obj; + } + ++/* Returns value structure corresponding to the given value object. */ ++struct value * ++value_object_to_value (PyObject *self) ++{ ++ value_object *real; ++ if (! PyObject_TypeCheck (self, &value_object_type)) ++ return NULL; ++ real = (value_object *) self; ++ return real->value; ++} ++ + /* Try to convert a Python value to a gdb value. If the value cannot + be converted, set a Python exception and return NULL. */ + +@@ -751,7 +857,34 @@ convert_value_from_python (PyObject *obj) + { + LONGEST l = PyLong_AsLongLong (obj); + +- if (! PyErr_Occurred ()) ++ if (PyErr_Occurred ()) ++ { ++ /* If the error was an overflow, we can try converting to ++ ULONGEST instead. */ ++ if (PyErr_ExceptionMatches (PyExc_OverflowError)) ++ { ++ PyObject *etype, *evalue, *etraceback, *zero; ++ ++ PyErr_Fetch (&etype, &evalue, &etraceback); ++ zero = PyInt_FromLong (0); ++ ++ /* Check whether obj is positive. */ ++ if (PyObject_RichCompareBool (obj, zero, Py_GT) > 0) ++ { ++ ULONGEST ul; ++ ++ ul = PyLong_AsUnsignedLongLong (obj); ++ if (! PyErr_Occurred ()) ++ value = value_from_ulongest (builtin_type_upylong, ul); ++ } ++ else ++ /* There's nothing we can do. */ ++ PyErr_Restore (etype, evalue, etraceback); ++ ++ Py_DECREF (zero); ++ } ++ } ++ else + value = value_from_longest (builtin_type_pylong, l); + } + else if (PyFloat_Check (obj)) +@@ -774,7 +907,7 @@ convert_value_from_python (PyObject *obj) + } + } + else if (PyObject_TypeCheck (obj, &value_object_type)) +- value = ((value_object *) obj)->value; ++ value = value_copy (((value_object *) obj)->value); + else + PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"), + PyString_AsString (PyObject_Str (obj))); +@@ -810,6 +943,14 @@ gdbpy_history (PyObject *self, PyObject *args) + return value_to_value_object (res_val); + } + ++/* Returns 1 in OBJ is a gdb.Value object, 0 otherwise. */ ++ ++int ++gdbpy_is_value_object (PyObject *obj) ++{ ++ return PyObject_TypeCheck (obj, &value_object_type); ++} ++ + void + gdbpy_initialize_values (void) + { +@@ -822,11 +963,24 @@ gdbpy_initialize_values (void) + values_in_python = NULL; + } + ++ ++ ++static PyGetSetDef value_object_getset[] = { ++ { "address", valpy_get_address, NULL, "The address of the value.", ++ NULL }, ++ { "is_optimized_out", valpy_get_is_optimized_out, NULL, ++ "Boolean telling whether the value is optimized out (i.e., not available).", ++ NULL }, ++ { "type", valpy_get_type, NULL, "Type of the value.", NULL }, ++ {NULL} /* Sentinel */ ++}; ++ + static PyMethodDef value_object_methods[] = { +- { "address", valpy_address, METH_NOARGS, "Return the address of the value." }, ++ { "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." }, + { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." }, +- { "string", valpy_string, METH_VARARGS, +- "Return Unicode string representation of the value." }, ++ { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS, ++ "string ([encoding] [, errors]) -> string\n\ ++Return Unicode string representation of the value." }, + {NULL} /* Sentinel */ + }; + +@@ -893,7 +1047,7 @@ PyTypeObject value_object_type = { + 0, /* tp_iternext */ + value_object_methods, /* tp_methods */ + 0, /* tp_members */ +- 0, /* tp_getset */ ++ value_object_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ +diff --git a/gdb/python/python.c b/gdb/python/python.c +index b3a27d6..995835b 100644 +--- a/gdb/python/python.c ++++ b/gdb/python/python.c +@@ -22,6 +22,12 @@ + #include "ui-out.h" + #include "cli/cli-script.h" + #include "gdbcmd.h" ++#include "objfiles.h" ++#include "observer.h" ++#include "gdb_regex.h" ++#include "language.h" ++#include "valprint.h" ++#include "event-loop.h" + + #include + +@@ -29,6 +35,10 @@ + false otherwise. */ + static int gdbpy_should_print_stack = 1; + ++/* This is true if we should auto-load python code when an objfile is ++ opened, false otherwise. */ ++static int gdbpy_auto_load = 1; ++ + #ifdef HAVE_PYTHON + + #include "python.h" +@@ -36,16 +46,29 @@ static int gdbpy_should_print_stack = 1; + #include "cli/cli-decode.h" + #include "charset.h" + #include "top.h" ++#include "solib.h" + #include "exceptions.h" + #include "python-internal.h" ++#include "linespec.h" ++#include "symtab.h" ++#include "source.h" + #include "version.h" ++#include "inferior.h" ++#include "gdbthread.h" + #include "target.h" + #include "gdbthread.h" ++#include "event-top.h" ++ ++static PyMethodDef GdbMethods[]; + + static PyMethodDef GdbMethods[]; + + PyObject *gdb_module; + ++/* Some string constants we may wish to use. */ ++PyObject *gdbpy_to_string_cst; ++PyObject *gdbpy_children_cst; ++PyObject *gdbpy_display_hint_cst; + PyObject *gdbpy_doc_cst; + + /* Given a command_line, return a command string suitable for passing +@@ -143,10 +166,10 @@ python_command (char *arg, int from_tty) + NULL (and set a Python exception) on error. Helper function for + get_parameter. */ + +-static PyObject * +-parameter_to_python (struct cmd_list_element *cmd) ++PyObject * ++gdbpy_parameter_value (enum var_types type, void *var) + { +- switch (cmd->var_type) ++ switch (type) + { + case var_string: + case var_string_noescape: +@@ -154,7 +177,7 @@ parameter_to_python (struct cmd_list_element *cmd) + case var_filename: + case var_enum: + { +- char *str = * (char **) cmd->var; ++ char *str = * (char **) var; + if (! str) + str = ""; + return PyString_Decode (str, strlen (str), host_charset (), NULL); +@@ -162,7 +185,7 @@ parameter_to_python (struct cmd_list_element *cmd) + + case var_boolean: + { +- if (* (int *) cmd->var) ++ if (* (int *) var) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +@@ -170,7 +193,7 @@ parameter_to_python (struct cmd_list_element *cmd) + + case var_auto_boolean: + { +- enum auto_boolean ab = * (enum auto_boolean *) cmd->var; ++ enum auto_boolean ab = * (enum auto_boolean *) var; + if (ab == AUTO_BOOLEAN_TRUE) + Py_RETURN_TRUE; + else if (ab == AUTO_BOOLEAN_FALSE) +@@ -180,15 +203,15 @@ parameter_to_python (struct cmd_list_element *cmd) + } + + case var_integer: +- if ((* (int *) cmd->var) == INT_MAX) ++ if ((* (int *) var) == INT_MAX) + Py_RETURN_NONE; + /* Fall through. */ + case var_zinteger: +- return PyLong_FromLong (* (int *) cmd->var); ++ return PyLong_FromLong (* (int *) var); + + case var_uinteger: + { +- unsigned int val = * (unsigned int *) cmd->var; ++ unsigned int val = * (unsigned int *) var; + if (val == UINT_MAX) + Py_RETURN_NONE; + return PyLong_FromUnsignedLong (val); +@@ -202,10 +225,11 @@ parameter_to_python (struct cmd_list_element *cmd) + value. */ + + static PyObject * +-get_parameter (PyObject *self, PyObject *args) ++gdbpy_parameter (PyObject *self, PyObject *args) + { + struct cmd_list_element *alias, *prefix, *cmd; + char *arg, *newarg; ++ int found = -1; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "s", &arg)) +@@ -215,19 +239,17 @@ get_parameter (PyObject *self, PyObject *args) + + TRY_CATCH (except, RETURN_MASK_ALL) + { +- if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd)) +- { +- xfree (newarg); +- return PyErr_Format (PyExc_RuntimeError, +- "could not find variable `%s'", arg); +- } ++ found = lookup_cmd_composition (newarg, &alias, &prefix, &cmd); + } + xfree (newarg); + GDB_PY_HANDLE_EXCEPTION (except); ++ if (!found) ++ return PyErr_Format (PyExc_RuntimeError, ++ "could not find parameter `%s'", arg); + + if (! cmd->var) +- return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg); +- return parameter_to_python (cmd); ++ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a parameter", arg); ++ return gdbpy_parameter_value (cmd->var_type, cmd->var); + } + + /* A Python function which evaluates a string using the gdb CLI. */ +@@ -266,6 +288,570 @@ execute_gdb_command (PyObject *self, PyObject *args) + Py_RETURN_NONE; + } + ++/* Implementation of gdb.solib_address (Long) -> String. ++ Returns the name of the shared library holding a given address, or None. */ ++ ++static PyObject * ++gdbpy_solib_address (PyObject *self, PyObject *args) ++{ ++ unsigned long long pc; ++ char *soname; ++ PyObject *str_obj; ++ ++ if (!PyArg_ParseTuple (args, "K", &pc)) ++ return NULL; ++ ++ soname = solib_address (pc); ++ if (soname) ++ str_obj = PyString_Decode (soname, strlen (soname), host_charset (), NULL); ++ else ++ { ++ str_obj = Py_None; ++ Py_INCREF (Py_None); ++ } ++ ++ return str_obj; ++} ++ ++static PyObject * ++gdbpy_find_pc_function (PyObject *self, PyObject *args) ++{ ++ unsigned long long pc; ++ struct symbol *sym; ++ PyObject *sym_obj; ++ ++ if (!PyArg_ParseTuple (args, "K", &pc)) ++ return NULL; ++ ++ sym = find_pc_function (pc); ++ if (sym) ++ return symbol_to_symbol_object (sym); ++ ++ Py_RETURN_NONE; ++} ++ ++/* Adds GDB value V to the pattern buffer in *PATTERN_BUF. If SIZE is not zero, ++ it specifies the number of bytes from V to copy to *PATTERN_BUF. The ++ function increases the size of *PATTERN_BUF as necessary, adjusting ++ *PATTERN_BUF_END and *PATTERN_BUF_SIZE in the process. */ ++ ++static void ++add_value_pattern (struct value *v, int size, char **pattern_buf, ++ char **pattern_buf_end, ULONGEST *pattern_buf_size) ++{ ++ int val_bytes; ++ ++ if (size) ++ { ++ LONGEST x = value_as_long (v); ++ ++ if (size == 1) ++ *(*pattern_buf_end)++ = x; ++ else ++ { ++ put_bits (x, *pattern_buf_end, size * 8, ++ gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG); ++ *pattern_buf_end += size; ++ } ++ } ++ else ++ { ++ val_bytes = TYPE_LENGTH (value_type (v)); ++ ++ increase_pattern_buffer (pattern_buf, pattern_buf_end, ++ pattern_buf_size, val_bytes); ++ ++ memcpy (*pattern_buf_end, value_contents_raw (v), val_bytes); ++ *pattern_buf_end += val_bytes; ++ } ++} ++ ++/* This function does the actual work of constructing the pattern buffer from ++ OBJ. If OBJ is an object which implements the read buffer protocol (such ++ as a string, a byte array or gdb.Membuf), then its contents are directly ++ copied to *PATTERN_BUF. If it is a list, then this function is recursively ++ called for each of its elements. If OBJ is an object which can be converted ++ to a GDB value, then the contents of the value are copied to PATTERN_BUF. ++ If SIZE is different than zero, then it limits the number of bytes which ++ are copied to the buffer in case OBJ is converted to a GDB value. That ++ means that SIZE influences only Python scalars and gdb.Value objects. ++ The function increases the size of *PATTERN_BUF as necessary, adjusting ++ *PATTERN_BUF_END and *PATTERN_BUF_SIZE in the process. ++ ++ Returns 1 on success or 0 on failure, with a Python exception set. This ++ function can also throw GDB exceptions. */ ++ ++static int ++add_pattern_element (PyObject *obj, int size, char **pattern_buf, ++ char **pattern_buf_end, ULONGEST *pattern_buf_size) ++{ ++ if (PyObject_CheckReadBuffer (obj)) ++ { ++ /* Handle string, Unicode string, byte array, gdb.Membuf and any other ++ object implementing the buffer protocol. The SIZE parameter is ++ ignored in this case. */ ++ ++ Py_ssize_t val_bytes; ++ const void *buffer; ++ ++ if (PyObject_AsReadBuffer (obj, &buffer, &val_bytes) == -1) ++ return 0; ++ ++ increase_pattern_buffer (pattern_buf, pattern_buf_end, ++ pattern_buf_size, val_bytes); ++ ++ memcpy (*pattern_buf_end, buffer, val_bytes); ++ *pattern_buf_end += val_bytes; ++ } ++ else if (gdbpy_is_value_object (obj)) ++ add_value_pattern (value_object_to_value (obj), size, pattern_buf, ++ pattern_buf_end, pattern_buf_size); ++ else if (PySequence_Check (obj)) ++ { ++ /* Handle lists and tuples. */ ++ ++ Py_ssize_t i, num_objs; ++ ++ num_objs = PySequence_Size (obj); ++ for (i = 0; i < num_objs; i++) ++ if (!add_pattern_element (PySequence_GetItem (obj, i), size, ++ pattern_buf, pattern_buf_end, ++ pattern_buf_size)) ++ return 0; ++ } ++ else ++ { ++ /* See if we can convert from a Python object to a GDB value. */ ++ ++ struct value *v = convert_value_from_python (obj); ++ ++ if (v) ++ add_value_pattern (v, size, pattern_buf, pattern_buf_end, ++ pattern_buf_size); ++ else ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/* Constructs the search pattern from OBJ, putting it in *PATTERN_BUFP, and its ++ size in *PATTERN_LENP. See the function add_pattern_element to learn how ++ the search pattern is obtained from OBJ. ++ ++ Returns 1 on success or 0 on failure, with a Python exception set. This ++ function can also throw GDB exceptions. */ ++ ++static int ++get_search_pattern (PyObject *obj, int size, char **pattern_bufp, ++ ULONGEST *pattern_lenp) ++{ ++ /* Buffer to hold the search pattern. */ ++ char *pattern_buf; ++ /* Current size of search pattern buffer. ++ We realloc space as needed. */ ++ ULONGEST pattern_buf_size; ++ /* Pointer to one past the last in-use part of pattern_buf. */ ++ char *pattern_buf_end; ++ struct cleanup *old_cleanups; ++ ++ allocate_pattern_buffer (&pattern_buf, &pattern_buf_end, &pattern_buf_size); ++ old_cleanups = make_cleanup (free_current_contents, &pattern_buf); ++ ++ if (!add_pattern_element (obj, size, &pattern_buf, &pattern_buf_end, ++ &pattern_buf_size)) ++ { ++ do_cleanups (old_cleanups); ++ ++ return 0; ++ } ++ ++ *pattern_bufp = pattern_buf; ++ *pattern_lenp = pattern_buf_end - pattern_buf; ++ ++ discard_cleanups (old_cleanups); ++ ++ return 1; ++} ++ ++/* Implementation of ++ gdb.search_memory (address, length, pattern [, size] [, max_count]). ++ The third argument may be either a pattern, or a list or tupple of patterns ++ to be searched. Size is the size in bytes of each search query value, either ++ 1, 2, 4 or 8. Returns a list of the addresses where matches were found. */ ++ ++PyObject * ++gdbpy_search_memory (PyObject *self, PyObject *args, PyObject *kw) ++{ ++ int size = 0; ++ long length; ++ unsigned int found_count = 0; ++ long max_count = 0; ++ CORE_ADDR start_addr; ++ char *pattern_buf; ++ static char *keywords[] = { "address", "length", "pattern", "size", ++ "max_count", NULL }; ++ ULONGEST pattern_len, search_space_len; ++ PyObject *pattern, *list = NULL, *start_addr_obj; ++ volatile struct gdb_exception except; ++ ++ /* Assume CORE_ADDR corresponds to unsigned long. */ ++ if (! PyArg_ParseTupleAndKeywords (args, kw, "OlO|il", keywords, ++ &start_addr_obj, &length, &pattern, ++ &size, &max_count)) ++ return NULL; ++ ++ if (!max_count) ++ max_count = LONG_MAX; ++ ++ if (!length) ++ { ++ PyErr_SetString (PyExc_ValueError, "empty search range"); ++ return NULL; ++ } ++ else if (length < 0) ++ { ++ PyErr_SetString (PyExc_ValueError, "invalid search range"); ++ return NULL; ++ } ++ else ++ { ++ /* Watch for overflows. */ ++ if (length > CORE_ADDR_MAX ++ || (start_addr + length - 1) < start_addr) ++ { ++ PyErr_SetString (PyExc_ValueError, "search range too large"); ++ return NULL; ++ } ++ ++ search_space_len = length; ++ } ++ ++ if (size != 0 && size != 1 && size != 2 && size != 4 && size != 8) ++ { ++ PyErr_SetString (PyExc_ValueError, "invalid pattern size"); ++ return NULL; ++ } ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ if (get_addr_from_python (start_addr_obj, &start_addr)) ++ { ++ if (get_search_pattern (pattern, size, &pattern_buf, &pattern_len)) ++ { ++ /* Any cleanups get automatically executed on an exception. */ ++ struct cleanup *cleanups = make_cleanup (xfree, pattern_buf); ++ ++ list = PyList_New (0); ++ ++ while (search_space_len >= pattern_len && found_count < max_count) ++ { ++ CORE_ADDR found_addr; ++ int found; ++ ++ found = search_memory (&start_addr, &search_space_len, ++ pattern_buf, pattern_len, &found_addr); ++ if (found <= 0) ++ break; ++ ++ PyList_Append (list, PyLong_FromUnsignedLong (found_addr)); ++ ++found_count; ++ } ++ ++ do_cleanups (cleanups); ++ } ++ } ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return list; ++} ++ ++/* A Python function which is a wrapper for decode_line_1. */ ++ ++static PyObject * ++gdbpy_decode_line (PyObject *self, PyObject *args) ++{ ++ struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to appease gcc. */ ++ struct symtab_and_line sal; ++ char *arg = NULL; ++ int free_sals = 0, i; ++ PyObject *result = NULL; ++ volatile struct gdb_exception except; ++ ++ if (! PyArg_ParseTuple (args, "|s", &arg)) ++ return NULL; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ if (arg) ++ { ++ char *copy; ++ ++ arg = strdup (arg); ++ copy = arg; ++ ++ sals = decode_line_1 (©, 0, 0, 0, 0, 0); ++ free_sals = 1; ++ } ++ else ++ { ++ set_default_source_symtab_and_line (); ++ sal = get_current_source_symtab_and_line (); ++ sals.sals = &sal; ++ sals.nelts = 1; ++ } ++ } ++ if (arg) ++ xfree (arg); ++ ++ if (except.reason < 0) ++ { ++ if (free_sals) ++ xfree (sals.sals); ++ /* We know this will always throw. */ ++ GDB_PY_HANDLE_EXCEPTION (except); ++ } ++ ++ if (sals.nelts) ++ { ++ result = PyTuple_New (sals.nelts); ++ for (i = 0; i < sals.nelts; ++i) ++ { ++ PyObject *obj; ++ char *str; ++ ++ obj = symtab_and_line_to_sal_object (sals.sals[i]); ++ if (! obj) ++ { ++ Py_DECREF (result); ++ result = NULL; ++ break; ++ } ++ ++ PyTuple_SetItem (result, i, obj); ++ } ++ } ++ ++ if (free_sals) ++ xfree (sals.sals); ++ ++ if (result) ++ return result; ++ Py_RETURN_NONE; ++} ++ ++/* Parse a string and evaluate it as an expression. */ ++static PyObject * ++gdbpy_parse_and_eval (PyObject *self, PyObject *args) ++{ ++ char *expr_str; ++ struct value *result = NULL; ++ volatile struct gdb_exception except; ++ ++ if (!PyArg_ParseTuple (args, "s", &expr_str)) ++ return NULL; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ result = parse_and_eval (expr_str); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ return value_to_value_object (result); ++} ++ ++ ++ ++/* Posting and handling events. */ ++ ++/* A single event. */ ++struct gdbpy_event ++{ ++ /* The Python event. This is just a callable object. */ ++ PyObject *event; ++ /* The next event. */ ++ struct gdbpy_event *next; ++}; ++ ++/* All pending events. */ ++static struct gdbpy_event *gdbpy_event_list; ++/* The final link of the event list. */ ++static struct gdbpy_event **gdbpy_event_list_end; ++ ++/* We use a file handler, and not an async handler, so that we can ++ wake up the main thread even when it is blocked in poll(). */ ++static int gdbpy_event_fds[2]; ++ ++/* The file handler callback. This reads from the internal pipe, and ++ then processes the Python event queue. This will always be run in ++ the main gdb thread. */ ++static void ++gdbpy_run_events (int err, gdb_client_data ignore) ++{ ++ PyGILState_STATE state; ++ char buffer[100]; ++ int r; ++ ++ state = PyGILState_Ensure (); ++ ++ /* Just read whatever is available on the fd. It is relatively ++ harmless if there are any bytes left over. */ ++ r = read (gdbpy_event_fds[0], buffer, sizeof (buffer)); ++ ++ while (gdbpy_event_list) ++ { ++ /* Dispatching the event might push a new element onto the event ++ loop, so we update here "atomically enough". */ ++ struct gdbpy_event *item = gdbpy_event_list; ++ gdbpy_event_list = gdbpy_event_list->next; ++ if (gdbpy_event_list == NULL) ++ gdbpy_event_list_end = &gdbpy_event_list; ++ ++ /* Ignore errors. */ ++ PyObject_CallObject (item->event, NULL); ++ ++ Py_DECREF (item->event); ++ xfree (item); ++ } ++ ++ PyGILState_Release (state); ++} ++ ++/* Submit an event to the gdb thread. */ ++static PyObject * ++gdbpy_post_event (PyObject *self, PyObject *args) ++{ ++ struct gdbpy_event *event; ++ PyObject *func; ++ int wakeup; ++ ++ if (!PyArg_ParseTuple (args, "O", &func)) ++ return NULL; ++ ++ if (!PyCallable_Check (func)) ++ { ++ PyErr_SetString (PyExc_RuntimeError, "Posted event is not callable"); ++ return NULL; ++ } ++ ++ Py_INCREF (func); ++ ++ /* From here until the end of the function, we have the GIL, so we ++ can operate on our global data structures without worrying. */ ++ wakeup = gdbpy_event_list == NULL; ++ ++ event = XNEW (struct gdbpy_event); ++ event->event = func; ++ event->next = NULL; ++ *gdbpy_event_list_end = event; ++ gdbpy_event_list_end = &event->next; ++ ++ /* Wake up gdb when needed. */ ++ if (wakeup) ++ { ++ char c = 'q'; /* Anything. */ ++ if (write (gdbpy_event_fds[1], &c, 1) != 1) ++ return PyErr_SetFromErrno (PyExc_IOError); ++ } ++ ++ Py_RETURN_NONE; ++} ++ ++/* Initialize the Python event handler. */ ++static void ++gdbpy_initialize_events (void) ++{ ++ if (!pipe (gdbpy_event_fds)) ++ { ++ gdbpy_event_list_end = &gdbpy_event_list; ++ add_file_handler (gdbpy_event_fds[0], gdbpy_run_events, NULL); ++ } ++} ++ ++ ++ ++/* Threads. */ ++ ++/* Callback function for use with iterate_over_threads. This function ++ just counts the number of threads. */ ++ ++static int ++count_callback (struct thread_info *info, void *user_data) ++{ ++ int *count = (int *) user_data; ++ ++*count; ++ return 0; ++} ++ ++/* Structure for storing some state when iterating over threads. */ ++ ++struct set_thread_info ++{ ++ PyObject *tuple; ++ int index; ++}; ++ ++/* Callback function for use with iterate_over_threads. This function ++ stores the thread ID into a Python tuple. */ ++ ++static int ++update_tuple_callback (struct thread_info *info, void *user_data) ++{ ++ struct set_thread_info *tinfo = (struct set_thread_info *) user_data; ++ PyTuple_SetItem (tinfo->tuple, tinfo->index, PyInt_FromLong (info->num)); ++ ++tinfo->index; ++ return 0; ++} ++ ++/* Python function which yields a tuple holding all valid thread IDs. */ ++ ++static PyObject * ++gdbpy_threads (PyObject *unused1, PyObject *unused2) ++{ ++ int thread_count = 0; ++ struct set_thread_info info; ++ PyObject *result; ++ ++ prune_threads (); ++ target_find_new_threads (); ++ ++ iterate_over_threads (count_callback, &thread_count); ++ ++ if (!thread_count) ++ Py_RETURN_NONE; ++ ++ result = PyTuple_New (thread_count); ++ info.tuple = result; ++ info.index = 0; ++ iterate_over_threads (update_tuple_callback, &info); ++ return result; ++} ++ ++/* Python function that returns the current thread's ID. */ ++ ++static PyObject * ++gdbpy_current_thread (PyObject *unused1, PyObject *unused2) ++{ ++ if (PIDGET (inferior_ptid) == 0) ++ Py_RETURN_NONE; ++ return PyInt_FromLong (pid_to_thread_id (inferior_ptid)); ++} ++ ++/* Python function for switching to a given thread. */ ++ ++static PyObject * ++gdbpy_switch_to_thread (PyObject *self, PyObject *args) ++{ ++ int id; ++ if (! PyArg_ParseTuple (args, "i", &id)) ++ return NULL; ++ if (! valid_thread_id (id)) ++ return PyErr_Format (PyExc_RuntimeError, "invalid thread id"); ++ switch_to_thread (thread_id_to_pid (id)); ++ Py_RETURN_NONE; ++} ++ + + + /* Printing. */ +@@ -302,6 +888,769 @@ gdbpy_print_stack (void) + PyErr_Clear (); + } + ++ ++ ++/* Script interface. */ ++ ++/* True if 'gdb -P' was used, false otherwise. */ ++static int running_python_script; ++ ++/* True if we are currently in a call to 'gdb.cli', false otherwise. */ ++static int in_cli; ++ ++/* Enter the command loop. */ ++ ++static PyObject * ++gdbpy_cli (PyObject *unused1, PyObject *unused2) ++{ ++ if (! running_python_script || in_cli) ++ return PyErr_Format (PyExc_RuntimeError, "cannot invoke CLI recursively"); ++ ++ in_cli = 1; ++ cli_command_loop (); ++ in_cli = 0; ++ ++ Py_RETURN_NONE; ++} ++ ++/* Set up the Python argument vector and evaluate a script. This is ++ used to implement 'gdb -P'. */ ++ ++void ++run_python_script (int argc, char **argv) ++{ ++ FILE *input; ++ PyGILState_STATE state; ++ ++ /* We never free this, since we plan to exit at the end. */ ++ state = PyGILState_Ensure (); ++ ++ running_python_script = 1; ++ PySys_SetArgv (argc - 1, argv + 1); ++ input = fopen (argv[0], "r"); ++ if (! input) ++ { ++ fprintf (stderr, "could not open %s: %s\n", argv[0], strerror (errno)); ++ exit (1); ++ } ++ PyRun_SimpleFile (input, argv[0]); ++ fclose (input); ++ exit (0); ++} ++ ++void ++source_python_script (FILE *stream, char *file) ++{ ++ PyGILState_STATE state; ++ ++ state = PyGILState_Ensure (); ++ ++ PyRun_SimpleFile (stream, file); ++ ++ fclose (stream); ++ PyGILState_Release (state); ++} ++ ++ ++ ++/* The "current" objfile. This is set when gdb detects that a new ++ objfile has been loaded. It is only set for the duration of a call ++ to gdbpy_new_objfile; it is NULL at other times. */ ++static struct objfile *gdbpy_current_objfile; ++ ++/* The file name we attempt to read. */ ++#define GDBPY_AUTO_FILENAME "-gdb.py" ++ ++/* This is a new_objfile observer callback which loads python code ++ based on the path to the objfile. */ ++static void ++gdbpy_new_objfile (struct objfile *objfile) ++{ ++ char *realname; ++ char *filename, *debugfile; ++ int len; ++ FILE *input; ++ PyGILState_STATE state; ++ struct cleanup *cleanups; ++ ++ if (!gdbpy_auto_load || !objfile || !objfile->name) ++ return; ++ ++ state = PyGILState_Ensure (); ++ ++ gdbpy_current_objfile = objfile; ++ ++ realname = gdb_realpath (objfile->name); ++ len = strlen (realname); ++ filename = xmalloc (len + sizeof (GDBPY_AUTO_FILENAME)); ++ memcpy (filename, realname, len); ++ strcpy (filename + len, GDBPY_AUTO_FILENAME); ++ ++ input = fopen (filename, "r"); ++ debugfile = filename; ++ ++ cleanups = make_cleanup (xfree, filename); ++ make_cleanup (xfree, realname); ++ ++ if (!input && debug_file_directory) ++ { ++ /* Also try the same file in the separate debug info directory. */ ++ debugfile = xmalloc (strlen (filename) ++ + strlen (debug_file_directory) + 1); ++ strcpy (debugfile, debug_file_directory); ++ /* FILENAME is absolute, so we don't need a "/" here. */ ++ strcat (debugfile, filename); ++ ++ make_cleanup (xfree, debugfile); ++ input = fopen (debugfile, "r"); ++ } ++ ++ if (!input && gdb_datadir) ++ { ++ /* Also try the same file in a subdirectory of gdb's data ++ directory. */ ++ debugfile = xmalloc (strlen (gdb_datadir) + strlen (filename) ++ + strlen ("/auto-load") + 1); ++ strcpy (debugfile, gdb_datadir); ++ strcat (debugfile, "/auto-load"); ++ /* FILENAME is absolute, so we don't need a "/" here. */ ++ strcat (debugfile, filename); ++ ++ make_cleanup (xfree, debugfile); ++ input = fopen (debugfile, "r"); ++ } ++ ++ if (input) ++ { ++ /* We don't want to throw an exception here -- but the user ++ would like to know that something went wrong. */ ++ if (PyRun_SimpleFile (input, debugfile)) ++ gdbpy_print_stack (); ++ fclose (input); ++ } ++ ++ do_cleanups (cleanups); ++ gdbpy_current_objfile = NULL; ++ ++ PyGILState_Release (state); ++} ++ ++/* Return the current Objfile, or None if there isn't one. */ ++static PyObject * ++gdbpy_get_current_objfile (PyObject *unused1, PyObject *unused2) ++{ ++ PyObject *result; ++ ++ if (! gdbpy_current_objfile) ++ Py_RETURN_NONE; ++ ++ result = objfile_to_objfile_object (gdbpy_current_objfile); ++ if (result) ++ Py_INCREF (result); ++ return result; ++} ++ ++/* Return a sequence holding all the Objfiles. */ ++static PyObject * ++gdbpy_objfiles (PyObject *unused1, PyObject *unused2) ++{ ++ struct objfile *objf; ++ PyObject *list; ++ ++ list = PyList_New (0); ++ if (!list) ++ return NULL; ++ ++ ALL_OBJFILES (objf) ++ { ++ PyObject *item = objfile_to_objfile_object (objf); ++ if (!item || PyList_Append (list, item) == -1) ++ { ++ Py_DECREF (list); ++ return NULL; ++ } ++ } ++ ++ return list; ++} ++ ++ ++ ++/* Helper function for find_pretty_printer which iterates over a ++ list, calls each function and inspects output. */ ++static PyObject * ++search_pp_list (PyObject *list, PyObject *value) ++{ ++ Py_ssize_t pp_list_size, list_index; ++ PyObject *function, *printer = NULL; ++ ++ pp_list_size = PyList_Size (list); ++ for (list_index = 0; list_index < pp_list_size; list_index++) ++ { ++ function = PyList_GetItem (list, list_index); ++ if (! function) ++ return NULL; ++ ++ /* gdbpy_instantiate_printer can return three possible return ++ values: NULL on error; Py_None if the pretty-printer ++ in the list cannot print the value; or a printer instance if ++ the printer can print the value. */ ++ printer = gdbpy_instantiate_printer (function, value); ++ if (! printer) ++ return NULL; ++ else if (printer != Py_None) ++ return printer; ++ ++ Py_DECREF (printer); ++ } ++ ++ Py_RETURN_NONE; ++} ++ ++/* Find the pretty-printing constructor function for TYPE. If no ++ pretty-printer exists, return NULL. If one exists, return a new ++ reference. */ ++static PyObject * ++find_pretty_printer (PyObject *value) ++{ ++ PyObject *pp_list = NULL; ++ PyObject *function = NULL; ++ struct objfile *obj; ++ volatile struct gdb_exception except; ++ ++ /* Look at the pretty-printer dictionary for each objfile. */ ++ ALL_OBJFILES (obj) ++ { ++ PyObject *objf = objfile_to_objfile_object (obj); ++ if (!objf) ++ continue; ++ ++ pp_list = objfpy_get_printers (objf, NULL); ++ function = search_pp_list (pp_list, value); ++ ++ /* If there is an error in any objfile list, abort the search and ++ exit. */ ++ if (! function) ++ { ++ Py_XDECREF (pp_list); ++ return NULL; ++ } ++ ++ if (function != Py_None) ++ goto done; ++ ++ /* In this loop, if function is not an instantiation of a ++ pretty-printer, and it is not null, then it is a return of ++ Py_RETURN_NONE, which must be decremented. */ ++ Py_DECREF (function); ++ Py_XDECREF (pp_list); ++ } ++ ++ pp_list = NULL; ++ /* Fetch the global pretty printer dictionary. */ ++ if (! PyObject_HasAttrString (gdb_module, "pretty_printers")) ++ goto done; ++ pp_list = PyObject_GetAttrString (gdb_module, "pretty_printers"); ++ if (! pp_list) ++ goto done; ++ if (! PyList_Check (pp_list)) ++ goto done; ++ ++ function = search_pp_list (pp_list, value); ++ ++ done: ++ Py_XDECREF (pp_list); ++ ++ return function; ++} ++ ++/* Pretty-print a single value, via the printer object PRINTER. If ++ the function returns a string, an xmalloc()d copy is returned. ++ Otherwise, if the function returns a value, a *OUT_VALUE is set to ++ the value, and NULL is returned. On error, *OUT_VALUE is set to ++ NULL and NULL is returned. */ ++static char * ++pretty_print_one_value (PyObject *printer, struct value **out_value) ++{ ++ char *output = NULL; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ PyObject *result; ++ ++ result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL); ++ if (result) ++ { ++ if (gdbpy_is_string (result)) ++ output = python_string_to_host_string (result); ++ else if (PyObject_TypeCheck (result, &value_object_type)) ++ { ++ /* If we just call convert_value_from_python for this ++ type, we won't know who owns the result. For this ++ one case we need to copy the resulting value. */ ++ struct value *v = value_object_to_value (result); ++ *out_value = value_copy (v); ++ } ++ else ++ *out_value = convert_value_from_python (result); ++ Py_DECREF (result); ++ } ++ } ++ ++ return output; ++} ++ ++/* Instantiate a pretty-printer given a constructor, CONS, and a ++ value, VAL. Return NULL on error. Ownership of the object ++ instance is transferred to the reciever */ ++PyObject * ++gdbpy_instantiate_printer (PyObject *cons, PyObject *value) ++{ ++ PyObject *result; ++ result = PyObject_CallFunctionObjArgs (cons, value, NULL); ++ return result; ++} ++ ++/* Return the display hint for the object printer, PRINTER. Return ++ NULL if there is no display_hint method, or if the method did not ++ return a string. On error, print stack trace and return NULL. On ++ success, return an xmalloc()d string. */ ++char * ++gdbpy_get_display_hint (PyObject *printer) ++{ ++ PyObject *hint; ++ char *result = NULL; ++ ++ if (! PyObject_HasAttr (printer, gdbpy_display_hint_cst)) ++ return NULL; ++ ++ hint = PyObject_CallMethodObjArgs (printer, gdbpy_display_hint_cst, NULL); ++ if (gdbpy_is_string (hint)) ++ result = python_string_to_host_string (hint); ++ if (hint) ++ Py_DECREF (hint); ++ else ++ gdbpy_print_stack (); ++ ++ return result; ++} ++ ++/* Helper for apply_val_pretty_printer which calls to_string and ++ formats the result. */ ++static void ++print_string_repr (PyObject *printer, const char *hint, ++ struct ui_file *stream, int recurse, ++ const struct value_print_options *options, ++ const struct language_defn *language) ++{ ++ char *output; ++ struct value *replacement = NULL; ++ ++ output = pretty_print_one_value (printer, &replacement); ++ if (output) ++ { ++ if (hint && !strcmp (hint, "string")) ++ { ++ struct type *string_char_type; ++ ++ /* OUTPUT is already in the hosts's charset. */ ++ string_char_type = language_string_char_type (language, ++ current_gdbarch); ++ LA_PRINT_STRING (stream, string_char_type, (gdb_byte *) output, ++ strlen (output), 0, options); ++ } ++ else ++ fputs_filtered (output, stream); ++ xfree (output); ++ } ++ else if (replacement) ++ common_val_print (replacement, stream, recurse, options, language); ++ else ++ gdbpy_print_stack (); ++} ++ ++static void ++py_restore_tstate (void *p) ++{ ++ PyFrameObject *frame = p; ++ PyThreadState *tstate = PyThreadState_GET (); ++ tstate->frame = frame; ++} ++ ++/* Create a dummy PyFrameObject, needed to work around ++ a Python-2.4 bug with generators. */ ++static PyObject * ++push_dummy_python_frame () ++{ ++ PyObject *empty_string, *null_tuple, *globals; ++ PyCodeObject *code; ++ PyFrameObject *frame; ++ PyThreadState *tstate; ++ ++ empty_string = PyString_FromString (""); ++ if (!empty_string) ++ return NULL; ++ ++ null_tuple = PyTuple_New (0); ++ if (!null_tuple) ++ { ++ Py_DECREF (empty_string); ++ return NULL; ++ } ++ ++ code = PyCode_New (0, /* argcount */ ++ 0, /* nlocals */ ++ 0, /* stacksize */ ++ 0, /* flags */ ++ empty_string, /* code */ ++ null_tuple, /* consts */ ++ null_tuple, /* names */ ++ null_tuple, /* varnames */ ++#if PYTHON_API_VERSION >= 1010 ++ null_tuple, /* freevars */ ++ null_tuple, /* cellvars */ ++#endif ++ empty_string, /* filename */ ++ empty_string, /* name */ ++ 1, /* firstlineno */ ++ empty_string /* lnotab */ ++ ); ++ ++ Py_DECREF (empty_string); ++ Py_DECREF (null_tuple); ++ ++ if (!code) ++ return NULL; ++ ++ globals = PyDict_New (); ++ if (!globals) ++ { ++ Py_DECREF (code); ++ return NULL; ++ } ++ ++ tstate = PyThreadState_GET (); ++ ++ frame = PyFrame_New (tstate, code, globals, NULL); ++ ++ Py_DECREF (globals); ++ Py_DECREF (code); ++ ++ if (!frame) ++ return NULL; ++ ++ tstate->frame = frame; ++ make_cleanup (py_restore_tstate, frame->f_back); ++ return (PyObject *) frame; ++} ++ ++/* Helper for apply_val_pretty_printer that formats children of the ++ printer, if any exist. */ ++static void ++print_children (PyObject *printer, const char *hint, ++ struct ui_file *stream, int recurse, ++ const struct value_print_options *options, ++ const struct language_defn *language) ++{ ++ int is_map, is_array, done_flag, pretty; ++ unsigned int i; ++ PyObject *children, *iter, *frame; ++ struct cleanup *cleanups; ++ ++ if (! PyObject_HasAttr (printer, gdbpy_children_cst)) ++ return; ++ ++ /* If we are printing a map or an array, we want some special ++ formatting. */ ++ is_map = hint && ! strcmp (hint, "map"); ++ is_array = hint && ! strcmp (hint, "array"); ++ ++ children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, ++ NULL); ++ if (! children) ++ { ++ gdbpy_print_stack (); ++ return; ++ } ++ ++ cleanups = make_cleanup_py_decref (children); ++ ++ iter = PyObject_GetIter (children); ++ if (!iter) ++ { ++ gdbpy_print_stack (); ++ goto done; ++ } ++ make_cleanup_py_decref (iter); ++ ++ /* Use the prettyprint_arrays option if we are printing an array, ++ and the pretty option otherwise. */ ++ pretty = is_array ? options->prettyprint_arrays : options->pretty; ++ ++ /* Manufacture a dummy Python frame to work around Python 2.4 bug, ++ where it insists on having a non-NULL tstate->frame when ++ a generator is called. */ ++ frame = push_dummy_python_frame (); ++ if (!frame) ++ { ++ gdbpy_print_stack (); ++ goto done; ++ } ++ make_cleanup_py_decref (frame); ++ ++ done_flag = 0; ++ for (i = 0; i < options->print_max; ++i) ++ { ++ PyObject *py_v, *item = PyIter_Next (iter); ++ char *name; ++ struct cleanup *inner_cleanup; ++ ++ if (! item) ++ { ++ if (PyErr_Occurred ()) ++ gdbpy_print_stack (); ++ /* Set a flag so we can know whether we printed all the ++ available elements. */ ++ else ++ done_flag = 1; ++ break; ++ } ++ ++ if (! PyArg_ParseTuple (item, "sO", &name, &py_v)) ++ { ++ gdbpy_print_stack (); ++ Py_DECREF (item); ++ continue; ++ } ++ inner_cleanup = make_cleanup_py_decref (item); ++ ++ /* Print initial "{". For other elements, there are three ++ cases: ++ 1. Maps. Print a "," after each value element. ++ 2. Arrays. Always print a ",". ++ 3. Other. Always print a ",". */ ++ if (i == 0) ++ fputs_filtered (" = {", stream); ++ else if (! is_map || i % 2 == 0) ++ fputs_filtered (pretty ? "," : ", ", stream); ++ ++ /* In summary mode, we just want to print "= {...}" if there is ++ a value. */ ++ if (options->summary) ++ { ++ /* This increment tricks the post-loop logic to print what ++ we want. */ ++ ++i; ++ /* Likewise. */ ++ pretty = 0; ++ break; ++ } ++ ++ if (! is_map || i % 2 == 0) ++ { ++ if (pretty) ++ { ++ fputs_filtered ("\n", stream); ++ print_spaces_filtered (2 + 2 * recurse, stream); ++ } ++ else ++ wrap_here (n_spaces (2 + 2 *recurse)); ++ } ++ ++ if (is_map && i % 2 == 0) ++ fputs_filtered ("[", stream); ++ else if (is_array) ++ { ++ /* We print the index, not whatever the child method ++ returned as the name. */ ++ if (options->print_array_indexes) ++ fprintf_filtered (stream, "[%d] = ", i); ++ } ++ else if (! is_map) ++ { ++ fputs_filtered (name, stream); ++ fputs_filtered (" = ", stream); ++ } ++ ++ if (gdbpy_is_string (py_v)) ++ { ++ char *text = python_string_to_host_string (py_v); ++ if (! text) ++ gdbpy_print_stack (); ++ else ++ { ++ fputs_filtered (text, stream); ++ xfree (text); ++ } ++ } ++ else ++ { ++ struct value *value = convert_value_from_python (py_v); ++ ++ if (value == NULL) ++ { ++ gdbpy_print_stack (); ++ error (_("Error while executing Python code.")); ++ } ++ else ++ common_val_print (value, stream, recurse + 1, options, language); ++ } ++ ++ if (is_map && i % 2 == 0) ++ fputs_filtered ("] = ", stream); ++ ++ do_cleanups (inner_cleanup); ++ } ++ ++ if (i) ++ { ++ if (!done_flag) ++ { ++ if (pretty) ++ { ++ fputs_filtered ("\n", stream); ++ print_spaces_filtered (2 + 2 * recurse, stream); ++ } ++ fputs_filtered ("...", stream); ++ } ++ if (pretty) ++ { ++ fputs_filtered ("\n", stream); ++ print_spaces_filtered (2 * recurse, stream); ++ } ++ fputs_filtered ("}", stream); ++ } ++ ++ done: ++ do_cleanups (cleanups); ++} ++ ++int ++apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, ++ int embedded_offset, CORE_ADDR address, ++ struct ui_file *stream, int recurse, ++ const struct value_print_options *options, ++ const struct language_defn *language) ++{ ++ PyObject *printer = NULL; ++ PyObject *val_obj = NULL; ++ struct value *value; ++ char *hint = NULL; ++ struct cleanup *cleanups; ++ int result = 0; ++ PyGILState_STATE state; ++ ++ state = PyGILState_Ensure (); ++ cleanups = make_cleanup_py_restore_gil (&state); ++ ++ /* Instantiate the printer. */ ++ if (valaddr) ++ valaddr += embedded_offset; ++ value = value_from_contents_and_address (type, valaddr, address); ++ ++ val_obj = value_to_value_object (value); ++ if (! val_obj) ++ goto done; ++ ++ /* Find the constructor. */ ++ printer = find_pretty_printer (val_obj); ++ Py_DECREF (val_obj); ++ make_cleanup_py_decref (printer); ++ if (! printer || printer == Py_None) ++ goto done; ++ ++ /* If we are printing a map, we want some special formatting. */ ++ hint = gdbpy_get_display_hint (printer); ++ make_cleanup (free_current_contents, &hint); ++ ++ /* Print the section */ ++ print_string_repr (printer, hint, stream, recurse, options, language); ++ print_children (printer, hint, stream, recurse, options, language); ++ result = 1; ++ ++ ++ done: ++ if (PyErr_Occurred ()) ++ gdbpy_print_stack (); ++ do_cleanups (cleanups); ++ return result; ++} ++ ++/* Apply a pretty-printer for the varobj code. PRINTER_OBJ is the ++ print object. It must have a 'to_string' method (but this is ++ checked by varobj, not here) which takes no arguments and ++ returns a string. This function returns an xmalloc()d string if ++ the printer returns a string. The printer may return a replacement ++ value instead; in this case *REPLACEMENT is set to the replacement ++ value, and this function returns NULL. On error, *REPLACEMENT is ++ set to NULL and this function also returns NULL. */ ++char * ++apply_varobj_pretty_printer (PyObject *printer_obj, ++ struct value **replacement) ++{ ++ char *result; ++ PyGILState_STATE state = PyGILState_Ensure (); ++ ++ *replacement = NULL; ++ result = pretty_print_one_value (printer_obj, replacement); ++ if (result == NULL); ++ gdbpy_print_stack (); ++ PyGILState_Release (state); ++ ++ return result; ++} ++ ++/* Find a pretty-printer object for the varobj module. Returns a new ++ reference to the object if successful; returns NULL if not. VALUE ++ is the value for which a printer tests to determine if it ++ can pretty-print the value. */ ++PyObject * ++gdbpy_get_varobj_pretty_printer (struct value *value) ++{ ++ PyObject *val_obj; ++ PyObject *pretty_printer = NULL; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ value = value_copy (value); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ ++ val_obj = value_to_value_object (value); ++ if (! val_obj) ++ return NULL; ++ ++ pretty_printer = find_pretty_printer (val_obj); ++ Py_DECREF (val_obj); ++ return pretty_printer; ++} ++ ++/* A Python function which wraps find_pretty_printer and instantiates ++ the resulting class. This accepts a Value argument and returns a ++ pretty printer instance, or None. This function is useful as an ++ argument to the MI command -var-set-visualizer. */ ++static PyObject * ++gdbpy_default_visualizer (PyObject *self, PyObject *args) ++{ ++ PyObject *val_obj; ++ PyObject *cons, *printer = NULL; ++ struct value *value; ++ ++ if (! PyArg_ParseTuple (args, "O", &val_obj)) ++ return NULL; ++ value = value_object_to_value (val_obj); ++ if (! value) ++ { ++ PyErr_SetString (PyExc_TypeError, "argument must be a gdb.Value"); ++ return NULL; ++ } ++ ++ cons = find_pretty_printer (val_obj); ++ return cons; ++} ++ + #else /* HAVE_PYTHON */ + + /* Dummy implementation of the gdb "python" command. */ +@@ -328,6 +1677,24 @@ eval_python_from_control_command (struct command_line *cmd) + error (_("Python scripting is not supported in this copy of GDB.")); + } + ++int ++apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, ++ int embedded_offset, CORE_ADDR address, ++ struct ui_file *stream, int format, ++ int deref_ref, int recurse, ++ enum val_prettyprint pretty, ++ const struct language_defn *language) ++{ ++ return 0; ++} ++ ++void ++source_python_script (FILE *stream) ++{ ++ fclose (stream); ++ error (_("Python scripting is not supported in this copy of GDB.")); ++} ++ + #endif /* HAVE_PYTHON */ + + +@@ -355,9 +1722,6 @@ show_python (char *args, int from_tty) + + /* Initialize the Python code. */ + +-/* Provide a prototype to silence -Wmissing-prototypes. */ +-extern initialize_file_ftype _initialize_python; +- + void + _initialize_python (void) + { +@@ -400,6 +1764,15 @@ Enables or disables printing of Python stack traces."), + &set_python_list, + &show_python_list); + ++ add_setshow_boolean_cmd ("auto-load", class_maintenance, ++ &gdbpy_auto_load, _("\ ++Enable or disable auto-loading of Python code when an object is opened."), _("\ ++Show whether Python code will be auto-loaded when an object is opened."), _("\ ++Enables or disables auto-loading of Python code when an object is opened."), ++ NULL, NULL, ++ &set_python_list, ++ &show_python_list); ++ + #ifdef HAVE_PYTHON + Py_Initialize (); + PyEval_InitThreads (); +@@ -410,11 +1783,36 @@ Enables or disables printing of Python stack traces."), + PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version); + PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name); + PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name); ++#ifdef PYTHONDIR ++ PyModule_AddStringConstant (gdb_module, "pythondir", PYTHONDIR); ++#else ++ if (gdb_datadir) ++ PyModule_AddStringConstant (gdb_module, "datadir", gdb_datadir); ++#endif + + gdbpy_initialize_values (); ++ gdbpy_initialize_breakpoints (); ++ gdbpy_initialize_frames (); ++ gdbpy_initialize_symtabs (); + gdbpy_initialize_commands (); ++ gdbpy_initialize_symbols (); ++ gdbpy_initialize_blocks (); ++ gdbpy_initialize_functions (); ++ gdbpy_initialize_types (); ++ gdbpy_initialize_parameters (); ++ gdbpy_initialize_objfile (); ++ gdbpy_initialize_events (); ++ gdbpy_initialize_membuf (); + + PyRun_SimpleString ("import gdb"); ++ PyRun_SimpleString ("gdb.pretty_printers = []"); ++ ++ observer_attach_new_objfile (gdbpy_new_objfile); ++ ++ gdbpy_to_string_cst = PyString_FromString ("to_string"); ++ gdbpy_children_cst = PyString_FromString ("children"); ++ gdbpy_display_hint_cst = PyString_FromString ("display_hint"); ++ gdbpy_doc_cst = PyString_FromString ("__doc__"); + + gdbpy_doc_cst = PyString_FromString ("__doc__"); + +@@ -442,6 +1840,15 @@ class GdbOutputFile:\n\ + \n\ + sys.stderr = GdbOutputFile()\n\ + sys.stdout = GdbOutputFile()\n\ ++if hasattr (gdb, 'datadir'):\n\ ++ gdb.pythondir = gdb.datadir + '/python'\n\ ++if hasattr (gdb, 'pythondir'):\n\ ++ sys.path.insert(0, gdb.pythondir)\n\ ++ gdb.__path__ = [gdb.pythondir + '/gdb']\n\ ++ from os.path import exists\n\ ++ ipy = gdb.pythondir + '/gdb/__init__.py'\n\ ++ if exists (ipy):\n\ ++ execfile (ipy)\n\ + "); + + /* Release the GIL while gdb runs. */ +@@ -461,9 +1868,84 @@ static PyMethodDef GdbMethods[] = + "Get a value from history" }, + { "execute", execute_gdb_command, METH_VARARGS, + "Execute a gdb command" }, +- { "get_parameter", get_parameter, METH_VARARGS, ++ { "cli", gdbpy_cli, METH_NOARGS, ++ "Enter the gdb CLI" }, ++ { "parameter", gdbpy_parameter, METH_VARARGS, + "Return a gdb parameter's value" }, + ++ { "breakpoints", gdbpy_breakpoints, METH_NOARGS, ++ "Return a tuple of all breakpoint objects" }, ++ ++ { "default_visualizer", gdbpy_default_visualizer, METH_VARARGS, ++ "Find the default visualizer for a Value." }, ++ ++ { "current_objfile", gdbpy_get_current_objfile, METH_NOARGS, ++ "Return the current Objfile being loaded, or None." }, ++ { "objfiles", gdbpy_objfiles, METH_NOARGS, ++ "Return a sequence of all loaded objfiles." }, ++ ++ { "frames", gdbpy_frames, METH_NOARGS, ++ "frames () -> (gdb.Frame, ...).\n\ ++Return a tuple of all frame objects." }, ++ { "newest_frame", gdbpy_newest_frame, METH_NOARGS, ++ "newest_frame () -> gdb.Frame.\n\ ++Return the newest frame object." }, ++ { "selected_frame", gdbpy_selected_frame, METH_NOARGS, ++ "selected_frame () -> gdb.Frame.\n\ ++Return the selected frame object." }, ++ { "frame_stop_reason_string", gdbpy_frame_stop_reason_string, METH_VARARGS, ++ "stop_reason_string (Integer) -> String.\n\ ++Return a string explaining unwind stop reason." }, ++ ++ { "lookup_type", (PyCFunction) gdbpy_lookup_type, ++ METH_VARARGS | METH_KEYWORDS, ++ "lookup_type (name [, block]) -> type\n\ ++Return a Type corresponding to the given name." }, ++ ++ { "lookup_symbol", (PyCFunction) gdbpy_lookup_symbol, ++ METH_VARARGS | METH_KEYWORDS, ++ "lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this)\n\ ++Return a tuple with the symbol corresponding to the given name (or None) and\n\ ++a boolean indicating if name is a field of the current implied argument\n\ ++`this' (when the current language is object-oriented)." }, ++ { "solib_address", gdbpy_solib_address, METH_VARARGS, ++ "solib_address (Long) -> String.\n\ ++Return the name of the shared library holding a given address, or None." }, ++ ++ { "find_pc_function", gdbpy_find_pc_function, METH_VARARGS, ++ "Return the function containing the given pc value, or None." }, ++ ++ { "block_for_pc", gdbpy_block_for_pc, METH_VARARGS, ++ "Return the block containing the given pc value, or None." }, ++ ++ { "decode_line", gdbpy_decode_line, METH_VARARGS, ++ "Decode a string argument the way that 'break' or 'edit' does.\n\ ++Return a tuple holding the file name (or None) and line number (or None).\n\ ++Note: may later change to return an object." }, ++ ++ { "threads", gdbpy_threads, METH_NOARGS, ++ "Return a tuple holding all the valid thread IDs." }, ++ { "current_thread", gdbpy_current_thread, METH_NOARGS, ++ "Return the thread ID of the current thread." }, ++ { "switch_to_thread", gdbpy_switch_to_thread, METH_VARARGS, ++ "Switch to a thread, given the thread ID." }, ++ ++ { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, ++ "Parse a string as an expression, evaluate it, and return the result." }, ++ ++ { "post_event", gdbpy_post_event, METH_VARARGS, ++ "Post an event into gdb's event loop." }, ++ ++ { "read_memory", gdbpy_read_memory, METH_VARARGS, ++ "read_memory (address, length) -> buffer\n\ ++Return a buffer object for reading from the inferior's memory." }, ++ { "write_memory", gdbpy_write_memory, METH_VARARGS, ++ "write_memory (address, buffer [, length])\n\ ++Write the given buffer object to the inferior's memory." }, ++ { "search_memory", (PyCFunction) gdbpy_search_memory, METH_VARARGS | METH_KEYWORDS, ++ "search_memory (address, length, pattern [, size] [, max_count]) -> list\n\ ++Return a list with the addresses where matches were found." }, ++ + { "write", gdbpy_write, METH_VARARGS, + "Write a string using gdb's filtered stream." }, + { "flush", gdbpy_flush, METH_NOARGS, +diff --git a/gdb/python/python.h b/gdb/python/python.h +index e63c447..767af86 100644 +--- a/gdb/python/python.h ++++ b/gdb/python/python.h +@@ -26,4 +26,14 @@ extern struct value *values_in_python; + + void eval_python_from_control_command (struct command_line *); + ++void source_python_script (FILE *stream, char *file); ++ ++void run_python_script (int argc, char **argv); ++ ++int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, ++ int embedded_offset, CORE_ADDR address, ++ struct ui_file *stream, int recurse, ++ const struct value_print_options *options, ++ const struct language_defn *language); ++ + #endif /* GDB_PYTHON_H */ +diff --git a/gdb/scm-lang.c b/gdb/scm-lang.c +index 345befd..e2568c8 100644 +--- a/gdb/scm-lang.c ++++ b/gdb/scm-lang.c +@@ -43,14 +43,14 @@ static int in_eval_c (void); + struct type *builtin_type_scm; + + void +-scm_printchar (int c, struct ui_file *stream) ++scm_printchar (int c, struct type *type, struct ui_file *stream) + { + fprintf_filtered (stream, "#\\%c", c); + } + + static void +-scm_printstr (struct ui_file *stream, const gdb_byte *string, +- unsigned int length, int width, int force_ellipses, ++scm_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, ++ unsigned int length, int force_ellipses, + const struct value_print_options *options) + { + fprintf_filtered (stream, "\"%s\"", string); +diff --git a/gdb/scm-lang.h b/gdb/scm-lang.h +index 6bf88f5..1798b2f 100644 +--- a/gdb/scm-lang.h ++++ b/gdb/scm-lang.h +@@ -59,7 +59,7 @@ extern void scm_scmval_print (LONGEST, struct ui_file *, int, + + extern int is_scmvalue_type (struct type *); + +-extern void scm_printchar (int, struct ui_file *); ++extern void scm_printchar (int, struct type *, struct ui_file *); + + extern struct value *scm_evaluate_string (char *, int); + +diff --git a/gdb/scm-valprint.c b/gdb/scm-valprint.c +index f0a7642..a32add5 100644 +--- a/gdb/scm-valprint.c ++++ b/gdb/scm-valprint.c +@@ -187,7 +187,8 @@ taloop: + if (SCM_ICHRP (svalue)) + { + svalue = SCM_ICHR (svalue); +- scm_printchar (svalue, stream); ++ scm_printchar (svalue, builtin_type (current_gdbarch)->builtin_char, ++ stream); + break; + } + else if (SCM_IFLAGP (svalue) +diff --git a/gdb/stabsread.c b/gdb/stabsread.c +index 2d7eb15..3b8eb29 100644 +--- a/gdb/stabsread.c ++++ b/gdb/stabsread.c +@@ -322,7 +322,7 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) + + if (typenums[0] == -1) + { +- return (alloc_type (objfile)); ++ return (alloc_type (objfile, NULL)); + } + + type_addr = dbx_lookup_type (typenums); +@@ -332,7 +332,7 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) + We will fill it in later if we find out how. */ + if (*type_addr == 0) + { +- *type_addr = alloc_type (objfile); ++ *type_addr = alloc_type (objfile, NULL); + } + + return (*type_addr); +@@ -589,6 +589,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, + int deftype; + int synonym = 0; + int i; ++ char *new_name = NULL; + + /* We would like to eliminate nameless symbols, but keep their types. + E.g. stab entry ":t10=*2" should produce a type 10, which is a pointer +@@ -683,9 +684,24 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, + { + normal: + SYMBOL_LANGUAGE (sym) = current_subfile->language; +- SYMBOL_SET_NAMES (sym, string, p - string, objfile); ++ if (current_subfile->language == language_cplus) ++ { ++ char *name = alloca (p - string + 1); ++ memcpy (name, string, p - string); ++ name[p - string] = '\0'; ++ new_name = cp_canonicalize_string (name); ++ } ++ ++ if (new_name != NULL) ++ { ++ SYMBOL_SET_NAMES (sym, new_name, strlen (new_name), objfile); ++ xfree (new_name); ++ } ++ else ++ SYMBOL_SET_NAMES (sym, string, p - string, objfile); ++ + if (SYMBOL_LANGUAGE (sym) == language_cplus) +- cp_scan_for_anonymous_namespaces (sym); ++ cp_scan_for_anonymous_namespaces (sym); + } + p++; + +@@ -1519,18 +1535,35 @@ again: + if (*p != ':') + return error_type (pp, objfile); + } +- to = type_name = +- (char *) obstack_alloc (&objfile->objfile_obstack, p - *pp + 1); +- +- /* Copy the name. */ +- from = *pp + 1; +- while (from < p) +- *to++ = *from++; +- *to = '\0'; ++ type_name = NULL; ++ if (current_subfile->language == language_cplus) ++ { ++ char *new_name, *name = alloca (p - *pp + 1); ++ memcpy (name, *pp, p - *pp); ++ name[p - *pp] = '\0'; ++ new_name = cp_canonicalize_string (name); ++ if (new_name != NULL) ++ { ++ type_name = obsavestring (new_name, strlen (new_name), ++ &objfile->objfile_obstack); ++ xfree (new_name); ++ } ++ } ++ if (type_name == NULL) ++ { ++ to = type_name = ++ (char *) obstack_alloc (&objfile->objfile_obstack, p - *pp + 1); ++ ++ /* Copy the name. */ ++ from = *pp + 1; ++ while (from < p) ++ *to++ = *from++; ++ *to = '\0'; ++ } + + /* Set the pointer ahead of the name which we just read, and + the colon. */ +- *pp = from + 1; ++ *pp = p + 1; + } + + /* If this type has already been declared, then reuse the same +diff --git a/gdb/stack.c b/gdb/stack.c +index 3bcf758..094a4ce 100644 +--- a/gdb/stack.c ++++ b/gdb/stack.c +@@ -380,6 +380,7 @@ print_frame_args (struct symbol *func, struct frame_info *frame, + + get_raw_print_options (&opts); + opts.deref_ref = 0; ++ opts.summary = 1; + common_val_print (val, stb->stream, 2, + &opts, language); + ui_out_field_stream (uiout, "value", stb); +@@ -579,20 +580,16 @@ print_frame_info (struct frame_info *frame, int print_level, + gdb_flush (gdb_stdout); + } + +-static void +-print_frame (struct frame_info *frame, int print_level, +- enum print_what print_what, int print_args, +- struct symtab_and_line sal) ++/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding ++ to FRAME. */ ++void ++find_frame_funname (struct frame_info *frame, char **funname, ++ enum language *funlang) + { + struct symbol *func; +- char *funname = NULL; +- enum language funlang = language_unknown; +- struct ui_stream *stb; +- struct cleanup *old_chain, *list_chain; +- struct value_print_options opts; + +- stb = ui_out_stream_new (uiout); +- old_chain = make_cleanup_ui_out_stream_delete (stb); ++ *funname = NULL; ++ *funlang = language_unknown; + + func = find_pc_function (get_frame_address_in_block (frame)); + if (func) +@@ -625,24 +622,24 @@ print_frame (struct frame_info *frame, int print_level, + /* We also don't know anything about the function besides + its address and name. */ + func = 0; +- funname = SYMBOL_PRINT_NAME (msymbol); +- funlang = SYMBOL_LANGUAGE (msymbol); ++ *funname = SYMBOL_PRINT_NAME (msymbol); ++ *funlang = SYMBOL_LANGUAGE (msymbol); + } + else + { +- funname = SYMBOL_PRINT_NAME (func); +- funlang = SYMBOL_LANGUAGE (func); +- if (funlang == language_cplus) ++ *funname = SYMBOL_PRINT_NAME (func); ++ *funlang = SYMBOL_LANGUAGE (func); ++ if (*funlang == language_cplus) + { + /* It seems appropriate to use SYMBOL_PRINT_NAME() here, + to display the demangled name that we already have + stored in the symbol table, but we stored a version + with DMGL_PARAMS turned on, and here we don't want to + display parameters. So remove the parameters. */ +- char *func_only = cp_remove_params (funname); ++ char *func_only = cp_remove_params (*funname); + if (func_only) + { +- funname = func_only; ++ *funname = func_only; + make_cleanup (xfree, func_only); + } + } +@@ -655,10 +652,27 @@ print_frame (struct frame_info *frame, int print_level, + + if (msymbol != NULL) + { +- funname = SYMBOL_PRINT_NAME (msymbol); +- funlang = SYMBOL_LANGUAGE (msymbol); ++ *funname = SYMBOL_PRINT_NAME (msymbol); ++ *funlang = SYMBOL_LANGUAGE (msymbol); + } + } ++} ++ ++static void ++print_frame (struct frame_info *frame, int print_level, ++ enum print_what print_what, int print_args, ++ struct symtab_and_line sal) ++{ ++ char *funname = NULL; ++ enum language funlang = language_unknown; ++ struct ui_stream *stb; ++ struct cleanup *old_chain, *list_chain; ++ struct value_print_options opts; ++ ++ stb = ui_out_stream_new (uiout); ++ old_chain = make_cleanup_ui_out_stream_delete (stb); ++ ++ find_frame_funname (frame, &funname, &funlang); + + annotate_frame_begin (print_level ? frame_relative_level (frame) : 0, + get_frame_pc (frame)); +@@ -694,7 +708,7 @@ print_frame (struct frame_info *frame, int print_level, + struct print_args_args args; + struct cleanup *args_list_chain; + args.frame = frame; +- args.func = func; ++ args.func = find_pc_function (get_frame_address_in_block (frame)); + args.stream = gdb_stdout; + args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args"); + catch_errors (print_args_stub, &args, "", RETURN_MASK_ERROR); +@@ -1208,24 +1222,24 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty) + else + count = -1; + +- if (info_verbose) +- { +- struct partial_symtab *ps; +- +- /* Read in symbols for all of the frames. Need to do this in a +- separate pass so that "Reading in symbols for xxx" messages +- don't screw up the appearance of the backtrace. Also if +- people have strong opinions against reading symbols for +- backtrace this may have to be an option. */ +- i = count; +- for (fi = trailing; fi != NULL && i--; fi = get_prev_frame (fi)) +- { +- QUIT; +- ps = find_pc_psymtab (get_frame_address_in_block (fi)); +- if (ps) +- PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in. */ +- } +- } ++ { ++ struct partial_symtab *ps; ++ ++ /* Read in symbols for all of the frames. Need to do this ++ unconditionally to ensure that psymbols are read. Also need to ++ do this in a separate pass so that "Reading in symbols for xxx" ++ messages don't screw up the appearance of the backtrace. Also ++ if people have strong opinions against reading symbols for ++ backtrace this may have to be an option. */ ++ i = count; ++ for (fi = trailing; fi != NULL && i--; fi = get_prev_frame (fi)) ++ { ++ QUIT; ++ ps = find_pc_psymtab (get_frame_address_in_block (fi)); ++ if (info_verbose && ps) ++ PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in. */ ++ } ++ } + + for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi)) + { +@@ -1373,6 +1387,8 @@ print_block_frame_locals (struct block *b, struct frame_info *frame, + case LOC_COMPUTED: + if (SYMBOL_IS_ARGUMENT (sym)) + break; ++ if (SYMBOL_DOMAIN (sym) == COMMON_BLOCK_DOMAIN) ++ break; + values_printed = 1; + print_variable_and_value (NULL, sym, frame, stream, 4 * num_tabs); + break; +@@ -1796,18 +1812,27 @@ return_command (char *retval_exp, int from_tty) + message. */ + if (retval_exp) + { ++ struct expression *retval_expr = parse_expression (retval_exp); ++ struct cleanup *old_chain = make_cleanup (xfree, retval_expr); + struct type *return_type = NULL; + + /* Compute the return value. Should the computation fail, this + call throws an error. */ +- return_value = parse_and_eval (retval_exp); ++ return_value = evaluate_expression (retval_expr); + + /* Cast return value to the return type of the function. Should + the cast fail, this call throws an error. */ + if (thisfun != NULL) + return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun)); + if (return_type == NULL) +- return_type = builtin_type (get_frame_arch (thisframe))->builtin_int; ++ { ++ if (retval_expr->elts[0].opcode != UNOP_CAST) ++ error (_("Return value type not available for selected " ++ "stack frame.\n" ++ "Please use an explicit cast of the value to return.")); ++ return_type = value_type (return_value); ++ } ++ do_cleanups (old_chain); + CHECK_TYPEDEF (return_type); + return_value = value_cast (return_type, return_value); + +diff --git a/gdb/stack.h b/gdb/stack.h +index 973a57f..56b1d91 100644 +--- a/gdb/stack.h ++++ b/gdb/stack.h +@@ -22,4 +22,9 @@ + + void select_frame_command (char *level_exp, int from_tty); + ++/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding ++ to FRAME. */ ++void find_frame_funname (struct frame_info *frame, char **funname, ++ enum language *funlang); ++ + #endif /* #ifndef STACK_H */ +diff --git a/gdb/symfile.c b/gdb/symfile.c +index 63b5c1d..b047e94 100644 +--- a/gdb/symfile.c ++++ b/gdb/symfile.c +@@ -929,6 +929,17 @@ new_symfile_objfile (struct objfile *objfile, int mainline, int verbo) + clear_complaints (&symfile_complaints, 0, verbo); + } + ++/* A helper function which returns true if OBJFILE has any debug ++ symbols, and false otherwise. */ ++static int ++has_any_debug_symbols (struct objfile *objfile) ++{ ++ return (objfile->psymtabs || objfile->quick_addrmap ++ || (objfile->separate_debug_objfile ++ && (objfile->separate_debug_objfile->psymtabs ++ || objfile->separate_debug_objfile->quick_addrmap))); ++} ++ + /* Process a symbol file, as either the main file or as a dynamically + loaded file. + +@@ -965,13 +976,15 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty, + /* Give user a chance to burp if we'd be + interactively wiping out any existing symbols. */ + +- if ((have_full_symbols () || have_partial_symbols ()) +- && mainline ++ if (mainline + && from_tty ++ && (have_full_symbols () || have_partial_symbols ()) + && !query (_("Load new symbol table from \"%s\"? "), name)) + error (_("Not confirmed.")); + + objfile = allocate_objfile (abfd, flags); ++ if (mainline) ++ objfile->flags |= OBJF_MAIN; + discard_cleanups (my_cleanups); + + if (addrs) +@@ -1007,6 +1020,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty, + + if ((flags & OBJF_READNOW) || readnow_symbol_files) + { ++ require_partial_symbols (objfile); ++ + if ((from_tty || info_verbose) && print_symbol_loading) + { + printf_unfiltered (_("expanding to full symbols...")); +@@ -1025,7 +1040,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty, + /* If the file has its own symbol tables it has no separate debug info. + `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS. + `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'. */ +- if (objfile->psymtabs == NULL) ++ if (!has_any_debug_symbols (objfile)) + debugfile = find_separate_debug_file (objfile); + if (debugfile) + { +@@ -1049,8 +1064,10 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty, + xfree (debugfile); + } + +- if (!have_partial_symbols () && !have_full_symbols () +- && print_symbol_loading) ++ /* has_any_debug_symbols is not fully compatible with the former calls which ++ would just be needlessly expensive here. */ ++ if ((from_tty || info_verbose) && print_symbol_loading ++ && !has_any_debug_symbols (objfile) && mainline) + { + wrap_here (""); + printf_unfiltered (_("(no debugging symbols found)")); +@@ -2423,13 +2440,15 @@ reread_symbols (void) + zero is OK since dbxread.c also does what it needs to do if + objfile->global_psymbols.size is 0. */ + (*objfile->sf->sym_read) (objfile, 0); +- if (!have_partial_symbols () && !have_full_symbols ()) ++ if (!has_any_debug_symbols (objfile)) + { + wrap_here (""); + printf_unfiltered (_("(no debugging symbols found)\n")); + wrap_here (""); + } + ++ objfile->flags &= ~OBJF_SYMTABS_READ; ++ + /* We're done reading the symbol file; finish off complaints. */ + clear_complaints (&symfile_complaints, 0, 1); + +@@ -2726,7 +2745,7 @@ allocate_symtab (char *filename, struct objfile *objfile) + } + + struct partial_symtab * +-allocate_psymtab (char *filename, struct objfile *objfile) ++allocate_psymtab (const char *filename, struct objfile *objfile) + { + struct partial_symtab *psymtab; + +@@ -3040,7 +3059,8 @@ again2: + + struct partial_symtab * + start_psymtab_common (struct objfile *objfile, +- struct section_offsets *section_offsets, char *filename, ++ struct section_offsets *section_offsets, ++ const char *filename, + CORE_ADDR textlow, struct partial_symbol **global_syms, + struct partial_symbol **static_syms) + { +diff --git a/gdb/symfile.h b/gdb/symfile.h +index 88f8326..50671c1 100644 +--- a/gdb/symfile.h ++++ b/gdb/symfile.h +@@ -140,6 +140,12 @@ struct sym_fns + + void (*sym_read) (struct objfile *, int); + ++ /* Read the partial symbols for an objfile. This may be NULL, in ++ which case gdb assumes that sym_read already read the partial ++ symbols. */ ++ ++ void (*sym_read_psymbols) (struct objfile *); ++ + /* Called when we are finished with an objfile. Should do all + cleanup that is specific to the object file format for the + particular objfile. */ +@@ -250,7 +256,7 @@ extern void free_section_addr_info (struct section_addr_info *); + + extern struct partial_symtab *start_psymtab_common (struct objfile *, + struct section_offsets *, +- char *, CORE_ADDR, ++ const char *, CORE_ADDR, + struct partial_symbol **, + struct partial_symbol **); + +@@ -300,7 +306,7 @@ extern int auto_solib_limit; + + extern void set_initial_language (void); + +-extern struct partial_symtab *allocate_psymtab (char *, struct objfile *); ++extern struct partial_symtab *allocate_psymtab (const char *, struct objfile *); + + extern void discard_psymtab (struct partial_symtab *); + +@@ -369,7 +375,7 @@ void free_symfile_segment_data (struct symfile_segment_data *data); + /* From dwarf2read.c */ + + extern int dwarf2_has_info (struct objfile *); +- ++extern void dwarf2_create_quick_addrmap (struct objfile *); + extern void dwarf2_build_psymtabs (struct objfile *, int); + extern void dwarf2_build_frame_info (struct objfile *); + +diff --git a/gdb/symtab.c b/gdb/symtab.c +index d2ba1f3..f9d27b2 100644 +--- a/gdb/symtab.c ++++ b/gdb/symtab.c +@@ -42,6 +42,7 @@ + #include "ada-lang.h" + #include "p-lang.h" + #include "addrmap.h" ++#include "cp-support.h" + + #include "hashtab.h" + +@@ -55,6 +56,7 @@ + #include "gdb_stat.h" + #include + #include "cp-abi.h" ++#include "cp-support.h" + #include "observer.h" + #include "gdb_assert.h" + #include "solist.h" +@@ -273,7 +275,7 @@ lookup_partial_symtab (const char *name) + make_cleanup (xfree, real_path); + } + +- ALL_PSYMTABS (objfile, pst) ++ ALL_PSYMTABS_REQUIRED (objfile, pst) + { + if (FILENAME_CMP (name, pst->filename) == 0) + { +@@ -870,7 +872,13 @@ find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section) + than the later used TEXTLOW/TEXTHIGH one. */ + + ALL_OBJFILES (objfile) +- if (objfile->psymtabs_addrmap != NULL) ++ { ++ if (objfile->quick_addrmap) ++ { ++ if (!addrmap_find (objfile->quick_addrmap, pc)) ++ continue; ++ } ++ if (require_partial_symbols (objfile)->psymtabs_addrmap != NULL) + { + struct partial_symtab *pst; + +@@ -903,6 +911,7 @@ find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section) + return pst; + } + } ++ } + + /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs + which still have no corresponding full SYMTABs read. But it is not +@@ -1170,6 +1179,22 @@ fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile) + return psym; + } + ++/* Ensure that the partial symbols for OBJFILE have been loaded. This ++ function always returns its argument, as a convenience. */ ++ ++struct objfile * ++require_partial_symbols (struct objfile *objfile) ++{ ++ if ((objfile->flags & OBJF_SYMTABS_READ) == 0) ++ { ++ objfile->flags |= OBJF_SYMTABS_READ; ++ ++ if (objfile->sf->sym_read_psymbols) ++ (*objfile->sf->sym_read_psymbols) (objfile); ++ } ++ return objfile; ++} ++ + /* Find the definition for a specified symbol name NAME + in domain DOMAIN, visible from lexical block BLOCK. + Returns the struct symbol pointer, or zero if no symbol is found. +@@ -1200,6 +1225,11 @@ lookup_symbol_in_language (const char *name, const struct block *block, + int needtofreename = 0; + struct symbol *returnval; + ++ if(strncmp(name, "::", 2) == 0){/* this must be a global name */ ++ name = name+2; ++ block = NULL; ++ } ++ + modified_name = name; + + /* If we are using C++ or Java, demangle the name before doing a lookup, so +@@ -1213,6 +1243,17 @@ lookup_symbol_in_language (const char *name, const struct block *block, + modified_name = demangled_name; + needtofreename = 1; + } ++ else ++ { ++ /* If we were given a non-mangled name, canonicalize it ++ according to the language (so far only for C++). */ ++ demangled_name = cp_canonicalize_string (name); ++ if (demangled_name) ++ { ++ modified_name = demangled_name; ++ needtofreename = 1; ++ } ++ } + } + else if (lang == language_java) + { +@@ -1296,13 +1337,15 @@ lookup_symbol_aux (const char *name, const char *linkage_name, + && block != NULL) + { + struct symbol *sym = NULL; ++ const struct block *function_block = block; ++ + /* 'this' is only defined in the function's block, so find the + enclosing function block. */ +- for (; block && !BLOCK_FUNCTION (block); +- block = BLOCK_SUPERBLOCK (block)); ++ for (; function_block && !BLOCK_FUNCTION (function_block); ++ function_block = BLOCK_SUPERBLOCK (function_block)); + +- if (block && !dict_empty (BLOCK_DICT (block))) +- sym = lookup_block_symbol (block, langdef->la_name_of_this, ++ if (function_block && !dict_empty (BLOCK_DICT (function_block))) ++ sym = lookup_block_symbol (function_block, langdef->la_name_of_this, + NULL, VAR_DOMAIN); + if (sym) + { +@@ -1361,22 +1404,24 @@ lookup_symbol_aux_local (const char *name, const char *linkage_name, + const domain_enum domain) + { + struct symbol *sym; +- const struct block *static_block = block_static_block (block); ++ const struct block *global_block = block_global_block (block); ++ const struct block *block_iterator = block; + + /* Check if either no block is specified or it's a global block. */ + +- if (static_block == NULL) ++ if (global_block == NULL) + return NULL; + +- while (block != static_block) ++ while (block_iterator != global_block) + { +- sym = lookup_symbol_aux_block (name, linkage_name, block, domain); ++ sym = lookup_symbol_aux_block (name, linkage_name, block_iterator, domain); + if (sym != NULL) + return sym; +- block = BLOCK_SUPERBLOCK (block); ++ ++ block_iterator = BLOCK_SUPERBLOCK (block_iterator); + } + +- /* We've reached the static block without finding a result. */ ++ /* We've reached the global block without finding a result. */ + + return NULL; + } +@@ -1450,6 +1495,7 @@ lookup_global_symbol_from_objfile (const struct objfile *objfile, + } + + /* Now go through psymtabs. */ ++ require_partial_symbols ((struct objfile *) objfile); + ALL_OBJFILE_PSYMTABS (objfile, ps) + { + if (!ps->readin +@@ -1520,7 +1566,7 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name, + struct symtab *s; + const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0); + +- ALL_PSYMTABS (objfile, ps) ++ ALL_PSYMTABS_REQUIRED (objfile, ps) + { + if (!ps->readin + && lookup_partial_symbol (ps, name, linkage_name, +@@ -1805,7 +1851,11 @@ basic_lookup_transparent_type (const char *name) + } + } + +- ALL_PSYMTABS (objfile, ps) ++ /* FIXME: .debug_pubnames should be read in. ++ ++ One may also try to the first pass without the require_partial_symbols ++ call but that would behave nondeterministically. */ ++ ALL_PSYMTABS_REQUIRED (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, NULL, + 1, STRUCT_DOMAIN)) +@@ -1853,7 +1903,12 @@ basic_lookup_transparent_type (const char *name) + } + } + +- ALL_PSYMTABS (objfile, ps) ++ /* FIXME: Something like .debug_pubnames containing also static symbols ++ should be read in. Compiler needs to be taught to generate it first. ++ ++ One may also try to the first pass without the require_partial_symbols ++ call but that would behave nondeterministically. */ ++ ALL_PSYMTABS_REQUIRED (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, NULL, 0, STRUCT_DOMAIN)) + { +@@ -1894,7 +1949,21 @@ find_main_psymtab (void) + struct partial_symtab *pst; + struct objfile *objfile; + +- ALL_PSYMTABS (objfile, pst) ++ ALL_OBJFILES (objfile) ++ { ++ if ((objfile->flags & OBJF_MAIN) == 0) ++ continue; ++ require_partial_symbols (objfile); ++ ALL_OBJFILE_PSYMTABS (objfile, pst) ++ { ++ if (lookup_partial_symbol (pst, main_name (), NULL, 1, VAR_DOMAIN)) ++ { ++ return pst; ++ } ++ } ++ } ++ ++ ALL_PSYMTABS_REQUIRED (objfile, pst) + { + if (lookup_partial_symbol (pst, main_name (), NULL, 1, VAR_DOMAIN)) + { +@@ -3085,7 +3154,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], + matching the regexp. That way we don't have to reproduce all of + the machinery below. */ + +- ALL_PSYMTABS (objfile, ps) ++ ALL_PSYMTABS_REQUIRED (objfile, ps) + { + struct partial_symbol **bound, **gbound, **sbound; + int keep_going = 1; +diff --git a/gdb/symtab.h b/gdb/symtab.h +index 8b086f3..801cd2b 100644 +--- a/gdb/symtab.h ++++ b/gdb/symtab.h +@@ -171,9 +171,6 @@ extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *); + #define SYMBOL_SECTION(symbol) (symbol)->ginfo.section + #define SYMBOL_OBJ_SECTION(symbol) (symbol)->ginfo.obj_section + +-#define SYMBOL_CPLUS_DEMANGLED_NAME(symbol) \ +- (symbol)->ginfo.language_specific.cplus_specific.demangled_name +- + /* Initializes the language dependent portion of a symbol + depending upon the language for the symbol. */ + #define SYMBOL_INIT_LANGUAGE_SPECIFIC(symbol,language) \ +@@ -394,7 +391,10 @@ typedef enum domain_enum_tag + FUNCTIONS_DOMAIN, + + /* All defined types */ +- TYPES_DOMAIN ++ TYPES_DOMAIN, ++ ++ /* Fortran common blocks. Their naming must be separate from VAR_DOMAIN. */ ++ COMMON_BLOCK_DOMAIN + } + domain_enum; + +@@ -472,7 +472,13 @@ enum address_class + in another object file or runtime common storage. + The linker might even remove the minimal symbol if the global + symbol is never referenced, in which case the symbol remains +- unresolved. */ ++ unresolved. ++ ++ GDB would normally find the symbol in the minimal symbol table if it will ++ not find it in the full symbol table. But a reference to an external ++ symbol in a local block shadowing other definition requires full symbol ++ without possibly having its address available for LOC_STATIC. Testcase ++ is provided as `gdb.dwarf2/dw2-unresolved.exp'. */ + + LOC_UNRESOLVED, + +@@ -1027,6 +1033,8 @@ extern void clear_pc_function_cache (void); + + /* from symtab.c: */ + ++struct objfile *require_partial_symbols (struct objfile *); ++ + /* lookup partial symbol table by filename */ + + extern struct partial_symtab *lookup_partial_symtab (const char *); +diff --git a/gdb/syscalls/gdb-syscalls.dtd b/gdb/syscalls/gdb-syscalls.dtd +new file mode 100644 +index 0000000..0d40ab4 +--- /dev/null ++++ b/gdb/syscalls/gdb-syscalls.dtd +@@ -0,0 +1,21 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gdb/syscalls/i386-linux.xml b/gdb/syscalls/i386-linux.xml +new file mode 100644 +index 0000000..6f2beee +--- /dev/null ++++ b/gdb/syscalls/i386-linux.xml +@@ -0,0 +1,334 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gdb/syscalls/ppc-linux.xml b/gdb/syscalls/ppc-linux.xml +new file mode 100644 +index 0000000..f09fabd +--- /dev/null ++++ b/gdb/syscalls/ppc-linux.xml +@@ -0,0 +1,304 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gdb/syscalls/ppc64-linux.xml b/gdb/syscalls/ppc64-linux.xml +new file mode 100644 +index 0000000..7ee929c +--- /dev/null ++++ b/gdb/syscalls/ppc64-linux.xml +@@ -0,0 +1,289 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gdb/target.c b/gdb/target.c +index b89d551..831070c 100644 +--- a/gdb/target.c ++++ b/gdb/target.c +@@ -443,6 +443,8 @@ update_current_target (void) + /* Do not inherit to_follow_fork. */ + INHERIT (to_insert_exec_catchpoint, t); + INHERIT (to_remove_exec_catchpoint, t); ++ INHERIT (to_passed_by_entrypoint, t); ++ INHERIT (to_set_syscall_catchpoint, t); + INHERIT (to_has_exited, t); + /* Do not inherit to_mourn_inferiour. */ + INHERIT (to_can_run, t); +@@ -586,9 +588,15 @@ update_current_target (void) + de_fault (to_insert_exec_catchpoint, + (void (*) (int)) + tcomplain); ++ de_fault (to_passed_by_entrypoint, ++ (int (*) (void)) ++ tcomplain); + de_fault (to_remove_exec_catchpoint, + (int (*) (int)) + tcomplain); ++ de_fault (to_set_syscall_catchpoint, ++ (int (*) (int, int, int, int, int *)) ++ tcomplain); + de_fault (to_has_exited, + (int (*) (int, int, int *)) + return_zero); +@@ -2677,9 +2685,9 @@ target_waitstatus_to_string (const struct target_waitstatus *ws) + case TARGET_WAITKIND_EXECD: + return xstrprintf ("%sexecd", kind_str); + case TARGET_WAITKIND_SYSCALL_ENTRY: +- return xstrprintf ("%ssyscall-entry", kind_str); ++ return xstrprintf ("%sentered syscall", kind_str); + case TARGET_WAITKIND_SYSCALL_RETURN: +- return xstrprintf ("%ssyscall-return", kind_str); ++ return xstrprintf ("%sexited syscall", kind_str); + case TARGET_WAITKIND_SPURIOUS: + return xstrprintf ("%sspurious", kind_str); + case TARGET_WAITKIND_IGNORE: +diff --git a/gdb/target.h b/gdb/target.h +index 7f4cd8f..8dcc3d6 100644 +--- a/gdb/target.h ++++ b/gdb/target.h +@@ -140,18 +140,34 @@ struct target_waitstatus + { + enum target_waitkind kind; + +- /* Forked child pid, execd pathname, exit status or signal number. */ ++ /* Forked child pid, execd pathname, exit status, signal number or ++ syscall name. */ + union + { + int integer; + enum target_signal sig; + ptid_t related_pid; + char *execd_pathname; +- int syscall_id; ++ int syscall_number; + } + value; + }; + ++/* The structure below stores information about a system call. ++ It is basically used in the "catch syscall" command, and in ++ every function that gives information about a system call. ++ ++ It's also good to mention that its fields represent everything ++ that we currently know about a syscall in GDB. */ ++struct syscall ++ { ++ /* The syscall number. */ ++ int number; ++ ++ /* The syscall name. */ ++ const char *name; ++ }; ++ + /* Return a pretty printed form of target_waitstatus. + Space for the result is malloc'd, caller must free. */ + extern char *target_waitstatus_to_string (const struct target_waitstatus *); +@@ -392,6 +408,8 @@ struct target_ops + int (*to_follow_fork) (struct target_ops *, int); + void (*to_insert_exec_catchpoint) (int); + int (*to_remove_exec_catchpoint) (int); ++ int (*to_passed_by_entrypoint) (void); ++ int (*to_set_syscall_catchpoint) (int, int, int, int, int *); + int (*to_has_exited) (int, int, int *); + void (*to_mourn_inferior) (struct target_ops *); + int (*to_can_run) (void); +@@ -723,6 +741,8 @@ extern int inferior_has_vforked (ptid_t pid, ptid_t *child_pid); + + extern int inferior_has_execd (ptid_t pid, char **execd_pathname); + ++extern int inferior_has_called_syscall (ptid_t pid, int *syscall_number); ++ + /* From exec.c */ + + extern void print_section_info (struct target_ops *, bfd *); +@@ -881,6 +901,21 @@ int target_follow_fork (int follow_child); + #define target_remove_exec_catchpoint(pid) \ + (*current_target.to_remove_exec_catchpoint) (pid) + ++/* Has the inferior already passed through its entrypoint? */ ++#define target_passed_by_entrypoint() \ ++ (*current_target.to_passed_by_entrypoint) () ++ ++/* Syscall catch. NEEDED is nonzero if any syscall catch (of any ++ kind) is requested. ANY_COUNT is nonzero if a generic ++ (filter-less) syscall catch is being requested. TABLE is an array ++ of ints, indexed by syscall number. An element in this array is ++ nonzero if that syscall should be caught. TABLE_SIZE is the number ++ of elements in TABLE. */ ++ ++#define target_set_syscall_catchpoint(pid, needed, any_count, table_size, table) \ ++ (*current_target.to_set_syscall_catchpoint) (pid, needed, any_count, \ ++ table_size, table) ++ + /* Returns TRUE if PID has exited. And, also sets EXIT_STATUS to the + exit code of PID, if any. */ + +@@ -1146,6 +1181,20 @@ extern int target_search_memory (CORE_ADDR start_addr, + ULONGEST pattern_len, + CORE_ADDR *found_addrp); + ++/* Utility functions which can be used by search_memory implementations. */ ++ ++void allocate_pattern_buffer (char **pattern_bufp, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size); ++ ++void increase_pattern_buffer (char **pattern_bufp, char **pattern_buf_end, ++ ULONGEST *pattern_buf_size, int val_bytes); ++ ++int search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len, ++ const char *pattern_buf, ULONGEST pattern_len, ++ CORE_ADDR *found_addr); ++ ++void put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p); ++ + /* Command logging facility. */ + + #define target_log_command(p) \ +diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog +index e3aaeab..e886869 100644 +--- a/gdb/testsuite/ChangeLog ++++ b/gdb/testsuite/ChangeLog +@@ -1,3 +1,7 @@ ++2009-03-05 Pedro Alves ++ ++ * gdb.arch/i386-permbkpt.S, gdb.arch/i386-permbkpt.exp: New. ++ + 2009-02-18 Jan Kratochvil + + * gdb.base/macscp.exp (objfile): Move it to ${objdir}/${subdir}/. +diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac +index 3d8fae4..5fb9067 100644 +--- a/gdb/testsuite/configure.ac ++++ b/gdb/testsuite/configure.ac +@@ -1,7 +1,7 @@ + # -*- Autoconf -*- + # Process this file with autoconf to produce a configure script. + +-# Copyright 2002, 2003, 2004, 2005 ++# Copyright 2002, 2003, 2004, 2005, 2008 + # Free Software Foundation, Inc. + # + # This program is free software; you can redistribute it and/or modify +diff --git a/gdb/testsuite/gdb.arch/i386-permbkpt.S b/gdb/testsuite/gdb.arch/i386-permbkpt.S +new file mode 100644 +index 0000000..02a31d6 +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/i386-permbkpt.S +@@ -0,0 +1,30 @@ ++/* Copyright 2009 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 3 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, see . ++ ++ This file is part of the gdb testsuite. */ ++ ++#define CONCAT1(a, b) CONCAT2(a, b) ++#define CONCAT2(a, b) a ## b ++ ++#ifdef SYMBOL_PREFIX ++# define SYMBOL(str) CONCAT1(SYMBOL_PREFIX, str) ++#else ++# define SYMBOL(str) str ++#endif ++ ++ .global SYMBOL(main) ++SYMBOL(main): ++ int3 ++ ret +diff --git a/gdb/testsuite/gdb.arch/i386-permbkpt.exp b/gdb/testsuite/gdb.arch/i386-permbkpt.exp +new file mode 100644 +index 0000000..f1930e5 +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/i386-permbkpt.exp +@@ -0,0 +1,52 @@ ++# Copyright (C) 2009 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 3 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, see . ++ ++ ++# This file is part of the gdb testsuite. ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++# Test inserting breakpoints over permanent breakpoints on i386 and amd64. ++ ++if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } then { ++ verbose "Skipping i386 test for multi break at permanent breakpoint location." ++ return ++} ++ ++set testfile "i386-permbkpt" ++set srcfile ${testfile}.S ++set binfile ${objdir}/${subdir}/${testfile} ++ ++# Some targets have leading underscores on assembly symbols. ++# TODO: detect this automatically ++set additional_flags "" ++if { [istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"] } then { ++ set additional_flags "additional_flags=-DSYMBOL_PREFIX=_" ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $additional_flags]] != "" } { ++ untested i386-permbkpt.exp ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_test "break main" "" "First permanent break" ++gdb_test "break main" "" "Second permanent break" +diff --git a/gdb/testsuite/gdb.arch/powerpc-power7.exp b/gdb/testsuite/gdb.arch/powerpc-power7.exp +new file mode 100644 +index 0000000..d9c48f9 +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/powerpc-power7.exp +@@ -0,0 +1,166 @@ ++# Copyright 2009 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. ++ ++# Test PowerPC Power7 instructions disassembly. ++ ++if {![istarget "powerpc*-*-*"]} then { ++ verbose "Skipping PowerPC Power7 instructions disassembly." ++ return ++} ++ ++set testfile "powerpc-power7" ++set srcfile ${testfile}.s ++set objfile ${objdir}/${subdir}/${testfile}.o ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}] != "" } { ++ untested "PowerPC Power7 instructions disassembly" ++ return -1 ++} ++ ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${objfile} ++ ++ ++# Disassemble the function. ++ ++set test "disass func" ++gdb_test_multiple $test $test { ++ -re "\r\nDump of assembler code for function func:(\r\n.*\r\n)End of assembler dump.\r\n$gdb_prompt $" { ++ set func $expect_out(1,string) ++ pass $test ++ } ++} ++ ++proc func_check {offset instr} { ++ global func ++ ++ # 0x0000000000000018 : stxvd2x vs43,r4,r5 ++ set patt ".*\r\n[string map {0x 0x0*} $offset] :\[ \t\]*[string map [list { } "\[ \t\]+" . {\.}] $instr]\[ \t\]*\r\n.*" ++ set test "Found $offset: $instr" ++ if [regexp -nocase -line $patt $func] { ++ pass $test ++ } else { ++ fail $test ++ } ++} ++ ++func_check 0x0 "lxvd2x vs3,r4,r5" ++func_check 0x4 "lxvd2ux vs3,r4,r5" ++func_check 0x8 "lxvd2x vs43,r4,r5" ++func_check 0xc "lxvd2ux vs43,r4,r5" ++func_check 0x10 "stxvd2x vs3,r4,r5" ++func_check 0x14 "stxvd2ux vs3,r4,r5" ++func_check 0x18 "stxvd2x vs43,r4,r5" ++func_check 0x1c "stxvd2ux vs43,r4,r5" ++func_check 0x20 "xxmrghd vs3,vs4,vs5" ++func_check 0x24 "xxmrghd vs43,vs44,vs45" ++func_check 0x28 "xxmrgld vs3,vs4,vs5" ++func_check 0x2c "xxmrgld vs43,vs44,vs45" ++func_check 0x30 "xxmrghd vs3,vs4,vs5" ++func_check 0x34 "xxmrghd vs43,vs44,vs45" ++func_check 0x38 "xxmrgld vs3,vs4,vs5" ++func_check 0x3c "xxmrgld vs43,vs44,vs45" ++func_check 0x40 "xxpermdi vs3,vs4,vs5,1" ++func_check 0x44 "xxpermdi vs43,vs44,vs45,1" ++func_check 0x48 "xxpermdi vs3,vs4,vs5,2" ++func_check 0x4c "xxpermdi vs43,vs44,vs45,2" ++func_check 0x50 "xvmovdp vs3,vs4" ++func_check 0x54 "xvmovdp vs43,vs44" ++func_check 0x58 "xvmovdp vs3,vs4" ++func_check 0x5c "xvmovdp vs43,vs44" ++func_check 0x60 "xvcpsgndp vs3,vs4,vs5" ++func_check 0x64 "xvcpsgndp vs43,vs44,vs45" ++func_check 0x68 "wait" ++func_check 0x6c "wait" ++func_check 0x70 "waitrsv" ++func_check 0x74 "waitrsv" ++func_check 0x78 "waitimpl" ++func_check 0x7c "waitimpl" ++func_check 0x80 "doze" ++func_check 0x84 "nap" ++func_check 0x88 "sleep" ++func_check 0x8c "rvwinkle" ++func_check 0x90 "prtyw r3,r4" ++func_check 0x94 "prtyd r13,r14" ++func_check 0x98 "mfcfar r10" ++func_check 0x9c "mtcfar r11" ++func_check 0xa0 "cmpb r3,r4,r5" ++func_check 0xa4 "lwzcix r10,r11,r12" ++func_check 0xa8 "dadd f16,f17,f18" ++func_check 0xac "daddq f20,f22,f24" ++func_check 0xb0 "dss 3" ++func_check 0xb4 "dssall" ++func_check 0xb8 "dst r5,r4,1" ++func_check 0xbc "dstt r8,r7,0" ++func_check 0xc0 "dstst r5,r6,3" ++func_check 0xc4 "dststt r4,r5,2" ++func_check 0xc8 "divwe r10,r11,r12" ++func_check 0xcc "divwe. r11,r12,r13" ++func_check 0xd0 "divweo r12,r13,r14" ++func_check 0xd4 "divweo. r13,r14,r15" ++func_check 0xd8 "divweu r10,r11,r12" ++func_check 0xdc "divweu. r11,r12,r13" ++func_check 0xe0 "divweuo r12,r13,r14" ++func_check 0xe4 "divweuo. r13,r14,r15" ++func_check 0xe8 "bpermd r7,r17,r27" ++func_check 0xec "popcntw r10,r20" ++func_check 0xf0 "popcntd r10,r20" ++func_check 0xf4 "ldbrx r20,r21,r22" ++func_check 0xf8 "stdbrx r20,r21,r22" ++func_check 0xfc "lfiwzx f10,0,r10" ++func_check 0x100 "lfiwzx f10,r9,r10" ++func_check 0x104 "fcfids f4,f5" ++func_check 0x108 "fcfids. f4,f5" ++func_check 0x10c "fcfidus f4,f5" ++func_check 0x110 "fcfidus. f4,f5" ++func_check 0x114 "fctiwu f4,f5" ++func_check 0x118 "fctiwu. f4,f5" ++func_check 0x11c "fctiwuz f4,f5" ++func_check 0x120 "fctiwuz. f4,f5" ++func_check 0x124 "fctidu f4,f5" ++func_check 0x128 "fctidu. f4,f5" ++func_check 0x12c "fctiduz f4,f5" ++func_check 0x130 "fctiduz. f4,f5" ++func_check 0x134 "fcfidu f4,f5" ++func_check 0x138 "fcfidu. f4,f5" ++func_check 0x13c "ftdiv cr0,f10,f11" ++func_check 0x140 "ftdiv cr7,f10,f11" ++func_check 0x144 "ftsqrt cr0,f10" ++func_check 0x148 "ftsqrt cr7,f10" ++func_check 0x14c "dcbtt r8,r9" ++func_check 0x150 "dcbtstt r8,r9" ++func_check 0x154 "dcffix f10,f12" ++func_check 0x158 "dcffix. f20,f22" ++func_check 0x15c "lbarx r10,r11,r12" ++func_check 0x160 "lbarx r10,r11,r12" ++func_check 0x164 "lbarx r10,r11,r12,1" ++func_check 0x168 "lharx r20,r21,r22" ++func_check 0x16c "lharx r20,r21,r22" ++func_check 0x170 "lharx r20,r21,r22,1" ++func_check 0x174 "stbcx. r10,r11,r12" ++func_check 0x178 "sthcx. r10,r11,r12" ++func_check 0x17c "fre f14,f15" ++func_check 0x180 "fre. f14,f15" ++func_check 0x184 "fres f14,f15" ++func_check 0x188 "fres. f14,f15" ++func_check 0x18c "frsqrte f14,f15" ++func_check 0x190 "frsqrte. f14,f15" ++func_check 0x194 "frsqrtes f14,f15" ++func_check 0x198 "frsqrtes. f14,f15" ++func_check 0x19c "isel r2,r3,r4,28" +diff --git a/gdb/testsuite/gdb.arch/powerpc-power7.s b/gdb/testsuite/gdb.arch/powerpc-power7.s +new file mode 100644 +index 0000000..98b2e79 +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/powerpc-power7.s +@@ -0,0 +1,107 @@ ++ .text ++ .globl func ++func: ++ .long 0x7c642e98 /* 0: lxvd2x vs3,r4,r5 */ ++ .long 0x7c642ed8 /* 4: lxvd2ux vs3,r4,r5 */ ++ .long 0x7d642e99 /* 8: lxvd2x vs43,r4,r5 */ ++ .long 0x7d642ed9 /* c: lxvd2ux vs43,r4,r5 */ ++ .long 0x7c642f98 /* 10: stxvd2x vs3,r4,r5 */ ++ .long 0x7c642fd8 /* 14: stxvd2ux vs3,r4,r5 */ ++ .long 0x7d642f99 /* 18: stxvd2x vs43,r4,r5 */ ++ .long 0x7d642fd9 /* 1c: stxvd2ux vs43,r4,r5 */ ++ .long 0xf0642850 /* 20: xxmrghd vs3,vs4,vs5 */ ++ .long 0xf16c6857 /* 24: xxmrghd vs43,vs44,vs45 */ ++ .long 0xf0642b50 /* 28: xxmrgld vs3,vs4,vs5 */ ++ .long 0xf16c6b57 /* 2c: xxmrgld vs43,vs44,vs45 */ ++ .long 0xf0642850 /* 30: xxmrghd vs3,vs4,vs5 */ ++ .long 0xf16c6857 /* 34: xxmrghd vs43,vs44,vs45 */ ++ .long 0xf0642b50 /* 38: xxmrgld vs3,vs4,vs5 */ ++ .long 0xf16c6b57 /* 3c: xxmrgld vs43,vs44,vs45 */ ++ .long 0xf0642950 /* 40: xxpermdi vs3,vs4,vs5,1 */ ++ .long 0xf16c6957 /* 44: xxpermdi vs43,vs44,vs45,1 */ ++ .long 0xf0642a50 /* 48: xxpermdi vs3,vs4,vs5,2 */ ++ .long 0xf16c6a57 /* 4c: xxpermdi vs43,vs44,vs45,2 */ ++ .long 0xf0642780 /* 50: xvmovdp vs3,vs4 */ ++ .long 0xf16c6787 /* 54: xvmovdp vs43,vs44 */ ++ .long 0xf0642780 /* 58: xvmovdp vs3,vs4 */ ++ .long 0xf16c6787 /* 5c: xvmovdp vs43,vs44 */ ++ .long 0xf0642f80 /* 60: xvcpsgndp vs3,vs4,vs5 */ ++ .long 0xf16c6f87 /* 64: xvcpsgndp vs43,vs44,vs45 */ ++ .long 0x7c00007c /* 68: wait */ ++ .long 0x7c00007c /* 6c: wait */ ++ .long 0x7c20007c /* 70: waitrsv */ ++ .long 0x7c20007c /* 74: waitrsv */ ++ .long 0x7c40007c /* 78: waitimpl */ ++ .long 0x7c40007c /* 7c: waitimpl */ ++ .long 0x4c000324 /* 80: doze */ ++ .long 0x4c000364 /* 84: nap */ ++ .long 0x4c0003a4 /* 88: sleep */ ++ .long 0x4c0003e4 /* 8c: rvwinkle */ ++ .long 0x7c830134 /* 90: prtyw r3,r4 */ ++ .long 0x7dcd0174 /* 94: prtyd r13,r14 */ ++ .long 0x7d5c02a6 /* 98: mfcfar r10 */ ++ .long 0x7d7c03a6 /* 9c: mtcfar r11 */ ++ .long 0x7c832bf8 /* a0: cmpb r3,r4,r5 */ ++ .long 0x7d4b662a /* a4: lwzcix r10,r11,r12 */ ++ .long 0xee119004 /* a8: dadd f16,f17,f18 */ ++ .long 0xfe96c004 /* ac: daddq f20,f22,f24 */ ++ .long 0x7c60066c /* b0: dss 3 */ ++ .long 0x7e00066c /* b4: dssall */ ++ .long 0x7c2522ac /* b8: dst r5,r4,1 */ ++ .long 0x7e083aac /* bc: dstt r8,r7,0 */ ++ .long 0x7c6532ec /* c0: dstst r5,r6,3 */ ++ .long 0x7e442aec /* c4: dststt r4,r5,2 */ ++ .long 0x7d4b6356 /* c8: divwe r10,r11,r12 */ ++ .long 0x7d6c6b57 /* cc: divwe. r11,r12,r13 */ ++ .long 0x7d8d7756 /* d0: divweo r12,r13,r14 */ ++ .long 0x7dae7f57 /* d4: divweo. r13,r14,r15 */ ++ .long 0x7d4b6316 /* d8: divweu r10,r11,r12 */ ++ .long 0x7d6c6b17 /* dc: divweu. r11,r12,r13 */ ++ .long 0x7d8d7716 /* e0: divweuo r12,r13,r14 */ ++ .long 0x7dae7f17 /* e4: divweuo. r13,r14,r15 */ ++ .long 0x7e27d9f8 /* e8: bpermd r7,r17,r27 */ ++ .long 0x7e8a02f4 /* ec: popcntw r10,r20 */ ++ .long 0x7e8a03f4 /* f0: popcntd r10,r20 */ ++ .long 0x7e95b428 /* f4: ldbrx r20,r21,r22 */ ++ .long 0x7e95b528 /* f8: stdbrx r20,r21,r22 */ ++ .long 0x7d4056ee /* fc: lfiwzx f10,0,r10 */ ++ .long 0x7d4956ee /* 100: lfiwzx f10,r9,r10 */ ++ .long 0xec802e9c /* 104: fcfids f4,f5 */ ++ .long 0xec802e9d /* 108: fcfids. f4,f5 */ ++ .long 0xec802f9c /* 10c: fcfidus f4,f5 */ ++ .long 0xec802f9d /* 110: fcfidus. f4,f5 */ ++ .long 0xfc80291c /* 114: fctiwu f4,f5 */ ++ .long 0xfc80291d /* 118: fctiwu. f4,f5 */ ++ .long 0xfc80291e /* 11c: fctiwuz f4,f5 */ ++ .long 0xfc80291f /* 120: fctiwuz. f4,f5 */ ++ .long 0xfc802f5c /* 124: fctidu f4,f5 */ ++ .long 0xfc802f5d /* 128: fctidu. f4,f5 */ ++ .long 0xfc802f5e /* 12c: fctiduz f4,f5 */ ++ .long 0xfc802f5f /* 130: fctiduz. f4,f5 */ ++ .long 0xfc802f9c /* 134: fcfidu f4,f5 */ ++ .long 0xfc802f9d /* 138: fcfidu. f4,f5 */ ++ .long 0xfc0a5900 /* 13c: ftdiv cr0,f10,f11 */ ++ .long 0xff8a5900 /* 140: ftdiv cr7,f10,f11 */ ++ .long 0xfc005140 /* 144: ftsqrt cr0,f10 */ ++ .long 0xff805140 /* 148: ftsqrt cr7,f10 */ ++ .long 0x7e084a2c /* 14c: dcbtt r8,r9 */ ++ .long 0x7e0849ec /* 150: dcbtstt r8,r9 */ ++ .long 0xed406644 /* 154: dcffix f10,f12 */ ++ .long 0xee80b645 /* 158: dcffix. f20,f22 */ ++ .long 0x7d4b6068 /* 15c: lbarx r10,r11,r12 */ ++ .long 0x7d4b6068 /* 160: lbarx r10,r11,r12 */ ++ .long 0x7d4b6069 /* 164: lbarx r10,r11,r12,1 */ ++ .long 0x7e95b0e8 /* 168: lharx r20,r21,r22 */ ++ .long 0x7e95b0e8 /* 16c: lharx r20,r21,r22 */ ++ .long 0x7e95b0e9 /* 170: lharx r20,r21,r22,1 */ ++ .long 0x7d4b656d /* 174: stbcx. r10,r11,r12 */ ++ .long 0x7d4b65ad /* 178: sthcx. r10,r11,r12 */ ++ .long 0xfdc07830 /* 17c: fre f14,f15 */ ++ .long 0xfdc07831 /* 180: fre. f14,f15 */ ++ .long 0xedc07830 /* 184: fres f14,f15 */ ++ .long 0xedc07831 /* 188: fres. f14,f15 */ ++ .long 0xfdc07834 /* 18c: frsqrte f14,f15 */ ++ .long 0xfdc07835 /* 190: frsqrte. f14,f15 */ ++ .long 0xedc07834 /* 194: frsqrtes f14,f15 */ ++ .long 0xedc07835 /* 198: frsqrtes. f14,f15 */ ++ .long 0x7c43271e /* 19c: isel r2,r3,r4,28 */ +diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S +new file mode 100644 +index 0000000..66f7a39 +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S +@@ -0,0 +1,455 @@ ++ .file "x86_64-vla-typedef.c" ++ .section .debug_abbrev,"",@progbits ++.Ldebug_abbrev0: ++ .section .debug_info,"",@progbits ++.Ldebug_info0: ++ .section .debug_line,"",@progbits ++.Ldebug_line0: ++ .text ++.Ltext0: ++.globl foo ++ .type foo, @function ++foo: ++.LFB2: ++ .file 1 "x86_64-vla-typedef.c" ++ .loc 1 22 0 ++ pushq %rbp ++.LCFI0: ++ movq %rsp, %rbp ++.LCFI1: ++ subq $64, %rsp ++.LCFI2: ++ movl %edi, -36(%rbp) ++ .loc 1 22 0 ++ movq %rsp, %rax ++ movq %rax, -48(%rbp) ++ .loc 1 23 0 ++ movl -36(%rbp), %edx ++ movslq %edx,%rax ++ subq $1, %rax ++ movq %rax, -24(%rbp) ++ .loc 1 24 0 ++ movslq %edx,%rax ++ addq $15, %rax ++ addq $15, %rax ++ shrq $4, %rax ++ salq $4, %rax ++ subq %rax, %rsp ++ movq %rsp, -56(%rbp) ++ movq -56(%rbp), %rax ++ addq $15, %rax ++ shrq $4, %rax ++ salq $4, %rax ++ movq %rax, -56(%rbp) ++ movq -56(%rbp), %rax ++ movq %rax, -16(%rbp) ++ .loc 1 27 0 ++ movl $0, -4(%rbp) ++ jmp .L2 ++.L3: ++ .loc 1 28 0 ++ movl -4(%rbp), %esi ++ movl -4(%rbp), %eax ++ movl %eax, %ecx ++ movq -16(%rbp), %rdx ++ movslq %esi,%rax ++ movb %cl, (%rdx,%rax) ++ .loc 1 27 0 ++ addl $1, -4(%rbp) ++.L2: ++ movl -4(%rbp), %eax ++ cmpl -36(%rbp), %eax ++ jl .L3 ++ .loc 1 30 0 ++ .globl break_here ++break_here: ++ movq -16(%rbp), %rax ++ movb $0, (%rax) ++ movq -48(%rbp), %rsp ++ .loc 1 31 0 ++ leave ++ ret ++.LFE2: ++ .size foo, .-foo ++ .section .debug_frame,"",@progbits ++.Lframe0: ++ .long .LECIE0-.LSCIE0 ++.LSCIE0: ++ .long 0xffffffff ++ .byte 0x1 ++ .string "" ++ .uleb128 0x1 ++ .sleb128 -8 ++ .byte 0x10 ++ .byte 0xc ++ .uleb128 0x7 ++ .uleb128 0x8 ++ .byte 0x90 ++ .uleb128 0x1 ++ .align 8 ++.LECIE0: ++.LSFDE0: ++ .long .LEFDE0-.LASFDE0 ++.LASFDE0: ++ .long .Lframe0 ++ .quad .LFB2 ++ .quad .LFE2-.LFB2 ++ .byte 0x4 ++ .long .LCFI0-.LFB2 ++ .byte 0xe ++ .uleb128 0x10 ++ .byte 0x86 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x6 ++ .align 8 ++.LEFDE0: ++ .section .eh_frame,"a",@progbits ++.Lframe1: ++ .long .LECIE1-.LSCIE1 ++.LSCIE1: ++ .long 0x0 ++ .byte 0x1 ++ .string "zR" ++ .uleb128 0x1 ++ .sleb128 -8 ++ .byte 0x10 ++ .uleb128 0x1 ++ .byte 0x3 ++ .byte 0xc ++ .uleb128 0x7 ++ .uleb128 0x8 ++ .byte 0x90 ++ .uleb128 0x1 ++ .align 8 ++.LECIE1: ++.LSFDE1: ++ .long .LEFDE1-.LASFDE1 ++.LASFDE1: ++ .long .LASFDE1-.Lframe1 ++ .long .LFB2 ++ .long .LFE2-.LFB2 ++ .uleb128 0x0 ++ .byte 0x4 ++ .long .LCFI0-.LFB2 ++ .byte 0xe ++ .uleb128 0x10 ++ .byte 0x86 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x6 ++ .align 8 ++.LEFDE1: ++ .text ++.Letext0: ++ .section .debug_loc,"",@progbits ++.Ldebug_loc0: ++.LLST0: ++ .quad .LFB2-.Ltext0 ++ .quad .LCFI0-.Ltext0 ++ .value 0x2 ++ .byte 0x77 ++ .sleb128 8 ++ .quad .LCFI0-.Ltext0 ++ .quad .LCFI1-.Ltext0 ++ .value 0x2 ++ .byte 0x77 ++ .sleb128 16 ++ .quad .LCFI1-.Ltext0 ++ .quad .LFE2-.Ltext0 ++ .value 0x2 ++ .byte 0x76 ++ .sleb128 16 ++ .quad 0x0 ++ .quad 0x0 ++ .section .debug_info ++ .long .Ldebug_end - .Ldebug_start ++.Ldebug_start: ++ .value 0x2 ++ .long .Ldebug_abbrev0 ++ .byte 0x8 ++ .uleb128 0x1 ++ .long .LASF2 ++ .byte 0x1 ++ .long .LASF3 ++ .long .LASF4 ++ .quad .Ltext0 ++ .quad .Letext0 ++ .long .Ldebug_line0 ++ .uleb128 0x2 ++ .byte 0x1 ++ .string "foo" ++ .byte 0x1 ++ .byte 0x16 ++ .byte 0x1 ++ .quad .LFB2 ++ .quad .LFE2 ++ .long .LLST0 ++ .long 0x83 ++ .uleb128 0x3 ++ .long .LASF5 ++ .byte 0x1 ++ .byte 0x15 ++ .long 0x83 ++ .byte 0x2 ++ .byte 0x91 ++ .sleb128 -52 ++.Ltag_typedef: ++ .uleb128 0x4 ++ .long .LASF6 ++ .byte 0x1 ++ .byte 0x17 ++ .long .Ltag_array_type - .debug_info ++ .uleb128 0x5 /* Abbrev Number: 5 (DW_TAG_variable) */ ++ .long .LASF0 ++ .byte 0x1 ++ .byte 0x18 ++#if 1 ++ .long .Ltag_typedef - .debug_info ++#else ++ /* Debugging only: Skip the typedef indirection. */ ++ .long .Ltag_array_type - .debug_info ++#endif ++ /* DW_AT_location: DW_FORM_block1: start */ ++ .byte 0x3 ++ .byte 0x91 ++ .sleb128 -32 ++#if 0 ++ .byte 0x6 /* DW_OP_deref */ ++#else ++ .byte 0x96 /* DW_OP_nop */ ++#endif ++ /* DW_AT_location: DW_FORM_block1: end */ ++ .uleb128 0x6 ++ .string "i" ++ .byte 0x1 ++ .byte 0x19 ++ .long 0x83 ++ .byte 0x2 ++ .byte 0x91 ++ .sleb128 -20 ++ .byte 0x0 ++ .uleb128 0x7 ++ .byte 0x4 ++ .byte 0x5 ++ .string "int" ++.Ltag_array_type: ++ .uleb128 0x8 /* Abbrev Number: 8 (DW_TAG_array_type) */ ++ .long 0xa0 + (2f - 1f) /* DW_AT_type: DW_FORM_ref4 */ ++ .long 0x9d + (2f - 1f) /* DW_AT_sibling: DW_FORM_ref4 */ ++1: /* DW_AT_data_location: DW_FORM_block1: start */ ++ .byte 2f - 3f /* length */ ++3: ++ .byte 0x97 /* DW_OP_push_object_address */ ++ .byte 0x6 /* DW_OP_deref */ ++2: /* DW_AT_data_location: DW_FORM_block1: end */ ++ .uleb128 0x9 ++ .long 0x9d + (2b - 1b) /* DW_AT_type: DW_FORM_ref4 */ ++ .byte 0x3 ++ .byte 0x91 ++ .sleb128 -40 ++ .byte 0x6 ++ .byte 0x0 ++ .uleb128 0xa ++ .byte 0x8 ++ .byte 0x7 ++ .uleb128 0xb ++ .byte 0x1 ++ .byte 0x6 ++ .long .LASF1 ++ .byte 0x0 ++.Ldebug_end: ++ .section .debug_abbrev ++ .uleb128 0x1 ++ .uleb128 0x11 ++ .byte 0x1 ++ .uleb128 0x25 ++ .uleb128 0xe ++ .uleb128 0x13 ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x1b ++ .uleb128 0xe ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x10 ++ .uleb128 0x6 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x2 ++ .uleb128 0x2e ++ .byte 0x1 ++ .uleb128 0x3f ++ .uleb128 0xc ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x27 ++ .uleb128 0xc ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x40 ++ .uleb128 0x6 ++ .uleb128 0x1 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x5 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x4 ++ .uleb128 0x16 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x5 ++ .uleb128 0x34 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x6 ++ .uleb128 0x34 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x7 ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x8 /* Abbrev Number: 8 (DW_TAG_array_type) */ ++ .uleb128 0x1 ++ .byte 0x1 ++ .uleb128 0x49 /* DW_AT_type */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x1 /* DW_AT_sibling */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x50 /* DW_AT_data_location */ ++ .uleb128 0xa /* DW_FORM_block1 */ ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x9 ++ .uleb128 0x21 ++ .byte 0x0 ++ .uleb128 0x49 /* DW_AT_type */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x2f ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0xa ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0xe ++ .byte 0x0 ++ .byte 0x0 ++ .byte 0x0 ++ .section .debug_pubnames,"",@progbits ++ .long 0x16 ++ .value 0x2 ++ .long .Ldebug_info0 ++ .long 0xa8 ++ .long 0x2d ++ .string "foo" ++ .long 0x0 ++ .section .debug_aranges,"",@progbits ++ .long 0x2c ++ .value 0x2 ++ .long .Ldebug_info0 ++ .byte 0x8 ++ .byte 0x0 ++ .value 0x0 ++ .value 0x0 ++ .quad .Ltext0 ++ .quad .Letext0-.Ltext0 ++ .quad 0x0 ++ .quad 0x0 ++ .section .debug_str,"MS",@progbits,1 ++.LASF0: ++ .string "array" ++.LASF5: ++ .string "size" ++.LASF3: ++ .string "x86_64-vla-typedef.c" ++.LASF6: ++ .string "array_t" ++.LASF1: ++ .string "char" ++.LASF4: ++ .string "gdb.arch" ++.LASF2: ++ .string "GNU C 4.3.2 20081105 (Red Hat 4.3.2-7)" ++ .ident "GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)" ++ .section .note.GNU-stack,"",@progbits +diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c +new file mode 100644 +index 0000000..b809c4e +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c +@@ -0,0 +1,43 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . */ ++ ++#if 0 ++ ++void ++foo (int size) ++{ ++ typedef char array_t[size]; ++ array_t array; ++ int i; ++ ++ for (i = 0; i < size; i++) ++ array[i] = i; ++ ++ array[0] = 0; /* break-here */ ++} ++ ++#else ++ ++int ++main (void) ++{ ++ foo (26); ++ foo (78); ++ return 0; ++} ++ ++#endif +diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp +new file mode 100644 +index 0000000..534120a +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp +@@ -0,0 +1,64 @@ ++# Copyright 2009 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 3 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, see . ++ ++# Test DW_AT_data_location accessed through DW_TAG_typedef intermediate. ++ ++if ![istarget "x86_64-*-*"] then { ++ verbose "Skipping over gdb.arch/x86_64-vla-typedef.exp test made only for x86_64." ++ return ++} ++ ++set testfile x86_64-vla-typedef ++set srcasmfile ${testfile}-foo.S ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++set binobjfile ${objdir}/${subdir}/${testfile}-foo.o ++if { [gdb_compile "${srcdir}/${subdir}/${srcasmfile}" "${binobjfile}" object {}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${binobjfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto_main] { ++ untested x86_64-vla-typedef ++ return -1 ++} ++ ++gdb_breakpoint "break_here" ++ ++gdb_continue_to_breakpoint "break_here" ++ ++gdb_test "whatis array" "type = array_t" "first: whatis array" ++ ++gdb_test "ptype array" "type = char \\\[26\\\]" "first: ptype array" ++ ++gdb_test "p array\[1\]" "\\$\[0-9\] = 1 '\\\\1'" ++gdb_test "p array\[2\]" "\\$\[0-9\] = 2 '\\\\2'" ++gdb_test "p array\[3\]" "\\$\[0-9\] = 3 '\\\\3'" ++gdb_test "p array\[4\]" "\\$\[0-9\] = 4 '\\\\4'" ++ ++gdb_continue_to_breakpoint "break_here" ++ ++gdb_test "whatis array" "type = array_t" "second: whatis array" ++ ++gdb_test "ptype array" "type = char \\\[78\\\]" "second: ptype array" +diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in +index 9f382db..12db521 100644 +--- a/gdb/testsuite/gdb.base/Makefile.in ++++ b/gdb/testsuite/gdb.base/Makefile.in +@@ -12,7 +12,7 @@ EXECUTABLES = all-types annota1 bitfields break \ + scope section_command setshow setvar shmain sigall signals \ + solib solib_sl so-impl-ld so-indr-cl \ + step-line step-test structs structs2 \ +- twice-tmp varargs vforked-prog watchpoint whatis ++ twice-tmp varargs vforked-prog watchpoint whatis catch-syscall + + MISCELLANEOUS = coremmap.data ../foobar.baz \ + shr1.sl shr2.sl solib_sl.sl solib1.sl solib2.sl +diff --git a/gdb/testsuite/gdb.base/call-rt-st.exp b/gdb/testsuite/gdb.base/call-rt-st.exp +index 3359c70..f73dd7f 100644 +--- a/gdb/testsuite/gdb.base/call-rt-st.exp ++++ b/gdb/testsuite/gdb.base/call-rt-st.exp +@@ -186,7 +186,7 @@ if {![gdb_skip_float_test "print print_two_floats(*f3)"] && \ + + if ![gdb_skip_stdio_test "print print_bit_flags_char(*cflags)"] { + print_struct_call "print_bit_flags_char(*cflags)" \ +- ".*alpha\[ \r\n\]+gamma\[ \r\n\]+epsilon\[ \r\n\]+.\[0-9\]+ = \\{alpha = 1 '\\\\001', beta = 0 '\\\\0', gamma = 1 '\\\\001', delta = 0 '\\\\0', epsilon = 1 '\\\\001', omega = 0 '\\\\0'\\}" ++ ".*alpha\[ \r\n\]+gamma\[ \r\n\]+epsilon\[ \r\n\]+.\[0-9\]+ = \\{alpha = 1 '\\\\1', beta = 0 '\\\\0', gamma = 1 '\\\\1', delta = 0 '\\\\0', epsilon = 1 '\\\\1', omega = 0 '\\\\0'\\}" + } + + if ![gdb_skip_stdio_test "print print_bit_flags_short(*sflags)"] { +diff --git a/gdb/testsuite/gdb.base/callfuncs.exp b/gdb/testsuite/gdb.base/callfuncs.exp +index 6d8aa45..be6a872 100644 +--- a/gdb/testsuite/gdb.base/callfuncs.exp ++++ b/gdb/testsuite/gdb.base/callfuncs.exp +@@ -437,7 +437,7 @@ gdb_test "print t_small_values(1,3,5,7,9,11,13,15,17,19)" \ + "The program being debugged stopped while.*" \ + "stop at nested call level 4" + gdb_test "backtrace" \ +- "\#0 t_small_values \\(arg1=1 '.001', arg2=3, arg3=5, arg4=7 '.a', arg5=9, arg6=11 '.v', arg7=13, arg8=15, arg9=17, arg10=19\\).*\#2 sum10 \\(i0=2, i1=4, i2=6, i3=8, i4=10, i5=12, i6=14, i7=16, i8=18, i9=20\\).*\#3 .*\#4 add \\(a=4, b=5\\).*\#5 .*\#6 add \\(a=2, b=3\\).*\#7 .*\#8 main.*" \ ++ "\#0 t_small_values \\(arg1=1 '.1', arg2=3, arg3=5, arg4=7 '.a', arg5=9, arg6=11 '.v', arg7=13, arg8=15, arg9=17, arg10=19\\).*\#2 sum10 \\(i0=2, i1=4, i2=6, i3=8, i4=10, i5=12, i6=14, i7=16, i8=18, i9=20\\).*\#3 .*\#4 add \\(a=4, b=5\\).*\#5 .*\#6 add \\(a=2, b=3\\).*\#7 .*\#8 main.*" \ + "backtrace at nested call level 4" + gdb_test "finish" "Value returned is .* = 100" \ + "Finish from nested call level 4" +diff --git a/gdb/testsuite/gdb.base/catch-syscall.c b/gdb/testsuite/gdb.base/catch-syscall.c +new file mode 100644 +index 0000000..64850de +--- /dev/null ++++ b/gdb/testsuite/gdb.base/catch-syscall.c +@@ -0,0 +1,25 @@ ++/* This file is used to test the 'catch syscall' feature on GDB. ++ ++ Please, if you are going to edit this file DO NOT change the syscalls ++ being called (nor the order of them). If you really must do this, then ++ take a look at catch-syscall.exp and modify there too. ++ ++ Written by Sergio Durigan Junior ++ September, 2008 */ ++ ++#include ++#include ++#include ++ ++int ++main (void) ++{ ++ /* A close() with a wrong argument. We are only ++ interested in the syscall. */ ++ close (-1); ++ ++ chroot ("."); ++ ++ /* The last syscall. Do not change this. */ ++ _exit (0); ++} +diff --git a/gdb/testsuite/gdb.base/catch-syscall.exp b/gdb/testsuite/gdb.base/catch-syscall.exp +new file mode 100644 +index 0000000..a9f6937 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/catch-syscall.exp +@@ -0,0 +1,386 @@ ++# Copyright 1997, 1999, 2007, 2008 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 3 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, see . ++ ++ ++# This program tests the 'catch syscall' functionality. ++# ++# It was written by Sergio Durigan Junior ++# on September/2008. ++ ++if { [is_remote target] || ![isnative] } then { ++ continue ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++global srcfile ++set testfile "catch-syscall" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++# All (but the last) syscalls from the example code ++# They are ordered according to the file, so do not change this. ++set all_syscalls { "close" "chroot" } ++# The last syscall (exit()) does not return, so ++# we cannot expect the catchpoint to be triggered ++# twice. It is a special case. ++set last_syscall "exit_group" ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested catch-syscall.exp ++ return -1 ++} ++ ++# Until "catch syscall" is implemented on other targets... ++if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then { ++ continue ++} ++ ++# This shall be updated whenever 'catch syscall' is implemented ++# on some architecture. ++#if { ![istarget "x86_64-*-linux*"] && ![istarget "i\[34567\]86-*-linux*"] ++if { ![istarget "i\[34567\]86-*-linux*"] ++ && ![istarget "powerpc-*-linux*"] && ![istarget "powerpc64-*-linux*"] } { ++ continue ++} ++ ++# Internal procedure used to check if, before any syscall is caught, ++# the command 'info breakpoints' correctly lists the catchpoints AND ++# says that nothing was caught yet. ++proc check_init_info_breakpoints {} { ++ global gdb_prompt ++ ++ # Verifying that the catchpoint appears in the 'info breakpoints' ++ # command, but with "". ++ set thistest "catch syscall appears in 'info breakpoints'" ++ gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall \"\".*" $thistest ++} ++ ++# This procedure checks if, after a syscall catchpoint is hit, the ++# command 'info breakpoints' correctly lists the syscall name. ++proc check_info_breakpoints { syscall } { ++ global gdb_prompt ++ ++ set thistest "syscall $syscall appears in 'info breakpoints'" ++ gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall (.)?${syscall}(.)?.*" $thistest ++} ++ ++# This procedure checks if there was a call to a syscall. ++proc check_call_to_syscall { syscall } { ++ global gdb_prompt ++ ++ set thistest "program has called $syscall" ++ gdb_test "continue" "Catchpoint .*(call to syscall .?${syscall}.?).*" $thistest ++ ++ # Checking if the syscall is reported to be caught in ++ # 'info breakpoints'. ++ check_info_breakpoints "$syscall" ++} ++ ++# This procedure checks if the syscall returned. ++proc check_return_from_syscall { syscall } { ++ global gdb_prompt ++ ++ set thistest "syscall $syscall has returned" ++ gdb_test "continue" "Catchpoint .*(returned from syscall (.)?${syscall}(.)?).*" $thistest ++ ++ # Checking if the syscall is reported to be caught in ++ # 'info breakpoints'. ++ check_info_breakpoints "$syscall" ++} ++ ++# Internal procedure that performs two 'continue' commands and checks if ++# a syscall call AND return occur. ++proc check_continue { syscall } { ++ global gdb_prompt ++ ++ # Testing if the 'continue' stops at the ++ # specified syscall_name. If it does, then it should ++ # first print that the infeior has called the syscall, ++ # and after print that the syscall has returned. ++ ++ # Testing if the inferiorr has called the syscall. ++ check_call_to_syscall $syscall ++ # And now, that the syscall has returned. ++ check_return_from_syscall $syscall ++} ++ ++# Inserts a syscall catchpoint with an argument. ++proc insert_catch_syscall_with_arg { syscall } { ++ global gdb_prompt ++ ++ # Trying to set the syscall ++ set thistest "catch syscall with arguments ($syscall)" ++ gdb_test "catch syscall $syscall" "Catchpoint .*(syscall\[(\]s\[)\] (.)?${syscall}(.)?).*" $thistest ++} ++ ++proc check_for_program_end {} { ++ global gdb_prompt ++ ++ # Deleting the catchpoints ++ delete_breakpoints ++ ++ set thistest "successful program end" ++ gdb_test "continue" "Program exited normally.*" $thistest ++ ++} ++ ++proc test_catch_syscall_without_args {} { ++ global gdb_prompt all_syscalls last_syscall ++ ++ # Trying to set the syscall ++ set thistest "setting catch syscall without arguments" ++ gdb_test "catch syscall" "Catchpoint .*(syscall).*" $thistest ++ ++ check_init_info_breakpoints ++ ++ # We have to check every syscall ++ foreach name $all_syscalls { ++ check_continue $name ++ } ++ ++ # At last but not least, we check if the inferior ++ # has called the last (exit) syscall. ++ check_call_to_syscall $last_syscall ++ ++ # Now let's see if the inferior correctly finishes. ++ check_for_program_end ++} ++ ++proc test_catch_syscall_with_args {} { ++ global gdb_prompt ++ set syscall_name "close" ++ ++ insert_catch_syscall_with_arg $syscall_name ++ check_init_info_breakpoints ++ ++ # Can we continue until we catch the syscall? ++ check_continue $syscall_name ++ ++ # Now let's see if the inferior correctly finishes. ++ check_for_program_end ++} ++ ++proc test_catch_syscall_with_wrong_args {} { ++ global gdb_prompt ++ # mlock is not called from the source ++ set syscall_name "mlock" ++ ++ insert_catch_syscall_with_arg $syscall_name ++ check_init_info_breakpoints ++ ++ # Now, we must verify if the program stops with a continue. ++ # If it doesn't, everything is right (since we don't have ++ # a syscall named "mlock" in it). Otherwise, this is a failure. ++ set thistest "catch syscall with unused syscall ($syscall_name)" ++ gdb_test "continue" "Program exited normally.*" $thistest ++} ++ ++proc test_catch_syscall_restarting_inferior {} { ++ global gdb_prompt ++ set syscall_name "chroot" ++ ++ insert_catch_syscall_with_arg $syscall_name ++ check_init_info_breakpoints ++ ++ # Let's first reach the call of the syscall. ++ check_call_to_syscall $syscall_name ++ ++ # Now, restart the program ++ rerun_to_main ++ ++ # And check for call/return ++ check_continue $syscall_name ++ ++ # Can we finish? ++ check_for_program_end ++} ++ ++proc do_syscall_tests {} { ++ global gdb_prompt srcdir ++ ++ # First, we need to set GDB datadir. ++ send_gdb "maintenance set gdb_datadir $srcdir/..\n" ++ gdb_expect 10 { ++ -re "$gdb_prompt $" { ++ verbose "Setting GDB datadir to $srcdir/..." 2 ++ } ++ timeout { ++ error "Couldn't set GDB datadir." ++ } ++ } ++ ++ # Verify that the 'catch syscall' help is available ++ set thistest "help catch syscall" ++ gdb_test "help catch syscall" "Catch system calls.*" $thistest ++ ++ # Try to set a catchpoint to a nonsense syscall ++ set thistest "catch syscall to a nonsense syscall is prohibited" ++ gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .*" $thistest ++ ++ # Testing the 'catch syscall' command without arguments. ++ # This test should catch any syscalls. ++ if [runto_main] then { test_catch_syscall_without_args } ++ ++ # Testing the 'catch syscall' command with arguments. ++ # This test should only catch the specified syscall. ++ if [runto_main] then { test_catch_syscall_with_args } ++ ++ # Testing the 'catch syscall' command with WRONG arguments. ++ # This test should not trigger any catchpoints. ++ if [runto_main] then { test_catch_syscall_with_wrong_args } ++ ++ # Testing the 'catch' syscall command during a restart of ++ # the inferior. ++ if [runto_main] then { test_catch_syscall_restarting_inferior } ++} ++ ++proc test_catch_syscall_fail_noxml {} { ++ global gdb_prompt ++ ++ # Sanitizing. ++ delete_breakpoints ++ ++ # Testing to see if we receive a warning when calling "catch syscall" ++ # without XML support. ++ set thistest "Catch syscall displays a warning when there is no XML support" ++ gdb_test "catch syscall" "warning: Could not open .*warning: Could not load the syscall XML file .*GDB will not be able to display syscall names.*Catchpoint .*(syscall).*" $thistest ++ ++ # Since the catchpoint was set, we must check if it's present at ++ # "info breakpoints" ++ check_init_info_breakpoints ++ ++ # Sanitizing. ++ delete_breakpoints ++} ++ ++proc test_catch_syscall_without_args_noxml {} { ++ # We will need the syscall names even not using it ++ # because we need to know know many syscalls are in ++ # the example file. ++ global gdb_prompt all_syscalls last_syscall ++ ++ delete_breakpoints ++ ++ set thistest "Catch syscall without arguments and without XML support" ++ gdb_test "catch syscall" "Catchpoint .*(syscall).*" ++ ++ # Now, we should be able to set a catchpoint, ++ # and GDB shall not display the warning anymore. ++ foreach name $all_syscalls { ++ # Unfortunately, we don't know the syscall number ++ # that will be caught because this information is ++ # arch-dependent. Thus, we try to catch anything ++ # similar to a number. ++ check_continue "\[0-9\]*" ++ } ++ ++ # At last but not least, we check if the inferior ++ # has called the last (exit) syscall. ++ check_call_to_syscall "\[0-9\]*" ++ ++ delete_breakpoints ++} ++ ++proc test_catch_syscall_with_args_noxml {} { ++ global gdb_prompt ++ ++ # The number of the "close" syscall. This is our ++ # options for a "long-estabilished" syscall in all ++ # Linux architectures, but unfortunately x86_64 and ++ # a few other platforms don't "follow the convention". ++ # Because of this, we need this ugly check :-(. ++ set close_number "" ++ if { [istarget "x86_64-*-linux*"] } { ++ set close_number "3" ++ } else { ++ set close_number "6" ++ } ++ ++ delete_breakpoints ++ ++ insert_catch_syscall_with_arg $close_number ++ check_init_info_breakpoints ++ ++ check_continue $close_number ++ ++ delete_breakpoints ++} ++ ++proc test_catch_syscall_with_wrong_args_noxml {} { ++ global gdb_prompt ++ ++ delete_breakpoints ++ ++ # Even without XML support, GDB should not accept unknown ++ # syscall names for the catchpoint. ++ set thistest "Catch a nonsense syscall without XML support" ++ gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .nonsense_syscall.*" $thistest ++ ++ delete_breakpoints ++} ++ ++proc do_syscall_tests_without_xml {} { ++ global gdb_prompt srcdir ++ ++ # In this case, we don't need to set GDB's datadir because ++ # we want GDB to display only numbers, not names. So, let's ++ # begin with the tests. ++ ++ # The first test is to see if GDB displays a warning when we ++ # try to catch syscalls without the XML support. ++ test_catch_syscall_fail_noxml ++ ++ # Now, let's test if we can catch syscalls without XML support. ++ # We should succeed, but GDB is not supposed to print syscall names. ++ if [runto_main] then { test_catch_syscall_without_args_noxml } ++ ++ # The only valid argument "catch syscall" should accept is the ++ # syscall number, and not the name (since it can't translate a ++ # name to a number). ++ # ++ # It's worth mentioning that we only try to catch the syscall ++ # close(). This is because the syscall number is an arch-dependent ++ # information, so we can't assume that we know every syscall number ++ # in this system. Therefore, we have decided to use a "long-estabilished" ++ # system call, and close() just sounded the right choice :-). ++ if [runto_main] then { test_catch_syscall_with_args_noxml } ++ ++ # Now, we'll try to provide a syscall name (valid or not) to the command, ++ # and expect it to fail. ++ if [runto_main] then { test_catch_syscall_with_wrong_args_noxml } ++} ++ ++# Start with a fresh gdb ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Execute the tests, using XML support ++do_syscall_tests ++ ++# Restart gdb ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Execute the tests, without XML support. In this case, GDB will ++# only display syscall numbers, and not syscall names. ++do_syscall_tests_without_xml +diff --git a/gdb/testsuite/gdb.base/charset.c b/gdb/testsuite/gdb.base/charset.c +index b640702..55a50ce 100644 +--- a/gdb/testsuite/gdb.base/charset.c ++++ b/gdb/testsuite/gdb.base/charset.c +@@ -20,11 +20,6 @@ + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@gnu.org */ + +-#include +-#include +-#include +- +- + /* X_string is a null-terminated string in the X charset whose + elements are as follows. X should be the name the `set charset' + command uses for the character set, in lower-case, with any +@@ -54,6 +49,21 @@ char iso_8859_1_string[NUM_CHARS]; + char ebcdic_us_string[NUM_CHARS]; + char ibm1047_string[NUM_CHARS]; + ++/* We make a phony wchar_t and then pretend that this platform uses ++ UCS-4 (or UCS-2, depending on the size -- same difference for the ++ purposes of this test). */ ++typedef unsigned int wchar_t; ++wchar_t ucs_4_string[NUM_CHARS]; ++ ++/* We also define a couple phony types for testing the u'' and U'' ++ support. It is ok if these have the wrong size on some platforms ++ -- the test case will skip the tests in that case. */ ++typedef unsigned short char16_t; ++typedef unsigned int char32_t; ++ ++/* Make sure to use the typedefs. */ ++char16_t uvar; ++char32_t Uvar; + + void + init_string (char string[], +@@ -62,7 +72,10 @@ init_string (char string[], + char line_feed, char carriage_return, char horizontal_tab, + char vertical_tab, char cent, char misc_ctrl) + { +- memset (string, x, NUM_CHARS); ++ int i; ++ ++ for (i = 0; i < NUM_CHARS; ++i) ++ string[i] = x; + string[0] = alert; + string[1] = backspace; + string[2] = form_feed; +@@ -85,13 +98,21 @@ fill_run (char string[], int start, int len, int first) + } + + ++void ++init_ucs4 () ++{ ++ int i; ++ ++ for (i = 0; i < NUM_CHARS; ++i) ++ ucs_4_string[i] = iso_8859_1_string[i] & 0xff; ++} ++ + int main () + { + #ifdef usestubs + set_debug_traps(); + breakpoint(); + #endif +- (void) malloc (1); + /* Initialize ascii_string. */ + init_string (ascii_string, + 120, +@@ -146,5 +167,7 @@ int main () + /* The digits, at least, are contiguous. */ + fill_run (ibm1047_string, 59, 10, 240); + +- puts ("All set!"); /* all strings initialized */ ++ init_ucs4 (); ++ ++ return 0; /* all strings initialized */ + } +diff --git a/gdb/testsuite/gdb.base/charset.exp b/gdb/testsuite/gdb.base/charset.exp +index fa26521..93f66c0 100644 +--- a/gdb/testsuite/gdb.base/charset.exp ++++ b/gdb/testsuite/gdb.base/charset.exp +@@ -47,13 +47,7 @@ proc parse_show_charset_output {testname} { + global gdb_prompt + + gdb_expect { +- -re "The current host and target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" { +- set host_charset $expect_out(1,string) +- set target_charset $expect_out(1,string) +- set retlist [list $host_charset $target_charset] +- pass $testname +- } +- -re "The current host character set is `(.*)'\\.\[\r\n\]+The current target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" { ++ -re "The host character set is \"(.*)\"\\.\[\r\n\]+The target character set is \"(.*)\"\\.\[\r\n\]+The target wide character set is \"(.*)\"\\.\[\r\n\]+$gdb_prompt $" { + set host_charset $expect_out(1,string) + set target_charset $expect_out(2,string) + set retlist [list $host_charset $target_charset] +@@ -81,79 +75,35 @@ proc parse_show_charset_output {testname} { + } + + +-# Try the various `show charset' commands. These are all aliases of each +-# other; `show target-charset' and `show host-charset' actually print +-# both the host and target charsets. ++# Try the various `show charset' commands. + + send_gdb "show charset\n" + set show_charset [parse_show_charset_output "show charset"] + + send_gdb "show target-charset\n" +-set show_target_charset [parse_show_charset_output "show target-charset"] ++set show_target_charset \ ++ [lindex [parse_show_charset_output "show target-charset"] 0] + +-if {[lsearch $show_charset $show_target_charset] >= 0} { ++if {[lsearch -exact $show_charset $show_target_charset] >= 0} { + pass "check `show target-charset' against `show charset'" + } else { + fail "check `show target-charset' against `show charset'" + } + + send_gdb "show host-charset\n" +-set show_host_charset [parse_show_charset_output "show host-charset"] ++set show_host_charset \ ++ [lindex [parse_show_charset_output "show host-charset"] 0] + +-if {[lsearch $show_charset $show_host_charset] >= 0} { ++if {[lsearch -exact $show_charset $show_host_charset] >= 0} { + pass "check `show host-charset' against `show charset'" + } else { + fail "check `show host-charset' against `show charset'" + } + +- +-# Get the list of supported (host) charsets as possible completions. +-send_gdb "set charset \t\t" +- +-# Check that we can at least use ASCII as a host character set. +-sleep 1 +-gdb_expect { +- -re "^set charset .*\r\nASCII.*\r\n$gdb_prompt set charset " { +- # We got the output that we wanted, including ASCII as possible +- # charset. Send a newline to get us back to the prompt. This will +- # also generate an error message. Let's not check here that the error +- # message makes sense, we do that below, as a separate testcase. +- send_gdb "\n" +- gdb_expect { +- -re ".*Requires an argument.*$gdb_prompt $" { +- pass "get valid character sets" +- } +- -re ".*$gdb_prompt $" { +- send_gdb "\n" +- gdb_expect { +- -re ".*$gdb_prompt $" { +- fail "get valid character sets" +- } +- } +- } +- timeout { +- fail "(timeout) get valid character sets" +- } +- } +- } +- -re ".*$gdb_prompt $" { +- # We got some output that ended with a regular prompt +- fail "get valid character sets" +- } +- -re ".*$gdb_prompt set charset.*$" { +- # We got some other output, send a cntrl-c to gdb to get us back +- # to the prompt. +- send_gdb "\003" +- fail "get valid character sets" +- } +- timeout { +- fail "get valid character sets (timeout)" +- } +-} +- + # Try a malformed `set charset'. ++# Also check that we can at least use ASCII as a host character set. + gdb_test "set charset" \ +- "Requires an argument. Valid arguments are.*" \ ++ "Requires an argument. Valid arguments are.* ASCII,.*" \ + "try malformed `set charset'" + + # Try using `set host-charset' on an invalid character set. +@@ -244,8 +194,10 @@ gdb_expect { + } + } + +-# Make sure that GDB supports every host/target charset combination. +-foreach host_charset [all_charset_names] { ++# We don't want to test all the charset names here, since that would ++# be too many combinations. We we pick a subset. ++set charset_subset {ASCII ISO-8859-1 EBCDIC-US IBM1047} ++foreach host_charset $charset_subset { + if {[valid_host_charset $host_charset]} { + + set testname "try `set host-charset $host_charset'" +@@ -279,7 +231,7 @@ foreach host_charset [all_charset_names] { + + # Now try setting every possible target character set, + # given that host charset. +- foreach target_charset [all_charset_names] { ++ foreach target_charset $charset_subset { + set testname "try `set target-charset $target_charset'" + send_gdb "set target-charset $target_charset\n" + gdb_expect { +@@ -404,23 +356,42 @@ gdb_expect { + } + + ++# We only try the wide character tests on machines where the wchar_t ++# typedef in the test case has the right size. ++set wchar_size [get_sizeof wchar_t 99] ++set wchar_ok 0 ++if {$wchar_size == 2} { ++ lappend charset_subset UCS-2 ++ set wchar_ok 1 ++} elseif {$wchar_size == 4} { ++ lappend charset_subset UCS-4 ++ set wchar_ok 1 ++} ++ + gdb_test "set host-charset ASCII" "" +-foreach target_charset [all_charset_names] { +- send_gdb "set target-charset $target_charset\n" ++foreach target_charset $charset_subset { ++ if {$target_charset == "UCS-4" || $target_charset == "UCS-2"} { ++ set param target-wide-charset ++ set L L ++ } else { ++ set param target-charset ++ set L "" ++ } ++ send_gdb "set $param $target_charset\n" + gdb_expect { + -re "$gdb_prompt $" { +- pass "set target-charset $target_charset" ++ pass "set $param $target_charset" + } + timeout { +- fail "set target-charset $target_charset (timeout)" ++ fail "set $param $target_charset (timeout)" + } + } + + # Try printing the null character. There seems to be a bug in + # gdb_test that requires us to use gdb_expect here. +- send_gdb "print '\\0'\n" ++ send_gdb "print $L'\\0'\n" + gdb_expect { +- -re "\\\$${decimal} = 0 '\\\\0'\[\r\n\]+$gdb_prompt $" { ++ -re "\\\$${decimal} = 0 $L'\\\\0'\[\r\n\]+$gdb_prompt $" { + pass "print the null character in ${target_charset}" + } + -re "$gdb_prompt $" { +@@ -435,8 +406,14 @@ foreach target_charset [all_charset_names] { + # a string in $target_charset. The variable's name is the + # character set's name, in lower-case, with all non-identifier + # characters replaced with '_', with "_string" stuck on the end. +- set var_name [string tolower "${target_charset}_string"] +- regsub -all -- "\[^a-z0-9_\]" $var_name "_" var_name ++ if {$target_charset == "UCS-2"} { ++ # We still use the ucs_4_string variable -- but the size is ++ # correct for UCS-2. ++ set var_name ucs_4_string ++ } else { ++ set var_name [string tolower "${target_charset}_string"] ++ regsub -all -- "\[^a-z0-9_\]" $var_name "_" var_name ++ } + + # Compute a regexp matching the results we expect. This is static, + # but it's easier than writing it out. +@@ -444,12 +421,12 @@ foreach target_charset [all_charset_names] { + set uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + set lowercase "abcdefghijklmnopqrstuvwxyz" + set digits "0123456789" +- set octal_escape "\\\\\[0-9\]\[0-9\]\[0-9\]" ++ set octal_escape "\\\\\[0-9\]+" + + send_gdb "print $var_name\n" + # ${escapes}${uppercase}${lowercase}${digits}${octal}${octal} + gdb_expect { +- -re ".* = \"(\\\\a|x)(\\\\b|x)(\\\\f|x)(\\\\n|x)(\\\\r|x)(\\\\t|x)(\\\\v|x)${uppercase}${lowercase}${digits}(\\\\\[0-9\]\[0-9\]\[0-9\]|x)(\\\\\[0-9\]\[0-9\]\[0-9\]|x).*\"\[\r\n\]+$gdb_prompt $" { ++ -re ".* = $L\"(\\\\a|x)(\\\\b|x)(\\\\f|x)(\\\\n|x)(\\\\r|x)(\\\\t|x)(\\\\v|x)${uppercase}${lowercase}${digits}(${octal_escape}|x)+\"\[\r\n\]+$gdb_prompt $" { + pass "print string in $target_charset" + } + -re "$gdb_prompt $" { +@@ -461,22 +438,22 @@ foreach target_charset [all_charset_names] { + } + + # Try entering a character literal, and see if it comes back unchanged. +- gdb_test "print 'A'" \ +- " = \[0-9-\]+ 'A'" \ ++ gdb_test "print $L'A'" \ ++ " = \[0-9-\]+ $L'A'" \ + "parse character literal in ${target_charset}" + + # Check that the character literal was encoded correctly. +- gdb_test "print 'A' == $var_name\[7\]" \ ++ gdb_test "print $L'A' == $var_name\[7\]" \ + " = 1" \ + "check value of parsed character literal in ${target_charset}" + + # Try entering a string literal, and see if it comes back unchanged. +- gdb_test "print \"abcdefABCDEF012345\"" \ +- " = \"abcdefABCDEF012345\"" \ ++ gdb_test "print $L\"abcdefABCDEF012345\"" \ ++ " = $L\"abcdefABCDEF012345\"" \ + "parse string literal in ${target_charset}" + + # Check that the string literal was encoded correctly. +- gdb_test "print \"q\"\[0\] == $var_name\[49\]" \ ++ gdb_test "print $L\"q\"\[0\] == $var_name\[49\]" \ + " = 1" \ + "check value of parsed string literal in ${target_charset}" + +@@ -509,7 +486,7 @@ foreach target_charset [all_charset_names] { + send_gdb "print $var_name\[$i\]\n" + set have_escape 1 + gdb_expect { +- -re "= \[0-9-\]+ '\\\\${escape}'\[\r\n\]+$gdb_prompt $" { ++ -re "= \[0-9-\]+ $L'\\\\${escape}'\[\r\n\]+$gdb_prompt $" { + pass "try printing '\\${escape}' in ${target_charset}" + } + -re "= \[0-9-\]+ 'x'\[\r\n\]+$gdb_prompt $" { +@@ -527,12 +504,12 @@ foreach target_charset [all_charset_names] { + if {$have_escape} { + + # Try parsing a backslash escape in a character literal. +- gdb_test "print '\\${escape}' == $var_name\[$i\]" \ ++ gdb_test "print $L'\\${escape}' == $var_name\[$i\]" \ + " = 1" \ + "check value of '\\${escape}' in ${target_charset}" + + # Try parsing a backslash escape in a string literal. +- gdb_test "print \"\\${escape}\"\[0\] == $var_name\[$i\]" \ ++ gdb_test "print $L\"\\${escape}\"\[0\] == $var_name\[$i\]" \ + " = 1" \ + "check value of \"\\${escape}\" in ${target_charset}" + } +@@ -540,10 +517,73 @@ foreach target_charset [all_charset_names] { + + # Try printing a character escape that doesn't exist. We should + # get the unescaped character, in the target character set. +- gdb_test "print '\\q'" " = \[0-9-\]+ 'q'" \ ++ gdb_test "print $L'\\q'" " = \[0-9-\]+ $L'q'" \ + "print escape that doesn't exist in $target_charset" +- gdb_test "print '\\q' == $var_name\[49\]" " = 1" \ ++ gdb_test "print $L'\\q' == $var_name\[49\]" " = 1" \ + "check value of escape that doesn't exist in $target_charset" + } + ++# Reset the target charset. ++gdb_test "set target-charset UTF-8" "" ++ ++# \242 is not a valid UTF-8 character. ++gdb_test "print \"\\242\"" " = \"\\\\242\"" \ ++ "non-representable target character" ++ ++gdb_test "print '\\x'" "\\\\x escape without a following hex digit." ++gdb_test "print '\\u'" "\\\\u escape without a following hex digit." ++gdb_test "print '\\9'" " = \[0-9\]+ '9'" ++ ++# Tests for wide- or unicode- strings. L is the prefix letter to use, ++# either "L" (for wide strings), "u" (for UCS-2), or "U" (for UCS-4). ++# NAME is used in the test names and should be related to the prefix ++# letter in some easy-to-undestand way. ++proc test_wide_or_unicode {L name} { ++ gdb_test "print $L\"ab\" $L\"c\"" " = $L\"abc\"" \ ++ "basic $name string concatenation" ++ gdb_test "print $L\"ab\" \"c\"" " = $L\"abc\"" \ ++ "narrow and $name string concatenation" ++ gdb_test "print \"ab\" $L\"c\"" " = $L\"abc\"" \ ++ "$name and narrow string concatenation" ++ gdb_test "print $L\"\\xe\" $L\"c\"" " = $L\"\\\\16c\"" \ ++ "$name string concatenation with escape" ++ gdb_test "print $L\"\" \"abcdef\" \"g\"" \ ++ "$L\"abcdefg\"" \ ++ "concatenate three strings with empty $name string" ++ ++ gdb_test "print $L'a'" "= \[0-9\]+ $L'a'" \ ++ "basic $name character" ++} ++ ++if {$wchar_ok} { ++ test_wide_or_unicode L wide ++} ++ ++set ucs2_ok [expr {[get_sizeof char16_t 99] == 2}] ++if {$ucs2_ok} { ++ test_wide_or_unicode u UCS-2 ++} ++ ++set ucs4_ok [expr {[get_sizeof char32_t 99] == 4}] ++if {$ucs4_ok} { ++ test_wide_or_unicode U UCS-4 ++} ++ ++# Test an invalid string combination. ++proc test_combination {L1 name1 L2 name2} { ++ gdb_test "print $L1\"abc\" $L2\"def\"" \ ++ "Undefined string concatenation." \ ++ "undefined concatenation of $name1 and $name2" ++} ++ ++if {$wchar_ok && $ucs2_ok} { ++ test_combination L wide u UCS-2 ++} ++if {$wchar_ok && $ucs4_ok} { ++ test_combination L wide U UCS-4 ++} ++if {$ucs2_ok && $ucs4_ok} { ++ test_combination u UCS-2 U UCS-4 ++} ++ + gdb_exit +diff --git a/gdb/testsuite/gdb.base/constvars.exp b/gdb/testsuite/gdb.base/constvars.exp +index d53a826..6d1bd12 100644 +--- a/gdb/testsuite/gdb.base/constvars.exp ++++ b/gdb/testsuite/gdb.base/constvars.exp +@@ -161,7 +161,7 @@ proc do_constvar_tests {} { + gdb_test "print laconic" " = 65 'A'" + local_compiler_xfail_check + gdb_test "ptype laconic" "type = const char" +- gdb_test "print laggard" " = 1 '.001'" ++ gdb_test "print laggard" " = 1 '.1'" + local_compiler_xfail_check + gdb_test "ptype laggard" "type = const unsigned char" + gdb_test "print lagoon" " = 2" +@@ -209,7 +209,7 @@ proc do_constvar_tests {} { + gdb_test "print *lewd" " = 65 'A'" + local_compiler_xfail_check + gdb_test "ptype lewd" "type = const char \\* const" +- gdb_test "print *lexicographer" " = 1 '.001'" ++ gdb_test "print *lexicographer" " = 1 '.1'" + local_compiler_xfail_check + gdb_test "ptype lexicographer" "type = const unsigned char \\* const" + gdb_test "print *lexicon" " = 2" +@@ -233,7 +233,7 @@ proc do_constvar_tests {} { + gdb_test "print *languish" " = 65 'A'" + local_compiler_xfail_check + gdb_test "ptype languish" "type = const char \\*" +- gdb_test "print *languor" " = 1 '.001'" ++ gdb_test "print *languor" " = 1 '.1'" + local_compiler_xfail_check + gdb_test "ptype languor" "type = const unsigned char \\*" + gdb_test "print *lank" " = 2" +diff --git a/gdb/testsuite/gdb.base/display.exp b/gdb/testsuite/gdb.base/display.exp +index d62e8bf..aa65373 100644 +--- a/gdb/testsuite/gdb.base/display.exp ++++ b/gdb/testsuite/gdb.base/display.exp +@@ -180,8 +180,12 @@ gdb_test "printf \"%p\\n\", 1" "0x1" + + # play with "print", too + # +-gdb_test "print/r j" ".*Undefined output format.*" +-gdb_test "print j" ".*" "debug test output" ++gdb_test "print/z j" ".*Undefined output format.*" ++gdb_test "print/d j" " = 0\[\\r\\n\]+" "debug test output 1" ++gdb_test "print/r j" " = 0\[\\r\\n\]+" "debug test output 1a" ++gdb_test "print/x j" " = 0x0\[\\r\\n\]+" "debug test output 2" ++gdb_test "print/r j" " = 0x0\[\\r\\n\]+" "debug test output 2a" ++gdb_test "print j" " = 0\[\\r\\n\]+" "debug test output 3" + + # x/0 j doesn't produce any output and terminates PA64 process when testing + if [istarget "hppa2.0w-hp-hpux11*"] { +diff --git a/gdb/testsuite/gdb.base/ending-run.exp b/gdb/testsuite/gdb.base/ending-run.exp +index 42b4577..cf33602 100644 +--- a/gdb/testsuite/gdb.base/ending-run.exp ++++ b/gdb/testsuite/gdb.base/ending-run.exp +@@ -69,7 +69,7 @@ gdb_expect { + gdb_test "b ending-run.c:1" ".*Breakpoint.*4.*" + gdb_test "b ending-run.c:14" ".*Note.*also.*Breakpoint.*5.*" "b ending-run.c:14, two" + gdb_test "cle ending-run.c:14" \ +- ".*Deleted breakpoints 4 5.*" "Cleared 2 by line" ++ ".*Deleted breakpoint 5.*" "Cleared 2 by line" + + send_gdb "inf line ending-run.c:14\n" + gdb_expect { +@@ -77,7 +77,7 @@ gdb_expect { + set line_nine $expect_out(1,string) + gdb_test "b ending-run.c:14" ".*Breakpoint 6.*ending-run.c, line 14.*" + gdb_test "b *$line_nine" ".*Note.*also.*Breakpoint 7.*" "Breakpoint 7 at *ending-run.c:14" +- gdb_test "cle" ".*Deleted breakpoints 6 7.*" "Clear 2 by default" ++ gdb_test "cle" ".*Deleted breakpoints 4 6 7.*" "Clear 2 by default" + } + -re ".*$gdb_prompt $" { + fail "need to fix test for new compile outcome" +diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp +index 4618a2c..40830c3 100644 +--- a/gdb/testsuite/gdb.base/help.exp ++++ b/gdb/testsuite/gdb.base/help.exp +@@ -603,7 +603,7 @@ gdb_test "help stepi" "Step one instruction exactly\.\[\r\n\]+Argument N means d + gdb_test "help signal" "Continue program giving it signal.*" "help signal" + # test help source + # vxgdb reads .vxgdbinit +-gdb_test "help source" "Read commands from a file named FILE\.\[\r\n\]+Optional -v switch \\(before the filename\\) causes each command in\[\r\n\]+FILE to be echoed as it is executed\.\[\r\n\]+Note that the file \"\[^\"\]*\" is read automatically in this way\[\r\n\]+when GDB is started\." "help source" ++gdb_test "help source" "Read commands from a file named FILE\.\[\r\n\]+Optional -v switch \\(before the filename\\) causes each command in\[\r\n\]+FILE to be echoed as it is executed\.\[\r\n\]+Note that the file \"\[^\"\]*\" is read automatically in this way\[\r\n\]+when GDB is started\.\[\r\n\]+Optional -p switch \\(before the filename\\) causes FILE to be evaluated\[\r\n\]+as Python code\." "help source" + # test help stack + test_class_help "stack" { + "Examining the stack\..*\[\r\n\]+" +diff --git a/gdb/testsuite/gdb.base/lineno-makeup-func.c b/gdb/testsuite/gdb.base/lineno-makeup-func.c +new file mode 100644 +index 0000000..1a0220e +--- /dev/null ++++ b/gdb/testsuite/gdb.base/lineno-makeup-func.c +@@ -0,0 +1,21 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . */ ++ ++void ++func (void) ++{ ++} +diff --git a/gdb/testsuite/gdb.base/lineno-makeup.c b/gdb/testsuite/gdb.base/lineno-makeup.c +new file mode 100644 +index 0000000..bb20e98 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/lineno-makeup.c +@@ -0,0 +1,35 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . */ ++ ++/* DW_AT_low_pc-DW_AT_high_pc should cover the function without line number ++ information (.debug_line) so we cannot use an external object file. ++ ++ It must not be just a label as it would alias on the next function even for ++ correct GDB. Therefore some stub data must be placed there. ++ ++ We need to provide a real stub function body as at least s390 ++ (s390_analyze_prologue) would skip the whole body till reaching `main'. */ ++ ++extern void func (void); ++asm ("func: .incbin \"gdb.base/lineno-makeup-func.bin\""); ++ ++int ++main (void) ++{ ++ func (); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/lineno-makeup.exp b/gdb/testsuite/gdb.base/lineno-makeup.exp +new file mode 100644 +index 0000000..0c75b84 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/lineno-makeup.exp +@@ -0,0 +1,78 @@ ++# Copyright 2009 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 3 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, see . ++ ++set testfile "lineno-makeup" ++set srcfuncfile ${testfile}-func.c ++set srcfile ${testfile}.c ++set objfuncfile ${objdir}/${subdir}/${testfile}-func.o ++set binfuncfile ${objdir}/${subdir}/${testfile}-func.bin ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfuncfile}" "${objfuncfile}" object {}] != "" } { ++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." ++} ++ ++set objcopy [catch "exec objcopy -O binary --only-section .text ${objfuncfile} ${binfuncfile}" output] ++verbose -log "objcopy=$objcopy: $output" ++if { $objcopy != 0 } { ++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." ++} ++set binfuncfilesize [file size $binfuncfile] ++verbose -log "file size $binfuncfile = $binfuncfilesize" ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set b_addr "" ++set test "break func" ++gdb_test_multiple $test $test { ++ -re "Breakpoint \[0-9\]+ at (0x\[0-9a-f\]+)\r\n$gdb_prompt $" { ++ set b_addr $expect_out(1,string) ++ pass $test ++ } ++ -re "Breakpoint \[0-9\]+ at (0x\[0-9a-f\]+): .*\r\n$gdb_prompt $" { ++ set b_addr $expect_out(1,string) ++ fail $test ++ } ++} ++verbose -log "b_addr=<$b_addr>" ++ ++set p_addr "" ++set test "print func" ++gdb_test_multiple $test $test { ++ -re "\\$\[0-9\]+ = {} (0x\[0-9a-f\]+) \r\n$gdb_prompt $" { ++ set p_addr $expect_out(1,string) ++ pass $test ++ } ++} ++verbose -log "p_addr=<$p_addr>" ++ ++set test "break address belongs to func" ++if {$b_addr == $p_addr} { ++ pass "$test (exact match)" ++} else { ++ set skip [expr $b_addr - $p_addr] ++ if {$skip > 0 && $skip < $binfuncfilesize} { ++ pass "$test (prologue skip by $skip bytes)" ++ } else { ++ fail $test ++ } ++} +diff --git a/gdb/testsuite/gdb.base/long_long.exp b/gdb/testsuite/gdb.base/long_long.exp +index d0ad5ba..5189324 100644 +--- a/gdb/testsuite/gdb.base/long_long.exp ++++ b/gdb/testsuite/gdb.base/long_long.exp +@@ -210,7 +210,7 @@ gdb_test_char "p/o *(char *)c" "01" + gdb_test_char "p/t *(char *)c" "1" + gdb_test_char "p/a *(char *)c" "0x1( <.*>)?" + gdb_test_char "p/f *(char *)c" "1" +-gdb_test_char "p/c *(char *)c" "1 '.001'" ++gdb_test_char "p/c *(char *)c" "1 '.1'" + + gdb_test_short "p/x *(short *)s" "" "0x123" "" + gdb_test_short "p/d *(short *)s" "" "291" "" +@@ -257,7 +257,7 @@ gdb_test "x/u w" "19088743" + gdb_test "x/o w" "0110642547" + gdb_test "x/t w" "00000001001000110100010101100111" + gdb_test_xptr "x/a" { b "" } { h "" } { w "0x1234567" } { g "0x123456789abcdef" } +-gdb_test "x/c b" "1 '.001'" ++gdb_test "x/c b" "1 '.1'" + if { $sizeof_double == 8 || $sizeof_long_double == 8 } { + gdb_test "x/f &val.oct" "-5.9822653797615723e-120" + } else { +@@ -273,7 +273,7 @@ gdb_test "x/2u g" "81985529216486895.*12046818088235383159" + gdb_test "x/2o g" "04432126361152746757.*01234567123456701234567" + gdb_test "x/2t g" "0000000100100011010001010110011110001001101010111100110111101111.*1010011100101110111001010011100101110111000001010011100101110111" + gdb_test_xptr "x/2a" { b "" } { h "" } { w "0x1234567.*0xa72ee539" } { g "0x123456789abcdef.*0xa72ee53977053977" } +-gdb_test "x/2c b" "1 '.001'.*-89 '.'" ++gdb_test "x/2c b" "1 '.1'.*-89 '.\[0-9\]*'" + if { $sizeof_double == 8 || $sizeof_long_double == 8 } { + gdb_test "x/2f &val.oct" "-5.9822653797615723e-120.*-5.9041889495880968e-100" + } else { +@@ -288,7 +288,7 @@ gdb_test "x/2bu b" "1.*167" + gdb_test "x/2bo b" "01.*0247" + gdb_test "x/2bt b" "00000001.*10100111" + gdb_test_ptr "x/2ba b" "" "" "0x1.*0xffffffa7" "0x1.*0xffffffffffffffa7" +-gdb_test "x/2bc b" "1 '.001'.*-89 '.'" ++gdb_test "x/2bc b" "1 '.1'.*-89 '.\[0-9\]*'" + gdb_test "x/2bf b" "1.*-89" + + gdb_test "x/2hx h" "0x0123.*0xa72e" +@@ -315,7 +315,7 @@ gdb_test "x/2gu g" "81985529216486895.*12046818088235383159" + gdb_test "x/2go g" "04432126361152746757.*01234567123456701234567" + gdb_test "x/2gt g" "0000000100100011010001010110011110001001101010111100110111101111.*1010011100101110111001010011100101110111000001010011100101110111" + gdb_test_ptr "x/2ga g" "" "" "0x89abcdef.*0x77053977" "0x123456789abcdef.*0xa72ee53977053977" +-gdb_test "x/2gc g" "-17 '.'.*119 'w'" ++gdb_test "x/2gc g" "-17 '.\[0-9\]*'.*119 'w'" + gdb_test "x/2gf g" "3.5127005640885037e-303.*-5.9822653797615723e-120" + + gdb_exit +diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp +index 7086e90..dd196d7 100644 +--- a/gdb/testsuite/gdb.base/macscp.exp ++++ b/gdb/testsuite/gdb.base/macscp.exp +@@ -26,13 +26,21 @@ set testfile "macscp" + set objfile ${objdir}/${subdir}/${testfile}.o + set binfile ${objdir}/${subdir}/${testfile} + +-set options { debug } ++set options { debug additional_flags=-DFROM_COMMANDLINE=ARG} + + get_compiler_info ${binfile} + if [test_compiler_info gcc*] { + lappend options additional_flags=-g3 + } + ++# Workaround ccache making lineno non-zero for command-line definitions. ++if {[find_gcc] == "gcc" && [file executable "/usr/bin/gcc"]} { ++ set result [catch "exec which gcc" output] ++ if {$result == 0 && [string first "/ccache/" $output] >= -1} { ++ lappend options "compiler=/usr/bin/gcc" ++ } ++} ++ + # Generate the intermediate object file. This is required by Darwin to + # have access to the .debug_macinfo section. + if {[gdb_compile "${srcdir}/${subdir}/macscp1.c" "${objfile}" \ +@@ -79,11 +87,15 @@ proc info_macro {macro} { + + if {$debug_me} {exp_internal 1} + gdb_expect { +- -re "Defined at \[^\r\n\]*(${filepat}):${decimal}\[\r\n\]" { ++ -re "Defined at \[^\r\n\]*(${filepat}):(${decimal})\[\r\n\]" { + # `location' and `definition' should be empty when we see + # this message. + if {[llength $location] == 0 && [llength $definition] == 0} { + set location $expect_out(1,string) ++ # Definitions from gcc command-line get suffixed by the lineno. ++ if {$expect_out(2,string) == "0" } { ++ set location "$location:$expect_out(2,string)" ++ } + exp_continue + } else { + # Exit this expect loop, with a result indicating failure. +@@ -198,6 +210,8 @@ proc list_and_check_macro {func macro expected} { + } + + ++list_and_check_macro main FROM_COMMANDLINE "macscp1.c:0 ARG" ++ + if {[list_and_check_macro main WHERE {macscp1.c {before macscp1_3}}]} { + return 0 + } +diff --git a/gdb/testsuite/gdb.base/multi-forks.exp b/gdb/testsuite/gdb.base/multi-forks.exp +index ac56fb0..f853180 100644 +--- a/gdb/testsuite/gdb.base/multi-forks.exp ++++ b/gdb/testsuite/gdb.base/multi-forks.exp +@@ -51,7 +51,62 @@ global gdb_prompt + + # This is a test of gdb's ability to follow the parent, child or both + # parent and child of multiple Unix fork() system calls. +-# ++ ++set exit_bp_loc [gdb_get_line_number "Set exit breakpoint here."] ++ ++# Insert a breakpoint at the location provided by the exit_bp_loc global ++# and resume the execution until hitting that breakpoint. We also make ++# sure to consume all the expected output from all processes as well, ++# to make sure it doesn't cause trouble during a subsequent test. ++ ++proc continue_to_exit_bp_loc {} { ++ global exit_bp_loc decimal gdb_prompt ++ ++ gdb_breakpoint $exit_bp_loc ++ ++ send_gdb "continue\n" ++ ++ # The output from the child processes can be interleaved arbitrarily ++ # with the output from GDB and the parent process. If we don't ++ # consume it all now, it can confuse later interactions. ++ set seen_done 0 ++ set seen_break 0 ++ set seen_prompt 0 ++ set seen_timeout 0 ++ while { ($seen_done < 16 || ! $seen_prompt) && ! $seen_timeout } { ++ # We don't know what order the interesting things will arrive in. ++ # Using a pattern of the form 'x|y|z' instead of -re x ... -re y ++ # ... -re z ensures that expect always chooses the match that ++ # occurs leftmost in the input, and not the pattern appearing ++ # first in the script that occurs anywhere in the input, so that ++ # we don't skip anything. ++ gdb_expect { ++ -re "($decimal done)|(Breakpoint)|($gdb_prompt)" { ++ if {[info exists expect_out(1,string)]} { ++ incr seen_done ++ } elseif {[info exists expect_out(2,string)]} { ++ set seen_break 1 ++ } elseif {[info exists expect_out(3,string)]} { ++ set seen_prompt 1 ++ } ++ array unset expect_out ++ } ++ timeout { set seen_timeout 1 } ++ } ++ } ++ ++ if { $seen_timeout } { ++ fail "run to exit 2 (timeout)" ++ } elseif { ! $seen_prompt } { ++ fail "run to exit 2 (no prompt)" ++ } elseif { ! $seen_break } { ++ fail "run to exit 2 (no breakpoint hit)" ++ } elseif { $seen_done != 16 } { ++ fail "run to exit 2 (missing done messages)" ++ } else { ++ pass "run to exit 2" ++ } ++} + + # The inferior program builds a tree of processes by executing a loop + # four times, calling fork at each iteration. Thus, at each +@@ -66,69 +121,17 @@ global gdb_prompt + # The result should be that each of the 4 forks returns zero. + + runto_main +-set exit_bp_loc [gdb_get_line_number "Set exit breakpoint here."] +-gdb_test "break $exit_bp_loc" "Breakpoint.* at .*" "Break at exit" +-gdb_test "set follow child" "" "" +- +-send_gdb "continue\n" +-gdb_expect { +- -re ".*Break.* main .*$gdb_prompt.*$" {} +- -re ".*$gdb_prompt $" {fail "run to exit 1"} +- default {fail "run to exit 1 (timeout)"} +-} ++gdb_test "set follow child" ++continue_to_exit_bp_loc + + gdb_test "print pids" "\\$.* = \\{0, 0, 0, 0\\}.*" "follow child, print pids" + + # Now set gdb to follow the parent. + # Result should be that none of the 4 forks returns zero. + +-delete_breakpoints + runto_main +-gdb_test "break $exit_bp_loc" "Breakpoint.* at .*" "Break at exit" + gdb_test "set follow parent" "" "" +- +-send_gdb "continue\n" +- +-# The output from the child processes can be interleaved arbitrarily +-# with the output from GDB and the parent process. If we don't +-# consume it all now, it can confuse later interactions. +-set seen_done 0 +-set seen_break 0 +-set seen_prompt 0 +-set seen_timeout 0 +-while { ($seen_done < 16 || ! $seen_prompt) && ! $seen_timeout } { +- # We don't know what order the interesting things will arrive in. +- # Using a pattern of the form 'x|y|z' instead of -re x ... -re y +- # ... -re z ensures that expect always chooses the match that +- # occurs leftmost in the input, and not the pattern appearing +- # first in the script that occurs anywhere in the input, so that +- # we don't skip anything. +- gdb_expect { +- -re "($decimal done)|(Breakpoint)|($gdb_prompt)" { +- if {[info exists expect_out(1,string)]} { +- incr seen_done +- } elseif {[info exists expect_out(2,string)]} { +- set seen_break 1 +- } elseif {[info exists expect_out(3,string)]} { +- set seen_prompt 1 +- } +- array unset expect_out +- } +- timeout { set seen_timeout 1 } +- } +-} +- +-if { $seen_timeout } { +- fail "run to exit 2 (timeout)" +-} elseif { ! $seen_prompt } { +- fail "run to exit 2 (no prompt)" +-} elseif { ! $seen_break } { +- fail "run to exit 2 (no breakpoint hit)" +-} elseif { $seen_done != 16 } { +- fail "run to exit 2 (missing done messages)" +-} else { +- pass "run to exit 2" +-} ++continue_to_exit_bp_loc + + gdb_test "print pids\[0\]==0 || pids\[1\]==0 || pids\[2\]==0 || pids\[3\]==0" \ + " = 0" "follow parent, print pids" +@@ -138,7 +141,7 @@ gdb_test "print pids\[0\]==0 || pids\[1\]==0 || pids\[2\]==0 || pids\[3\]==0" \ + # + + runto_main +-gdb_test "break $exit_bp_loc" "Breakpoint.* at .*" "" ++gdb_breakpoint $exit_bp_loc + + gdb_test "help set detach-on-fork" "whether gdb will detach the child.*" \ + "help set detach" +diff --git a/gdb/testsuite/gdb.base/pointers.exp b/gdb/testsuite/gdb.base/pointers.exp +index 91838a2..2d0a70e 100644 +--- a/gdb/testsuite/gdb.base/pointers.exp ++++ b/gdb/testsuite/gdb.base/pointers.exp +@@ -389,7 +389,7 @@ gdb_expect { + + send_gdb "print *pUC\n" + gdb_expect { +- -re ".\[0-9\]* = 21 \'.025\'.*$gdb_prompt $" { ++ -re ".\[0-9\]* = 21 \'.25\'.*$gdb_prompt $" { + pass "print value of *pUC" + } + -re ".*$gdb_prompt $" { fail "print value of *pUC" } +diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp +index 1e17da4..b6f8a1f 100644 +--- a/gdb/testsuite/gdb.base/printcmds.exp ++++ b/gdb/testsuite/gdb.base/printcmds.exp +@@ -137,12 +137,12 @@ proc test_print_all_chars {} { + global gdb_prompt + + gdb_test "p ctable1\[0\]" " = 0 '\\\\0'" +- gdb_test "p ctable1\[1\]" " = 1 '\\\\001'" +- gdb_test "p ctable1\[2\]" " = 2 '\\\\002'" +- gdb_test "p ctable1\[3\]" " = 3 '\\\\003'" +- gdb_test "p ctable1\[4\]" " = 4 '\\\\004'" +- gdb_test "p ctable1\[5\]" " = 5 '\\\\005'" +- gdb_test "p ctable1\[6\]" " = 6 '\\\\006'" ++ gdb_test "p ctable1\[1\]" " = 1 '\\\\1'" ++ gdb_test "p ctable1\[2\]" " = 2 '\\\\2'" ++ gdb_test "p ctable1\[3\]" " = 3 '\\\\3'" ++ gdb_test "p ctable1\[4\]" " = 4 '\\\\4'" ++ gdb_test "p ctable1\[5\]" " = 5 '\\\\5'" ++ gdb_test "p ctable1\[6\]" " = 6 '\\\\6'" + gdb_test "p ctable1\[7\]" " = 7 '\\\\a'" + gdb_test "p ctable1\[8\]" " = 8 '\\\\b'" + gdb_test "p ctable1\[9\]" " = 9 '\\\\t'" +@@ -150,24 +150,24 @@ proc test_print_all_chars {} { + gdb_test "p ctable1\[11\]" " = 11 '\\\\v'" + gdb_test "p ctable1\[12\]" " = 12 '\\\\f'" + gdb_test "p ctable1\[13\]" " = 13 '\\\\r'" +- gdb_test "p ctable1\[14\]" " = 14 '\\\\016'" +- gdb_test "p ctable1\[15\]" " = 15 '\\\\017'" +- gdb_test "p ctable1\[16\]" " = 16 '\\\\020'" +- gdb_test "p ctable1\[17\]" " = 17 '\\\\021'" +- gdb_test "p ctable1\[18\]" " = 18 '\\\\022'" +- gdb_test "p ctable1\[19\]" " = 19 '\\\\023'" +- gdb_test "p ctable1\[20\]" " = 20 '\\\\024'" +- gdb_test "p ctable1\[21\]" " = 21 '\\\\025'" +- gdb_test "p ctable1\[22\]" " = 22 '\\\\026'" +- gdb_test "p ctable1\[23\]" " = 23 '\\\\027'" +- gdb_test "p ctable1\[24\]" " = 24 '\\\\030'" +- gdb_test "p ctable1\[25\]" " = 25 '\\\\031'" +- gdb_test "p ctable1\[26\]" " = 26 '\\\\032'" +- gdb_test "p ctable1\[27\]" " = 27 '\\\\033'" +- gdb_test "p ctable1\[28\]" " = 28 '\\\\034'" +- gdb_test "p ctable1\[29\]" " = 29 '\\\\035'" +- gdb_test "p ctable1\[30\]" " = 30 '\\\\036'" +- gdb_test "p ctable1\[31\]" " = 31 '\\\\037'" ++ gdb_test "p ctable1\[14\]" " = 14 '\\\\16'" ++ gdb_test "p ctable1\[15\]" " = 15 '\\\\17'" ++ gdb_test "p ctable1\[16\]" " = 16 '\\\\20'" ++ gdb_test "p ctable1\[17\]" " = 17 '\\\\21'" ++ gdb_test "p ctable1\[18\]" " = 18 '\\\\22'" ++ gdb_test "p ctable1\[19\]" " = 19 '\\\\23'" ++ gdb_test "p ctable1\[20\]" " = 20 '\\\\24'" ++ gdb_test "p ctable1\[21\]" " = 21 '\\\\25'" ++ gdb_test "p ctable1\[22\]" " = 22 '\\\\26'" ++ gdb_test "p ctable1\[23\]" " = 23 '\\\\27'" ++ gdb_test "p ctable1\[24\]" " = 24 '\\\\30'" ++ gdb_test "p ctable1\[25\]" " = 25 '\\\\31'" ++ gdb_test "p ctable1\[26\]" " = 26 '\\\\32'" ++ gdb_test "p ctable1\[27\]" " = 27 '\\\\33'" ++ gdb_test "p ctable1\[28\]" " = 28 '\\\\34'" ++ gdb_test "p ctable1\[29\]" " = 29 '\\\\35'" ++ gdb_test "p ctable1\[30\]" " = 30 '\\\\36'" ++ gdb_test "p ctable1\[31\]" " = 31 '\\\\37'" + gdb_test "p ctable1\[32\]" " = 32 ' '" + gdb_test "p ctable1\[33\]" " = 33 '!'" + gdb_test "p ctable1\[34\]" " = 34 '\"'" +@@ -475,13 +475,13 @@ proc test_print_strings {} { + gdb_test "p &ctable1\[0\]" \ + " = \\(unsigned char \\*\\) \"\"" + gdb_test "p &ctable1\[1\]" \ +- " = \\(unsigned char \\*\\) \"\\\\001\\\\002\\\\003\\\\004\\\\005\\\\006\\\\a\\\\b\"..." ++ " = \\(unsigned char \\*\\) \"\\\\1\\\\2\\\\3\\\\4\\\\5\\\\6\\\\a\\\\b\"..." + gdb_test "p &ctable1\[1*8\]" \ +- " = \\(unsigned char \\*\\) \"\\\\b\\\\t\\\\n\\\\v\\\\f\\\\r\\\\016\\\\017\"..." ++ " = \\(unsigned char \\*\\) \"\\\\b\\\\t\\\\n\\\\v\\\\f\\\\r\\\\16\\\\17\"..." + gdb_test "p &ctable1\[2*8\]" \ +- " = \\(unsigned char \\*\\) \"\\\\020\\\\021\\\\022\\\\023\\\\024\\\\025\\\\026\\\\027\"..." ++ " = \\(unsigned char \\*\\) \"\\\\20\\\\21\\\\22\\\\23\\\\24\\\\25\\\\26\\\\27\"..." + gdb_test "p &ctable1\[3*8\]" \ +- " = \\(unsigned char \\*\\) \"\\\\030\\\\031\\\\032\\\\033\\\\034\\\\035\\\\036\\\\037\"..." ++ " = \\(unsigned char \\*\\) \"\\\\30\\\\31\\\\32\\\\33\\\\34\\\\35\\\\36\\\\37\"..." + gdb_test "p &ctable1\[4*8\]" \ + " = \\(unsigned char \\*\\) \" !\\\\\"#\\\$%&'\"..." + gdb_test "p &ctable1\[5*8\]" \ +@@ -622,7 +622,7 @@ proc test_print_string_constants {} { + set timeout 60; + + gdb_test "p \"a string\"" " = \"a string\"" +- gdb_test "p \"embedded \\000 null\"" " = \"embedded \\\\000 null\"" ++ gdb_test "p \"embedded \\000 null\"" " = \"embedded \\\\0 null\"" + gdb_test "p \"abcd\"\[2\]" " = 99 'c'" + gdb_test "p sizeof (\"abcdef\")" " = 7" + gdb_test "ptype \"foo\"" " = char \\\[4\\\]" +diff --git a/gdb/testsuite/gdb.base/return-nodebug.c b/gdb/testsuite/gdb.base/return-nodebug.c +new file mode 100644 +index 0000000..e1211b3 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/return-nodebug.c +@@ -0,0 +1,49 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . */ ++ ++#include ++ ++static TYPE ++init (void) ++{ ++ return 0; ++} ++ ++static TYPE ++func (void) ++{ ++ return 31; ++} ++ ++static void ++marker (void) ++{ ++} ++ ++int ++main (void) ++{ ++ /* Preinitialize registers to 0 to avoid false PASS by leftover garbage. */ ++ init (); ++ ++ printf ("result=" FORMAT "\n", CAST func ()); ++ ++ /* Cannot `next' with no debug info. */ ++ marker (); ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/return-nodebug.exp b/gdb/testsuite/gdb.base/return-nodebug.exp +new file mode 100644 +index 0000000..7d43776 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/return-nodebug.exp +@@ -0,0 +1,61 @@ ++# Copyright (C) 2009 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 3 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, see . ++ ++proc do_test {type} { ++ set typenospace [string map {{ } -} $type] ++ ++ global pf_prefix ++ set old_prefix $pf_prefix ++ lappend pf_prefix "$typenospace:" ++ ++ if {[runto "func"]} { ++ # Verify that we do not crash when using "return" from a function with ++ # no debugging info. Such function has no `struct symbol'. It may ++ # still have an associated `struct minimal_symbol'. ++ ++ gdb_test "return -1" \ ++ "Return value type not available for selected stack frame\\.\r\nPlease use an explicit cast of the value to return\\." \ ++ "return from function with no debug info without a cast" ++ ++ # Cast of the result to the proper width must be done explicitely. ++ gdb_test "return ($type) -1" "#0 .* main \\(.*" \ ++ "return from function with no debug info with a cast" \ ++ "Make selected stack frame return now\\? \\(y or n\\) " "y" ++ ++ # And if it returned the full width of the result. ++ gdb_test "adv marker" "\r\nresult=-1\r\n.* in marker \\(.*" \ ++ "full width of the returned result" ++ } ++ ++ set pf_prefix $old_prefix ++} ++ ++foreach case {{{signed char} %d (int)} \ ++ {{short} %d (int)} \ ++ {{int} %d} \ ++ {{long} %ld} \ ++ {{long long} %lld}} { ++ set type [lindex $case 0] ++ set format [lindex $case 1] ++ set cast [lindex $case 2] ++ ++ set typeesc [string map {{ } {\ }} $type] ++ set typenospace [string map {{ } -} $type] ++ ++ if {[prepare_for_testing return-nodebug.exp "return-nodebug-$typenospace" "return-nodebug.c" \ ++ [list "additional_flags=-DFORMAT=\"$format\" -DTYPE=$typeesc -DCAST=$cast"]] == 0} { ++ do_test $type ++ } ++} +diff --git a/gdb/testsuite/gdb.base/setvar.exp b/gdb/testsuite/gdb.base/setvar.exp +index 2350a33..3be8424 100644 +--- a/gdb/testsuite/gdb.base/setvar.exp ++++ b/gdb/testsuite/gdb.base/setvar.exp +@@ -121,7 +121,7 @@ proc test_set { args } { + # + + test_set "set variable v_char=0" "print v_char" ".\[0-9\]* = 0 \'.0\'" "set variable char=0" +-test_set "set variable v_char=1" "print v_char" ".\[0-9\]* = 1 \'.001\'" "set variable char=1" ++test_set "set variable v_char=1" "print v_char" ".\[0-9\]* = 1 \'.1\'" "set variable char=1" + test_set "set variable v_char=7" "print v_char" ".\[0-9\]* = 7 \'.a\'" "set variable char=7 (Bel)" + test_set "set variable v_char=32" "print v_char" ".\[0-9\]* = 32 \' \'" "set variable char=32 (SPC)" + test_set "set variable v_char=65" "print v_char" ".\[0-9\]* = 65 \'A\'" "set variable char=65 ('A')" +@@ -132,7 +132,7 @@ test_set "set variable v_char=127" "print v_char" ".\[0-9\]* = 127 \'.177\'" + # test "set variable" for type "signed char" + # + test_set "set variable v_char=0" "print v_signed_char" ".\[0-9\]* = 0 \'.0\'" "set variable signed char=0" +-test_set "set variable v_signed_char=1" "print v_signed_char" ".\[0-9\]* = 1 \'.001\'" "set variable signed char=1" ++test_set "set variable v_signed_char=1" "print v_signed_char" ".\[0-9\]* = 1 \'.1\'" "set variable signed char=1" + test_set "set variable v_signed_char=7" "print v_signed_char" ".\[0-9\]* = 7 \'.a\'" "set variable signed char=7 (Bel)" + test_set "set variable v_signed_char=32" "print v_signed_char" ".\[0-9\]* = 32 \' \'" "set variable signed char=32 (SPC)" + test_set "set variable v_signed_char=65" "print v_signed_char" ".\[0-9\]* = 65 \'A\'" "set variable signed char=65 ('A')" +@@ -151,7 +151,7 @@ gdb_test "print v_signed_char" ".\[0-9\]* = -1 \'.377\'" \ + # test "set variable" for type "unsigned char" + # + test_set "set variable v_unsigned_char=0" "print v_unsigned_char" ".\[0-9\]* = 0 \'.0\'" "set variable unsigned char=0" +-test_set "set variable v_unsigned_char=1" "print v_unsigned_char" ".\[0-9\]* = 1 \'.001\'" "set variable unsigned char=1" ++test_set "set variable v_unsigned_char=1" "print v_unsigned_char" ".\[0-9\]* = 1 \'.1\'" "set variable unsigned char=1" + test_set "set variable v_unsigned_char=7" "print v_unsigned_char" ".\[0-9\]* = 7 \'.a\'" "set variable unsigned char=7 (Bel)" + test_set "set variable v_unsigned_char=32" "print v_unsigned_char" ".\[0-9\]* = 32 \' \'" "set variable unsigned char=32 (SPC)" + test_set "set variable v_unsigned_char=65" "print v_unsigned_char" ".\[0-9\]* = 65 \'A\'" "set variable unsigned char=65 ('A')" +diff --git a/gdb/testsuite/gdb.base/store.exp b/gdb/testsuite/gdb.base/store.exp +index 963bb19..feab6bd 100644 +--- a/gdb/testsuite/gdb.base/store.exp ++++ b/gdb/testsuite/gdb.base/store.exp +@@ -74,7 +74,7 @@ proc check_set { t l r new add } { + "${prefix}; print incremented l, expecting ${add}" + } + +-check_set "charest" "-1 .*" "-2 .*" "4 ..004." "2 ..002." ++check_set "charest" "-1 .*" "-2 .*" "4 ..4." "2 ..2." + check_set "short" "-1" "-2" "4" "2" + check_set "int" "-1" "-2" "4" "2" + check_set "long" "-1" "-2" "4" "2" +@@ -102,7 +102,7 @@ proc up_set { t l r new } { + "${prefix}; print new l, expecting ${new}" + } + +-up_set "charest" "-1 .*" "-2 .*" "4 ..004." ++up_set "charest" "-1 .*" "-2 .*" "4 ..4." + up_set "short" "-1" "-2" "4" + up_set "int" "-1" "-2" "4" + up_set "long" "-1" "-2" "4" +diff --git a/gdb/testsuite/gdb.base/valgrind-attach.c b/gdb/testsuite/gdb.base/valgrind-attach.c +new file mode 100644 +index 0000000..84b57db +--- /dev/null ++++ b/gdb/testsuite/gdb.base/valgrind-attach.c +@@ -0,0 +1,28 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . */ ++ ++#include ++ ++int ++main (void) ++{ ++ int *a = malloc (1); ++ ++ a[10] = 0; /* crash-here */ ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/valgrind-attach.exp b/gdb/testsuite/gdb.base/valgrind-attach.exp +new file mode 100644 +index 0000000..1f9b26e +--- /dev/null ++++ b/gdb/testsuite/gdb.base/valgrind-attach.exp +@@ -0,0 +1,94 @@ ++# Copyright 2009 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 3 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, see . ++ ++set testfile valgrind-attach ++set shfile ${testfile}.sh ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++gdb_exit ++gdb_stop_suppressing_tests; ++ ++set VALGRIND "valgrind" ++ ++# Syntax for ${shfile} is: ++set VALGRIND_SPAWN "sh ${srcdir}/${subdir}/${shfile} $binfile $VALGRIND $GDB $INTERNAL_GDBFLAGS $GDBFLAGS [host_info gdb_opts]" ++ ++set test "spawn valgrind" ++verbose "Spawning $VALGRIND_SPAWN" ++ ++if [info exists gdb_spawn_id] { ++ fail $test ++ return -1 ++} ++ ++if ![is_remote host] { ++ if { [which $VALGRIND] == 0 } then { ++ untested "Couldn't find $VALGRIND" ++ return -1 ++ } ++} ++set res [remote_spawn host "$VALGRIND_SPAWN"] ++if { $res < 0 || $res == "" } { ++ perror "Spawning $VALGRIND_SPAWN failed." ++ return -1 ++} ++set gdb_spawn_id -1; ++ ++gdb_expect { ++ -re "---- Attach to debugger \\? --- \\\[Return/N/n/Y/y/C/c\\\] ---- $" { ++ pass $test ++ } ++ eof { ++ perror "(eof) $VALGRIND never initialized" ++ remote_close host ++ return -1 ++ } ++ timeout { ++ perror "(timeout) $VALGRIND never initialized" ++ remote_close host ++ return -1 ++ } ++} ++send_gdb "y\n" ++ ++set test "spawn gdb" ++set test2 "crash line caught" ++gdb_expect { ++ -re "starting debugger with cmd:.* in main .* crash-here .*\[\r\n\]$gdb_prompt $" { ++ pass $test ++ pass $test2 ++ } ++ -re "starting debugger with cmd:.*\[\r\n\]$gdb_prompt $" { ++ pass $test ++ fail $test2 ++ } ++ eof { ++ perror "(eof) $GDB never initialized" ++ remote_close host ++ return -1 ++ } ++ timeout { ++ perror "(timeout) $GDB never initialized" ++ remote_close host ++ return -1 ++ } ++} ++ ++remote_close host +diff --git a/gdb/testsuite/gdb.base/valgrind-attach.sh b/gdb/testsuite/gdb.base/valgrind-attach.sh +new file mode 100755 +index 0000000..f02c6f7 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/valgrind-attach.sh +@@ -0,0 +1,20 @@ ++#! /bin/sh ++ ++# Copyright 2009 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 3 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, see . ++ ++BINFILE="$1"; shift ++VALGRIND="$1"; shift ++"$VALGRIND" --db-attach=yes --db-command="$* %f %p" "$BINFILE" +diff --git a/gdb/testsuite/gdb.base/vla-overflow.c b/gdb/testsuite/gdb.base/vla-overflow.c +new file mode 100644 +index 0000000..c5d5ee0 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla-overflow.c +@@ -0,0 +1,30 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . */ ++ ++#include ++ ++int ++main (int argc, char **argv) ++{ ++ int array[argc]; ++ ++ array[0] = array[0]; ++ ++ abort (); ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/vla-overflow.exp b/gdb/testsuite/gdb.base/vla-overflow.exp +new file mode 100644 +index 0000000..7203a48 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla-overflow.exp +@@ -0,0 +1,108 @@ ++# Copyright 2008 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 3 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, see . ++ ++# We could crash in: ++# #0 block_linkage_function (bl=0x0) at ../../gdb/block.c:69 ++# #1 in dwarf_block_get_frame_base (...) at ../../gdb/dwarf2block.c:97 ++# 97 framefunc = block_linkage_function (get_frame_block (frame, NULL)); ++# #2 in execute_stack_op (...) at ../../gdb/dwarf2expr.c:496 ++# #3 in dwarf_block_exec_core () at ../../gdb/dwarf2block.c:156 ++# #4 dwarf_block_exec (...) at ../../gdb/dwarf2block.c:206 ++# #5 in range_type_count_bound_internal (...) at ../../gdb/gdbtypes.c:1430 ++# #6 in create_array_type (...) at ../../gdb/gdbtypes.c:840 ++# ... ++# #21 in psymtab_to_symtab (...) at ../../gdb/symfile.c:292 ++# ... ++# #29 in backtrace_command_1 () at ../../gdb/stack.c:1273 ++ ++set testfile vla-overflow ++set shfile ${objdir}/${subdir}/${testfile}-gdb.sh ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++set f [open "|getconf PAGESIZE" "r"] ++gets $f pagesize ++close $f ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set pid_of_gdb [exp_pid -i [board_info host fileid]] ++ ++if { [runto_main] < 0 } { ++ untested vla-overflow ++ return -1 ++} ++ ++# Get the GDB memory size when we stay at main. ++ ++proc memory_v_pages_get {} { ++ global pid_of_gdb pagesize ++ set fd [open "/proc/$pid_of_gdb/statm"] ++ gets $fd line ++ close $fd ++ # number of pages of virtual memory ++ scan $line "%d" drs ++ return $drs ++} ++ ++set pages_found [memory_v_pages_get] ++ ++set mb_reserve 10 ++verbose -log "pages_found = $pages_found, mb_reserve = $mb_reserve" ++set kb_found [expr $pages_found * $pagesize / 1024] ++set kb_permit [expr $kb_found + 1 * 1024 + $mb_reserve * 1024] ++verbose -log "kb_found = $kb_found, kb_permit = $kb_permit" ++ ++# Create the ulimit wrapper. ++set f [open $shfile "w"] ++puts $f "#! /bin/sh" ++puts $f "ulimit -v $kb_permit" ++puts $f "exec $GDB \"\$@\"" ++close $f ++remote_exec host "chmod +x $shfile" ++ ++gdb_exit ++set GDBold $GDB ++set GDB "$shfile" ++gdb_start ++set GDB $GDBold ++ ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set pid_of_gdb [exp_pid -i [board_info host fileid]] ++ ++# Check the size again after the second run. ++# We must not stop in main as it would cache `array' and never crash later. ++ ++gdb_run_cmd ++ ++verbose -log "kb_found before abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" ++ ++gdb_test "" "Program received signal SIGABRT, Aborted..*" "Enter abort()" ++ ++verbose -log "kb_found in abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" ++ ++# `abort' can get expressed as `*__GI_abort'. ++gdb_test "bt" "in \[^ \]*abort \\(.* in main \\(.*" "Backtrace after abort()" ++ ++verbose -log "kb_found in bt after abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" +diff --git a/gdb/testsuite/gdb.base/vla.c b/gdb/testsuite/gdb.base/vla.c +new file mode 100644 +index 0000000..e1f3ed1 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla.c +@@ -0,0 +1,55 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . */ ++ ++#include ++ ++void ++marker (void) ++{ ++} ++ ++void ++bar (char *a, char *b, char *c, int size) ++{ ++ memset (a, '1', size); ++ memset (b, '2', size); ++ memset (c, '3', 48); ++} ++ ++void ++foo (int size) ++{ ++ char temp1[size]; ++ char temp3[48]; ++ ++ temp1[size - 1] = '\0'; ++ { ++ char temp2[size]; ++ ++ bar (temp1, temp2, temp3, size); ++ ++ marker (); /* break-here */ ++ } ++} ++ ++int ++main (void) ++{ ++ foo (26); ++ foo (78); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/vla.exp b/gdb/testsuite/gdb.base/vla.exp +new file mode 100644 +index 0000000..5da7378 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla.exp +@@ -0,0 +1,62 @@ ++# Copyright 2008 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 3 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, see . ++ ++set testfile vla ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto_main] { ++ untested vla ++ return -1 ++} ++ ++gdb_breakpoint [gdb_get_line_number "break-here"] ++ ++gdb_continue_to_breakpoint "break-here" ++ ++gdb_test "whatis temp1" "type = char \\\[variable\\\]" "first: whatis temp1" ++gdb_test "whatis temp2" "type = char \\\[variable\\\]" "first: whatis temp2" ++gdb_test "whatis temp3" "type = char \\\[48\\\]" "first: whatis temp3" ++ ++gdb_test "ptype temp1" "type = char \\\[26\\\]" "first: ptype temp1" ++gdb_test "ptype temp2" "type = char \\\[26\\\]" "first: ptype temp2" ++gdb_test "ptype temp3" "type = char \\\[48\\\]" "first: ptype temp3" ++ ++gdb_test "p temp1" " = '1' " "first: print temp1" ++gdb_test "p temp2" " = '2' " "first: print temp2" ++gdb_test "p temp3" " = '3' " "first: print temp3" ++ ++gdb_continue_to_breakpoint "break-here" ++ ++gdb_test "whatis temp1" "type = char \\\[variable\\\]" "second: whatis temp1" ++gdb_test "whatis temp2" "type = char \\\[variable\\\]" "second: whatis temp2" ++gdb_test "whatis temp3" "type = char \\\[48\\\]" "second: whatis temp3" ++ ++gdb_test "ptype temp1" "type = char \\\[78\\\]" "second: ptype temp1" ++gdb_test "ptype temp2" "type = char \\\[78\\\]" "second: ptype temp2" ++gdb_test "ptype temp3" "type = char \\\[48\\\]" "second: ptype temp3" ++ ++gdb_test "p temp1" " = '1' " "second: print temp1" ++gdb_test "p temp2" " = '2' " "second: print temp2" ++gdb_test "p temp3" " = '3' " "second: print temp3" +diff --git a/gdb/testsuite/gdb.cp/Makefile.in b/gdb/testsuite/gdb.cp/Makefile.in +index 1787ad5..391bfc2 100644 +--- a/gdb/testsuite/gdb.cp/Makefile.in ++++ b/gdb/testsuite/gdb.cp/Makefile.in +@@ -4,7 +4,7 @@ srcdir = @srcdir@ + EXECUTABLES = ambiguous annota2 anon-union cplusfuncs cttiadd \ + derivation inherit local member-ptr method misc \ + overload ovldbreak ref-typ ref-typ2 templates userdef virtfunc namespace \ +- ref-types ref-params method2 pr9594 ++ ref-types ref-params method2 pr9594 gdb2495 + + all info install-info dvi install uninstall installcheck check: + @echo "Nothing to be done for $@..." +diff --git a/gdb/testsuite/gdb.cp/abstract-origin.cc b/gdb/testsuite/gdb.cp/abstract-origin.cc +new file mode 100644 +index 0000000..e2de3fb +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/abstract-origin.cc +@@ -0,0 +1,42 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . ++ */ ++ ++extern void f (int *); ++ ++class A ++{ ++public: ++ A(int i); ++}; ++ ++A::A(int i) ++{ ++ static int *problem = new int(i); ++ f (problem); /* break-here */ ++} ++ ++void f (int *) ++{ ++} ++ ++int ++main (void) ++{ ++ A a(42); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.cp/abstract-origin.exp b/gdb/testsuite/gdb.cp/abstract-origin.exp +new file mode 100644 +index 0000000..92cc23c +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/abstract-origin.exp +@@ -0,0 +1,40 @@ ++# Copyright 2008 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 3 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, see . ++ ++set testfile abstract-origin ++set srcfile ${testfile}.cc ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto_main] { ++ untested abstract-origin ++ return -1 ++} ++ ++gdb_breakpoint [gdb_get_line_number "break-here"] ++gdb_continue_to_breakpoint "break-here" ++ ++# The Bug was: No symbol "problem" in current context. ++gdb_test "p problem" " = \\(int \\*\\) 0x.*" +diff --git a/gdb/testsuite/gdb.cp/cplusfuncs.cc b/gdb/testsuite/gdb.cp/cplusfuncs.cc +index 7f033d6..1a50a32 100644 +--- a/gdb/testsuite/gdb.cp/cplusfuncs.cc ++++ b/gdb/testsuite/gdb.cp/cplusfuncs.cc +@@ -191,6 +191,12 @@ char * dm_type_char_star (char * p) { return p; } + int dm_type_foo_ref (foo & foo) { return foo.ifoo; } + int * dm_type_int_star (int * p) { return p; } + long * dm_type_long_star (long * p) { return p; } ++int dm_type_short (short i) { return i; } ++int dm_type_long (long i) { return i; } + int dm_type_unsigned_int (unsigned int i) { return i; } ++int dm_type_unsigned_short (unsigned short i) { return i; } ++int dm_type_unsigned_long (unsigned long i) { return i; } + int dm_type_void (void) { return 0; } + void * dm_type_void_star (void * p) { return p; } ++typedef int myint; ++int dm_type_typedef (myint i) { return i; } +diff --git a/gdb/testsuite/gdb.cp/cplusfuncs.exp b/gdb/testsuite/gdb.cp/cplusfuncs.exp +index 5e08768..8c8e038 100644 +--- a/gdb/testsuite/gdb.cp/cplusfuncs.exp ++++ b/gdb/testsuite/gdb.cp/cplusfuncs.exp +@@ -66,9 +66,25 @@ set dm_type_unsigned_int "unsigned" + set dm_type_void "" + set dm_type_void_star "void*" + ++# Some other vagaries of GDB's type printing machinery. The integer types ++# may have unsigned before or after their length, and may have "int" ++# appended. The char* conversion operator may have name "char*" even if ++# the type is "char *", because the name comes from the debug information ++# and the type from GDB. Function types may not see through typedefs. ++ ++set dm_type_short "short" ++set dm_type_long "long" ++set dm_type_unsigned_short "unsigned short" ++set dm_type_unsigned_long "unsigned long" ++set dm_operator_char_star "char*" ++set dm_operator_char_star_quoted "char\\*" ++set dm_type_typedef 0 ++ + proc probe_demangler { } { + global gdb_prompt + global dm_operator_comma ++ global dm_operator_char_star ++ global dm_operator_char_star_quoted + global dm_type_char_star + global dm_type_char_star_quoted + global dm_type_foo_ref +@@ -77,6 +93,11 @@ proc probe_demangler { } { + global dm_type_unsigned_int + global dm_type_void + global dm_type_void_star ++ global dm_type_short ++ global dm_type_unsigned_short ++ global dm_type_long ++ global dm_type_unsigned_long ++ global dm_type_typedef + + send_gdb "print &'foo::operator,(foo&)'\n" + gdb_expect { +@@ -97,6 +118,26 @@ proc probe_demangler { } { + } + } + ++ send_gdb "print &'foo::operator char*()'\n" ++ gdb_expect { ++ -re ".*foo::operator char \\*\\(void\\).*\r\n$gdb_prompt $" { ++ # v2 demangler or GDB type printer ++ set dm_operator_char_star "char *" ++ set dm_operator_char_star_quoted "char \\*" ++ pass "detect dm_operator_char_star" ++ } ++ -re ".*foo::operator char\\*\\(\\).*\r\n$gdb_prompt $" { ++ # v3 demangler ++ pass "detect dm_operator_char_star" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "detect dm_operator_char_star" ++ } ++ timeout { ++ fail "detect dm_operator_char_star" ++ } ++ } ++ + send_gdb "print &'dm_type_char_star'\n" + gdb_expect { + -re ".*dm_type_char_star\\(char \\*\\).*\r\n$gdb_prompt $" { +@@ -166,6 +207,11 @@ proc probe_demangler { } { + # v3 demangler + pass "detect dm_type_long_star" + } ++ -re ".*dm_type_long_star\\(long int \\*\\).*\r\n$gdb_prompt $" { ++ # GCC v3 and GDB's type printer ++ set dm_type_long_star "long int *" ++ pass "detect dm_type_long_star" ++ } + -re ".*$gdb_prompt $" { + fail "detect dm_type_long_star" + } +@@ -230,6 +276,101 @@ proc probe_demangler { } { + fail "detect dm_type_void_star (timeout)" + } + } ++ ++ send_gdb "print &'dm_type_short'\n" ++ gdb_expect { ++ -re ".*dm_type_short\\(short\\).*\r\n$gdb_prompt $" { ++ # v2 and v3 demanglers ++ pass "detect dm_type_short" ++ } ++ -re ".*dm_type_short\\(short int\\).*\r\n$gdb_prompt $" { ++ # GDB type printer ++ set dm_type_short "short int" ++ pass "detect dm_type_short" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "detect dm_type_short" ++ } ++ timeout { ++ fail "detect dm_type_short (timeout)" ++ } ++ } ++ ++ send_gdb "print &'dm_type_unsigned_short'\n" ++ gdb_expect { ++ -re ".*dm_type_unsigned_short\\(unsigned short\\).*\r\n$gdb_prompt $" { ++ # v2 and v3 demanglers ++ pass "detect dm_type_unsigned_short" ++ } ++ -re ".*dm_type_unsigned_short\\(short unsigned int\\).*\r\n$gdb_prompt $" { ++ # GDB type printer ++ set dm_type_unsigned_short "short unsigned int" ++ pass "detect dm_type_unsigned_short" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "detect dm_type_unsigned_short" ++ } ++ timeout { ++ fail "detect dm_type_unsigned_short (timeout)" ++ } ++ } ++ ++ send_gdb "print &'dm_type_long'\n" ++ gdb_expect { ++ -re ".*dm_type_long\\(long\\).*\r\n$gdb_prompt $" { ++ # v2 and v3 demanglers ++ pass "detect dm_type_long" ++ } ++ -re ".*dm_type_long\\(long int\\).*\r\n$gdb_prompt $" { ++ # GDB type printer ++ set dm_type_long "long int" ++ pass "detect dm_type_long" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "detect dm_type_long" ++ } ++ timeout { ++ fail "detect dm_type_long (timeout)" ++ } ++ } ++ ++ send_gdb "print &'dm_type_unsigned_long'\n" ++ gdb_expect { ++ -re ".*dm_type_unsigned_long\\(unsigned long\\).*\r\n$gdb_prompt $" { ++ # v2 and v3 demanglers ++ pass "detect dm_type_unsigned_long" ++ } ++ -re ".*dm_type_unsigned_long\\(long unsigned int\\).*\r\n$gdb_prompt $" { ++ # GDB type printer ++ set dm_type_unsigned_long "long unsigned int" ++ pass "detect dm_type_unsigned_long" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "detect dm_type_unsigned_long" ++ } ++ timeout { ++ fail "detect dm_type_unsigned_long (timeout)" ++ } ++ } ++ ++ send_gdb "print &'dm_type_typedef'\n" ++ gdb_expect { ++ -re ".*dm_type_typedef\\(int\\).*\r\n$gdb_prompt $" { ++ # v2 and v3 demanglers ++ pass "detect dm_type_typedef" ++ } ++ -re ".*dm_type_typedef\\(myint\\).*\r\n$gdb_prompt $" { ++ # GDB type printer ++ set dm_type_typedef 1 ++ pass "detect dm_type_typedef" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "detect dm_type_typedef" ++ } ++ timeout { ++ fail "detect dm_type_typedef (timeout)" ++ } ++ } + } + + # +@@ -345,8 +486,9 @@ proc print_addr { name } { + + proc test_lookup_operator_functions {} { + global dm_operator_comma ++ global dm_operator_char_star + global dm_type_char_star +- global dm_type_char_star_quoted ++ global dm_operator_char_star_quoted + global dm_type_foo_ref + global dm_type_void + global dm_type_void_star +@@ -404,8 +546,8 @@ proc test_lookup_operator_functions {} { + + info_func "operator int(" "int foo::operator int($dm_type_void);" + info_func "operator()(" "void foo::operator()($dm_type_foo_ref);" +- info_func "operator $dm_type_char_star_quoted\(" \ +- "char *foo::operator $dm_type_char_star\($dm_type_void);" ++ info_func "operator $dm_operator_char_star_quoted\(" \ ++ "char *foo::operator $dm_operator_char_star\($dm_type_void);" + + } + +@@ -420,6 +562,7 @@ proc test_paddr_operator_functions {} { + global dm_type_unsigned_int + global dm_type_void + global dm_type_void_star ++ global dm_operator_char_star + + print_addr "foo::operator*($dm_type_foo_ref)" + print_addr "foo::operator%($dm_type_foo_ref)" +@@ -470,7 +613,7 @@ proc test_paddr_operator_functions {} { + } + + print_addr "foo::operator int($dm_type_void)" +- print_addr "foo::operator $dm_type_char_star\($dm_type_void)" ++ print_addr "foo::operator $dm_operator_char_star\($dm_type_void)" + } + + # +@@ -480,17 +623,21 @@ proc test_paddr_operator_functions {} { + proc test_paddr_overloaded_functions {} { + global dm_type_unsigned_int + global dm_type_void ++ global dm_type_short ++ global dm_type_unsigned_short ++ global dm_type_long ++ global dm_type_unsigned_long + + print_addr "overload1arg($dm_type_void)" + print_addr "overload1arg(char)" + print_addr "overload1arg(signed char)" + print_addr "overload1arg(unsigned char)" +- print_addr "overload1arg(short)" +- print_addr "overload1arg(unsigned short)" ++ print_addr "overload1arg($dm_type_short)" ++ print_addr "overload1arg($dm_type_unsigned_short)" + print_addr "overload1arg(int)" + print_addr "overload1arg($dm_type_unsigned_int)" +- print_addr "overload1arg(long)" +- print_addr "overload1arg(unsigned long)" ++ print_addr "overload1arg($dm_type_long)" ++ print_addr "overload1arg($dm_type_unsigned_long)" + print_addr "overload1arg(float)" + print_addr "overload1arg(double)" + +@@ -513,17 +660,31 @@ proc test_paddr_hairy_functions {} { + global dm_type_char_star + global dm_type_int_star + global dm_type_long_star ++ global dm_type_typedef + + print_addr_2 "hairyfunc1" "hairyfunc1(int)" +- print_addr_2 "hairyfunc2" "hairyfunc2(int (*)($dm_type_char_star))" +- print_addr_2 "hairyfunc3" "hairyfunc3(int (*)(short (*)($dm_type_long_star)))" +- print_addr_2 "hairyfunc4" "hairyfunc4(int (*)(short (*)($dm_type_char_star)))" +- +- # gdb-gnats bug gdb/19: +- # "gdb v3 demangler fails on hairyfunc5 hairyfunc6 hairyfunc7" +- print_addr_2_kfail "hairyfunc5" "hairyfunc5(int (*(*)($dm_type_char_star))(long))" "hairyfunc5(int (*)(long) (*)(char*))" "gdb/19" +- print_addr_2_kfail "hairyfunc6" "hairyfunc6(int (*(*)($dm_type_int_star))(long))" "hairyfunc6(int (*)(long) (*)(int*))" "gdb/19" +- print_addr_2_kfail "hairyfunc7" "hairyfunc7(int (*(*)(int (*)($dm_type_char_star)))(long))" "hairyfunc7(int (*)(long) (*)(int (*)(char*)))" "gdb/19" ++ ++ if {$dm_type_typedef == 0} { ++ print_addr_2 "hairyfunc2" "hairyfunc2(int (*)($dm_type_char_star))" ++ print_addr_2 "hairyfunc3" "hairyfunc3(int (*)(short (*)($dm_type_long_star)))" ++ print_addr_2 "hairyfunc4" "hairyfunc4(int (*)(short (*)($dm_type_char_star)))" ++ ++ # gdb-gnats bug gdb/19: ++ # "gdb v3 demangler fails on hairyfunc5 hairyfunc6 hairyfunc7" ++ print_addr_2_kfail "hairyfunc5" "hairyfunc5(int (*(*)($dm_type_char_star))(long))" "hairyfunc5(int (*)(long) (*)(char*))" "gdb/19" ++ print_addr_2_kfail "hairyfunc6" "hairyfunc6(int (*(*)($dm_type_int_star))(long))" "hairyfunc6(int (*)(long) (*)(int*))" "gdb/19" ++ print_addr_2_kfail "hairyfunc7" "hairyfunc7(int (*(*)(int (*)($dm_type_char_star)))(long))" "hairyfunc7(int (*)(long) (*)(int (*)(char*)))" "gdb/19" ++ } else { ++ print_addr_2 "hairyfunc2" "hairyfunc2(PFPc_i)" ++ print_addr_2 "hairyfunc3" "hairyfunc3(PFPFPl_s_i)" ++ print_addr_2 "hairyfunc4" "hairyfunc4(PFPFPc_s_i)" ++ ++ # gdb-gnats bug gdb/19: ++ # "gdb v3 demangler fails on hairyfunc5 hairyfunc6 hairyfunc7" ++ print_addr_2 "hairyfunc5" "hairyfunc5(PFPc_PFl_i)" ++ print_addr_2 "hairyfunc6" "hairyfunc6(PFPi_PFl_i)" ++ print_addr_2 "hairyfunc7" "hairyfunc7(PFPFPc_i_PFl_i)" ++ } + } + + proc do_tests {} { +diff --git a/gdb/testsuite/gdb.cp/expand-sals.cc b/gdb/testsuite/gdb.cp/expand-sals.cc +new file mode 100644 +index 0000000..6169a05 +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/expand-sals.cc +@@ -0,0 +1,53 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright (C) 2009 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 3 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, see . */ ++ ++int ++func () ++{ ++ return 42; /* func-line */ ++} ++ ++volatile int global_x; ++ ++class A ++{ ++public: ++ A () ++ { ++ global_x = func (); /* caller-line */ ++ } ++}; ++ ++/* class B is here just to make the `func' calling line above having multiple ++ instances - multiple locations. Template cannot be used as its instances ++ would have different function names which get discarded by GDB ++ expand_line_sal_maybe. */ ++ ++class B : public A ++{ ++}; ++ ++int ++main (void) ++{ ++ A a; ++ B b; ++ ++ return 0; /* exit-line */ ++} +diff --git a/gdb/testsuite/gdb.cp/expand-sals.exp b/gdb/testsuite/gdb.cp/expand-sals.exp +new file mode 100644 +index 0000000..6e04cbf +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/expand-sals.exp +@@ -0,0 +1,100 @@ ++# Copyright 2009 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 3 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, see . ++ ++if { [skip_cplus_tests] } { continue } ++ ++set srcfile expand-sals.cc ++if { [prepare_for_testing expand-sals.exp expand-sals $srcfile {debug c++}] } { ++ return -1 ++} ++if ![runto_main] { ++ return -1 ++} ++ ++gdb_breakpoint [gdb_get_line_number "exit-line"] ++ ++gdb_breakpoint [gdb_get_line_number "func-line"] ++gdb_continue_to_breakpoint "func" ".*func-line.*" ++ ++gdb_test "up" "caller-line.*" ++ ++# PC should not be at the boundary of source lines to make the original bug ++# exploitable. ++ ++set test "p/x \$pc" ++set pc {} ++gdb_test_multiple $test $test { ++ -re "\\$\[0-9\]+ = (0x\[0-9a-f\]+)\r\n$gdb_prompt $" { ++ set pc $expect_out(1,string) ++ pass $test ++ } ++} ++ ++set test "info line" ++set end {} ++gdb_test_multiple $test $test { ++ -re "Line \[0-9\]+ of .* starts at address 0x\[0-9a-f\]+.* and ends at (0x\[0-9a-f\]+).*\\.\r\n$gdb_prompt $" { ++ set end $expect_out(1,string) ++ pass $test ++ } ++} ++ ++set test "caller line has trailing code" ++if {$pc != $end} { ++ pass $test ++} else { ++ fail $test ++} ++ ++# Original problem was an internal error here. Still sanity multiple locations ++# were found at this code place as otherwise this test would not test anything. ++set test "break" ++gdb_test_multiple $test $test { ++ -re "Breakpoint \[0-9\]+ at .*, line \[0-9\]+\\. \\(\[2-9\] locations\\)\r\n$gdb_prompt $" { ++ pass $test ++ } ++ -re "Breakpoint \[0-9\]+ at .*, line \[0-9\]+\\.\r\n$gdb_prompt $" { ++ # It just could not be decided if GDB is OK by this testcase. ++ setup_xfail *-*-* ++ fail $test ++ return 0 ++ } ++} ++ ++gdb_continue_to_breakpoint "caller" ".*caller-line.*" ++ ++# Test GDB caught this return call and not the next one through B::B() ++gdb_test "bt" \ ++ "#0 \[^\r\n\]* (A::)?A \[^\r\n\]*\r\n#1 \[^\r\n\]* main \[^\r\n\]*" \ ++ "bt from A" ++ ++gdb_continue_to_breakpoint "next caller instance" ".*caller-line.*" ++ ++# Test that GDB caught now already A through B::B() in the other instance. ++# As discussed in GDB expand_line_sal_maybe it would more match the original ++# instance behavior to catch here the `func' breakpoint and catch the ++# multiple-locations breakpoint only during the call return. This is not the ++# case, expecting here to catch the breakpoint before the call happens. ++ ++gdb_test "bt" \ ++ "#0 \[^\r\n\]* (A::)?A \[^\r\n\]*\r\n#1 \[^\r\n\]* (B::)?B \[^\r\n\]*\r\n#2 \[^\r\n\]* main \[^\r\n\]*" \ ++ "bt from B before the call" ++ ++gdb_continue_to_breakpoint "next caller func" ".*func-line.*" ++ ++# Verify GDB really could not catch the originally intended point of the return ++# from func. ++ ++gdb_continue_to_breakpoint "uncaught return" ".*exit-line.*" +diff --git a/gdb/testsuite/gdb.cp/gdb1355.exp b/gdb/testsuite/gdb.cp/gdb1355.exp +index 77687a6..66d16cf 100644 +--- a/gdb/testsuite/gdb.cp/gdb1355.exp ++++ b/gdb/testsuite/gdb.cp/gdb1355.exp +@@ -68,11 +68,11 @@ set s_tail ".*" + + set f_i "${ws}int m_int;" + set f_c "${ws}char m_char;" +-set f_li "${ws}long int m_long_int;" ++set f_li "${ws}long m_long_int;" + set f_ui "${ws}unsigned int m_unsigned_int;" +-set f_lui "${ws}long unsigned int m_long_unsigned_int;" +-set f_si "${ws}short int m_short_int;" +-set f_sui "${ws}short unsigned int m_short_unsigned_int;" ++set f_lui "${ws}unsigned long m_long_unsigned_int;" ++set f_si "${ws}short m_short_int;" ++set f_sui "${ws}unsigned short m_short_unsigned_int;" + set f_uc "${ws}unsigned char m_unsigned_char;" + set f_f "${ws}float m_float;" + set f_d "${ws}double m_double;" +diff --git a/gdb/testsuite/gdb.cp/gdb2495.cc b/gdb/testsuite/gdb.cp/gdb2495.cc +new file mode 100644 +index 0000000..4df265f +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/gdb2495.cc +@@ -0,0 +1,90 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . ++ */ ++ ++#include ++#include ++ ++using namespace std; ++ ++class SimpleException ++{ ++ ++public: ++ ++ void raise_signal (int dummy) ++ { ++ if (dummy > 0) ++ raise(SIGABRT); ++ } ++ ++ int no_throw_function () ++ { ++ return 1; ++ } ++ ++ void throw_function () ++ { ++ throw 1; ++ } ++ ++ int throw_function_with_handler () ++ { ++ try ++ { ++ throw 1; ++ } ++ catch (...) ++ { ++ cout << "Handled" << endl; ++ } ++ ++ return 2; ++ } ++ ++ void call_throw_function_no_handler () ++ { ++ throw_function (); ++ } ++ ++ void call_throw_function_handler () ++ { ++ throw_function_with_handler (); ++ } ++}; ++SimpleException exceptions; ++ ++int ++main() ++{ ++ // Have to call all these functions ++ // so not optimized away. ++ exceptions.raise_signal (-1); ++ exceptions.no_throw_function (); ++ exceptions.throw_function_with_handler (); ++ exceptions.call_throw_function_handler (); ++ try ++ { ++ exceptions.throw_function (); ++ exceptions.call_throw_function_no_handler (); ++ } ++ catch (...) ++ { ++ } ++ return 0; ++} ++ +diff --git a/gdb/testsuite/gdb.cp/gdb2495.exp b/gdb/testsuite/gdb.cp/gdb2495.exp +new file mode 100644 +index 0000000..62c09c2 +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/gdb2495.exp +@@ -0,0 +1,160 @@ ++# Copyright 2008 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 3 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, see . ++ ++ ++# In gdb inferior function calls, if a C++ exception is raised in the ++# dummy-frame, and the exception handler is (normally, and expected to ++# be) out-of-frame, the default C++ handler will (wrongly) be called ++# in an inferior function call. ++# This is incorrect as an exception can normally and legally be handled ++# out-of-frame. The confines of the dummy frame prevent the unwinder ++# from finding the correct handler (or any handler, unless it is ++# in-frame). The default handler calls std::terminate. This will kill ++# the inferior. Assert that terminate should never be called in an ++# inferior function call. These tests test the functionality around ++# unwinding that sequence and also tests the flag behaviour gating this ++# functionality. ++ ++# This test is largley based off gdb.base/callfuncs.exp. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++if { [skip_cplus_tests] } { continue } ++ ++set prms_id 2495 ++set bug_id 0 ++ ++set testfile "gdb2495" ++set srcfile ${testfile}.cc ++set binfile $objdir/$subdir/$testfile ++ ++# Create and source the file that provides information about the compiler ++# used to compile the test case. ++if [get_compiler_info ${binfile} "c++"] { ++ return -1 ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { ++ untested gdb2495.exp ++ return -1 ++} ++ ++# Some targets can't do function calls, so don't even bother with this ++# test. ++if [target_info exists gdb,cannot_call_functions] { ++ setup_xfail "*-*-*" 2416 ++ fail "This target can not call functions" ++ continue ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto_main] then { ++ perror "couldn't run to main" ++ continue ++} ++ ++# See http://sources.redhat.com/gdb/bugs/2495 ++ ++# Test normal baseline behaviour. Call a function that ++# does not raise an exception ... ++gdb_test "p exceptions.no_throw_function()" " = 1" ++# And one that does but handles it in-frame ... ++gdb_test "p exceptions.throw_function_with_handler()" " = 2" ++# Both should return normally. ++ ++# Test basic unwind. Call a function that raises an exception but ++# does not handle it. It should be rewound ... ++gdb_test "p exceptions.throw_function()" \ ++ "The program being debugged entered a std::terminate call .*" \ ++ "Call a function that raises an exception without a handler." ++ ++# Make sure that after rewinding we are back at the call parent. ++gdb_test "bt" \ ++ "#0 main.*" \ ++ "bt after returning from a popped frame" ++ ++# Make sure the only breakpoint is the one set via the runto_main ++# call and that the std::terminate breakpoint has evaporated and ++# cleaned-up. ++gdb_test "info breakpoints" \ ++ "gdb.cp/gdb2495\.cc.*" ++ ++# Turn off this new behaviour ... ++send_gdb "set unwind-on-terminating-exception off\n" ++gdb_expect { ++ -re "$gdb_prompt $" {pass "set unwind-on-terminating-exception"} ++ timeout {fail "(timeout) set unwind-on-terminating-exception"} ++} ++ ++# Check that it is turned off ... ++gdb_test "show unwind-on-terminating-exception" \ ++ "exception is unhandled while in a call dummy is off.*" \ ++ "Turn off unwind on terminating exception flag" ++ ++# Check that the old behaviour is restored. ++gdb_test "p exceptions.throw_function()" \ ++ "The program being debugged stopped while in a function called .*" \ ++ "Call a function that raises an exception with unwinding off.." ++ ++ ++# Restart back at main ++if ![runto_main] then { ++ perror "couldn't run to main" ++ continue ++} ++ ++ ++# Check to see if our new behaviour alters the unwind signal ++# behaviour. It should not. Test both on and off states. ++ ++# Turn on unwind on signal behaviour ... ++send_gdb "set unwindonsignal on\n" ++gdb_expect { ++ -re "$gdb_prompt $" {pass "set unwindonsignal on"} ++ timeout {fail "(timeout) set unwindonsignal on"} ++} ++ ++# Check that it is turned on ... ++gdb_test "show unwindonsignal" \ ++ "signal is received while in a call dummy is on.*" \ ++ "Turn on unwind on signal" ++ ++# Check to see if new behaviour interferes with ++# normal signal handling in inferior function calls. ++gdb_test "p exceptions.raise_signal(1)" \ ++ "To change this behavior use \"set unwindonsignal off\".*" ++ ++# And reverse. Turn off ++send_gdb "set unwindonsignal off\n" ++gdb_expect { ++ -re "$gdb_prompt $" {pass "set unwindonsignal off"} ++ timeout {fail "(timeout) set unwindonsignal off"} ++} ++ ++# Check that it is turned off ... ++gdb_test "show unwindonsignal" \ ++ "signal is received while in a call dummy is off.*" \ ++ "Turn off unwind on signal" ++ ++# Check to see if new behaviour interferes with ++# normal signal handling in inferior function calls. ++gdb_test "p exceptions.raise_signal(1)" \ ++ "To change this behavior use \"set unwindonsignal on\".*" +diff --git a/gdb/testsuite/gdb.cp/member-ptr.cc b/gdb/testsuite/gdb.cp/member-ptr.cc +index 1dff70a..648b2af 100644 +--- a/gdb/testsuite/gdb.cp/member-ptr.cc ++++ b/gdb/testsuite/gdb.cp/member-ptr.cc +@@ -138,6 +138,7 @@ class Diamond : public Padding, public Left, public Right + { + public: + virtual int vget_base (); ++ int (*func_ptr) (int); + }; + + int Diamond::vget_base () +@@ -145,6 +146,12 @@ int Diamond::vget_base () + return this->Left::x + 2000; + } + ++int ++func (int x) ++{ ++ return 19 + x; ++} ++ + int main () + { + A a; +@@ -162,6 +169,7 @@ int main () + int (Diamond::*right_vpmf) (); + int (Base::*base_vpmf) (); + int Diamond::*diamond_pmi; ++ int (* Diamond::*diamond_pfunc_ptr) (int); + + PMI null_pmi; + PMF null_pmf; +@@ -179,6 +187,7 @@ int main () + + diamond.Left::x = 77; + diamond.Right::x = 88; ++ diamond.func_ptr = func; + + /* Some valid pointer to members from a base class. */ + left_pmf = (int (Diamond::*) ()) (int (Left::*) ()) (&Base::get_x); +@@ -193,11 +202,19 @@ int main () + /* A pointer to data member from a base class. */ + diamond_pmi = (int Diamond::*) (int Left::*) &Base::x; + ++ /* A pointer to data member, where the member is itself a pointer to ++ a function. */ ++ diamond_pfunc_ptr = (int (* Diamond::*) (int)) &Diamond::func_ptr; ++ + null_pmi = NULL; + null_pmf = NULL; + + pmi = NULL; /* Breakpoint 1 here. */ + ++ // Invalid (uses diamond_pfunc_ptr as a function): ++ // diamond.*diamond_pfunc_ptr (20); ++ (diamond.*diamond_pfunc_ptr) (20); ++ + k = (a.*pmf)(3); + + pmi = &A::jj; +diff --git a/gdb/testsuite/gdb.cp/member-ptr.exp b/gdb/testsuite/gdb.cp/member-ptr.exp +index b69d4ad..476711f 100644 +--- a/gdb/testsuite/gdb.cp/member-ptr.exp ++++ b/gdb/testsuite/gdb.cp/member-ptr.exp +@@ -390,6 +390,33 @@ gdb_test_multiple "print ((int) pmi) == ((char *) &a.j - (char *) & a)" $name { + } + } + ++# Check pointers to data members, which are themselves pointers to ++# functions. These behave like data members, not like pointers to ++# member functions. ++ ++gdb_test "ptype diamond_pfunc_ptr" \ ++ "type = int \\(\\*Diamond::\\*\\)\\(int\\)" ++ ++gdb_test "ptype diamond.*diamond_pfunc_ptr" \ ++ "type = int \\(\\*\\)\\(int\\)" ++ ++# This one is invalid; () binds more tightly than .*, so it tries to ++# call the member pointer as a normal pointer-to-function. ++ ++gdb_test "print diamond.*diamond_pfunc_ptr (20)" \ ++ "Invalid data type for function to be called." ++ ++# With parentheses, it is valid. ++ ++gdb_test "print (diamond.*diamond_pfunc_ptr) (20)" \ ++ "$vhn = 39" ++ ++# Make sure that we do not interpret this as either a member pointer ++# call or a member function call. ++ ++gdb_test "print diamond.func_ptr (20)" \ ++ "$vhn = 39" ++ + # ========================== + # pointer to member function + # ========================== +@@ -608,6 +635,9 @@ gdb_test_multiple "print (a.*pmf)(3)" $name { + } + } + ++gdb_test "ptype a.*pmf" "type = int \\(A \\*, int\\)" ++gdb_test "ptype (a.*pmf)(3)" "type = int" ++ + # Print out a pointer to data member which requires looking into + # a base class. + gdb_test "print diamond_pmi" "$vhn = &Base::x" +diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc +new file mode 100644 +index 0000000..6b180d6 +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc +@@ -0,0 +1,20 @@ ++namespace A { ++ int x = 11; ++ namespace{ ++ int xx = 22; ++ } ++} ++ ++using namespace A; ++ ++namespace{ ++ int xxx = 33; ++}; ++ ++int main() ++{ ++ x; ++ xx; ++ xxx; ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp +new file mode 100644 +index 0000000..e4bb9f8 +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp +@@ -0,0 +1,49 @@ ++# Copyright 2008 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 3 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, see . ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile namespace-multiple-imports ++set srcfile ${testfile}.cc ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++############################################ ++# test printing of namespace imported within ++# the function. ++ ++if ![runto_main] then { ++ perror "couldn't run to breakpoint main" ++ continue ++} ++ ++gdb_test "print x" "\\$\[0-9\].* = 11" ++gdb_test "print xx" "\\$\[0-9\].* = 22" ++gdb_test "print xxx" "\\$\[0-9\].* = 33" +diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc +new file mode 100644 +index 0000000..97af850 +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/namespace-using.cc +@@ -0,0 +1,131 @@ ++//-------------------------- ++namespace M{ ++ int x = 911; ++} ++ ++namespace N{ ++ int x = 912; ++} ++ ++int marker10(){ ++ using namespace M; ++ int y = x+1; // marker10 stop ++ using namespace N; ++ return y; ++} ++//-------------------------- ++namespace J { ++ int jx = 44; ++} ++ ++namespace K{ ++ int marker9(){ ++ //x; ++ return marker10(); ++ } ++} ++ ++namespace L{ ++ using namespace J; ++ int marker8(){ ++ jx; ++ return K::marker9(); ++ } ++} ++//-------------------------- ++ ++//-------------------------- ++namespace G{ ++ namespace H { ++ int ghx = 6; ++ } ++} ++ ++namespace I{ ++ ++ int marker7(){ ++ using namespace G::H; ++ ghx; ++ return L::marker8(); ++ } ++} ++//-------------------------- ++ ++//-------------------------- ++namespace E{ ++ namespace F{ ++ int efx = 5; ++ } ++} ++using namespace E::F; ++int marker6(){ ++ efx; ++ return I::marker7(); ++} ++//-------------------------- ++ ++namespace A ++{ ++ int _a = 1; ++ int x = 2; ++ ++} ++ ++namespace C ++{ ++ int cc = 3; ++} ++ ++namespace D ++{ ++ int dx = 4; ++} ++ ++using namespace C; ++int marker5() ++{ ++ cc; ++ return marker6(); ++} ++ ++int marker4() ++{ ++ using D::dx; ++ return marker5(); ++} ++ ++int marker3() ++{ ++ return marker4(); ++} ++ ++int marker2() ++{ ++ namespace B = A; ++ B::_a; ++ return marker3(); ++} ++ ++int marker1() ++{ ++ int total = 0; ++ { ++ int b = 1; ++ { ++ using namespace A; ++ int c = 2; ++ { ++ int d = 3; ++ total = _a + b + c + d + marker2(); // marker1 stop ++ } ++ } ++ } ++ return total; ++} ++ ++int main() ++{ ++ using namespace A; ++ _a; ++ return marker1(); ++} +diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp +new file mode 100644 +index 0000000..ab6e6a4 +--- /dev/null ++++ b/gdb/testsuite/gdb.cp/namespace-using.exp +@@ -0,0 +1,183 @@ ++# Copyright 2008 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 3 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, see . ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile namespace-using ++set srcfile ${testfile}.cc ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++############################################ ++# test printing of namespace imported within ++# the function. ++ ++if ![runto_main] then { ++ perror "couldn't run to breakpoint main" ++ continue ++} ++ ++gdb_test "print _a" "= 1" ++ ++# Test that names are not printed when they ++# are not imported ++ ++gdb_breakpoint marker3 ++gdb_continue_to_breakpoint "marker3" ++ ++#send_gdb "break marker3\n" ++#send_gdb "continue\n" ++ ++gdb_test "print _a" "No symbol \"_a\" in current context." "Print _a without import" ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++ ++############################################ ++# test printing of namespace imported into ++# a scope containing the pc. ++ ++if ![runto_main] then { ++ perror "couldn't run to breakpoint main" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "marker1 stop"] ++gdb_continue_to_breakpoint "marker1 stop" ++ ++gdb_test "print _a" "= 1" "print _a in a nested scope" ++ ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++############################################ ++# test printing of namespace imported into ++# file scope. ++ ++ ++if ![runto marker5] then { ++ perror "couldn't run to breakpoint marker5" ++ continue ++} ++ ++gdb_test "print cc" "= 3" ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++ ++############################################ ++# Test printing of namespace aliases ++ ++if ![runto marker2] then { ++ perror "couldn't run to breakpoint marker2" ++ continue ++} ++ ++gdb_test "print B::_a" "= 1" ++ ++gdb_test "print _a" "No symbol \"_a\" in current context." "print _a in namespace alias scope" ++gdb_test "print x" "No symbol \"x\" in current context." "print x in namespace alias scope" ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++ ++############################################ ++# Test printing of namespace aliases ++ ++if ![runto marker4] then { ++ perror "couldn't run to breakpoint marker4" ++ continue ++} ++ ++gdb_test "print dx" "= 4" ++ ++############################################ ++# Test printing of namespace aliases ++ ++if ![runto marker6] then { ++ perror "couldn't run to breakpoint marker6" ++ continue ++} ++ ++gdb_test "print efx" "= 5" ++ ++############################################ ++# Test printing of variables imported from ++# nested namespaces ++ ++if ![runto I::marker7] then { ++ perror "couldn't run to breakpoint I::marker7" ++ continue ++} ++ ++gdb_test "print ghx" "= 6" ++ ++############################################ ++# Test that variables are not printed in a namespace ++# that is sibling to the namespace containing an import ++ ++if ![runto L::marker8] then { ++ perror "couldn't run to breakpoint L::marker8" ++ continue ++} ++ ++gdb_test "print jx" "= 44" ++ ++gdb_breakpoint "K::marker9" ++gdb_continue_to_breakpoint "K::marker9" ++ ++gdb_test "print jx" "No symbol \"jx\" in current context." ++ ++############################################ ++# Test that variables are only printed after the line ++# containing the import ++ ++if ![runto_main] then { ++ perror "couldn't run to breakpoint main" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "marker10 stop"] ++gdb_continue_to_breakpoint "marker10 stop" ++ ++# Assert that M::x is printed and not N::x ++gdb_test "print x" "= 911" "print x (from M::x)" +diff --git a/gdb/testsuite/gdb.cp/namespace.exp b/gdb/testsuite/gdb.cp/namespace.exp +index 76b1b82..2042db2 100644 +--- a/gdb/testsuite/gdb.cp/namespace.exp ++++ b/gdb/testsuite/gdb.cp/namespace.exp +@@ -24,6 +24,7 @@ + # for namespaces. + # Note: As of 2000-06-03, they passed under g++ - djb + ++load_lib "cp-support.exp" + + if $tracelevel then { + strace $tracelevel +@@ -259,11 +260,16 @@ gdb_test "ptype E" "type = namespace C::D::E" + gdb_test "ptype CClass" "type = (class C::CClass \{\r\n public:|struct C::CClass \{)\r\n int x;\r\n\}" + gdb_test "ptype CClass::NestedClass" "type = (class C::CClass::NestedClass \{\r\n public:|struct C::CClass::NestedClass \{)\r\n int y;\r\n\}" + gdb_test "ptype NestedClass" "No symbol \"NestedClass\" in current context." +-setup_kfail "gdb/1448" "*-*-*" +-gdb_test "ptype ::C::CClass" "type = class C::CClass \{\r\n public:\r\n int x;\r\n\}" +-setup_kfail "gdb/1448" "*-*-*" +-gdb_test "ptype ::C::CClass::NestedClass" "type = class C::CClass::NestedClass \{\r\n public:\r\n int y;\r\n\}" +-setup_kfail "gdb/1448" "*-*-*" ++cp_test_ptype_class \ ++ "ptype ::C::CClass" "" "class" "C::CClass" \ ++ { ++ { field public "int x;" } ++ } ++cp_test_ptype_class \ ++ "ptype ::C::CClass::NestedClass" "" "class" "C::CClass::NestedClass" \ ++ { ++ { field public "int y;" } ++ } + gdb_test "ptype ::C::NestedClass" "No symbol \"NestedClass\" in namespace \"C\"." + gdb_test "ptype C::CClass" "No symbol \"CClass\" in namespace \"C::C\"." + gdb_test "ptype C::CClass::NestedClass" "No type \"CClass\" within class or namespace \"C::C\"." +@@ -273,8 +279,11 @@ gdb_test "ptype C::NestedClass" "No symbol \"NestedClass\" in namespace \"C::C\" + + gdb_test "print cOtherFile" "\\$\[0-9\].* = 316" + gdb_test "ptype OtherFileClass" "type = (class C::OtherFileClass \{\r\n public:|struct C::OtherFileClass \{)\r\n int z;\r\n\}" +-setup_kfail "gdb/1448" "*-*-*" +-gdb_test "ptype ::C::OtherFileClass" "type = class C::OtherFileClass \{\r\n public:\r\n int z;\r\n\}" ++cp_test_ptype_class \ ++ "ptype ::C::OtherFileClass" "" "class" "C::OtherFileClass" \ ++ { ++ { field public "int z;" } ++ } + gdb_test "ptype C::OtherFileClass" "No symbol \"OtherFileClass\" in namespace \"C::C\"." + + # Some anonymous namespace tests. +diff --git a/gdb/testsuite/gdb.cp/overload.exp b/gdb/testsuite/gdb.cp/overload.exp +index 24025a2..a72932e 100644 +--- a/gdb/testsuite/gdb.cp/overload.exp ++++ b/gdb/testsuite/gdb.cp/overload.exp +@@ -74,12 +74,12 @@ set re_methods "${re_methods}${ws}int overload1arg\\((void|)\\);" + set re_methods "${re_methods}${ws}int overload1arg\\(char\\);" + set re_methods "${re_methods}${ws}int overload1arg\\(signed char\\);" + set re_methods "${re_methods}${ws}int overload1arg\\(unsigned char\\);" +-set re_methods "${re_methods}${ws}int overload1arg\\(short\\);" +-set re_methods "${re_methods}${ws}int overload1arg\\(unsigned short\\);" ++set re_methods "${re_methods}${ws}int overload1arg\\(short( int)?\\);" ++set re_methods "${re_methods}${ws}int overload1arg\\((unsigned short|short unsigned)( int)?\\);" + set re_methods "${re_methods}${ws}int overload1arg\\(int\\);" + set re_methods "${re_methods}${ws}int overload1arg\\(unsigned int\\);" +-set re_methods "${re_methods}${ws}int overload1arg\\(long\\);" +-set re_methods "${re_methods}${ws}int overload1arg\\(unsigned long\\);" ++set re_methods "${re_methods}${ws}int overload1arg\\(long( int)?\\);" ++set re_methods "${re_methods}${ws}int overload1arg\\((unsigned long|long unsigned)( int)?\\);" + set re_methods "${re_methods}${ws}int overload1arg\\(float\\);" + set re_methods "${re_methods}${ws}int overload1arg\\(double\\);" + set re_methods "${re_methods}${ws}int overloadfnarg\\((void|)\\);" +diff --git a/gdb/testsuite/gdb.cp/ovldbreak.exp b/gdb/testsuite/gdb.cp/ovldbreak.exp +index 8a6b795..897171c 100644 +--- a/gdb/testsuite/gdb.cp/ovldbreak.exp ++++ b/gdb/testsuite/gdb.cp/ovldbreak.exp +@@ -127,10 +127,24 @@ proc set_bp_overloaded {name expectedmenu mychoice bpnumber linenumber} { + } + + # This is the expected menu for overload1arg. +-# Note the arg type variations on lines 6 and 13. ++# Note the arg type variations for void and integer types. + # This accommodates different versions of g++. + +-set menu_overload1arg "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\((unsigned int|unsigned)\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\((void|)\\) at.*$srcfile:110\r\n> $" ++set menu_overload1arg "\\\[0\\\] cancel\r\n" ++append menu_overload1arg "\\\[1\\\] all\r\n" ++append menu_overload1arg "\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n" ++append menu_overload1arg "\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n" ++append menu_overload1arg "\\\[4\\\] foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r\n" ++append menu_overload1arg "\\\[5\\\] foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r\n" ++append menu_overload1arg "\\\[6\\\] foo::overload1arg\\((unsigned int|unsigned)\\) at.*$srcfile:117\r\n" ++append menu_overload1arg "\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n" ++append menu_overload1arg "\\\[8\\\] foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r\n" ++append menu_overload1arg "\\\[9\\\] foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r\n" ++append menu_overload1arg "\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n" ++append menu_overload1arg "\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n" ++append menu_overload1arg "\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n" ++append menu_overload1arg "\\\[13\\\] foo::overload1arg\\((void|)\\) at.*$srcfile:110\r\n" ++append menu_overload1arg "> $" + + # Set multiple-symbols to "ask", to allow us to test the use + # of the multiple-choice menu when breaking on an overloaded method. +@@ -157,17 +171,17 @@ set_bp_overloaded "foo::overload1arg" "$menu_overload1arg" 13 13 110 + + gdb_test "info break" \ + "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main(\\(void\\))? at.*$srcfile:49\r + \[\t \]+breakpoint already hit 1 time\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short\\) at.*$srcfile:114\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long\\) at.*$srcfile:118\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \ +@@ -215,17 +229,17 @@ gdb_expect { + + gdb_test "info break" \ + "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main(\\(void\\))? at.*$srcfile:49\r + \[\t \]+breakpoint already hit 1 time\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short\\) at.*$srcfile:114\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long\\) at.*$srcfile:118\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \ +@@ -296,12 +310,12 @@ gdb_test "info break" \ + "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long\\) at.*$srcfile:118\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r +-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short\\) at.*$srcfile:114\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r ++\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r +diff --git a/gdb/testsuite/gdb.cp/ref-types.exp b/gdb/testsuite/gdb.cp/ref-types.exp +index 4784cb2..b2e55cf 100644 +--- a/gdb/testsuite/gdb.cp/ref-types.exp ++++ b/gdb/testsuite/gdb.cp/ref-types.exp +@@ -284,7 +284,7 @@ gdb_expect { + + send_gdb "print UC\n" + gdb_expect { +- -re ".\[0-9\]* = 21 '\.025'\.*$gdb_prompt $" { ++ -re ".\[0-9\]* = 21 '\.25'\.*$gdb_prompt $" { + pass "print value of UC" + } + -re ".*$gdb_prompt $" { fail "print value of UC" } +@@ -557,7 +557,7 @@ gdb_expect { + + send_gdb "print rUC\n" + gdb_expect { +- -re ".\[0-9\]* = \\(unsigned char &\\) @$hex: 21 \'.025\'.*$gdb_prompt $" { ++ -re ".\[0-9\]* = \\(unsigned char &\\) @$hex: 21 \'.25\'.*$gdb_prompt $" { + pass "print value of rUC" + } + -re ".*$gdb_prompt $" { fail "print value of rUC" } +diff --git a/gdb/testsuite/gdb.cp/templates.exp b/gdb/testsuite/gdb.cp/templates.exp +index cd9b770..f49caff 100644 +--- a/gdb/testsuite/gdb.cp/templates.exp ++++ b/gdb/testsuite/gdb.cp/templates.exp +@@ -329,13 +329,11 @@ gdb_expect { + + send_gdb "print Foo::foo\n" + gdb_expect { +- -re "\\$\[0-9\]* = \\{.*char \\*\\((class |)Foo \\*(| const), int, .*char \\*\\)\\} $hex ::foo\\(int, .*char.*\\*\\)>\r\n$gdb_prompt $" { pass "print Foo::foo" } ++ -re "\\$\[0-9\]* = \\{.*char \\*\\((class |)Foo<(volatile char|char volatile) ?\\*> \\*(| const), int, .*char \\*\\)\\} $hex ::foo\\(int, .*char.*\\*\\)>\r\n$gdb_prompt $" { pass "print Foo::foo" } + -re "No symbol \"Foo\" in current context.\r\n$gdb_prompt $" + { +- # This used to be a kfail gdb/33. That problem has been +- # fixed, but now gdb/931 and gdb/1512 are rearing their ugly +- # heads. +- kfail "gdb/931" "print Foo::foo" ++ # This used to be a kfail gdb/33 and then kfail gdb/931. ++ fail "print Foo::foo" + } + -re "$gdb_prompt $" { fail "print Foo::foo" } + timeout { fail "(timeout) print Foo::foo" } +@@ -343,13 +341,11 @@ gdb_expect { + + send_gdb "print Foo::foo\n" + gdb_expect { +- -re "\\$\[0-9\]* = \\{.*char \\*\\((class |)Foo \\*(| const), int, .*char \\*\\)\\} $hex ::foo\\(int, .*char.*\\*\\)>\r\n$gdb_prompt $" { pass "print Foo::foo" } ++ -re "\\$\[0-9\]* = \\{.*char \\*\\((class |)Foo<(volatile char|char volatile) ?\\*> \\*(| const), int, .*char \\*\\)\\} $hex ::foo\\(int, .*char.*\\*\\)>\r\n$gdb_prompt $" { pass "print Foo::foo" } + -re "No symbol \"Foo\" in current context.\r\n$gdb_prompt $" + { +- # This used to be a kfail gdb/33. That problem has been +- # fixed, but now gdb/931 and gdb/1512 are rearing their ugly +- # heads. +- kfail "gdb/931" "print Foo::foo" ++ # This used to be a kfail gdb/33 and then kfail gdb/931. ++ fail "print Foo::foo" + } + -re "$gdb_prompt $" { fail "print Foo::foo" } + timeout { fail "(timeout) print Foo::foo" } +@@ -459,7 +455,7 @@ send_gdb "ptype quxint\n" + gdb_expect { + -re "type = class Qux \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*.*int qux\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint" } + -re "type = class Qux \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int qux\\(int, int\\);.*\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint" } +- -re "type = class Qux \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int qux\\(int, int\\);.*\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint" } ++ -re "type = class Qux \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int qux\\(int, int\\);.*\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint" } + -re "type = class Qux \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int qux\\(int, int\\);.*\r\n\\}\r\n$gdb_prompt $" { + kfail "gdb/1512" "ptype quxint" + } +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.c b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c +new file mode 100644 +index 0000000..1f02d90 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c +@@ -0,0 +1,42 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 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. */ ++ ++ ++/* The function `func1' traced into must have debug info on offset > 0; ++ (DW_UNSND (attr)). This is the reason of `func0' existence. */ ++ ++void ++func0(int a, int b) ++{ ++} ++ ++/* `func1' being traced into must have some arguments to dump. */ ++ ++void ++func1(int a, int b) ++{ ++ func0 (a,b); ++} ++ ++int ++main(void) ++{ ++ func1 (1, 2); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp +new file mode 100644 +index 0000000..1c6e84a +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp +@@ -0,0 +1,79 @@ ++# Copyright 2006 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. ++ ++# Minimal DWARF-2 unit test ++ ++# This test can only be run on targets which support DWARF-2. ++# For now pick a sampling of likely targets. ++if {![istarget *-*-linux*] ++ && ![istarget *-*-gnu*] ++ && ![istarget *-*-elf*] ++ && ![istarget *-*-openbsd*] ++ && ![istarget arm-*-eabi*] ++ && ![istarget powerpc-*-eabi*]} { ++ return 0 ++} ++ ++set testfile "dw2-stripped" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile}.x ++ ++remote_exec build "rm -f ${binfile}" ++ ++# get the value of gcc_compiled ++if [get_compiler_info ${binfile}] { ++ return -1 ++} ++ ++# This test can only be run on gcc as we use additional_flags=FIXME ++if {$gcc_compiled == 0} { ++ return 0 ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-ggdb3}] != "" } { ++ return -1 ++} ++ ++remote_exec build "objcopy -R .debug_loc ${binfile}" ++set strip_output [remote_exec build "objdump -h ${binfile}"] ++ ++set test "stripping test file preservation" ++if [ regexp ".debug_info " $strip_output] { ++ pass "$test (.debug_info preserved)" ++} else { ++ fail "$test (.debug_info got also stripped)" ++} ++ ++set test "stripping test file functionality" ++if [ regexp ".debug_loc " $strip_output] { ++ fail "$test (.debug_loc still present)" ++} else { ++ pass "$test (.debug_loc stripped)" ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# For C programs, "start" should stop in main(). ++ ++gdb_test "start" \ ++ ".*main \\(\\) at .*" \ ++ "start" ++gdb_test "step" \ ++ "func.* \\(.*\\) at .*" \ ++ "step" +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-strp.S b/gdb/testsuite/gdb.dwarf2/dw2-strp.S +index a1602a5..293cc1b 100644 +--- a/gdb/testsuite/gdb.dwarf2/dw2-strp.S ++++ b/gdb/testsuite/gdb.dwarf2/dw2-strp.S +@@ -28,7 +28,8 @@ + /* CU die */ + .uleb128 1 /* Abbrev: DW_TAG_compile_unit */ + .4byte .Lproducer /* DW_AT_producer */ +- .byte 1 /* DW_AT_language (C) */ ++ /* Use C++ to exploit a bug in parsing DW_AT_name "". */ ++ .byte 4 /* DW_AT_language (C++) - */ + + .Larray_type: + .uleb128 2 /* Abbrev: DW_TAG_array_type */ +@@ -60,6 +61,10 @@ + .Lconst_type: + .uleb128 6 /* Abbrev: DW_TAG_const_type */ + .4byte .Larray_type-.Lcu1_begin/* DW_AT_type */ ++ ++ .uleb128 7 /* Abbrev: DW_TAG_variable (name "") */ ++ .4byte .Lemptyname /* DW_AT_name */ ++ + .byte 0 /* End of children of CU */ + .Lcu1_end: + +@@ -126,6 +131,15 @@ + .uleb128 0x13 /* DW_FORM_ref4 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ ++ ++ .uleb128 7 /* Abbrev code */ ++ .uleb128 0x34 /* DW_TAG_variable */ ++ .byte 0x0 /* DW_children_no */ ++ .uleb128 0x3 /* DW_AT_name */ ++ .uleb128 0xe /* DW_FORM_strp */ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ ++ + .byte 0x0 /* Terminator */ + + /* String table */ +@@ -140,3 +154,5 @@ + .string "a_string" + .Lvarcontents: + .string "hello world!\n" ++.Lemptyname: ++ .string "" +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unresolved-main.c b/gdb/testsuite/gdb.dwarf2/dw2-unresolved-main.c +new file mode 100644 +index 0000000..c24eb96 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/dw2-unresolved-main.c +@@ -0,0 +1,46 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . */ ++ ++#include ++ ++asm (".globl cu_text_start"); ++asm ("cu_text_start:"); ++ ++int ++main (void) ++{ ++ unsigned char var = 1; ++ ++ if (var != 1) ++ abort (); ++ { ++ extern unsigned char var; ++ ++ /* Do not rely on the `extern' DIE output by GCC (GCC PR debug/39563). */ ++asm (".globl extern_block_start"); ++asm ("extern_block_start:"); ++ if (var != 2) ++ abort (); ++asm (".globl extern_block_end"); ++asm ("extern_block_end:"); ++ } ++ ++ return 0; ++} ++ ++asm (".globl cu_text_end"); ++asm ("cu_text_end:"); +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unresolved.S b/gdb/testsuite/gdb.dwarf2/dw2-unresolved.S +new file mode 100644 +index 0000000..4c098f3 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/dw2-unresolved.S +@@ -0,0 +1,171 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2007, 2008, 2009 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 3 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, see . */ ++ ++ .data ++ ++/* VAR1 is wrong here, in the real inferior it is located on stack. As both ++ places are never modified and they are initialized to the same value it ++ makes no difference. Ensure the name clash for "var". */ ++var1: .byte 1 ++ ++ .globl var ++var: .byte 2 ++ ++/* Debug information */ ++ ++ .section .debug_info ++.Lcu1_begin: ++ /* CU header */ ++ .4byte .Lcu1_end - .Lcu1_start /* Length of Compilation Unit */ ++.Lcu1_start: ++ .2byte 2 /* DWARF Version */ ++ .4byte .Labbrev1_begin /* Offset into abbrev section */ ++ .byte 4 /* Pointer size */ ++ ++ /* CU die */ ++ .uleb128 1 /* Abbrev: DW_TAG_compile_unit */ ++ .4byte cu_text_end /* DW_AT_high_pc */ ++ .4byte cu_text_start /* DW_AT_low_pc */ ++ .ascii "dw2-unresolved-main.c\0" /* DW_AT_name */ ++ .ascii "GNU C 4.3.2\0" /* DW_AT_producer */ ++ .byte 1 /* DW_AT_language (C) */ ++ ++.Ltype_uchar: ++ .uleb128 2 /* Abbrev: DW_TAG_base_type */ ++ .ascii "unsigned char\0" /* DW_AT_name */ ++ .byte 1 /* DW_AT_byte_size */ ++ .byte 7 /* DW_AT_encoding */ ++ ++ /* main */ ++ .uleb128 3 /* Abbrev: DW_TAG_subprogram */ ++ .byte 1 /* DW_AT_decl_file */ ++ .byte 2 /* DW_AT_decl_line */ ++ .ascii "main\0" /* DW_AT_name */ ++ .4byte .Ltype_uchar-.Lcu1_begin /* DW_AT_type */ ++ .4byte cu_text_start /* DW_AT_low_pc */ ++ .4byte cu_text_end /* DW_AT_high_pc */ ++ ++ .uleb128 4 /* Abbrev: DW_TAG_variable (location) */ ++ .ascii "var\0" /* DW_AT_name */ ++ .byte 2f - 1f /* DW_AT_location */ ++1: .byte 3 /* DW_OP_addr */ ++/* See VAR1 definition why this DIE is not correct. */ ++ .4byte var1 /* */ ++2: .4byte .Ltype_uchar-.Lcu1_begin /* DW_AT_type */ ++ ++ .uleb128 6 /* Abbrev: DW_TAG_lexical_block */ ++ .4byte extern_block_start /* DW_AT_low_pc */ ++ .4byte extern_block_end /* DW_AT_high_pc */ ++ ++ .uleb128 5 /* Abbrev: DW_TAG_variable (extern) */ ++ .ascii "var\0" /* DW_AT_name */ ++ .4byte .Ltype_uchar-.Lcu1_begin /* DW_AT_type */ ++ .byte 1 /* DW_AT_external */ ++ ++ .byte 0 /* End of children of the lexical block */ ++ ++ .byte 0 /* End of children of main */ ++ ++ .byte 0 /* End of children of CU */ ++ ++.Lcu1_end: ++ ++/* Abbrev table */ ++ .section .debug_abbrev ++.Labbrev1_begin: ++ .uleb128 1 /* Abbrev code */ ++ .uleb128 0x11 /* DW_TAG_compile_unit */ ++ .byte 1 /* has_children */ ++ .uleb128 0x12 /* DW_AT_high_pc */ ++ .uleb128 0x1 /* DW_FORM_addr */ ++ .uleb128 0x11 /* DW_AT_low_pc */ ++ .uleb128 0x1 /* DW_FORM_addr */ ++ .uleb128 0x3 /* DW_AT_name */ ++ .uleb128 0x8 /* DW_FORM_string */ ++ .uleb128 0x25 /* DW_AT_producer */ ++ .uleb128 0x8 /* DW_FORM_string */ ++ .uleb128 0x13 /* DW_AT_language */ ++ .uleb128 0xb /* DW_FORM_data1 */ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ ++ ++ .uleb128 2 /* Abbrev code */ ++ .uleb128 0x24 /* DW_TAG_base_type */ ++ .byte 0 /* has_children */ ++ .uleb128 0x3 /* DW_AT_name */ ++ .uleb128 0x8 /* DW_FORM_string */ ++ .uleb128 0xb /* DW_AT_byte_size */ ++ .uleb128 0xb /* DW_FORM_data1 */ ++ .uleb128 0x3e /* DW_AT_encoding */ ++ .uleb128 0xb /* DW_FORM_data1 */ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ ++ ++ .uleb128 3 /* Abbrev code */ ++ .uleb128 0x2e /* DW_TAG_subprogram */ ++ .byte 1 /* has_children */ ++ .uleb128 0x3a /* DW_AT_decl_file */ ++ .uleb128 0xb /* DW_FORM_data1 */ ++ .uleb128 0x3b /* DW_AT_decl_line */ ++ .uleb128 0xb /* DW_FORM_data1 */ ++ .uleb128 0x3 /* DW_AT_name */ ++ .uleb128 0x8 /* DW_FORM_string */ ++ .uleb128 0x49 /* DW_AT_type */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x11 /* DW_AT_low_pc */ ++ .uleb128 0x1 /* DW_FORM_addr */ ++ .uleb128 0x12 /* DW_AT_high_pc */ ++ .uleb128 0x1 /* DW_FORM_addr */ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ ++ ++ .uleb128 4 /* Abbrev code (location) */ ++ .uleb128 0x34 /* DW_TAG_variable */ ++ .byte 0 /* has_children */ ++ .uleb128 0x3 /* DW_AT_name */ ++ .uleb128 0x8 /* DW_FORM_string */ ++ .uleb128 0x2 /* DW_AT_location */ ++ .uleb128 0xa /* DW_FORM_block1 */ ++ .uleb128 0x49 /* DW_AT_type */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ ++ ++ .uleb128 5 /* Abbrev code (extern) */ ++ .uleb128 0x34 /* DW_TAG_variable */ ++ .byte 0 /* has_children */ ++ .uleb128 0x3 /* DW_AT_name */ ++ .uleb128 0x8 /* DW_FORM_string */ ++ .uleb128 0x49 /* DW_AT_type */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x3f /* DW_AT_external */ ++ .uleb128 0xc /* DW_FORM_flag */ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ ++ ++ .uleb128 6 /* Abbrev code */ ++ .uleb128 0x0b /* DW_TAG_lexical_block */ ++ .byte 1 /* has_children */ ++ .uleb128 0x11 /* DW_AT_low_pc */ ++ .uleb128 0x1 /* DW_FORM_addr */ ++ .uleb128 0x12 /* DW_AT_high_pc */ ++ .uleb128 0x1 /* DW_FORM_addr */ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ ++ ++ .byte 0x0 /* Terminator */ ++ .byte 0x0 /* Terminator */ +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unresolved.exp b/gdb/testsuite/gdb.dwarf2/dw2-unresolved.exp +new file mode 100644 +index 0000000..b955da9 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/dw2-unresolved.exp +@@ -0,0 +1,41 @@ ++# Copyright 2009 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 3 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, see . ++ ++# This test can only be run on targets which support DWARF-2 and use gas. ++# For now pick a sampling of likely targets. ++if {![istarget *-*-linux*] ++ && ![istarget *-*-gnu*] ++ && ![istarget *-*-elf*] ++ && ![istarget *-*-openbsd*] ++ && ![istarget arm-*-eabi*] ++ && ![istarget powerpc-*-eabi*]} { ++ return 0 ++} ++ ++if { [prepare_for_testing dw2-unresolved.exp "dw2-unresolved" {dw2-unresolved-main.c dw2-unresolved.S} {nodebug}] } { ++ return -1 ++} ++ ++if ![runto_main] { ++ return -1 ++} ++ ++# This testcase tests LOC_UNRESOLVED works right. ++ ++gdb_breakpoint "*extern_block_start" ++gdb_continue_to_breakpoint "*extern_block_start" ++ ++# Expect the inner value 2. Value 1 from the outer local block is shadowed. ++gdb_test "print var" "= 2( '.*')?" +diff --git a/gdb/testsuite/gdb.fortran/common-block.exp b/gdb/testsuite/gdb.fortran/common-block.exp +new file mode 100644 +index 0000000..888f6c3 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/common-block.exp +@@ -0,0 +1,101 @@ ++# Copyright 2008 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. ++ ++# This file was written by Jan Kratochvil . ++ ++set testfile "common-block" ++set srcfile ${testfile}.f90 ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto MAIN__] then { ++ perror "couldn't run to breakpoint MAIN__" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "stop-here-out"] ++gdb_continue_to_breakpoint "stop-here-out" ++ ++# Common block naming with source name /foo/: ++# .symtab DW_TAG_common_block's DW_AT_name ++# Intel Fortran foo_ foo_ ++# GNU Fortran foo_ foo ++#set suffix "_" ++set suffix "" ++ ++set int4 {(integer\(kind=4\)|INTEGER\(4\))} ++set real4 {(real\(kind=4\)|REAL\(4\))} ++set real8 {(real\(kind=8\)|REAL\(8\))} ++ ++gdb_test "whatis foo$suffix" "No symbol \"foo$suffix\" in current context." ++gdb_test "ptype foo$suffix" "No symbol \"foo$suffix\" in current context." ++gdb_test "p foo$suffix" "No symbol \"foo$suffix\" in current context." ++gdb_test "whatis fo_o$suffix" "No symbol \"fo_o$suffix\" in current context." ++gdb_test "ptype fo_o$suffix" "No symbol \"fo_o$suffix\" in current context." ++gdb_test "p fo_o$suffix" "No symbol \"fo_o$suffix\" in current context." ++ ++gdb_test "info locals" "ix_x = 11\r\niy_y = 22\r\niz_z = 33\r\nix = 1\r\niy = 2\r\niz = 3" "info locals out" ++gdb_test "info common" "Contents of F77 COMMON block 'fo_o':\r\nix_x = 11\r\niy_y = 22\r\niz_z = 33\r\n\r\nContents of F77 COMMON block 'foo':\r\nix = 1\r\niy = 2\r\niz = 3" "info common out" ++ ++gdb_test "ptype ix" "type = $int4" "ptype ix out" ++gdb_test "ptype iy" "type = $real4" "ptype iy out" ++gdb_test "ptype iz" "type = $real8" "ptype iz out" ++gdb_test "ptype ix_x" "type = $int4" "ptype ix_x out" ++gdb_test "ptype iy_y" "type = $real4" "ptype iy_y out" ++gdb_test "ptype iz_z" "type = $real8" "ptype iz_z out" ++ ++gdb_test "p ix" " = 1 *" "p ix out" ++gdb_test "p iy" " = 2 *" "p iy out" ++gdb_test "p iz" " = 3 *" "p iz out" ++gdb_test "p ix_x" " = 11 *" "p ix_x out" ++gdb_test "p iy_y" " = 22 *" "p iy_y out" ++gdb_test "p iz_z" " = 33 *" "p iz_z out" ++ ++gdb_breakpoint [gdb_get_line_number "stop-here-in"] ++gdb_continue_to_breakpoint "stop-here-in" ++ ++gdb_test "whatis foo$suffix" "No symbol \"foo$suffix\" in current context." "whatis foo$suffix in" ++gdb_test "ptype foo$suffix" "No symbol \"foo$suffix\" in current context." "ptype foo$suffix in" ++gdb_test "p foo$suffix" "No symbol \"foo$suffix\" in current context." "p foo$suffix in" ++gdb_test "whatis fo_o$suffix" "No symbol \"fo_o$suffix\" in current context." "whatis fo_o$suffix in" ++gdb_test "ptype fo_o$suffix" "No symbol \"fo_o$suffix\" in current context." "ptype fo_o$suffix in" ++gdb_test "p fo_o$suffix" "No symbol \"fo_o$suffix\" in current context." "p fo_o$suffix in" ++ ++gdb_test "info locals" "ix = 11\r\niy2 = 22\r\niz = 33\r\nix_x = 1\r\niy_y = 2\r\niz_z2 = 3\r\niy = 5\r\niz_z = 55" "info locals in" ++gdb_test "info common" "Contents of F77 COMMON block 'fo_o':\r\nix = 11\r\niy2 = 22\r\niz = 33\r\n\r\nContents of F77 COMMON block 'foo':\r\nix_x = 1\r\niy_y = 2\r\niz_z2 = 3" "info common in" ++ ++gdb_test "ptype ix" "type = $int4" "ptype ix in" ++gdb_test "ptype iy2" "type = $real4" "ptype iy2 in" ++gdb_test "ptype iz" "type = $real8" "ptype iz in" ++gdb_test "ptype ix_x" "type = $int4" "ptype ix_x in" ++gdb_test "ptype iy_y" "type = $real4" "ptype iy_y in" ++gdb_test "ptype iz_z2" "type = $real8" "ptype iz_z2 in" ++ ++gdb_test "p ix" " = 11 *" "p ix in" ++gdb_test "p iy2" " = 22 *" "p iy2 in" ++gdb_test "p iz" " = 33 *" "p iz in" ++gdb_test "p ix_x" " = 1 *" "p ix_x in" ++gdb_test "p iy_y" " = 2 *" "p iy_y in" ++gdb_test "p iz_z2" " = 3 *" "p iz_z2 in" +diff --git a/gdb/testsuite/gdb.fortran/common-block.f90 b/gdb/testsuite/gdb.fortran/common-block.f90 +new file mode 100644 +index 0000000..b614e8a +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/common-block.f90 +@@ -0,0 +1,67 @@ ++! Copyright 2008 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. ++! ++! Ihis file is the Fortran source file for dynamic.exp. ++! Original file written by Jakub Jelinek . ++! Modified for the GDB testcase by Jan Kratochvil . ++ ++subroutine in ++ ++ INTEGER*4 ix ++ REAL*4 iy2 ++ REAL*8 iz ++ ++ INTEGER*4 ix_x ++ REAL*4 iy_y ++ REAL*8 iz_z2 ++ ++ common /fo_o/ix,iy2,iz ++ common /foo/ix_x,iy_y,iz_z2 ++ ++ iy = 5 ++ iz_z = 55 ++ ++ if (ix .ne. 11 .or. iy2 .ne. 22.0 .or. iz .ne. 33.0) call abort ++ if (ix_x .ne. 1 .or. iy_y .ne. 2.0 .or. iz_z2 .ne. 3.0) call abort ++ ++ ix = 0 ! stop-here-in ++ ++end subroutine in ++ ++program common_test ++ ++ INTEGER*4 ix ++ REAL*4 iy ++ REAL*8 iz ++ ++ INTEGER*4 ix_x ++ REAL*4 iy_y ++ REAL*8 iz_z ++ ++ common /foo/ix,iy,iz ++ common /fo_o/ix_x,iy_y,iz_z ++ ++ ix = 1 ++ iy = 2.0 ++ iz = 3.0 ++ ++ ix_x = 11 ++ iy_y = 22.0 ++ iz_z = 33.0 ++ ++ call in ! stop-here-out ++ ++end program common_test +diff --git a/gdb/testsuite/gdb.fortran/dynamic.exp b/gdb/testsuite/gdb.fortran/dynamic.exp +new file mode 100644 +index 0000000..77a1203 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/dynamic.exp +@@ -0,0 +1,156 @@ ++# Copyright 2007 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. ++ ++# This file was written by Jan Kratochvil . ++ ++# This file is part of the gdb testsuite. It contains tests for dynamically ++# allocated Fortran arrays. ++# It depends on the GCC dynamic Fortran arrays DWARF support: ++# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22244 ++ ++set testfile "dynamic" ++set srcfile ${testfile}.f90 ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto MAIN__] then { ++ perror "couldn't run to breakpoint MAIN__" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "varx-init"] ++gdb_continue_to_breakpoint "varx-init" ++gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx unallocated" ++gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx unallocated" ++gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) unallocated" ++gdb_test "p varx(1,5,17)=1" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17)=1 unallocated" ++gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) unallocated" ++ ++gdb_breakpoint [gdb_get_line_number "varx-allocated"] ++gdb_continue_to_breakpoint "varx-allocated" ++# $1 = (( ( 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0) --- , 0) ) ( ( 0, 0, ...) ...) ...) ++gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx allocated" ++# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1. ++gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varx allocated" ++ ++gdb_breakpoint [gdb_get_line_number "varx-filled"] ++gdb_continue_to_breakpoint "varx-filled" ++gdb_test "p varx(2, 5, 17)" "\\$\[0-9\]* = 6" ++gdb_test "p varx(1, 5, 17)" "\\$\[0-9\]* = 7" ++gdb_test "p varx(2, 6, 18)" "\\$\[0-9\]* = 8" ++gdb_test "p varx(6, 15, 28)" "\\$\[0-9\]* = 9" ++# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type. ++gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv unassociated" ++gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv unassociated" ++ ++gdb_breakpoint [gdb_get_line_number "varv-associated"] ++gdb_continue_to_breakpoint "varv-associated" ++gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 6" "p varx(3, 7, 19) with varv associated" ++gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 6" "p varv(3, 7, 19) associated" ++# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1. ++gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varv associated" ++gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx with varv associated" ++# Intel Fortran Compiler 10.1.008 uses the pointer type. ++gdb_test "ptype varv" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)\\)?" "ptype varv associated" ++ ++gdb_breakpoint [gdb_get_line_number "varv-filled"] ++gdb_continue_to_breakpoint "varv-filled" ++gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 10" "p varx(3, 7, 19) with varv filled" ++gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 10" "p varv(3, 7, 19) filled" ++ ++gdb_breakpoint [gdb_get_line_number "varv-deassociated"] ++gdb_continue_to_breakpoint "varv-deassociated" ++# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type. ++gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv deassociated" ++gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv deassociated" ++gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varv deassociated" ++gdb_test "p varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\." ++gdb_test "ptype varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\." ++ ++gdb_breakpoint [gdb_get_line_number "varx-deallocated"] ++gdb_continue_to_breakpoint "varx-deallocated" ++gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx deallocated" ++gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx deallocated" ++gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varx deallocated" ++gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) deallocated" ++gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) deallocated" ++ ++gdb_breakpoint [gdb_get_line_number "vary-passed"] ++gdb_continue_to_breakpoint "vary-passed" ++# $1 = (( ( 1, 1, 1, 1, 1, 1) ( 1, 1, 1, 1, 1, 1) --- , 1) ) ( ( 1, 1, ...) ...) ...) ++gdb_test "p vary" "\\$\[0-9\]* = \\(\[()1, .\]*\\)" ++ ++gdb_breakpoint [gdb_get_line_number "vary-filled"] ++gdb_continue_to_breakpoint "vary-filled" ++gdb_test "ptype vary" "type = real(\\(kind=4\\)|\\*4) \\(10,10\\)" ++gdb_test "p vary(1, 1)" "\\$\[0-9\]* = 8" ++gdb_test "p vary(2, 2)" "\\$\[0-9\]* = 9" ++gdb_test "p vary(1, 3)" "\\$\[0-9\]* = 10" ++# $1 = (( ( 3, 3, 3, 3, 3, 3) ( 3, 3, 3, 3, 3, 3) --- , 3) ) ( ( 3, 3, ...) ...) ...) ++gdb_test "p varw" "\\$\[0-9\]* = \\(\[()3, .\]*\\)" ++ ++gdb_breakpoint [gdb_get_line_number "varw-almostfilled"] ++gdb_continue_to_breakpoint "varw-almostfilled" ++gdb_test "ptype varw" "type = real(\\(kind=4\\)|\\*4) \\(5,4,3\\)" ++gdb_test "p varw(3,1,1)=1" "\\$\[0-9\]* = 1" ++# $1 = (( ( 6, 5, 1, 5, 5, 5) ( 5, 5, 5, 5, 5, 5) --- , 5) ) ( ( 5, 5, ...) ...) ...) ++gdb_test "p varw" "\\$\[0-9\]* = \\( *\\( *\\( *6, *5, *1,\[()5, .\]*\\)" "p varw filled" ++# "up" works with GCC but other Fortran compilers may copy the values into the ++# outer function only on the exit of the inner function. ++gdb_test "finish" ".*call bar \\(y, x\\)" ++gdb_test "p z(2,4,5)" "\\$\[0-9\]* = 3" ++gdb_test "p z(2,4,6)" "\\$\[0-9\]* = 6" ++gdb_test "p z(2,4,7)" "\\$\[0-9\]* = 5" ++gdb_test "p z(4,4,6)" "\\$\[0-9\]* = 1" ++ ++gdb_breakpoint [gdb_get_line_number "varz-almostfilled"] ++gdb_continue_to_breakpoint "varz-almostfilled" ++# GCC uses the pointer type here, Intel Fortran Compiler 10.1.008 does not. ++gdb_test "ptype varz" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(\\*\\)\\)?" ++# Intel Fortran Compiler 10.1.008 has a bug here - (2:11,7:7) ++# as it produces DW_AT_lower_bound == DW_AT_upper_bound == 7. ++gdb_test "ptype vart" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(2:11,7:\\*\\)\\)?" ++gdb_test "p varz" "\\$\[0-9\]* = \\(\\)" ++gdb_test "p vart" "\\$\[0-9\]* = \\(\\)" ++gdb_test "p varz(3)" "\\$\[0-9\]* = 4" ++# maps to foo::vary(1,1) ++gdb_test "p vart(2,7)" "\\$\[0-9\]* = 8" ++# maps to foo::vary(2,2) ++gdb_test "p vart(3,8)" "\\$\[0-9\]* = 9" ++# maps to foo::vary(1,3) ++gdb_test "p vart(2,9)" "\\$\[0-9\]* = 10" ++ ++set test "quit #1" ++gdb_test_multiple "quit" $test { ++ -re "The program is running. Quit anyway \\(and kill it\\)\\? \\(y or n\\) " { ++ pass $test ++ } ++} ++set test "quit #2" ++gdb_test_multiple "y" $test { ++ eof { ++ pass $test ++ } ++} +diff --git a/gdb/testsuite/gdb.fortran/dynamic.f90 b/gdb/testsuite/gdb.fortran/dynamic.f90 +new file mode 100644 +index 0000000..0f43564 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/dynamic.f90 +@@ -0,0 +1,98 @@ ++! Copyright 2007 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. ++! ++! Ihis file is the Fortran source file for dynamic.exp. ++! Original file written by Jakub Jelinek . ++! Modified for the GDB testcase by Jan Kratochvil . ++ ++subroutine baz ++ real, target, allocatable :: varx (:, :, :) ++ real, pointer :: varv (:, :, :) ++ real, target :: varu (1, 2, 3) ++ logical :: l ++ allocate (varx (1:6, 5:15, 17:28)) ! varx-init ++ l = allocated (varx) ++ varx(:, :, :) = 6 ! varx-allocated ++ varx(1, 5, 17) = 7 ++ varx(2, 6, 18) = 8 ++ varx(6, 15, 28) = 9 ++ varv => varx ! varx-filled ++ l = associated (varv) ++ varv(3, 7, 19) = 10 ! varv-associated ++ varv => null () ! varv-filled ++ l = associated (varv) ++ deallocate (varx) ! varv-deassociated ++ l = allocated (varx) ++ varu(:, :, :) = 10 ! varx-deallocated ++ allocate (varv (1:6, 5:15, 17:28)) ++ l = associated (varv) ++ varv(:, :, :) = 6 ++ varv(1, 5, 17) = 7 ++ varv(2, 6, 18) = 8 ++ varv(6, 15, 28) = 9 ++ deallocate (varv) ++ l = associated (varv) ++ varv => varu ++ varv(1, 1, 1) = 6 ++ varv(1, 2, 3) = 7 ++ l = associated (varv) ++end subroutine baz ++subroutine foo (vary, varw) ++ real :: vary (:, :) ++ real :: varw (:, :, :) ++ vary(:, :) = 4 ! vary-passed ++ vary(1, 1) = 8 ++ vary(2, 2) = 9 ++ vary(1, 3) = 10 ++ varw(:, :, :) = 5 ! vary-filled ++ varw(1, 1, 1) = 6 ++ varw(2, 2, 2) = 7 ! varw-almostfilled ++end subroutine foo ++subroutine bar (varz, vart) ++ real :: varz (*) ++ real :: vart (2:11, 7:*) ++ varz(1:3) = 4 ++ varz(2) = 5 ! varz-almostfilled ++ vart(2,7) = vart(2,7) ++end subroutine bar ++program test ++ interface ++ subroutine foo (vary, varw) ++ real :: vary (:, :) ++ real :: varw (:, :, :) ++ end subroutine ++ end interface ++ interface ++ subroutine bar (varz, vart) ++ real :: varz (*) ++ real :: vart (2:11, 7:*) ++ end subroutine ++ end interface ++ real :: x (10, 10), y (5), z(8, 8, 8) ++ x(:,:) = 1 ++ y(:) = 2 ++ z(:,:,:) = 3 ++ call baz ++ call foo (x, z(2:6, 4:7, 6:8)) ++ call bar (y, x) ++ if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort ++ if (x (1, 3) .ne. 10) call abort ++ if (z (2, 4, 6) .ne. 6 .or. z (3, 5, 7) .ne. 7 .or. z (2, 4, 7) .ne. 5) call abort ++ if (any (y .ne. (/4, 5, 4, 2, 2/))) call abort ++ call foo (transpose (x), z) ++ if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort ++ if (x (3, 1) .ne. 10) call abort ++end +diff --git a/gdb/testsuite/gdb.fortran/logical.exp b/gdb/testsuite/gdb.fortran/logical.exp +new file mode 100644 +index 0000000..ef76f43 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/logical.exp +@@ -0,0 +1,44 @@ ++# Copyright 2007 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. ++ ++# This file was written by Jan Kratochvil . ++ ++set testfile "logical" ++set srcfile ${testfile}.f90 ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto MAIN__] then { ++ perror "couldn't run to breakpoint MAIN__" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "stop-here"] ++gdb_continue_to_breakpoint "stop-here" ++gdb_test "p l" " = \\.TRUE\\." ++gdb_test "p l1" " = \\.TRUE\\." ++gdb_test "p l2" " = \\.TRUE\\." ++gdb_test "p l4" " = \\.TRUE\\." ++gdb_test "p l8" " = \\.TRUE\\." +diff --git a/gdb/testsuite/gdb.fortran/logical.f90 b/gdb/testsuite/gdb.fortran/logical.f90 +new file mode 100644 +index 0000000..4229304 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/logical.f90 +@@ -0,0 +1,33 @@ ++! Copyright 2008 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. ++! ++! Ihis file is the Fortran source file for dynamic.exp. ++! Original file written by Jakub Jelinek . ++! Modified for the GDB testcase by Jan Kratochvil . ++ ++program test ++ logical :: l ++ logical (kind=1) :: l1 ++ logical (kind=2) :: l2 ++ logical (kind=4) :: l4 ++ logical (kind=8) :: l8 ++ l = .TRUE. ++ l1 = .TRUE. ++ l2 = .TRUE. ++ l4 = .TRUE. ++ l8 = .TRUE. ++ l = .FALSE. ! stop-here ++end +diff --git a/gdb/testsuite/gdb.fortran/string.exp b/gdb/testsuite/gdb.fortran/string.exp +new file mode 100644 +index 0000000..ab72206 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/string.exp +@@ -0,0 +1,72 @@ ++# Copyright 2008 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. ++ ++# This file was written by Jan Kratochvil . ++ ++# This file is part of the gdb testsuite. It contains tests for Fortran ++# strings with dynamic length. ++ ++set testfile "string" ++set srcfile ${testfile}.f90 ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto MAIN__] then { ++ perror "couldn't run to breakpoint MAIN__" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "var-init"] ++gdb_continue_to_breakpoint "var-init" ++gdb_test "ptype c" "type = character(\\(kind=1\\)|\\*1)" ++gdb_test "ptype d" "type = character(\\(kind=8\\)|\\*8)" ++gdb_test "ptype e" "type = character(\\(kind=4\\)|\\*4)" ++gdb_test "ptype f" "type = character(\\(kind=4\\)|\\*4) \\(7,8:10\\)" ++gdb_test "ptype *e" "Attempt to take contents of a non-pointer value." ++gdb_test "ptype *f" "type = character(\\(kind=4\\)|\\*4) \\(7\\)" ++gdb_test "p c" "\\$\[0-9\]* = 'c'" ++gdb_test "p d" "\\$\[0-9\]* = 'd '" ++gdb_test "p e" "\\$\[0-9\]* = 'g '" ++gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\)" ++gdb_test "p *e" "Attempt to take contents of a non-pointer value." ++gdb_test "p *f" "Attempt to take contents of a non-pointer value." ++ ++gdb_breakpoint [gdb_get_line_number "var-finish"] ++gdb_continue_to_breakpoint "var-finish" ++gdb_test "p e" "\\$\[0-9\]* = 'e '" "p e re-set" ++gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'f ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\( 'f2 ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\( 'f ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\)" "p *f re-set" ++ ++set test "quit #1" ++gdb_test_multiple "quit" $test { ++ -re "The program is running. Quit anyway \\(and kill it\\)\\? \\(y or n\\) " { ++ pass $test ++ } ++} ++set test "quit #2" ++gdb_test_multiple "y" $test { ++ eof { ++ pass $test ++ } ++} +diff --git a/gdb/testsuite/gdb.fortran/string.f90 b/gdb/testsuite/gdb.fortran/string.f90 +new file mode 100644 +index 0000000..226dc5d +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/string.f90 +@@ -0,0 +1,37 @@ ++! Copyright 2008 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. ++! ++! Ihis file is the Fortran source file for dynamic.exp. ++! Original file written by Jakub Jelinek . ++! Modified for the GDB testcase by Jan Kratochvil . ++ ++subroutine foo (e, f) ++ character (len=1) :: c ++ character (len=8) :: d ++ character (len=*) :: e ++ character (len=*) :: f (1:7, 8:10) ++ c = 'c' ++ d = 'd' ++ e = 'e' ! var-init ++ f = 'f' ++ f(1,9) = 'f2' ++ c = 'c' ! var-finish ++end subroutine foo ++ character (len=4) :: g, h (1:7, 8:10) ++ g = 'g' ++ h = 'h' ++ call foo (g, h) ++end +diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp +index 495ae45..d08d7a4 100644 +--- a/gdb/testsuite/gdb.gdb/selftest.exp ++++ b/gdb/testsuite/gdb.gdb/selftest.exp +@@ -95,6 +95,10 @@ proc do_steps_and_nexts {} { + set description "step over ttyarg initialization" + set command "step" + } ++ -re ".*python_script = 0.*$gdb_prompt $" { ++ set description "step over python_script initialization" ++ set command "step" ++ } + -re ".*time_at_startup = get_run_time.*$gdb_prompt $" { + set description "next over get_run_time and everything it calls" + set command "next" +diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp +index 6ea59fc..0f91af7 100644 +--- a/gdb/testsuite/gdb.mi/mi-break.exp ++++ b/gdb/testsuite/gdb.mi/mi-break.exp +@@ -85,11 +85,11 @@ proc test_tbreak_creation_and_listing {} { + mi_create_breakpoint "-t basics.c:callee2" 2 del callee2 ".*basics.c" $line_callee2_body $hex \ + "insert temp breakpoint at basics.c:callee2" + +- mi_create_breakpoint "-t basics.c:$line_callee3_head" 3 del callee3 ".*basics.c" $line_callee3_body $hex \ ++ mi_create_breakpoint "-t basics.c:$line_callee3_head" 3 del callee3 ".*basics.c" $line_callee3_head $hex \ + "insert temp breakpoint at basics.c:\$line_callee3_head" + + # Getting the quoting right is tricky. That is "\"\":$line_callee4_head" +- mi_create_breakpoint "-t \"\\\"${srcfile}\\\":$line_callee4_head\"" 4 del callee4 ".*basics.c" $line_callee4_body $hex \ ++ mi_create_breakpoint "-t \"\\\"${srcfile}\\\":$line_callee4_head\"" 4 del callee4 ".*basics.c" $line_callee4_head $hex \ + "insert temp breakpoint at \"\":\$line_callee4_head" + + mi_gdb_test "666-break-list" \ +diff --git a/gdb/testsuite/gdb.mi/mi-simplerun.exp b/gdb/testsuite/gdb.mi/mi-simplerun.exp +index 654146a..14a1446 100644 +--- a/gdb/testsuite/gdb.mi/mi-simplerun.exp ++++ b/gdb/testsuite/gdb.mi/mi-simplerun.exp +@@ -74,10 +74,10 @@ proc test_breakpoints_creation_and_listing {} { + mi_create_breakpoint "basics.c:callee2" 2 keep callee2 ".*basics.c" $line_callee2_body $hex \ + "insert breakpoint at basics.c:callee2" + +- mi_create_breakpoint "basics.c:$line_callee3_head" 3 keep callee3 ".*basics.c" $line_callee3_body $hex \ ++ mi_create_breakpoint "basics.c:$line_callee3_head" 3 keep callee3 ".*basics.c" $line_callee3_head $hex \ + "insert breakpoint at basics.c:\$line_callee3_head" + +- mi_create_breakpoint "\"\\\"${srcfile}\\\":$line_callee4_head\"" 4 keep callee4 ".*basics.c" $line_callee4_body $hex \ ++ mi_create_breakpoint "\"\\\"${srcfile}\\\":$line_callee4_head\"" 4 keep callee4 ".*basics.c" $line_callee4_head $hex \ + "insert breakpoint at \"\":\$line_callee4_head" + + mi_gdb_test "204-break-list" \ +diff --git a/gdb/testsuite/gdb.mi/mi2-break.exp b/gdb/testsuite/gdb.mi/mi2-break.exp +index d08081a..7f43315 100644 +--- a/gdb/testsuite/gdb.mi/mi2-break.exp ++++ b/gdb/testsuite/gdb.mi/mi2-break.exp +@@ -85,11 +85,11 @@ proc test_tbreak_creation_and_listing {} { + mi_create_breakpoint "-t basics.c:callee2" 2 del callee2 ".*basics.c" $line_callee2_body $hex \ + "insert temp breakpoint at basics.c:callee2" + +- mi_create_breakpoint "-t basics.c:$line_callee3_head" 3 del callee3 ".*basics.c" $line_callee3_body $hex \ ++ mi_create_breakpoint "-t basics.c:$line_callee3_head" 3 del callee3 ".*basics.c" $line_callee3_head $hex \ + "insert temp breakpoint at basics.c:\$line_callee3_head" + + # Getting the quoting right is tricky. That is "\"\":$line_callee4_head" +- mi_create_breakpoint "-t \"\\\"${srcfile}\\\":$line_callee4_head\"" 4 del callee4 ".*basics.c" $line_callee4_body $hex \ ++ mi_create_breakpoint "-t \"\\\"${srcfile}\\\":$line_callee4_head\"" 4 del callee4 ".*basics.c" $line_callee4_head $hex \ + "insert temp breakpoint at \"\":\$line_callee4_head" + + mi_gdb_test "666-break-list" \ +diff --git a/gdb/testsuite/gdb.mi/mi2-simplerun.exp b/gdb/testsuite/gdb.mi/mi2-simplerun.exp +index eddb2ed..13443ee 100644 +--- a/gdb/testsuite/gdb.mi/mi2-simplerun.exp ++++ b/gdb/testsuite/gdb.mi/mi2-simplerun.exp +@@ -74,10 +74,10 @@ proc test_breakpoints_creation_and_listing {} { + mi_create_breakpoint "basics.c:callee2" 2 keep callee2 ".*basics.c" $line_callee2_body $hex \ + "insert breakpoint at basics.c:callee2" + +- mi_create_breakpoint "basics.c:$line_callee3_head" 3 keep callee3 ".*basics.c" $line_callee3_body $hex \ ++ mi_create_breakpoint "basics.c:$line_callee3_head" 3 keep callee3 ".*basics.c" $line_callee3_head $hex \ + "insert breakpoint at basics.c:\$line_callee3_head" + +- mi_create_breakpoint "\"\\\"${srcfile}\\\":$line_callee4_head\"" 4 keep callee4 ".*basics.c" $line_callee4_body $hex \ ++ mi_create_breakpoint "\"\\\"${srcfile}\\\":$line_callee4_head\"" 4 keep callee4 ".*basics.c" $line_callee4_head $hex \ + "insert breakpoint at \"\":\$line_callee4_head" + + mi_gdb_test "204-break-list" \ +diff --git a/gdb/testsuite/gdb.opt/array-from-register-func.c b/gdb/testsuite/gdb.opt/array-from-register-func.c +new file mode 100644 +index 0000000..729f457 +--- /dev/null ++++ b/gdb/testsuite/gdb.opt/array-from-register-func.c +@@ -0,0 +1,22 @@ ++/* This file is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . */ ++ ++int ++func (int *arr) ++{ ++ return arr[0]; ++} +diff --git a/gdb/testsuite/gdb.opt/array-from-register.c b/gdb/testsuite/gdb.opt/array-from-register.c +new file mode 100644 +index 0000000..3090e7e +--- /dev/null ++++ b/gdb/testsuite/gdb.opt/array-from-register.c +@@ -0,0 +1,28 @@ ++/* This file is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . */ ++ ++extern int func (int *arr); ++ ++int ++main (void) ++{ ++ int arr[] = { 42 }; ++ ++ func (arr); ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.opt/array-from-register.exp b/gdb/testsuite/gdb.opt/array-from-register.exp +new file mode 100644 +index 0000000..f2de718 +--- /dev/null ++++ b/gdb/testsuite/gdb.opt/array-from-register.exp +@@ -0,0 +1,33 @@ ++# Copyright 2009 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. ++# ++# This file is part of the gdb testsuite. ++ ++if { [prepare_for_testing array-from-register.exp "array-from-register" \ ++ {array-from-register.c array-from-register-func.c} \ ++ {debug optimize=-O2}] } { ++ return -1 ++} ++ ++if ![runto func] then { ++ return -1 ++} ++ ++gdb_test "p arr" "\\$\[0-9\]+ = \\(int \\*\\) *0x\[0-9a-f\]+" ++ ++# Seen regression: ++# Address requested for identifier "arr" which is in register $rdi ++gdb_test "p arr\[0\]" "\\$\[0-9\]+ = 42" +diff --git a/gdb/testsuite/gdb.python/Makefile.in b/gdb/testsuite/gdb.python/Makefile.in +index 79be9e7..c49f713 100644 +--- a/gdb/testsuite/gdb.python/Makefile.in ++++ b/gdb/testsuite/gdb.python/Makefile.in +@@ -1,7 +1,7 @@ + VPATH = @srcdir@ + srcdir = @srcdir@ + +-EXECUTABLES = python-value ++EXECUTABLES = python-value python-prettyprint python-template + + all info install-info dvi install uninstall installcheck check: + @echo "Nothing to be done for $@..." +diff --git a/gdb/testsuite/gdb.python/find.c b/gdb/testsuite/gdb.python/find.c +new file mode 100644 +index 0000000..35ddd8c +--- /dev/null ++++ b/gdb/testsuite/gdb.python/find.c +@@ -0,0 +1,64 @@ ++/* Testcase for the search_memory Python function. ++ This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2009 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 3 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, see . ++ ++ Please email any bugs, comments, and/or additions to this file to: ++ bug-gdb@gnu.org */ ++ ++/* Based on the gdb.base/find.c testcase. */ ++ ++#include ++#include ++ ++#define CHUNK_SIZE 16000 /* same as findcmd.c's */ ++#define BUF_SIZE (2 * CHUNK_SIZE) /* at least two chunks */ ++ ++static int8_t int8_search_buf[100]; ++static int16_t int16_search_buf[100]; ++static int32_t int32_search_buf[100]; ++static int64_t int64_search_buf[100]; ++ ++static char *search_buf; ++static int search_buf_size; ++ ++static int x; ++ ++static void ++stop_here () ++{ ++ x = 1; // stop here ++} ++ ++static void ++init_bufs () ++{ ++ search_buf_size = BUF_SIZE; ++ search_buf = malloc (search_buf_size); ++ if (search_buf == NULL) ++ exit (1); ++ memset (search_buf, 'x', search_buf_size); ++} ++ ++int ++main () ++{ ++ init_bufs (); ++ ++ stop_here (); ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.python/find.exp b/gdb/testsuite/gdb.python/find.exp +new file mode 100644 +index 0000000..defc31c +--- /dev/null ++++ b/gdb/testsuite/gdb.python/find.exp +@@ -0,0 +1,203 @@ ++# Copyright 2008, 2009 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 3 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, see . ++ ++# This tests the search_memory Python function. ++# Based on the gdb.base/find.exp testcase. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}... ++# Run a test named NAME, consisting of multiple lines of input. ++# After each input line INPUT, search for result line RESULT. ++# Succeed if all results are seen; fail otherwise. ++proc gdb_py_test_multiple {name args} { ++ global gdb_prompt ++ foreach {input result} $args { ++ if {[gdb_test_multiple $input "$name - $input" { ++ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" { ++ pass "$name - $input" ++ } ++ }]} { ++ return 1 ++ } ++ } ++ return 0 ++} ++ ++set testfile "find" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug nowarnings}] != "" } { ++ untested find.exp ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_test_multiple "python print 'hello, world!'" "verify python support" { ++ -re "not supported.*$gdb_prompt $" { ++ unsupported "python support is disabled" ++ return -1 ++ } ++ -re "$gdb_prompt $" {} ++} ++ ++gdb_test "break $srcfile:stop_here" \ ++ "Breakpoint.*at.* file .*$srcfile, line.*" \ ++ "breakpoint function in file" ++ ++gdb_run_cmd ++gdb_expect { ++ -re "Breakpoint \[0-9\]+,.*stop_here.* at .*$srcfile:.*$gdb_prompt $" { ++ pass "run until function breakpoint" ++ } ++ -re "$gdb_prompt $" { ++ fail "run until function breakpoint" ++ } ++ timeout { ++ fail "run until function breakpoint (timeout)" ++ } ++} ++ ++# We've now got the target program in a state where we can test "find". ++ ++set hex_number {0x[0-9a-fA-F][0-9a-fA-F]*} ++set dec_number {[0-9]+} ++set history_prefix {[$][0-9]* = } ++set newline {[\r\n]+} ++set pattern_not_found "${newline}.]" ++set one_pattern_found "${newline}.${dec_number}L]" ++set two_patterns_found "${newline}.${dec_number}L, ${dec_number}L]" ++ ++# Test string pattern. ++ ++gdb_test "set *(int32_t*) &int8_search_buf\[10\] = 0x61616161" "" "" ++gdb_test "py search_buf = gdb.selected_frame ().read_var ('int8_search_buf')" "" "" ++gdb_test "py start_addr = search_buf.address" "" "" ++gdb_test "py length = search_buf.type.sizeof" "" "" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, 'aaa')" \ ++ "${two_patterns_found}" "find string pattern" ++ ++# Test not finding pattern because search range too small, with ++# potential find at the edge of the range. ++ ++gdb_test "py print gdb.search_memory (start_addr, 10+3, 'aaaa')" \ ++ "${pattern_not_found}" "pattern not found at end of range" ++ ++# Increase the search range by 1 and we should find the pattern. ++ ++gdb_test "py print gdb.search_memory (start_addr, 10+3+1, \['a', 'a', 'a', 'a'\])" \ ++ "${one_pattern_found}" "pattern found at end of range" ++ ++# Test max-count with size, with different parameter position ++ ++gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], 1, 1)" \ ++ "${one_pattern_found}" "size = 1, max_count = 1" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], 1, 2)" \ ++ "${two_patterns_found}" "size = 1, max_count = 2, normal ordering" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], size = 1, max_count = 2)" \ ++ "${two_patterns_found}" "size = 1, max_count = 2, normal ordering, with keywords" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], max_count = 2, size = 1)" \ ++ "${two_patterns_found}" "size = 1, max_count = 2, inverted ordering" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, \['a', 'a'\], max_count = 2)" \ ++ "${two_patterns_found}" "max_count = 2, with keyword" ++ ++# Test 16-bit pattern. ++ ++gdb_test "set int16_search_buf\[10\] = 0x1234" "" "" ++gdb_test "py search_buf = gdb.selected_frame ().read_var ('int16_search_buf')" "" "" ++gdb_test "py start_addr = search_buf.address" "" "" ++gdb_test "py length = search_buf.type.sizeof" "" "" ++gdb_test "py pattern = gdb.parse_and_eval ('(int16_t) 0x1234')" "" "" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, 0x1234, 2)" \ ++ "${one_pattern_found}" "find 16-bit pattern, with python pattern" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, pattern)" \ ++ "${one_pattern_found}" "find 16-bit pattern, with value pattern" ++ ++# Test 32-bit pattern. ++ ++gdb_test "set int32_search_buf\[10\] = 0x12345678" "" "" ++gdb_test "py search_buf = gdb.selected_frame ().read_var ('int32_search_buf')" "" "" ++gdb_test "py start_addr = search_buf.address" "" "" ++gdb_test "py length = search_buf.type.sizeof" "" "" ++gdb_test "py pattern = gdb.parse_and_eval ('(int32_t) 0x12345678')" "" "" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, 0x12345678, 4)" \ ++ "${one_pattern_found}" "find 32-bit pattern, with python pattern" ++gdb_test "py print gdb.search_memory (start_addr, length, pattern)" \ ++ "${one_pattern_found}" "find 32-bit pattern, with value pattern" ++ ++# Test 64-bit pattern. ++ ++gdb_test "set int64_search_buf\[10\] = 0xfedcba9876543210LL" "" "" ++gdb_test "py search_buf = gdb.selected_frame ().read_var ('int64_search_buf')" "" "" ++gdb_test "py start_addr = search_buf.address" "" "" ++gdb_test "py length = search_buf.type.sizeof" "" "" ++gdb_test "py pattern = gdb.parse_and_eval ('(int64_t) 0xfedcba9876543210LL')" "" "" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, 0xfedcba9876543210, 8)" \ ++ "${one_pattern_found}" "find 64-bit pattern, with python pattern" ++gdb_test "py print gdb.search_memory (start_addr, length, pattern)" \ ++ "${one_pattern_found}" "find 64-bit pattern, with value pattern" ++ ++# Test mixed-sized patterns. ++ ++gdb_test "set *(int8_t*) &search_buf\[10\] = 0x62" "" "" ++gdb_test "set *(int16_t*) &search_buf\[11\] = 0x6363" "" "" ++gdb_test "set *(int32_t*) &search_buf\[13\] = 0x64646464" "" "" ++gdb_test "py search_buf = gdb.selected_frame ().read_var ('search_buf')" "" "" ++gdb_test "py start_addr = search_buf\[0\].address" "" "" ++gdb_test "py pattern1 = gdb.parse_and_eval ('(int8_t) 0x62')" "" "" ++gdb_test "py pattern2 = gdb.parse_and_eval ('(int16_t) 0x6363')" "" "" ++gdb_test "py pattern3 = gdb.parse_and_eval ('(int32_t) 0x64646464')" "" "" ++ ++gdb_test "py print gdb.search_memory (start_addr, 100, \[pattern1, pattern2, pattern3\])" \ ++ "${one_pattern_found}" "find mixed-sized pattern" ++ ++# Test search spanning a large range, in the particular case of native ++# targets, test the search spanning multiple chunks. ++# Remote targets may implement the search differently. ++ ++set CHUNK_SIZE 16000 ; ++ ++gdb_test "set *(int32_t*) &search_buf\[0*${CHUNK_SIZE}+100\] = 0x12345678" "" "" ++gdb_test "set *(int32_t*) &search_buf\[1*${CHUNK_SIZE}+100\] = 0x12345678" "" "" ++gdb_test "py start_addr = gdb.selected_frame ().read_var ('search_buf')" "" "" ++gdb_test "py length = gdb.selected_frame ().read_var ('search_buf_size')" "" "" ++ ++gdb_test "py print gdb.search_memory (start_addr, length, 0x12345678, 4)" \ ++ "${two_patterns_found}" "search spanning large range" ++ ++# For native targets, test a pattern straddling a chunk boundary. ++ ++if [isnative] { ++ gdb_test "set *(int32_t*) &search_buf\[${CHUNK_SIZE}-1\] = 0xfdb97531" "" "" ++ ++ gdb_test "py print gdb.search_memory (start_addr, length, 0xfdb97531, 4)" \ ++ "${one_pattern_found}" "find pattern straddling chunk boundary" ++} +diff --git a/gdb/testsuite/gdb.python/python-cmd.exp b/gdb/testsuite/gdb.python/python-cmd.exp +index 6c73ff2..f6ef938 100644 +--- a/gdb/testsuite/gdb.python/python-cmd.exp ++++ b/gdb/testsuite/gdb.python/python-cmd.exp +@@ -92,6 +92,32 @@ gdb_py_test_multiple "input subcommand" \ + + gdb_test "prefix_cmd subcmd ugh" "subcmd output, arg = ugh" "call subcmd" + ++# Test prefix command using keyword arguments. ++ ++gdb_py_test_multiple "input prefix command, keyword arguments" \ ++ "python" "" \ ++ "class prefix_cmd2 (gdb.Command):" "" \ ++ " def __init__ (self):" "" \ ++ " super (prefix_cmd2, self).__init__ (\"prefix_cmd2\", gdb.COMMAND_OBSCURE, prefix = True, completer_class = gdb.COMPLETE_FILENAME)" "" \ ++ " def invoke (self, arg, from_tty):" "" \ ++ " print \"prefix_cmd2 output, arg = %s\" % arg" "" \ ++ "prefix_cmd2 ()" "" \ ++ "end" "" ++ ++gdb_test "prefix_cmd2 argh" "prefix_cmd2 output, arg = argh" "call prefix command, keyword arguments" ++ ++gdb_py_test_multiple "input subcommand under prefix_cmd2" \ ++ "python" "" \ ++ "class subcmd (gdb.Command):" "" \ ++ " def __init__ (self):" "" \ ++ " super (subcmd, self).__init__ (\"prefix_cmd2 subcmd\", gdb.COMMAND_OBSCURE)" "" \ ++ " def invoke (self, arg, from_tty):" "" \ ++ " print \"subcmd output, arg = %s\" % arg" "" \ ++ "subcmd ()" "" \ ++ "end" "" ++ ++gdb_test "prefix_cmd2 subcmd ugh" "subcmd output, arg = ugh" "call subcmd under prefix_cmd2" ++ + # Test a subcommand in an existing GDB prefix. + + gdb_py_test_multiple "input new subcommand" \ +diff --git a/gdb/testsuite/gdb.python/python-frame.c b/gdb/testsuite/gdb.python/python-frame.c +new file mode 100644 +index 0000000..22eb9f2 +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-frame.c +@@ -0,0 +1,14 @@ ++int f2 (int a) ++{ ++ return ++a; ++} ++ ++int f1 (int a, int b) ++{ ++ return f2(a) + b; ++} ++ ++int main (int argc, char *argv[]) ++{ ++ return f1 (1, 2); ++} +diff --git a/gdb/testsuite/gdb.python/python-frame.exp b/gdb/testsuite/gdb.python/python-frame.exp +new file mode 100644 +index 0000000..674c25e +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-frame.exp +@@ -0,0 +1,92 @@ ++# Copyright (C) 2009 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 3 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, see . ++ ++# This file is part of the GDB testsuite. It tests the mechanism ++# exposing values to Python. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile "python-frame" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++# Run a command in GDB, and report a failure if a Python exception is thrown. ++# If report_pass is true, report a pass if no exception is thrown. ++proc gdb_py_test_silent_cmd {cmd name report_pass} { ++ global gdb_prompt ++ ++ gdb_test_multiple $cmd $name { ++ -re "Traceback.*$gdb_prompt $" { fail $name } ++ -re "$gdb_prompt $" { if $report_pass { pass $name } } ++ } ++} ++ ++# Start with a fresh gdb. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_test_multiple "python print 'hello, world!'" "verify python support" { ++ -re "not supported.*$gdb_prompt $" { ++ unsupported "python support is disabled" ++ return -1 ++ } ++ -re "$gdb_prompt $" {} ++} ++ ++# The following tests require execution. ++ ++if ![runto_main] then { ++ fail "Can't run to main" ++ return 0 ++} ++ ++gdb_breakpoint "f2" ++gdb_continue_to_breakpoint "breakpoint at f2" ++gdb_test "up" "" "" ++ ++gdb_py_test_silent_cmd "python frames = gdb.frames ()" "get frames list" 1 ++gdb_test "python print frames" "\\(, , \\)" "verify frames list" ++gdb_py_test_silent_cmd "python f0 = frames\[0\]" "get first frame" 0 ++gdb_py_test_silent_cmd "python f1 = frames\[1\]" "get second frame" 0 ++ ++gdb_test "python print 'result =', f0.equals (f1)" " = False" "test equals (false)" ++gdb_test "python print 'result =', f0.equals (f0)" " = True" "test equals (true)" ++gdb_test "python print 'result =', f0.is_valid ()" " = True" "test Frame.is_valid" ++gdb_test "python print 'result =', f0.name ()" " = f2" "test Frame.name" ++gdb_test "python print 'result =', f0.type () == gdb.NORMAL_FRAME" " = True" "test Frame.type" ++gdb_test "python print 'result =', f0.unwind_stop_reason () == gdb.FRAME_UNWIND_NO_REASON" " = True" "test Frame.type" ++gdb_test "python print 'result =', gdb.frame_stop_reason_string (gdb.FRAME_UNWIND_INNER_ID)" " = previous frame inner to this frame \\(corrupt stack\\?\\)" "test gdb.frame_stop_reason_string" ++gdb_test "python print 'result =', f0.pc ()" " = \[0-9\]+" "test Frame.pc" ++gdb_test "python print 'result =', f0.addr_in_block ()" " = \[0-9\]+" "test Frame.addr_in_block" ++gdb_test "python print 'result =', f0.older ().equals (f1)" " = True" "test Frame.older" ++gdb_test "python print 'result =', f1.newer ().equals (f0)" " = True" "test Frame.newer" ++gdb_test "python print 'result =', f0.read_var ('variable_which_surely_doesnt_exist')" \ ++ "ValueError: variable 'variable_which_surely_doesnt_exist' not found.*Error while executing Python code." \ ++ "test Frame.read_var - error" ++gdb_test "python print 'result =', f0.read_var ('a')" " = 1" "test Frame.read_var - success" ++ ++gdb_test "python print 'result =', gdb.newest_frame ().equals (f0)" " = True" "test gdb.newest_frame" ++gdb_test "python print 'result =', gdb.selected_frame ().equals (f1)" " = True" "test gdb.selected_frame" ++ ++gdb_test "python print 'result =', f0.block ()" "" "test Frame.block" +diff --git a/gdb/testsuite/gdb.python/python-function.exp b/gdb/testsuite/gdb.python/python-function.exp +new file mode 100644 +index 0000000..7feca2b +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-function.exp +@@ -0,0 +1,79 @@ ++# Copyright (C) 2009 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 3 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, see . ++ ++# This file is part of the GDB testsuite. It tests the mechanism ++# exposing convenience functions to Python. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}... ++# Run a test named NAME, consisting of multiple lines of input. ++# After each input line INPUT, search for result line RESULT. ++# Succeed if all results are seen; fail otherwise. ++proc gdb_py_test_multiple {name args} { ++ global gdb_prompt ++ foreach {input result} $args { ++ if {[gdb_test_multiple $input "$name - $input" { ++ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" { ++ pass "$name - $input" ++ } ++ }]} { ++ return 1 ++ } ++ } ++ return 0 ++} ++ ++# Start with a fresh gdb. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++ ++gdb_test_multiple "python print 'hello, world!'" "verify python support" { ++ -re "not supported.*$gdb_prompt $" { ++ unsupported "python support is disabled" ++ return -1 ++ } ++ -re "$gdb_prompt $" {} ++} ++ ++gdb_py_test_multiple "input convenience function" \ ++ "python" "" \ ++ "class test_func (gdb.Function):" "" \ ++ " def __init__ (self):" "" \ ++ " super (test_func, self).__init__ (\"test_func\")" "" \ ++ " def invoke (self, arg):" "" \ ++ " return \"test_func output, arg = %s\" % arg.string ()" "" \ ++ "test_func ()" "" \ ++ "end" "" ++ ++gdb_test "print \$test_func (\"ugh\")" "= \"test_func output, arg = ugh\"" "call function" ++ ++# Test returning a gdb.Value from the function. This segfaulted GDB at one point. ++ ++gdb_py_test_multiple "input value-returning convenience function" \ ++ "python" "" \ ++ "class Double (gdb.Function):" "" \ ++ " def __init__ (self):" "" \ ++ " super (Double, self).__init__ (\"double\")" "" \ ++ " def invoke (self, n):" "" \ ++ " return n*2" "" \ ++ "Double ()" "" \ ++ "end" "" ++ ++gdb_test "print \$double (1)" "= 2" "call value-returning function" +diff --git a/gdb/testsuite/gdb.python/python-mi.exp b/gdb/testsuite/gdb.python/python-mi.exp +new file mode 100644 +index 0000000..5c9f3c7 +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-mi.exp +@@ -0,0 +1,124 @@ ++# Copyright (C) 2008 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 3 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, see . ++ ++# This file is part of the GDB testsuite. It tests Python-based ++# pretty-printing for MI. ++ ++load_lib mi-support.exp ++set MIFLAGS "-i=mi2" ++ ++gdb_exit ++if [mi_gdb_start] { ++ continue ++} ++ ++set testfile "python-prettyprint" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DMI}] != "" } { ++ untested mi2-var-child.exp ++ return -1 ++} ++ ++mi_delete_breakpoints ++mi_gdb_reinitialize_dir $srcdir/$subdir ++mi_gdb_load ${binfile} ++ ++if {[lsearch -exact [mi_get_features] python] < 0} { ++ unsupported "python support is disabled" ++ return -1 ++} ++ ++mi_runto main ++ ++mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" "" ++ ++mi_continue_to_line [gdb_get_line_number {MI breakpoint here} ${testfile}.c] \ ++ "step to breakpoint" ++ ++mi_create_floating_varobj container c "create container varobj" ++ ++mi_list_varobj_children container { ++} "examine container children=0" ++ ++mi_next "next over update 1" ++ ++mi_varobj_update_dynamic container { ++ { {container.\[0\]} {\[0\]} 0 int } ++} "varobj update 1" ++ ++mi_next "next over update 2" ++ ++mi_varobj_update_dynamic container { ++ { {container.\[0\]} {\[0\]} 0 int } ++ { {container.\[1\]} {\[1\]} 0 int } ++} "varobj update 2" ++ ++mi_gdb_test "-var-set-visualizer container None" \ ++ "\\^done" \ ++ "clear visualizer" ++ ++mi_gdb_test "-var-update container" \ ++ "\\^done,changelist=\\\[\\\]" \ ++ "varobj update after clearing" ++ ++mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \ ++ "\\^done" \ ++ "choose default visualizer" ++ ++mi_varobj_update_dynamic container { ++ { {container.\[0\]} {\[0\]} 0 int } ++ { {container.\[1\]} {\[1\]} 0 int } ++} "varobj update after choosing default" ++ ++mi_gdb_test "-var-set-visualizer container ContainerPrinter" \ ++ "\\^done" \ ++ "choose visualizer using expression" ++ ++mi_varobj_update_dynamic container { ++ { {container.\[0\]} {\[0\]} 0 int } ++ { {container.\[1\]} {\[1\]} 0 int } ++} "varobj update after choosing via expression" ++ ++mi_gdb_test "-var-set-child-range container 1 2" \ ++ "\\^done" \ ++ "select child range" ++ ++mi_gdb_test "-var-update container" \ ++ "\\^done,changelist=\\\[\\\]" \ ++ "varobj update after selecting child range" ++ ++mi_list_varobj_children_range container 2 { ++ { {container.\[1\]} {\[1\]} 0 int } ++} "list varobj children after selecting child range" ++ ++mi_gdb_test "-var-set-child-range container -1 -1" \ ++ "\\^done" \ ++ "reset child range" ++ ++mi_gdb_test "-var-update container" \ ++ "\\^done,changelist=\\\[\\\]" \ ++ "varobj update after resetting child range" ++ ++mi_list_varobj_children container { ++ { {container.\[0\]} {\[0\]} 0 int } ++ { {container.\[1\]} {\[1\]} 0 int } ++} "list varobj children after resetting child range" ++ ++mi_continue_to_line \ ++ [gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \ ++ "step to second breakpoint" ++ ++mi_varobj_update_with_type_change container int 0 "update after type change" +diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c +new file mode 100644 +index 0000000..399be23 +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-prettyprint.c +@@ -0,0 +1,191 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008, 2009 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 3 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, see . */ ++ ++struct s ++{ ++ int a; ++ int *b; ++}; ++ ++struct ss ++{ ++ struct s a; ++ struct s b; ++}; ++ ++#ifdef __cplusplus ++struct S : public s { ++ int zs; ++}; ++ ++struct SS { ++ int zss; ++ S s; ++}; ++ ++struct SSS ++{ ++ SSS (int x, const S& r); ++ int a; ++ const S &b; ++}; ++SSS::SSS (int x, const S& r) : a(x), b(r) { } ++ ++class VirtualTest ++{ ++ private: ++ int value; ++ ++ public: ++ VirtualTest () ++ { ++ value = 1; ++ } ++}; ++ ++class Vbase1 : public virtual VirtualTest { }; ++class Vbase2 : public virtual VirtualTest { }; ++class Vbase3 : public virtual VirtualTest { }; ++ ++class Derived : public Vbase1, public Vbase2, public Vbase3 ++{ ++ private: ++ int value; ++ ++ public: ++ Derived () ++ { ++ value = 2; ++ } ++}; ++ ++#endif ++ ++typedef struct string_repr ++{ ++ struct whybother ++ { ++ const char *contents; ++ } whybother; ++} string; ++ ++/* This lets us avoid malloc. */ ++int array[100]; ++ ++struct container ++{ ++ string name; ++ int len; ++ int *elements; ++}; ++ ++typedef struct container zzz_type; ++ ++string ++make_string (const char *s) ++{ ++ string result; ++ result.whybother.contents = s; ++ return result; ++} ++ ++zzz_type ++make_container (const char *s) ++{ ++ zzz_type result; ++ ++ result.name = make_string (s); ++ result.len = 0; ++ result.elements = 0; ++ ++ return result; ++} ++ ++void ++add_item (zzz_type *c, int val) ++{ ++ if (c->len == 0) ++ c->elements = array; ++ c->elements[c->len] = val; ++ ++c->len; ++} ++ ++void init_s(struct s *s, int a) ++{ ++ s->a = a; ++ s->b = &s->a; ++} ++ ++void init_ss(struct ss *s, int a, int b) ++{ ++ init_s(&s->a, a); ++ init_s(&s->b, b); ++} ++ ++void do_nothing(void) ++{ ++ int c; ++ ++ c = 23; /* Another MI breakpoint */ ++} ++ ++int ++main () ++{ ++ struct ss ss; ++ struct ss ssa[2]; ++ string x = make_string ("this is x"); ++ zzz_type c = make_container ("container"); ++ const struct string_repr cstring = { { "const string" } }; ++ ++ init_ss(&ss, 1, 2); ++ init_ss(ssa+0, 3, 4); ++ init_ss(ssa+1, 5, 6); ++ ++#ifdef __cplusplus ++ S cps; ++ ++ cps.zs = 7; ++ init_s(&cps, 8); ++ ++ SS cpss; ++ cpss.zss = 9; ++ init_s(&cpss.s, 10); ++ ++ SS cpssa[2]; ++ cpssa[0].zss = 11; ++ init_s(&cpssa[0].s, 12); ++ cpssa[1].zss = 13; ++ init_s(&cpssa[1].s, 14); ++ ++ SSS sss(15, cps); ++ ++ SSS& ref (sss); ++ ++ Derived derived; ++ ++#endif ++ ++ add_item (&c, 23); /* MI breakpoint here */ ++ add_item (&c, 72); ++ ++#ifdef MI ++ do_nothing (); ++#endif ++ ++ return 0; /* break to inspect struct and union */ ++} +diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp +new file mode 100644 +index 0000000..f83b1cd +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-prettyprint.exp +@@ -0,0 +1,92 @@ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++# This file is part of the GDB testsuite. It tests Python-based ++# pretty-printing for the CLI. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile "python-prettyprint" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++# Start with a fresh gdb. ++gdb_exit ++gdb_start ++gdb_test_multiple "python print 'hello, world!'" "verify python support" { ++ -re "not supported.*$gdb_prompt $" { ++ unsupported "python support is disabled" ++ return -1 ++ } ++ -re "$gdb_prompt $" {} ++} ++ ++proc run_lang_tests {lang} { ++ global srcdir subdir srcfile binfile testfile hex ++ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug $lang"] != "" } { ++ untested "Couldn't compile ${srcfile} in $lang mode" ++ return -1 ++ } ++ ++ set nl "\[\r\n\]+" ++ ++ # Start with a fresh gdb. ++ gdb_exit ++ gdb_start ++ gdb_reinitialize_dir $srcdir/$subdir ++ gdb_load ${binfile} ++ ++ ++ if ![runto_main ] then { ++ perror "couldn't run to breakpoint" ++ return ++ } ++ ++ gdb_test "set print pretty on" "" ++ ++ gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \ ++ ".*Breakpoint.*" ++ gdb_test "continue" ".*Breakpoint.*" ++ ++ gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" "" ++ ++ gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>" ++ gdb_test "print ssa\[1\]" " = a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>" ++ gdb_test "print ssa" " = {a=< a=<3> b=<$hex>> b=< a=<4> b=<$hex>>, a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>}" ++ ++ if {$lang == "c++"} { ++ gdb_test "print cps" "= a=<8> b=<$hex>" ++ gdb_test "print cpss" " = {$nl *zss = 9, *$nl *s = a=<10> b=<$hex>$nl}" ++ gdb_test "print cpssa\[0\]" " = {$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl}" ++ gdb_test "print cpssa\[1\]" " = {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl}" ++ gdb_test "print cpssa" " = {{$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl *}, {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl *}}" ++ gdb_test "print sss" "= a=<15> b=< a=<8> b=<$hex>>" ++ gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>" ++ gdb_test "print derived" \ ++ " = \{.* = pp class name: Vbase1.* = \{.* = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.* = \{.*members of Vbase3.*members of Derived:.*value = 2.*" ++ } ++ ++ gdb_test "print x" " = $hex \"this is x\"" ++ gdb_test "print cstring" " = $hex \"const string\"" ++ ++ gdb_test "print c" " = container $hex \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}" ++ ++ gdb_test "continue" "Program exited normally\." ++} ++ ++run_lang_tests "c" ++run_lang_tests "c++" +diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py +new file mode 100644 +index 0000000..a53e412 +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-prettyprint.py +@@ -0,0 +1,151 @@ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++# This file is part of the GDB testsuite. It tests python pretty ++# printers. ++ ++import re ++ ++# Test returning a Value from a printer. ++class string_print: ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ return self.val['whybother']['contents'] ++ ++# Test a class-based printer. ++class ContainerPrinter: ++ class _iterator: ++ def __init__ (self, pointer, len): ++ self.start = pointer ++ self.pointer = pointer ++ self.end = pointer + len ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.pointer == self.end: ++ raise StopIteration ++ result = self.pointer ++ self.pointer = self.pointer + 1 ++ return ('[%d]' % int (result - self.start), result.dereference()) ++ ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ return 'container %s with %d elements' % (self.val['name'], self.val['len']) ++ ++ def children(self): ++ return self._iterator(self.val['elements'], self.val['len']) ++ ++class pp_s: ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ a = self.val["a"] ++ b = self.val["b"] ++ if a.address != b: ++ raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b))) ++ return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" ++ ++class pp_ss: ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">" ++ ++class pp_sss: ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">" ++ ++class pp_multiple_virtual: ++ def __init__ (self, val): ++ self.val = val ++ ++ def to_string (self): ++ return "pp value variable is: " + str (self.val['value']) ++ ++class pp_vbase1: ++ def __init__ (self, val): ++ self.val = val ++ ++ def to_string (self): ++ return "pp class name: " + self.val.type.tag ++ ++def lookup_function (val): ++ "Look-up and return a pretty-printer that can print val." ++ ++ # Get the type. ++ type = val.type ++ ++ # If it points to a reference, get the reference. ++ if type.code == gdb.TYPE_CODE_REF: ++ type = type.target () ++ ++ # Get the unqualified type, stripped of typedefs. ++ type = type.unqualified ().strip_typedefs () ++ ++ # Get the type name. ++ typename = type.tag ++ ++ if typename == None: ++ return None ++ ++ # Iterate over local dictionary of types to determine ++ # if a printer is registered for that type. Return an ++ # instantiation of the printer if found. ++ for function in pretty_printers_dict: ++ if function.match (typename): ++ return pretty_printers_dict[function] (val) ++ ++ # Cannot find a pretty printer. Return None. ++ ++ return None ++ ++ ++def register_pretty_printers (): ++ pretty_printers_dict[re.compile ('^struct s$')] = pp_s ++ pretty_printers_dict[re.compile ('^s$')] = pp_s ++ pretty_printers_dict[re.compile ('^S$')] = pp_s ++ ++ pretty_printers_dict[re.compile ('^struct ss$')] = pp_ss ++ pretty_printers_dict[re.compile ('^ss$')] = pp_ss ++ pretty_printers_dict[re.compile ('^const S &$')] = pp_s ++ pretty_printers_dict[re.compile ('^SSS$')] = pp_sss ++ ++ pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual ++ pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1 ++ ++ # Note that we purposely omit the typedef names here. ++ # Printer lookup is based on canonical name. ++ # However, we do need both tagged and untagged variants, to handle ++ # both the C and C++ cases. ++ pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print ++ pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter ++ pretty_printers_dict[re.compile ('^string_repr$')] = string_print ++ pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter ++ ++pretty_printers_dict = {} ++ ++register_pretty_printers () ++gdb.pretty_printers.append (lookup_function) +diff --git a/gdb/testsuite/gdb.python/python-template.cc b/gdb/testsuite/gdb.python/python-template.cc +new file mode 100644 +index 0000000..bd6a212 +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-template.cc +@@ -0,0 +1,30 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 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 3 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, see . */ ++ ++template ++struct Foo { ++}; ++ ++#ifndef TYPE ++#define TYPE int ++#endif ++ ++int main() ++{ ++ Foo foo; ++ return 0; // break here ++} +diff --git a/gdb/testsuite/gdb.python/python-template.exp b/gdb/testsuite/gdb.python/python-template.exp +new file mode 100644 +index 0000000..1ace5d6 +--- /dev/null ++++ b/gdb/testsuite/gdb.python/python-template.exp +@@ -0,0 +1,75 @@ ++# Copyright (C) 2008, 2009 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 3 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, see . ++ ++# This file is part of the GDB testsuite. It tests the mechanism ++# exposing values to Python. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile "python-template" ++set srcfile ${testfile}.cc ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \ ++ {debug c++}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++# Start with a fresh gdb. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++ ++gdb_test_multiple "python print 23" "verify python support" { ++ -re "not supported.*$gdb_prompt $" { ++ unsupported "python support is disabled" ++ return -1 ++ } ++ -re "$gdb_prompt $" {} ++} ++ ++proc test_template_arg {type} { ++ global testfile srcdir subdir srcfile binfile ++ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ ++ executable \ ++ [list debug c++ additional_flags="-DTYPE=$type"]] != "" } { ++ untested $type ++ return -1 ++ } ++ gdb_load ${binfile} ++ if ![runto_main ] then { ++ perror "couldn't run to breakpoint" ++ return ++ } ++ # There is no executable code in main(), so we are where we want to be ++ gdb_test "print foo" "" ++ gdb_test "python foo = gdb.history(0)" "" ++ ++ # Replace '*' with '\*' in regex. ++ regsub -all {\*} $type {\*} t ++ gdb_test "python print foo.type.template_argument(0)" $t $type ++} ++ ++test_template_arg "const int" ++test_template_arg "volatile int" ++test_template_arg "const int &" ++test_template_arg "volatile int &" ++test_template_arg "volatile int * const" ++test_template_arg "volatile int * const *" ++test_template_arg "const int * volatile" ++test_template_arg "const int * volatile * const * volatile *" +diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c +index 17e5c62..9637fe9 100644 +--- a/gdb/testsuite/gdb.python/python-value.c ++++ b/gdb/testsuite/gdb.python/python-value.c +@@ -33,13 +33,17 @@ enum e + TWO = 2 + }; + ++typedef struct s *PTR; ++ + enum e evalue = TWO; + + int + main (int argc, char *argv[]) + { ++ char *cp = argv[0]; /* Prevent gcc from optimizing argv[] out. */ + struct s s; + union u u; ++ PTR x = &s; + + s.a = 3; + s.b = 5; +diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp +index 8f5e0ab..c1a051c 100644 +--- a/gdb/testsuite/gdb.python/python-value.exp ++++ b/gdb/testsuite/gdb.python/python-value.exp +@@ -70,6 +70,9 @@ proc test_value_creation {} { + gdb_py_test_silent_cmd "python a = gdb.Value (u'unicode test')" "create unicode value" 1 + gdb_test "python print a" "\"unicode test\"" "print Unicode string" + gdb_test "python print a.__class__" "" "verify type of unicode string" ++ ++ # Test address attribute is None in a non-addressable value ++ gdb_test "python print 'result =', i.address" "= None" "Test address attribute in non-addressable value" + } + + proc test_value_numeric_ops {} { +@@ -225,6 +228,43 @@ proc test_value_in_inferior {} { + + # Check that the dereferenced value is sane + gdb_test "python print arg0" "0x.*$testfile\"" "verify dereferenced value" ++ ++ # Smoke-test is_optimized_out attribute ++ gdb_test "python print 'result =', arg0.is_optimized_out" "= False" "Test is_optimized_out attribute" ++ ++ # Test address attribute ++ gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute" ++} ++ ++proc test_value_after_death {} { ++ # Construct a type while the inferior is still running. ++ gdb_py_test_silent_cmd "python ptrtype = gdb.lookup_type('PTR')" \ ++ "create PTR type" 1 ++ ++ # Check the type has the expected name. ++ gdb_test "python print ptrtype" "PTR" \ ++ "check initial PTR type" ++ ++ # Kill the inferior and remove the symbols. ++ gdb_test "kill" "" "kill the inferior" \ ++ "Kill the program being debugged. .y or n. $" \ ++ "y" ++ gdb_test "file" "" "Discard the symbols" \ ++ "Discard symbol table from.*y or n. $" \ ++ "y" ++ ++ # Now create a value using that type. Relies on arg0, created by ++ # test_value_in_inferior. ++ gdb_py_test_silent_cmd "python castval = arg0.cast(ptrtype.pointer())" \ ++ "cast arg0 to PTR" 1 ++ ++ # Make sure the type is deleted. ++ gdb_py_test_silent_cmd "python ptrtype = None" \ ++ "delete PTR type" 1 ++ ++ # Now see if the value's type is still valid. ++ gdb_test "python print castval.type" "PTR \\*" \ ++ "print value's type" + } + + +@@ -256,3 +296,4 @@ if ![runto_main] then { + } + + test_value_in_inferior ++test_value_after_death +diff --git a/gdb/testsuite/lib/cp-support.exp b/gdb/testsuite/lib/cp-support.exp +index dbd2f59..44e1b51 100644 +--- a/gdb/testsuite/lib/cp-support.exp ++++ b/gdb/testsuite/lib/cp-support.exp +@@ -222,7 +222,7 @@ proc cp_test_ptype_class { in_command in_testname in_key in_tag in_class_table { + + set parse_okay 0 + gdb_test_multiple "$in_command" "$in_testname // parse failed" { +- -re "type = (struct|class)${wsopt}(\[A-Za-z0-9_\]*)${wsopt}((:\[^\{\]*)?)${wsopt}\{(.*)\}${wsopt}(\[^\r\n\]*)\[\r\n\]+$gdb_prompt $" { ++ -re "type = (struct|class)${wsopt}(\[A-Za-z0-9_:\]*)${wsopt}((:\[^\{\]*)?)${wsopt}\{(.*)\}${wsopt}(\[^\r\n\]*)\[\r\n\]+$gdb_prompt $" { + set parse_okay 1 + set actual_key $expect_out(1,string) + set actual_tag $expect_out(2,string) +@@ -231,6 +231,7 @@ proc cp_test_ptype_class { in_command in_testname in_key in_tag in_class_table { + set actual_tail $expect_out(6,string) + } + } ++ + if { ! $parse_okay } then { return } + + # Check the actual key. It would be nice to require that it match +diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp +index 820ab20..8b8e7c6 100644 +--- a/gdb/testsuite/lib/gdb.exp ++++ b/gdb/testsuite/lib/gdb.exp +@@ -1162,9 +1162,12 @@ proc default_gdb_start { } { + global gdb_prompt + global timeout + global gdb_spawn_id; ++ global env + + gdb_stop_suppressing_tests; + ++ set env(LC_CTYPE) C ++ + verbose "Spawning $GDB $INTERNAL_GDBFLAGS $GDBFLAGS" + + if [info exists gdb_spawn_id] { +diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp +index f62c240..bda7ea1 100644 +--- a/gdb/testsuite/lib/mi-support.exp ++++ b/gdb/testsuite/lib/mi-support.exp +@@ -1237,6 +1237,21 @@ proc mi_varobj_update_with_type_change { name new_type new_children testname } { + mi_gdb_test "-var-update $name" $er $testname + } + ++# Update a dynamic varobj named NAME. CHILDREN is a list of children, ++# in the same form as mi_list_varobj_children. TESTNAME is the name ++# of the test. ++proc mi_varobj_update_dynamic {name children testname} { ++ set children_exp_j [mi_child_regexp $children 0] ++ ++ set er "\\^done,changelist=\\\[" ++ ++ append er "{name=\"$name\",in_scope=\"true\",type_changed=\"false\"" ++ append er ",children=\\\[$children_exp_j.*\\\]}\\\]" ++ ++ verbose -log "Expecting: $er" ++ mi_gdb_test "-var-update $name" $er $testname ++} ++ + proc mi_check_varobj_value { name value testname } { + + mi_gdb_test "-var-evaluate-expression $name" \ +@@ -1244,6 +1259,42 @@ proc mi_check_varobj_value { name value testname } { + $testname + } + ++# Helper proc which constructs a child regexp for ++# mi_list_varobj_children and mi_varobj_update_dynamic. ++proc mi_child_regexp {children add_child} { ++ set children_exp {} ++ set whatever "\"\[^\"\]+\"" ++ ++ if {$add_child} { ++ set pre "child=" ++ } else { ++ set pre "" ++ } ++ ++ foreach item $children { ++ ++ set name [lindex $item 0] ++ set exp [lindex $item 1] ++ set numchild [lindex $item 2] ++ if {[llength $item] == 5} { ++ set type [lindex $item 3] ++ set value [lindex $item 4] ++ ++ lappend children_exp\ ++ "$pre{name=\"$name\",exp=\"$exp\",numchild=\"$numchild\",value=\"$value\",type=\"$type\"\(,thread-id=\"\[0-9\]+\")?}" ++ } elseif {[llength $item] == 4} { ++ set type [lindex $item 3] ++ ++ lappend children_exp\ ++ "$pre{name=\"$name\",exp=\"$exp\",numchild=\"$numchild\",type=\"$type\"\(,thread-id=\"\[0-9\]+\")?}" ++ } else { ++ lappend children_exp\ ++ "$pre{name=\"$name\",exp=\"$exp\",numchild=\"$numchild\"(,thread-id=\"\[0-9\]+\")?}" ++ } ++ } ++ return [join $children_exp ","] ++} ++ + # Check the results of the: + # + # -var-list-children VARNAME +@@ -1265,39 +1316,23 @@ proc mi_check_varobj_value { name value testname } { + # have no value. + # + proc mi_list_varobj_children { varname children testname } { ++ mi_list_varobj_children_range $varname [llength $children] $children \ ++ $testname ++} + ++# Like mi_list_varobj_children, but assumes that a subrange has been ++# selected with -var-set-child-range. NUMCHILDREN is the total number ++# of children. ++proc mi_list_varobj_children_range {varname numchildren children testname} { + set options "" + if {[llength $varname] == 2} { + set options [lindex $varname 1] + set varname [lindex $varname 0] + } + +- set numchildren [llength $children] +- set children_exp {} + set whatever "\"\[^\"\]+\"" + +- foreach item $children { +- +- set name [lindex $item 0] +- set exp [lindex $item 1] +- set numchild [lindex $item 2] +- if {[llength $item] == 5} { +- set type [lindex $item 3] +- set value [lindex $item 4] +- +- lappend children_exp\ +- "child={name=\"$name\",exp=\"$exp\",numchild=\"$numchild\",value=\"$value\",type=\"$type\"\(,thread-id=\"\[0-9\]+\")?}" +- } elseif {[llength $item] == 4} { +- set type [lindex $item 3] +- +- lappend children_exp\ +- "child={name=\"$name\",exp=\"$exp\",numchild=\"$numchild\",type=\"$type\"\(,thread-id=\"\[0-9\]+\")?}" +- } else { +- lappend children_exp\ +- "child={name=\"$name\",exp=\"$exp\",numchild=\"$numchild\"(,thread-id=\"\[0-9\]+\")?}" +- } +- } +- set children_exp_j [join $children_exp ","] ++ set children_exp_j [mi_child_regexp $children 1] + if {$numchildren} { + set expected "\\^done,numchild=\".*\",children=\\\[$children_exp_j.*\\\]" + } { +@@ -1770,3 +1805,25 @@ proc mi_check_thread_states { xstates test } { + verbose -log "expecting: $pattern" + mi_gdb_test "-thread-info" $pattern $test + } ++ ++# Return a list of MI features supported by this gdb. ++proc mi_get_features {} { ++ global expect_out mi_gdb_prompt ++ ++ send_gdb "-list-features\n" ++ ++ gdb_expect { ++ -re "\\^done,features=\\\[(.*)\\\]\r\n$mi_gdb_prompt$" { ++ regsub -all -- \" $expect_out(1,string) "" features ++ return [split $features ,] ++ } ++ -re ".*\r\n$mi_gdb_prompt$" { ++ verbose -log "got $expect_out(buffer)" ++ return "" ++ } ++ timeout { ++ verbose -log "timeout in mi_gdb_prompt" ++ return "" ++ } ++ } ++} +diff --git a/gdb/thread.c b/gdb/thread.c +index 9dea7c2..326e44e 100644 +--- a/gdb/thread.c ++++ b/gdb/thread.c +@@ -61,7 +61,6 @@ static int thread_alive (struct thread_info *); + static void info_threads_command (char *, int); + static void thread_apply_command (char *, int); + static void restore_current_thread (ptid_t); +-static void prune_threads (void); + + /* Frontend view of the thread state. Possible extensions: stepping, + finishing, until(ling),... */ +@@ -459,16 +458,23 @@ thread_alive (struct thread_info *tp) + return 1; + } + +-static void ++void + prune_threads (void) + { +- struct thread_info *tp, *next; ++ struct thread_info *tp; ++ struct thread_info **prevp = &thread_list; + +- for (tp = thread_list; tp; tp = next) ++ for (tp = *prevp; tp; tp = *prevp) + { +- next = tp->next; ++ /* If the thread has died, free it and unlink it from the list. ++ Otherwise, advance to the next thread. */ + if (!thread_alive (tp)) +- delete_thread (tp->ptid); ++ { ++ *prevp = tp->next; ++ free_thread (tp); ++ } ++ else ++ prevp = &tp->next; + } + } + +diff --git a/gdb/top.c b/gdb/top.c +index d676f02..d6b17f0 100644 +--- a/gdb/top.c ++++ b/gdb/top.c +@@ -377,6 +377,7 @@ execute_command (char *p, int from_tty) + } + + free_all_values (); ++ free_all_types (); + + /* Force cleanup of any alloca areas if using C alloca instead of + a builtin alloca. */ +@@ -1246,7 +1247,8 @@ quit_target (void *arg) + struct qt_args *qt = (struct qt_args *)arg; + + /* Kill or detach all inferiors. */ +- iterate_over_inferiors (kill_or_detach, qt); ++ if (target_has_execution) ++ iterate_over_inferiors (kill_or_detach, qt); + + /* Give all pushed targets a chance to do minimal cleanup, and pop + them all out. */ +diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c +index 83df64e..003ef3a 100644 +--- a/gdb/tracepoint.c ++++ b/gdb/tracepoint.c +@@ -1587,7 +1587,7 @@ encode_actions (struct tracepoint *t, char ***tdp_actions, + case UNOP_MEMVAL: + /* safe because we know it's a simple expression */ + tempval = evaluate_expression (exp); +- addr = VALUE_ADDRESS (tempval) + value_offset (tempval); ++ addr = value_address (tempval); + len = TYPE_LENGTH (check_typedef (exp->elts[1].type)); + add_memrange (collect, memrange_absolute, addr, len); + break; +diff --git a/gdb/typeprint.c b/gdb/typeprint.c +index 1f824fa..4a92a13 100644 +--- a/gdb/typeprint.c ++++ b/gdb/typeprint.c +@@ -35,6 +35,7 @@ + #include "gdb_string.h" + #include "exceptions.h" + #include "valprint.h" ++#include "dwarf2loc.h" + #include + + extern void _initialize_typeprint (void); +@@ -76,6 +77,9 @@ void + type_print (struct type *type, char *varstring, struct ui_file *stream, + int show) + { ++ if (show >= 0) ++ type = check_typedef (type); ++ + LA_PRINT_TYPE (type, varstring, stream, show, 0); + } + +@@ -115,7 +119,8 @@ whatis_exp (char *exp, int show) + { + struct expression *expr; + struct value *val; +- struct cleanup *old_chain = NULL; ++ /* Required at least for the object_address_set call. */ ++ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + struct type *real_type = NULL; + struct type *type; + int full = 0; +@@ -126,12 +131,13 @@ whatis_exp (char *exp, int show) + if (exp) + { + expr = parse_expression (exp); +- old_chain = make_cleanup (free_current_contents, &expr); ++ make_cleanup (free_current_contents, &expr); + val = evaluate_type (expr); + } + else + val = access_value_history (0); + ++ object_address_set (VALUE_ADDRESS (val)); + type = value_type (val); + + get_user_print_options (&opts); +@@ -168,8 +174,7 @@ whatis_exp (char *exp, int show) + type_print (type, "", gdb_stdout, show); + printf_filtered ("\n"); + +- if (exp) +- do_cleanups (old_chain); ++ do_cleanups (old_chain); + } + + static void +@@ -236,7 +241,7 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream) + break; + + case TYPE_CODE_CHAR: +- LA_PRINT_CHAR ((unsigned char) val, stream); ++ LA_PRINT_CHAR ((unsigned char) val, type, stream); + break; + + case TYPE_CODE_BOOL: +diff --git a/gdb/typeprint.h b/gdb/typeprint.h +index f561310..b39fd17 100644 +--- a/gdb/typeprint.h ++++ b/gdb/typeprint.h +@@ -26,4 +26,6 @@ void print_type_scalar (struct type * type, LONGEST, struct ui_file *); + + void c_type_print_varspec_suffix (struct type *, struct ui_file *, int, + int, int); ++ ++void c_type_print_args (struct type *, struct ui_file *, int); + #endif +diff --git a/gdb/ui-file.c b/gdb/ui-file.c +index 02a0314..5c8c96e 100644 +--- a/gdb/ui-file.c ++++ b/gdb/ui-file.c +@@ -22,6 +22,7 @@ + + #include "defs.h" + #include "ui-file.h" ++#include "gdb_obstack.h" + #include "gdb_string.h" + + #include +@@ -263,7 +264,7 @@ set_ui_file_data (struct ui_file *file, void *data, + } + + /* ui_file utility function for converting a ``struct ui_file'' into +- a memory buffer''. */ ++ a memory buffer. */ + + struct accumulated_ui_file + { +@@ -297,6 +298,23 @@ ui_file_xstrdup (struct ui_file *file, + *length = acc.length; + return acc.buffer; + } ++ ++static void ++do_ui_file_obsavestring (void *context, const char *buffer, long length) ++{ ++ struct obstack *obstack = (struct obstack *) context; ++ obstack_grow (obstack, buffer, length); ++} ++ ++char * ++ui_file_obsavestring (struct ui_file *file, struct obstack *obstack, ++ long *length) ++{ ++ ui_file_put (file, do_ui_file_obsavestring, obstack); ++ *length = obstack_object_size (obstack); ++ obstack_1grow (obstack, '\0'); ++ return obstack_finish (obstack); ++} + + /* A pure memory based ``struct ui_file'' that can be used an output + buffer. The buffers accumulated contents are available via +diff --git a/gdb/ui-file.h b/gdb/ui-file.h +index 1562d5a..d86a7eb 100644 +--- a/gdb/ui-file.h ++++ b/gdb/ui-file.h +@@ -19,6 +19,7 @@ + #ifndef UI_FILE_H + #define UI_FILE_H + ++struct obstack; + struct ui_file; + + /* Create a generic ui_file object with null methods. */ +@@ -77,7 +78,10 @@ extern void ui_file_put (struct ui_file *src, ui_file_put_method_ftype *write, v + appended NUL. */ + extern char *ui_file_xstrdup (struct ui_file *file, long *length); + +- ++/* Similar to ui_file_xstrdup, but return a new string allocated on ++ OBSTACK. */ ++extern char *ui_file_obsavestring (struct ui_file *file, ++ struct obstack *obstack, long *length); + + extern long ui_file_read (struct ui_file *file, char *buf, long length_buf); + +diff --git a/gdb/utils.c b/gdb/utils.c +index 9224839..88a9a39 100644 +--- a/gdb/utils.c ++++ b/gdb/utils.c +@@ -272,6 +272,19 @@ make_cleanup_fclose (FILE *file) + } + + static void ++do_obstack_free (void *arg) ++{ ++ struct obstack *ob = arg; ++ obstack_free (ob, NULL); ++} ++ ++struct cleanup * ++make_cleanup_obstack_free (struct obstack *obstack) ++{ ++ return make_cleanup (do_obstack_free, obstack); ++} ++ ++static void + do_ui_file_delete (void *arg) + { + ui_file_delete (arg); +@@ -1554,21 +1567,33 @@ query (const char *ctlstr, ...) + va_end (args); + } + +-/* Print an error message saying that we couldn't make sense of a +- \^mumble sequence in a string or character constant. START and END +- indicate a substring of some larger string that contains the +- erroneous backslash sequence, missing the initial backslash. */ +-static NORETURN int +-no_control_char_error (const char *start, const char *end) ++/* A helper for parse_escape that converts a host character to a ++ target character. C is the host character. If conversion is ++ possible, then the target character is stored in *TARGET_C and the ++ function returns 1. Otherwise, the function returns 0. */ ++ ++static int ++host_char_to_target (int c, int *target_c) + { +- int len = end - start; +- char *copy = alloca (end - start + 1); ++ struct obstack host_data; ++ char the_char = c; ++ struct cleanup *cleanups; ++ int result = 0; ++ ++ obstack_init (&host_data); ++ cleanups = make_cleanup_obstack_free (&host_data); ++ ++ convert_between_encodings (target_charset (), host_charset (), ++ &the_char, 1, 1, &host_data, translit_none); + +- memcpy (copy, start, len); +- copy[len] = '\0'; ++ if (obstack_object_size (&host_data) == 1) ++ { ++ result = 1; ++ *target_c = *(char *) obstack_base (&host_data); ++ } + +- error (_("There is no control character `\\%s' in the `%s' character set."), +- copy, target_charset ()); ++ do_cleanups (cleanups); ++ return result; + } + + /* Parse a C escape sequence. STRING_PTR points to a variable +@@ -1591,53 +1616,13 @@ parse_escape (char **string_ptr) + { + int target_char; + int c = *(*string_ptr)++; +- if (c_parse_backslash (c, &target_char)) +- return target_char; +- else +- switch (c) +- { ++ switch (c) ++ { + case '\n': + return -2; + case 0: + (*string_ptr)--; + return 0; +- case '^': +- { +- /* Remember where this escape sequence started, for reporting +- errors. */ +- char *sequence_start_pos = *string_ptr - 1; +- +- c = *(*string_ptr)++; +- +- if (c == '?') +- { +- /* XXXCHARSET: What is `delete' in the host character set? */ +- c = 0177; +- +- if (!host_char_to_target (c, &target_char)) +- error (_("There is no character corresponding to `Delete' " +- "in the target character set `%s'."), host_charset ()); +- +- return target_char; +- } +- else if (c == '\\') +- target_char = parse_escape (string_ptr); +- else +- { +- if (!host_char_to_target (c, &target_char)) +- no_control_char_error (sequence_start_pos, *string_ptr); +- } +- +- /* Now target_char is something like `c', and we want to find +- its control-character equivalent. */ +- if (!target_char_to_control_char (target_char, &target_char)) +- no_control_char_error (sequence_start_pos, *string_ptr); +- +- return target_char; +- } +- +- /* XXXCHARSET: we need to use isdigit and value-of-digit +- methods of the host character set here. */ + + case '0': + case '1': +@@ -1648,16 +1633,16 @@ parse_escape (char **string_ptr) + case '6': + case '7': + { +- int i = c - '0'; ++ int i = host_hex_value (c); + int count = 0; + while (++count < 3) + { + c = (**string_ptr); +- if (c >= '0' && c <= '7') ++ if (isdigit (c) && c != '8' && c != '9') + { + (*string_ptr)++; + i *= 8; +- i += c - '0'; ++ i += host_hex_value (c); + } + else + { +@@ -1666,14 +1651,39 @@ parse_escape (char **string_ptr) + } + return i; + } +- default: +- if (!host_char_to_target (c, &target_char)) +- error +- ("The escape sequence `\%c' is equivalent to plain `%c', which" +- " has no equivalent\n" "in the `%s' character set.", c, c, +- target_charset ()); +- return target_char; +- } ++ ++ case 'a': ++ c = '\a'; ++ break; ++ case 'b': ++ c = '\b'; ++ break; ++ case 'f': ++ c = '\f'; ++ break; ++ case 'n': ++ c = '\n'; ++ break; ++ case 'r': ++ c = '\r'; ++ break; ++ case 't': ++ c = '\t'; ++ break; ++ case 'v': ++ c = '\v'; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (!host_char_to_target (c, &target_char)) ++ error ++ ("The escape sequence `\%c' is equivalent to plain `%c', which" ++ " has no equivalent\n" "in the `%s' character set.", c, c, ++ target_charset ()); ++ return target_char; + } + + /* Print the character C on STREAM as part of the contents of a literal +diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c +index 9850de4..285fe3f 100644 +--- a/gdb/v850-tdep.c ++++ b/gdb/v850-tdep.c +@@ -705,7 +705,7 @@ v850_push_dummy_call (struct gdbarch *gdbarch, + if (!v850_type_is_scalar (value_type (*args)) + && TYPE_LENGTH (value_type (*args)) > E_MAX_RETTYPE_SIZE_IN_REGS) + { +- store_unsigned_integer (valbuf, 4, VALUE_ADDRESS (*args)); ++ store_unsigned_integer (valbuf, 4, value_address (*args)); + len = 4; + val = valbuf; + } +diff --git a/gdb/valarith.c b/gdb/valarith.c +index f38cdb8..8e103cf 100644 +--- a/gdb/valarith.c ++++ b/gdb/valarith.c +@@ -164,9 +164,9 @@ an integer nor a pointer of the same type.")); + struct value * + value_subscript (struct value *array, struct value *idx) + { +- struct value *bound; + int c_style = current_language->c_style_arrays; + struct type *tarray; ++ LONGEST index = value_as_long (idx); + + array = coerce_ref (array); + tarray = check_typedef (value_type (array)); +@@ -179,13 +179,26 @@ value_subscript (struct value *array, struct value *idx) + get_discrete_bounds (range_type, &lowerbound, &upperbound); + + if (VALUE_LVAL (array) != lval_memory) +- return value_subscripted_rvalue (array, idx, lowerbound); ++ { ++ if (index >= lowerbound && index <= upperbound) ++ { ++ CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray)); ++ CORE_ADDR offset = (index - lowerbound) * element_size; ++ ++ return value_subscripted_rvalue (array, offset); ++ } ++ error (_("array or string index out of range")); ++ } + + if (c_style == 0) + { +- LONGEST index = value_as_long (idx); + if (index >= lowerbound && index <= upperbound) +- return value_subscripted_rvalue (array, idx, lowerbound); ++ { ++ CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray)); ++ CORE_ADDR offset = (index - lowerbound) * element_size; ++ ++ return value_subscripted_rvalue (array, offset); ++ } + /* Emit warning unless we have an array of unknown size. + An array of unknown size has lowerbound 0 and upperbound -1. */ + if (upperbound > -1) +@@ -194,49 +207,52 @@ value_subscript (struct value *array, struct value *idx) + c_style = 1; + } + +- if (lowerbound != 0) +- { +- bound = value_from_longest (value_type (idx), (LONGEST) lowerbound); +- idx = value_binop (idx, bound, BINOP_SUB); +- } +- ++ index -= lowerbound; + array = value_coerce_array (array); + } + + if (c_style) +- return value_ind (value_ptradd (array, idx)); ++ { ++ struct value *idx; ++ ++ idx = value_from_longest (builtin_type_int32, index); ++ return value_ind (value_ptradd (array, idx)); ++ } + else + error (_("not an array or string")); + } + +-/* Return the value of EXPR[IDX], expr an aggregate rvalue +- (eg, a vector register). This routine used to promote floats +- to doubles, but no longer does. */ ++/* Return the value of *((void *) ARRAY + ELEMENT), ARRAY an aggregate rvalue ++ (eg, a vector register). This routine used to promote floats to doubles, ++ but no longer does. OFFSET is zero-based with 0 for the lowermost existing ++ element, it must be expressed in bytes (therefore multiplied by ++ check_typedef (TYPE_TARGET_TYPE (array_type)). */ + + struct value * +-value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound) ++value_subscripted_rvalue (struct value *array, CORE_ADDR offset) + { + struct type *array_type = check_typedef (value_type (array)); + struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type)); +- unsigned int elt_size = TYPE_LENGTH (elt_type); +- LONGEST index = value_as_long (idx); +- unsigned int elt_offs = elt_size * longest_to_int (index - lowerbound); + struct value *v; + +- if (index < lowerbound || elt_offs >= TYPE_LENGTH (array_type)) +- error (_("no such vector element")); ++ /* Do not check TYPE_LENGTH (array_type) as we may have been given the ++ innermost dimension of a multi-dimensional Fortran array where its length ++ is shorter than the possibly accessed element offset. */ + + v = allocate_value (elt_type); + if (VALUE_LVAL (array) == lval_memory && value_lazy (array)) + set_value_lazy (v, 1); + else +- memcpy (value_contents_writeable (v), +- value_contents (array) + elt_offs, elt_size); ++ { ++ unsigned int elt_size = TYPE_LENGTH (elt_type); ++ memcpy (value_contents_writeable (v), ++ value_contents (array) + offset, elt_size); ++ } + + set_value_component_location (v, array); + VALUE_REGNUM (v) = VALUE_REGNUM (array); + VALUE_FRAME_ID (v) = VALUE_FRAME_ID (array); +- set_value_offset (v, value_offset (array) + elt_offs); ++ set_value_offset (v, value_offset (array) + offset); + return v; + } + +diff --git a/gdb/valops.c b/gdb/valops.c +index 9810f2b..14c562e 100644 +--- a/gdb/valops.c ++++ b/gdb/valops.c +@@ -38,6 +38,7 @@ + #include "cp-support.h" + #include "dfp.h" + #include "user-regs.h" ++#include "dwarf2loc.h" + + #include + #include "gdb_string.h" +@@ -254,9 +255,8 @@ value_cast_structs (struct type *type, struct value *v2) + if (v) + { + /* Downcasting is possible (t1 is superclass of v2). */ +- CORE_ADDR addr2 = VALUE_ADDRESS (v2); +- addr2 -= (VALUE_ADDRESS (v) +- + value_offset (v) ++ CORE_ADDR addr2 = value_address (v2); ++ addr2 -= (value_address (v) + + value_embedded_offset (v)); + return value_at (type, addr2); + } +@@ -371,8 +371,6 @@ value_cast (struct type *type, struct value *arg2) + new_length = val_length / element_length; + if (val_length % element_length != 0) + warning (_("array element type size does not divide object size in cast")); +- /* FIXME-type-allocation: need a way to free this type when +- we are done with it. */ + range_type = create_range_type ((struct type *) NULL, + TYPE_TARGET_TYPE (range_type), + low_bound, +@@ -511,7 +509,7 @@ value_cast (struct type *type, struct value *arg2) + } + else if (VALUE_LVAL (arg2) == lval_memory) + return value_at_lazy (type, +- VALUE_ADDRESS (arg2) + value_offset (arg2)); ++ value_address (arg2)); + else if (code1 == TYPE_CODE_VOID) + { + return value_zero (builtin_type_void, not_lval); +@@ -568,6 +566,64 @@ value_one (struct type *type, enum lval_type lv) + return val; + } + ++/* object_address_set must be already called before this function. */ ++ ++const char * ++object_address_data_not_valid (struct type *type) ++{ ++ /* Attributes are present only at the target type of a typedef. Make the ++ call conditional as it would otherwise loop through type_length_get. */ ++ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) ++ CHECK_TYPEDEF (type); ++ ++ /* DW_AT_associated has a preference over DW_AT_allocated. */ ++ if (TYPE_NOT_ASSOCIATED (type) ++ || (TYPE_ASSOCIATED (type) != NULL ++ && 0 == dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (type)))) ++ return N_("object is not associated"); ++ ++ if (TYPE_NOT_ALLOCATED (type) ++ || (TYPE_ALLOCATED (type) != NULL ++ && 0 == dwarf_locexpr_baton_eval (TYPE_ALLOCATED (type)))) ++ return N_("object is not allocated"); ++ ++ return NULL; ++} ++ ++/* Return non-zero if the variable is valid. If it is valid the function ++ may store the data address (DW_AT_DATA_LOCATION) of TYPE at *ADDRESS_RETURN. ++ You must set *ADDRESS_RETURN as VALUE_ADDRESS (VAL) before calling this ++ function. If no DW_AT_DATA_LOCATION is present for TYPE the address at ++ *ADDRESS_RETURN is left unchanged. ADDRESS_RETURN must not be NULL, use ++ object_address_data_not_valid () for just the data validity check. */ ++ ++int ++object_address_get_data (struct type *type, CORE_ADDR *address_return) ++{ ++ gdb_assert (address_return != NULL); ++ ++ object_address_set (*address_return); ++ ++ /* TYPE_DATA_LOCATION_DWARF_BLOCK / TYPE_DATA_LOCATION_ADDR are present only ++ at the target type of a typedef. */ ++ CHECK_TYPEDEF (type); ++ ++ if (object_address_data_not_valid (type) != NULL) ++ { ++ /* Do not try to evaluate DW_AT_data_location as it may even crash ++ (it would just return the value zero in the gfortran case). */ ++ return 0; ++ } ++ ++ if (TYPE_DATA_LOCATION_IS_ADDR (type)) ++ *address_return = TYPE_DATA_LOCATION_ADDR (type); ++ else if (TYPE_DATA_LOCATION_DWARF_BLOCK (type) != NULL) ++ *address_return ++ = dwarf_locexpr_baton_eval (TYPE_DATA_LOCATION_DWARF_BLOCK (type)); ++ ++ return 1; ++} ++ + /* Return a value with type TYPE located at ADDR. + + Call value_at only if the data needs to be fetched immediately; +@@ -593,7 +649,7 @@ value_at (struct type *type, CORE_ADDR addr) + read_memory (addr, value_contents_all_raw (val), TYPE_LENGTH (type)); + + VALUE_LVAL (val) = lval_memory; +- VALUE_ADDRESS (val) = addr; ++ set_value_address (val, addr); + + return val; + } +@@ -611,7 +667,7 @@ value_at_lazy (struct type *type, CORE_ADDR addr) + val = allocate_value_lazy (type); + + VALUE_LVAL (val) = lval_memory; +- VALUE_ADDRESS (val) = addr; ++ set_value_address (val, addr); + + return val; + } +@@ -637,11 +693,19 @@ value_fetch_lazy (struct value *val) + allocate_value_contents (val); + if (VALUE_LVAL (val) == lval_memory) + { +- CORE_ADDR addr = VALUE_ADDRESS (val) + value_offset (val); +- int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val))); ++ CORE_ADDR addr = VALUE_ADDRESS (val); ++ ++ if (object_address_get_data (value_type (val), &addr)) ++ { ++ struct type *type = value_enclosing_type (val); ++ int length = TYPE_LENGTH (check_typedef (type)); + +- if (length) +- read_memory (addr, value_contents_all_raw (val), length); ++ if (length) ++ { ++ addr += value_offset (val); ++ read_memory (addr, value_contents_all_raw (val), length); ++ } ++ } + } + else if (VALUE_LVAL (val) == lval_register) + { +@@ -709,7 +773,7 @@ value_fetch_lazy (struct value *val) + VALUE_REGNUM (new_val)); + else if (VALUE_LVAL (new_val) == lval_memory) + fprintf_unfiltered (gdb_stdlog, " address=0x%s", +- paddr_nz (VALUE_ADDRESS (new_val))); ++ paddr_nz (value_address (new_val))); + else + fprintf_unfiltered (gdb_stdlog, " computed"); + +@@ -813,16 +877,15 @@ value_assign (struct value *toval, struct value *fromval) + error (_("Can't handle bitfields which don't fit in a %d bit word."), + (int) sizeof (LONGEST) * HOST_CHAR_BIT); + +- read_memory (VALUE_ADDRESS (toval) + value_offset (toval), +- buffer, changed_len); ++ read_memory (value_address (toval), buffer, changed_len); + modify_field (buffer, value_as_long (fromval), + value_bitpos (toval), value_bitsize (toval)); +- changed_addr = VALUE_ADDRESS (toval) + value_offset (toval); ++ changed_addr = value_address (toval); + dest_buffer = buffer; + } + else + { +- changed_addr = VALUE_ADDRESS (toval) + value_offset (toval); ++ changed_addr = value_address (toval); + changed_len = TYPE_LENGTH (type); + dest_buffer = value_contents (fromval); + } +@@ -985,11 +1048,11 @@ value_repeat (struct value *arg1, int count) + + val = allocate_repeat_value (value_enclosing_type (arg1), count); + +- read_memory (VALUE_ADDRESS (arg1) + value_offset (arg1), ++ read_memory (value_address (arg1), + value_contents_all_raw (val), + TYPE_LENGTH (value_enclosing_type (val))); + VALUE_LVAL (val) = lval_memory; +- VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + value_offset (arg1); ++ set_value_address (val, value_address (arg1)); + + return val; + } +@@ -1036,10 +1099,11 @@ address_of_variable (struct symbol *var, struct block *b) + + val = value_of_variable (var, b); + +- if ((VALUE_LVAL (val) == lval_memory && value_lazy (val)) ++ if ((VALUE_LVAL (val) == lval_memory && value_lazy (val) ++ && object_address_get_data (type, &VALUE_ADDRESS (val))) + || TYPE_CODE (type) == TYPE_CODE_FUNC) + { +- CORE_ADDR addr = VALUE_ADDRESS (val); ++ CORE_ADDR addr = value_address (val); + return value_from_pointer (lookup_pointer_type (type), addr); + } + +@@ -1145,6 +1209,7 @@ struct value * + value_coerce_array (struct value *arg1) + { + struct type *type = check_typedef (value_type (arg1)); ++ CORE_ADDR address; + + /* If the user tries to do something requiring a pointer with an + array that has not yet been pushed to the target, then this would +@@ -1154,8 +1219,12 @@ value_coerce_array (struct value *arg1) + if (VALUE_LVAL (arg1) != lval_memory) + error (_("Attempt to take address of value not located in memory.")); + ++ address = VALUE_ADDRESS (arg1); ++ if (!object_address_get_data (type, &address)) ++ error (_("Attempt to take address of non-valid value.")); ++ + return value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), +- (VALUE_ADDRESS (arg1) + value_offset (arg1))); ++ address + value_offset (arg1)); + } + + /* Given a value which is a function, return a value which is a pointer +@@ -1170,7 +1239,7 @@ value_coerce_function (struct value *arg1) + error (_("Attempt to take address of value not located in memory.")); + + retval = value_from_pointer (lookup_pointer_type (value_type (arg1)), +- (VALUE_ADDRESS (arg1) + value_offset (arg1))); ++ (value_address (arg1))); + return retval; + } + +@@ -1205,8 +1274,7 @@ value_addr (struct value *arg1) + + /* Get target memory address */ + arg2 = value_from_pointer (lookup_pointer_type (value_type (arg1)), +- (VALUE_ADDRESS (arg1) +- + value_offset (arg1) ++ (value_address (arg1) + + value_embedded_offset (arg1))); + + /* This may be a pointer to a base subobject; so remember the +@@ -1352,6 +1420,24 @@ value_array (int lowbound, int highbound, struct value **elemvec) + return val; + } + ++struct value * ++value_typed_string (char *ptr, int len, struct type *char_type) ++{ ++ struct value *val; ++ int lowbound = current_language->string_lower_bound; ++ int highbound = len / TYPE_LENGTH (char_type); ++ struct type *rangetype = create_range_type ((struct type *) NULL, ++ builtin_type_int32, ++ lowbound, ++ highbound + lowbound - 1); ++ struct type *stringtype ++ = create_array_type ((struct type *) NULL, char_type, rangetype); ++ ++ val = allocate_value (stringtype); ++ memcpy (value_contents_raw (val), ptr, len); ++ return val; ++} ++ + /* Create a value for a string constant by allocating space in the + inferior, copying the data into that space, and returning the + address with type TYPE_CODE_STRING. PTR points to the string +@@ -1600,8 +1686,7 @@ search_struct_field (char *name, struct value *arg1, int offset, + + boffset = baseclass_offset (type, i, + value_contents (arg1) + offset, +- VALUE_ADDRESS (arg1) +- + value_offset (arg1) + offset); ++ value_address (arg1) + offset); + if (boffset == -1) + error (_("virtual baseclass botch")); + +@@ -1616,13 +1701,13 @@ search_struct_field (char *name, struct value *arg1, int offset, + + v2 = allocate_value (basetype); + base_addr = +- VALUE_ADDRESS (arg1) + value_offset (arg1) + boffset; ++ value_address (arg1) + boffset; + if (target_read_memory (base_addr, + value_contents_raw (v2), + TYPE_LENGTH (basetype)) != 0) + error (_("virtual baseclass botch")); + VALUE_LVAL (v2) = lval_memory; +- VALUE_ADDRESS (v2) = base_addr; ++ set_value_address (v2, base_addr); + } + else + { +@@ -1745,8 +1830,7 @@ search_struct_method (char *name, struct value **arg1p, + if (offset < 0 || offset >= TYPE_LENGTH (type)) + { + gdb_byte *tmp = alloca (TYPE_LENGTH (baseclass)); +- if (target_read_memory (VALUE_ADDRESS (*arg1p) +- + value_offset (*arg1p) + offset, ++ if (target_read_memory (value_address (*arg1p) + offset, + tmp, TYPE_LENGTH (baseclass)) != 0) + error (_("virtual baseclass botch")); + base_valaddr = tmp; +@@ -1755,8 +1839,7 @@ search_struct_method (char *name, struct value **arg1p, + base_valaddr = value_contents (*arg1p) + offset; + + base_offset = baseclass_offset (type, i, base_valaddr, +- VALUE_ADDRESS (*arg1p) +- + value_offset (*arg1p) + offset); ++ value_address (*arg1p) + offset); + if (base_offset == -1) + error (_("virtual baseclass botch")); + } +@@ -1965,7 +2048,7 @@ find_method_list (struct value **argp, char *method, + base_offset = value_offset (*argp) + offset; + base_offset = baseclass_offset (type, i, + value_contents (*argp) + base_offset, +- VALUE_ADDRESS (*argp) + base_offset); ++ value_address (*argp) + base_offset); + if (base_offset == -1) + error (_("virtual baseclass botch")); + } +@@ -2083,12 +2166,25 @@ find_overload_match (struct type **arg_types, int nargs, + if (method) + { + gdb_assert (obj); ++ ++ /* OBJ may be a pointer value rather than the object itself. */ ++ obj = coerce_ref (obj); ++ while (TYPE_CODE (check_typedef (value_type (obj))) == TYPE_CODE_PTR) ++ obj = coerce_ref (value_ind (obj)); + obj_type_name = TYPE_NAME (value_type (obj)); +- /* Hack: evaluate_subexp_standard often passes in a pointer +- value rather than the object itself, so try again. */ +- if ((!obj_type_name || !*obj_type_name) +- && (TYPE_CODE (value_type (obj)) == TYPE_CODE_PTR)) +- obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (value_type (obj))); ++ ++ /* First check whether this is a data member, e.g. a pointer to ++ a function. */ ++ if (TYPE_CODE (check_typedef (value_type (obj))) == TYPE_CODE_STRUCT) ++ { ++ *valp = search_struct_field (name, obj, 0, ++ check_typedef (value_type (obj)), 0); ++ if (*valp) ++ { ++ *staticp = 1; ++ return 0; ++ } ++ } + + fns_ptr = value_find_oload_method_list (&temp, name, + 0, &num_fns, +@@ -2108,16 +2204,29 @@ find_overload_match (struct type **arg_types, int nargs, + } + else + { +- const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym); ++ const char *qualified_name = SYMBOL_NATURAL_NAME (fsym); + +- /* If we have a C++ name, try to extract just the function +- part. */ +- if (qualified_name) +- func_name = cp_func_name (qualified_name); ++ /* If we have a function with a C++ name, try to extract just ++ the function part. Do not try this for non-functions (e.g. ++ function pointers). */ ++ if (qualified_name ++ && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC) ++ { ++ func_name = cp_func_name (qualified_name); ++ ++ /* If cp_func_name did not remove anything, the name of the ++ symbol did not include scope or argument types - it was ++ probably a C-style function. */ ++ if (func_name && strcmp (func_name, qualified_name) == 0) ++ { ++ xfree (func_name); ++ func_name = NULL; ++ } ++ } + +- /* If there was no C++ name, this must be a C-style function. +- Just return the same symbol. Do the same if cp_func_name +- fails for some reason. */ ++ /* If there was no C++ name, this must be a C-style function or ++ not a function at all. Just return the same symbol. Do the ++ same if cp_func_name fails for some reason. */ + if (func_name == NULL) + { + *symp = fsym; +@@ -2558,8 +2667,8 @@ check_field (struct type *type, const char *name) + the comment before value_struct_elt_for_reference. */ + + struct value * +-value_aggregate_elt (struct type *curtype, +- char *name, int want_address, ++value_aggregate_elt (struct type *curtype, char *name, ++ struct type *expect_type, int want_address, + enum noside noside) + { + switch (TYPE_CODE (curtype)) +@@ -2567,7 +2676,7 @@ value_aggregate_elt (struct type *curtype, + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + return value_struct_elt_for_reference (curtype, 0, curtype, +- name, NULL, ++ name, expect_type, + want_address, noside); + case TYPE_CODE_NAMESPACE: + return value_namespace_elt (curtype, name, +@@ -2671,7 +2780,7 @@ value_struct_elt_for_reference (struct type *domain, int offset, + if (intype) + { + while (j--) +- if (TYPE_FN_FIELD_TYPE (f, j) == intype) ++ if (compare_parameters (TYPE_FN_FIELD_TYPE (f, j), intype)) + break; + if (j < 0) + error (_("no member function matches that type instantiation")); +@@ -2725,7 +2834,7 @@ value_struct_elt_for_reference (struct type *domain, int offset, + result = allocate_value (lookup_methodptr_type (TYPE_FN_FIELD_TYPE (f, j))); + cplus_make_method_ptr (value_type (result), + value_contents_writeable (result), +- VALUE_ADDRESS (v), 0); ++ value_address (v), 0); + } + } + return result; +@@ -2791,7 +2900,7 @@ value_maybe_namespace_elt (const struct type *curtype, + struct symbol *sym; + struct value *result; + +- sym = cp_lookup_symbol_namespace (namespace_name, name, NULL, ++ sym = cp_lookup_symbol_namespace_incremental (namespace_name, name, NULL, + get_selected_block (0), + VAR_DOMAIN); + +@@ -2884,7 +2993,7 @@ value_full_object (struct value *argp, + /* Go back by the computed top_offset from the beginning of the + object, adjusting for the embedded offset of argp if that's what + value_rtti_type used for its computation. */ +- new_val = value_at_lazy (real_type, VALUE_ADDRESS (argp) - top + ++ new_val = value_at_lazy (real_type, value_address (argp) - top + + (using_enc ? 0 : value_embedded_offset (argp))); + deprecated_set_value_type (new_val, value_type (argp)); + set_value_embedded_offset (new_val, (using_enc +@@ -2989,8 +3098,6 @@ value_slice (struct value *array, int lowbound, int length) + || lowbound + length - 1 > upperbound) + error (_("slice out of range")); + +- /* FIXME-type-allocation: need a way to free this type when we are +- done with it. */ + slice_range_type = create_range_type ((struct type *) NULL, + TYPE_TARGET_TYPE (range_type), + lowbound, +diff --git a/gdb/valprint.c b/gdb/valprint.c +index b02e9df..a9e8227 100644 +--- a/gdb/valprint.c ++++ b/gdb/valprint.c +@@ -34,6 +34,7 @@ + #include "doublest.h" + #include "exceptions.h" + #include "dfp.h" ++#include "python/python.h" + + #include + +@@ -80,7 +81,9 @@ struct value_print_options user_print_options = + 0, /* print_array_indexes */ + 0, /* deref_ref */ + 1, /* static_field_print */ +- 1 /* pascal_static_field_print */ ++ 1, /* pascal_static_field_print */ ++ 0, /* raw */ ++ 0 /* summary */ + }; + + /* Initialize *OPTS to be a copy of the user print options. */ +@@ -257,6 +260,15 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + return (0); + } + ++ if (!options->raw) ++ { ++ ret = apply_val_pretty_printer (type, valaddr, embedded_offset, ++ address, stream, recurse, options, ++ language); ++ if (ret) ++ return ret; ++ } ++ + TRY_CATCH (except, RETURN_MASK_ERROR) + { + ret = language->la_val_print (type, valaddr, embedded_offset, address, +@@ -287,6 +299,13 @@ value_check_printable (struct value *val, struct ui_file *stream) + return 0; + } + ++ if (TYPE_CODE (value_type (val)) == TYPE_CODE_INTERNAL_FUNCTION) ++ { ++ fprintf_filtered (stream, _(""), ++ value_internal_function_name (val)); ++ return 0; ++ } ++ + return 1; + } + +@@ -308,7 +327,7 @@ common_val_print (struct value *val, struct ui_file *stream, int recurse, + return 0; + + return val_print (value_type (val), value_contents_all (val), +- value_embedded_offset (val), VALUE_ADDRESS (val), ++ value_embedded_offset (val), value_address (val), + stream, recurse, options, language); + } + +@@ -324,6 +343,18 @@ value_print (struct value *val, struct ui_file *stream, + if (!value_check_printable (val, stream)) + return 0; + ++ if (!options->raw) ++ { ++ int r = apply_val_pretty_printer (value_type (val), ++ value_contents_all (val), ++ value_embedded_offset (val), ++ value_address (val), ++ stream, 0, options, ++ current_language); ++ if (r) ++ return r; ++ } ++ + return LA_VALUE_PRINT (val, stream, options); + } + +@@ -919,7 +950,8 @@ print_hex_chars (struct ui_file *stream, const gdb_byte *valaddr, + Omit any leading zero chars. */ + + void +-print_char_chars (struct ui_file *stream, const gdb_byte *valaddr, ++print_char_chars (struct ui_file *stream, struct type *type, ++ const gdb_byte *valaddr, + unsigned len, enum bfd_endian byte_order) + { + const gdb_byte *p; +@@ -932,7 +964,7 @@ print_char_chars (struct ui_file *stream, const gdb_byte *valaddr, + + while (p < valaddr + len) + { +- LA_EMIT_CHAR (*p, stream, '\''); ++ LA_EMIT_CHAR (*p, type, stream, '\''); + ++p; + } + } +@@ -944,7 +976,7 @@ print_char_chars (struct ui_file *stream, const gdb_byte *valaddr, + + while (p >= valaddr) + { +- LA_EMIT_CHAR (*p, stream, '\''); ++ LA_EMIT_CHAR (*p, type, stream, '\''); + --p; + } + } +@@ -1085,6 +1117,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr, + + for (; i < len && things_printed < options->print_max; i++) + { ++ size_t elt_offset = i * eltlen; + if (i != 0) + { + if (options->prettyprint_arrays) +@@ -1104,7 +1137,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr, + rep1 = i + 1; + reps = 1; + while ((rep1 < len) && +- !memcmp (valaddr + i * eltlen, valaddr + rep1 * eltlen, eltlen)) ++ !memcmp (valaddr + elt_offset, valaddr + rep1 * eltlen, eltlen)) + { + ++reps; + ++rep1; +@@ -1112,7 +1145,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr, + + if (reps > options->repeat_count_threshold) + { +- val_print (elttype, valaddr + i * eltlen, 0, address + i * eltlen, ++ val_print (elttype, valaddr + elt_offset, 0, address + elt_offset, + stream, recurse + 1, options, current_language); + annotate_elt_rep (reps); + fprintf_filtered (stream, " ", reps); +@@ -1123,7 +1156,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr, + } + else + { +- val_print (elttype, valaddr + i * eltlen, 0, address + i * eltlen, ++ val_print (elttype, valaddr + elt_offset, 0, address + elt_offset, + stream, recurse + 1, options, current_language); + annotate_elt (); + things_printed++; +@@ -1315,7 +1348,8 @@ read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit, + whichever is smaller. */ + + int +-val_print_string (CORE_ADDR addr, int len, int width, struct ui_file *stream, ++val_print_string (struct type *elttype, CORE_ADDR addr, int len, ++ struct ui_file *stream, + const struct value_print_options *options) + { + int force_ellipsis = 0; /* Force ellipsis to be printed if nonzero. */ +@@ -1325,6 +1359,7 @@ val_print_string (CORE_ADDR addr, int len, int width, struct ui_file *stream, + int bytes_read; + gdb_byte *buffer = NULL; /* Dynamically growable fetch buffer. */ + struct cleanup *old_chain = NULL; /* Top of the old cleanup chain. */ ++ int width = TYPE_LENGTH (elttype); + + /* First we need to figure out the limit on the number of characters we are + going to attempt to fetch and print. This is actually pretty simple. If +@@ -1378,7 +1413,7 @@ val_print_string (CORE_ADDR addr, int len, int width, struct ui_file *stream, + { + fputs_filtered (" ", stream); + } +- LA_PRINT_STRING (stream, buffer, bytes_read / width, width, force_ellipsis, options); ++ LA_PRINT_STRING (stream, elttype, buffer, bytes_read / width, force_ellipsis, options); + } + + if (errcode != 0) +diff --git a/gdb/valprint.h b/gdb/valprint.h +index 8b65af6..4f63fa6 100644 +--- a/gdb/valprint.h ++++ b/gdb/valprint.h +@@ -84,6 +84,12 @@ struct value_print_options + /* If nonzero, print static fields for Pascal. FIXME: C++ and Java + share one flag, why not Pascal too? */ + int pascal_static_field_print; ++ ++ /* Controls Python pretty-printing. */ ++ int raw; ++ ++ /* If nonzero, print the value in "summary" form. */ ++ int summary; + }; + + /* The global print options set by the user. In general this should +@@ -134,9 +140,10 @@ extern void print_decimal_chars (struct ui_file *, const gdb_byte *, + extern void print_hex_chars (struct ui_file *, const gdb_byte *, + unsigned int, enum bfd_endian); + +-extern void print_char_chars (struct ui_file *, const gdb_byte *, +- unsigned int, enum bfd_endian); ++extern void print_char_chars (struct ui_file *, struct type *, ++ const gdb_byte *, unsigned int, enum bfd_endian); + + int read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit, + gdb_byte **buffer, int *bytes_read); ++ + #endif +diff --git a/gdb/value.c b/gdb/value.c +index 4d4329e..5c81d83 100644 +--- a/gdb/value.c ++++ b/gdb/value.c +@@ -36,6 +36,7 @@ + #include "block.h" + #include "dfp.h" + #include "objfiles.h" ++#include "cli/cli-decode.h" + #include "valprint.h" + + #include "python/python.h" +@@ -44,6 +45,23 @@ + + void _initialize_values (void); + ++/* Definition of a user function. */ ++struct internal_function ++{ ++ /* The name of the function. It is a bit odd to have this in the ++ function itself -- the user might use a differently-named ++ convenience variable to hold the function. */ ++ char *name; ++ ++ /* The handler. */ ++ internal_function_fn handler; ++ ++ /* User data for the handler. */ ++ void *cookie; ++}; ++ ++static struct cmd_list_element *functionlist; ++ + struct value + { + /* Type of value; either not an lval, or one of the various +@@ -203,6 +221,10 @@ struct value_history_chunk + static struct value_history_chunk *value_history_chain; + + static int value_history_count; /* Abs number of last entry stored */ ++ ++/* The type of internal functions. */ ++ ++static struct type *internal_fn_type; + + /* List of all value objects currently allocated + (except for those released by calls to release_value) +@@ -225,9 +247,11 @@ allocate_value_lazy (struct type *type) + val->next = all_values; + all_values = val; + val->type = type; ++ type_incref (type); + val->enclosing_type = type; ++ type_incref (type); + VALUE_LVAL (val) = not_lval; +- VALUE_ADDRESS (val) = 0; ++ val->location.address = 0; + VALUE_FRAME_ID (val) = null_frame_id; + val->offset = 0; + val->bitpos = 0; +@@ -269,13 +293,9 @@ struct value * + allocate_repeat_value (struct type *type, int count) + { + int low_bound = current_language->string_lower_bound; /* ??? */ +- /* FIXME-type-allocation: need a way to free this type when we are +- done with it. */ + struct type *range_type + = create_range_type ((struct type *) NULL, builtin_type_int32, + low_bound, count + low_bound - 1); +- /* FIXME-type-allocation: need a way to free this type when we are +- done with it. */ + return allocate_value (create_array_type ((struct type *) NULL, + type, range_type)); + } +@@ -335,6 +355,8 @@ value_type (struct value *value) + void + deprecated_set_value_type (struct value *value, struct type *type) + { ++ type_incref (type); ++ type_decref (value->type); + value->type = type; + } + +@@ -509,6 +531,32 @@ deprecated_value_address_hack (struct value *value) + return &value->location.address; + } + ++CORE_ADDR ++value_address (struct value *value) ++{ ++ if (value->lval == lval_internalvar ++ || value->lval == lval_internalvar_component) ++ return 0; ++ return value->location.address + value->offset; ++} ++ ++CORE_ADDR ++value_raw_address (struct value *value) ++{ ++ if (value->lval == lval_internalvar ++ || value->lval == lval_internalvar_component) ++ return 0; ++ return value->location.address; ++} ++ ++void ++set_value_address (struct value *value, CORE_ADDR addr) ++{ ++ gdb_assert (value->lval != lval_internalvar ++ && value->lval != lval_internalvar_component); ++ value->location.address = addr; ++} ++ + struct internalvar ** + deprecated_value_internalvar_hack (struct value *value) + { +@@ -547,11 +595,16 @@ value_mark (void) + return all_values; + } + ++/* Deallocate a value and run destructors if needed. */ ++ + void + value_free (struct value *val) + { + if (val) + { ++ type_decref (val->type); ++ type_decref (val->enclosing_type); ++ + if (VALUE_LVAL (val) == lval_computed) + { + struct lval_funcs *funcs = val->location.computed.funcs; +@@ -655,6 +708,8 @@ value_copy (struct value *arg) + val = allocate_value_lazy (encl_type); + else + val = allocate_value (encl_type); ++ type_incref (arg->type); ++ type_decref (val->type); + val->type = arg->type; + VALUE_LVAL (val) = VALUE_LVAL (arg); + val->location = arg->location; +@@ -693,6 +748,7 @@ set_value_component_location (struct value *component, struct value *whole) + VALUE_LVAL (component) = VALUE_LVAL (whole); + + component->location = whole->location; ++ + if (VALUE_LVAL (whole) == lval_computed) + { + struct lval_funcs *funcs = whole->location.computed.funcs; +@@ -700,6 +756,8 @@ set_value_component_location (struct value *component, struct value *whole) + if (funcs->copy_closure) + component->location.computed.closure = funcs->copy_closure (whole); + } ++ ++ object_address_get_data (value_type (whole), &VALUE_ADDRESS (component)); + } + + +@@ -830,6 +888,25 @@ show_values (char *num_exp, int from_tty) + num_exp[1] = '\0'; + } + } ++ ++/* Sanity check for memory leaks and proper types reference counting. */ ++ ++static void ++value_history_cleanup (void *unused) ++{ ++ while (value_history_chain) ++ { ++ struct value_history_chunk *chunk = value_history_chain; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE (chunk->values); i++) ++ value_free (chunk->values[i]); ++ ++ value_history_chain = chunk->next; ++ xfree (chunk); ++ } ++ value_history_count = 0; ++} + + /* Internal variables. These are variables within the debugger + that hold values assigned by debugger commands. +@@ -878,7 +955,7 @@ init_if_undefined_command (char* args, int from_tty) + the return value is NULL. */ + + struct internalvar * +-lookup_only_internalvar (char *name) ++lookup_only_internalvar (const char *name) + { + struct internalvar *var; + +@@ -894,7 +971,7 @@ lookup_only_internalvar (char *name) + NAME should not normally include a dollar sign. */ + + struct internalvar * +-create_internalvar (char *name) ++create_internalvar (const char *name) + { + struct internalvar *var; + var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); +@@ -902,6 +979,7 @@ create_internalvar (char *name) + var->value = allocate_value (builtin_type_void); + var->endian = gdbarch_byte_order (current_gdbarch); + var->make_value = NULL; ++ var->canonical = 0; + release_value (var->value); + var->next = internalvars; + internalvars = var; +@@ -934,7 +1012,7 @@ create_internalvar_type_lazy (char *name, internalvar_make_value fun) + one is created, with a void value. */ + + struct internalvar * +-lookup_internalvar (char *name) ++lookup_internalvar (const char *name) + { + struct internalvar *var; + +@@ -1031,6 +1109,9 @@ set_internalvar (struct internalvar *var, struct value *val) + { + struct value *newval; + ++ if (var->canonical) ++ error (_("Cannot overwrite convenience function %s"), var->name); ++ + newval = value_copy (val); + newval->modifiable = 1; + +@@ -1042,7 +1123,7 @@ set_internalvar (struct internalvar *var, struct value *val) + + /* Begin code which must not call error(). If var->value points to + something free'd, an error() obviously leaves a dangling pointer. +- But we also get a danling pointer if var->value points to ++ But we also get a dangling pointer if var->value points to + something in the value chain (i.e., before release_value is + called), because after the error free_all_values will get called before + long. */ +@@ -1059,6 +1140,76 @@ internalvar_name (struct internalvar *var) + return var->name; + } + ++static struct value * ++value_create_internal_function (const char *name, ++ internal_function_fn handler, ++ void *cookie) ++{ ++ struct value *result = allocate_value (internal_fn_type); ++ gdb_byte *addr = value_contents_writeable (result); ++ struct internal_function **fnp = (struct internal_function **) addr; ++ struct internal_function *ifn = XNEW (struct internal_function); ++ ifn->name = xstrdup (name); ++ ifn->handler = handler; ++ ifn->cookie = cookie; ++ *fnp = ifn; ++ return result; ++} ++ ++char * ++value_internal_function_name (struct value *val) ++{ ++ gdb_byte *addr = value_contents_writeable (val); ++ struct internal_function *ifn = * (struct internal_function **) addr; ++ return ifn->name; ++} ++ ++struct value * ++call_internal_function (struct value *func, int argc, struct value **argv) ++{ ++ gdb_byte *addr = value_contents_writeable (func); ++ struct internal_function *ifn = * (struct internal_function **) addr; ++ return (*ifn->handler) (ifn->cookie, argc, argv); ++} ++ ++/* The 'function' command. This does nothing -- it is just a ++ placeholder to let "help function NAME" work. This is also used as ++ the implementation of the sub-command that is created when ++ registering an internal function. */ ++static void ++function_command (char *command, int from_tty) ++{ ++ /* Do nothing. */ ++} ++ ++/* Clean up if an internal function's command is destroyed. */ ++static void ++function_destroyer (struct cmd_list_element *self, void *ignore) ++{ ++ xfree (self->name); ++ xfree (self->doc); ++} ++ ++/* Add a new internal function. NAME is the name of the function; DOC ++ is a documentation string describing the function. HANDLER is ++ called when the function is invoked. COOKIE is an arbitrary ++ pointer which is passed to HANDLER and is intended for "user ++ data". */ ++void ++add_internal_function (const char *name, const char *doc, ++ internal_function_fn handler, void *cookie) ++{ ++ struct cmd_list_element *cmd; ++ struct internalvar *var = lookup_internalvar (name); ++ struct value *fnval = value_create_internal_function (name, handler, cookie); ++ set_internalvar (var, fnval); ++ var->canonical = 1; ++ ++ cmd = add_cmd (xstrdup (name), no_class, function_command, (char *) doc, ++ &functionlist); ++ cmd->destroyer = function_destroyer; ++} ++ + /* Update VALUE before discarding OBJFILE. COPIED_TYPES is used to + prevent cycles / duplicates. */ + +@@ -1067,12 +1218,21 @@ preserve_one_value (struct value *value, struct objfile *objfile, + htab_t copied_types) + { + if (TYPE_OBJFILE (value->type) == objfile) +- value->type = copy_type_recursive (objfile, value->type, copied_types); ++ { ++ /* No need to decref the old type here, since we know it has no ++ reference count. */ ++ value->type = copy_type_recursive (value->type, copied_types); ++ type_incref (value->type); ++ } + + if (TYPE_OBJFILE (value->enclosing_type) == objfile) +- value->enclosing_type = copy_type_recursive (objfile, +- value->enclosing_type, +- copied_types); ++ { ++ /* No need to decref the old type here, since we know it has no ++ reference count. */ ++ value->enclosing_type = copy_type_recursive (value->enclosing_type, ++ copied_types); ++ type_incref (value->enclosing_type); ++ } + } + + /* Update the internal variables and value history when OBJFILE is +@@ -1196,7 +1356,7 @@ value_as_address (struct value *val) + + Upon entry to this function, if VAL is a value of type `function' + (that is, TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC), then +- VALUE_ADDRESS (val) is the address of the function. This is what ++ value_address (val) is the address of the function. This is what + you'll get if you evaluate an expression like `main'. The call + to COERCE_ARRAY below actually does all the usual unary + conversions, which includes converting values of type `function' +@@ -1216,7 +1376,7 @@ value_as_address (struct value *val) + function, just return its address directly. */ + if (TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC + || TYPE_CODE (value_type (val)) == TYPE_CODE_METHOD) +- return VALUE_ADDRESS (val); ++ return value_address (val); + + val = coerce_array (val); + +@@ -1447,7 +1607,7 @@ value_static_field (struct type *type, int fieldno) + } + if (retval && VALUE_LVAL (retval) == lval_memory) + SET_FIELD_PHYSADDR (TYPE_FIELD (type, fieldno), +- VALUE_ADDRESS (retval)); ++ value_address (retval)); + } + return retval; + } +@@ -1465,6 +1625,8 @@ value_change_enclosing_type (struct value *val, struct type *new_encl_type) + val->contents = + (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type)); + ++ type_incref (new_encl_type); ++ type_decref (val->enclosing_type); + val->enclosing_type = new_encl_type; + return val; + } +@@ -1516,6 +1678,8 @@ value_primitive_field (struct value *arg1, int offset, + memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1), + TYPE_LENGTH (value_enclosing_type (arg1))); + } ++ type_incref (type); ++ type_decref (v->type); + v->type = type; + v->offset = value_offset (arg1); + v->embedded_offset = (offset + value_embedded_offset (arg1) +@@ -1592,7 +1756,7 @@ value_fn_field (struct value **arg1p, struct fn_field *f, int j, struct type *ty + v = allocate_value (ftype); + if (sym) + { +- VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); ++ set_value_address (v, BLOCK_START (SYMBOL_BLOCK_VALUE (sym))); + } + else + { +@@ -1601,9 +1765,9 @@ value_fn_field (struct value **arg1p, struct fn_field *f, int j, struct type *ty + struct objfile *objfile = msymbol_objfile (msym); + struct gdbarch *gdbarch = get_objfile_arch (objfile); + +- VALUE_ADDRESS (v) +- = gdbarch_convert_from_func_ptr_addr +- (gdbarch, SYMBOL_VALUE_ADDRESS (msym), ¤t_target); ++ set_value_address (v, ++ gdbarch_convert_from_func_ptr_addr ++ (gdbarch, SYMBOL_VALUE_ADDRESS (msym), ¤t_target)); + } + + if (arg1p) +@@ -1750,6 +1914,41 @@ pack_long (gdb_byte *buf, struct type *type, LONGEST num) + } + + ++/* Pack NUM into BUF using a target format of TYPE. */ ++ ++void ++pack_unsigned_long (gdb_byte *buf, struct type *type, ULONGEST num) ++{ ++ int len; ++ ++ type = check_typedef (type); ++ len = TYPE_LENGTH (type); ++ ++ switch (TYPE_CODE (type)) ++ { ++ case TYPE_CODE_INT: ++ case TYPE_CODE_CHAR: ++ case TYPE_CODE_ENUM: ++ case TYPE_CODE_FLAGS: ++ case TYPE_CODE_BOOL: ++ case TYPE_CODE_RANGE: ++ case TYPE_CODE_MEMBERPTR: ++ store_unsigned_integer (buf, len, num); ++ break; ++ ++ case TYPE_CODE_REF: ++ case TYPE_CODE_PTR: ++ store_typed_address (buf, type, (CORE_ADDR) num); ++ break; ++ ++ default: ++ error (_("\ ++Unexpected type (%d) encountered for unsigned integer constant."), ++ TYPE_CODE (type)); ++ } ++} ++ ++ + /* Convert C numbers into newly allocated values. */ + + struct value * +@@ -1763,6 +1962,19 @@ value_from_longest (struct type *type, LONGEST num) + } + + ++/* Convert C unsigned numbers into newly allocated values. */ ++ ++struct value * ++value_from_ulongest (struct type *type, ULONGEST num) ++{ ++ struct value *val = allocate_value (type); ++ ++ pack_unsigned_long (value_contents_raw (val), type, num); ++ ++ return val; ++} ++ ++ + /* Create a value representing a pointer of type TYPE to the address + ADDR. */ + struct value * +@@ -1816,8 +2028,9 @@ value_from_contents_and_address (struct type *type, + set_value_lazy (v, 1); + else + memcpy (value_contents_raw (v), valaddr, TYPE_LENGTH (type)); +- VALUE_ADDRESS (v) = address; +- VALUE_LVAL (v) = lval_memory; ++ set_value_address (v, address); ++ if (address != 0) ++ VALUE_LVAL (v) = lval_memory; + return v; + } + +@@ -1944,4 +2157,15 @@ init-if-undefined VARIABLE = EXPRESSION\n\ + Set an internal VARIABLE to the result of the EXPRESSION if it does not\n\ + exist or does not contain a value. The EXPRESSION is not evaluated if the\n\ + VARIABLE is already initialized.")); ++ ++ add_prefix_cmd ("function", no_class, function_command, _("\ ++Placeholder command for showing help on convenience functions."), ++ &functionlist, "function ", 0, &cmdlist); ++ ++ internal_fn_type = alloc_type (OBJFILE_INTERNAL, NULL); ++ TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION; ++ TYPE_LENGTH (internal_fn_type) = sizeof (struct internal_function *); ++ TYPE_NAME (internal_fn_type) = ""; ++ ++ make_final_cleanup (value_history_cleanup, NULL); + } +diff --git a/gdb/value.h b/gdb/value.h +index aa43365..1ad3c75 100644 +--- a/gdb/value.h ++++ b/gdb/value.h +@@ -272,12 +272,23 @@ extern void set_value_component_location (struct value *component, + extern enum lval_type *deprecated_value_lval_hack (struct value *); + #define VALUE_LVAL(val) (*deprecated_value_lval_hack (val)) + +-/* If lval == lval_memory, this is the address in the inferior. If +- lval == lval_register, this is the byte offset into the registers +- structure. */ ++/* Backward compatibility for the Fedora merge branch. */ + extern CORE_ADDR *deprecated_value_address_hack (struct value *); + #define VALUE_ADDRESS(val) (*deprecated_value_address_hack (val)) + ++/* If lval == lval_memory, return the address in the inferior. If ++ lval == lval_register, return the byte offset into the registers ++ structure. Otherwise, return 0. The returned address ++ includes the offset, if any. */ ++extern CORE_ADDR value_address (struct value *); ++ ++/* Like value_address, except the result does not include value's ++ offset. */ ++extern CORE_ADDR value_raw_address (struct value *); ++ ++/* Set the address of a value. */ ++extern void set_value_address (struct value *, CORE_ADDR); ++ + /* Pointer to internal variable. */ + extern struct internalvar **deprecated_value_internalvar_hack (struct value *); + #define VALUE_INTERNALVAR(val) (*deprecated_value_internalvar_hack (val)) +@@ -314,6 +325,9 @@ struct internalvar + struct value *value; + internalvar_make_value make_value; + int endian; ++ /* True if this internalvar is the canonical name for a convenience ++ function. */ ++ int canonical; + }; + + +@@ -342,12 +356,17 @@ extern LONGEST unpack_field_as_long (struct type *type, + extern void pack_long (gdb_byte *buf, struct type *type, LONGEST num); + + extern struct value *value_from_longest (struct type *type, LONGEST num); ++extern struct value *value_from_ulongest (struct type *type, ULONGEST num); + extern struct value *value_from_pointer (struct type *type, CORE_ADDR addr); + extern struct value *value_from_double (struct type *type, DOUBLEST num); + extern struct value *value_from_decfloat (struct type *type, + const gdb_byte *decbytes); + extern struct value *value_from_string (char *string); + ++extern const char *object_address_data_not_valid (struct type *type); ++extern int object_address_get_data (struct type *type, ++ CORE_ADDR *address_return); ++ + extern struct value *value_at (struct type *type, CORE_ADDR addr); + extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr); + +@@ -388,6 +407,8 @@ extern struct value *value_mark (void); + + extern void value_free_to_mark (struct value *mark); + ++extern struct value *value_typed_string (char *ptr, int len, ++ struct type *char_type); + extern struct value *value_string (char *ptr, int len); + extern struct value *value_bitstring (char *ptr, int len); + +@@ -435,6 +456,7 @@ extern struct value *value_struct_elt (struct value **argp, + + extern struct value *value_aggregate_elt (struct type *curtype, + char *name, ++ struct type *expect_type, + int want_address, + enum noside noside); + +@@ -533,14 +555,14 @@ extern void set_internalvar_component (struct internalvar *var, + int bitpos, int bitsize, + struct value *newvalue); + +-extern struct internalvar *lookup_only_internalvar (char *name); ++extern struct internalvar *lookup_only_internalvar (const char *name); + +-extern struct internalvar *create_internalvar (char *name); ++extern struct internalvar *create_internalvar (const char *name); + + extern struct internalvar * + create_internalvar_type_lazy (char *name, internalvar_make_value fun); + +-extern struct internalvar *lookup_internalvar (char *name); ++extern struct internalvar *lookup_internalvar (const char *name); + + extern int value_equal (struct value *arg1, struct value *arg2); + +@@ -619,7 +641,7 @@ extern int common_val_print (struct value *val, + const struct value_print_options *options, + const struct language_defn *language); + +-extern int val_print_string (CORE_ADDR addr, int len, int width, ++extern int val_print_string (struct type *elttype, CORE_ADDR addr, int len, + struct ui_file *stream, + const struct value_print_options *options); + +@@ -658,5 +680,22 @@ extern struct value *value_allocate_space_in_inferior (int); + + extern struct value *value_of_local (const char *name, int complain); + +-extern struct value * value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound); ++extern struct value *value_subscripted_rvalue (struct value *array, ++ CORE_ADDR offset); ++ ++/* User function handler. */ ++ ++typedef struct value *(*internal_function_fn) (void *cookie, ++ int argc, ++ struct value **argv); ++ ++void add_internal_function (const char *name, const char *doc, ++ internal_function_fn handler, ++ void *cookie); ++ ++struct value *call_internal_function (struct value *function, ++ int argc, struct value **argv); ++ ++char *value_internal_function_name (struct value *); ++ + #endif /* !defined (VALUE_H) */ +diff --git a/gdb/varobj.c b/gdb/varobj.c +index 2ec6d90..1237c96 100644 +--- a/gdb/varobj.c ++++ b/gdb/varobj.c +@@ -29,11 +29,20 @@ + + #include "gdb_assert.h" + #include "gdb_string.h" ++#include "gdb_regex.h" + + #include "varobj.h" + #include "vec.h" + #include "gdbthread.h" + #include "inferior.h" ++#include "valprint.h" ++ ++#if HAVE_PYTHON ++#include "python/python.h" ++#include "python/python-internal.h" ++#else ++typedef int PyObject; ++#endif + + /* Non-zero if we want to see trace of varobj level stuff. */ + +@@ -138,6 +147,12 @@ struct varobj + /* Children of this object. */ + VEC (varobj_p) *children; + ++ /* Whether the children of this varobj were requested. This field is ++ used to decide if dynamic varobj should recompute their children. ++ In the event that the frontend never asked for the children, we ++ can avoid that. */ ++ int children_requested; ++ + /* Description of the root variable. Points to root variable for children. */ + struct varobj_root *root; + +@@ -159,6 +174,16 @@ struct varobj + not fetched if either the variable is frozen, or any parents is + frozen. */ + int not_fetched; ++ ++ /* Sub-range of children which the MI consumer has requested. If ++ FROM < 0 or TO < 0, means that all children have been ++ requested. */ ++ int from; ++ int to; ++ ++ /* The pretty-printer that has been constructed. If NULL, then a ++ new printer object is needed, and one will be constructed. */ ++ PyObject *pretty_printer; + }; + + struct cpstack +@@ -190,6 +215,10 @@ static void uninstall_variable (struct varobj *); + + static struct varobj *create_child (struct varobj *, int, char *); + ++static struct varobj * ++create_child_with_value (struct varobj *parent, int index, const char *name, ++ struct value *value); ++ + /* Utility routines */ + + static struct varobj *new_variable (void); +@@ -200,6 +229,8 @@ static void free_variable (struct varobj *var); + + static struct cleanup *make_cleanup_free_variable (struct varobj *var); + ++static struct cleanup *make_cleanup_uninstall_variable (struct varobj *var); ++ + static struct type *get_type (struct varobj *var); + + static struct type *get_value_type (struct varobj *var); +@@ -215,6 +246,8 @@ static char *cppop (struct cpstack **pstack); + static int install_new_value (struct varobj *var, struct value *value, + int initial); + ++static void install_default_visualizer (struct varobj *var); ++ + /* Language-specific routines. */ + + static enum varobj_languages variable_language (struct varobj *var); +@@ -232,13 +265,17 @@ static struct value *value_of_child (struct varobj *parent, int index); + static char *my_value_of_variable (struct varobj *var, + enum varobj_display_formats format); + +-static char *value_get_print_value (struct value *value, +- enum varobj_display_formats format); ++char *value_get_print_value (struct value *value, ++ enum varobj_display_formats format, ++ PyObject *value_formatter); + + static int varobj_value_is_changeable_p (struct varobj *var); + + static int is_root_p (struct varobj *var); + ++static struct varobj * ++varobj_add_child (struct varobj *var, const char *name, struct value *value); ++ + /* C implementation */ + + static int c_number_of_children (struct varobj *var); +@@ -570,8 +607,10 @@ varobj_create (char *objname, + do_cleanups (old_chain); + return NULL; + } ++ make_cleanup_uninstall_variable (var); + } + ++ install_default_visualizer (var); + discard_cleanups (old_chain); + return var; + } +@@ -678,6 +717,33 @@ varobj_delete (struct varobj *var, char ***dellist, int only_children) + return delcount; + } + ++/* Convenience function for varobj_set_visualizer. Instantiate a ++ pretty-printer for a given value. */ ++static PyObject * ++instantiate_pretty_printer (PyObject *constructor, struct value *value) ++{ ++#if HAVE_PYTHON ++ PyObject *val_obj = NULL; ++ PyObject *printer; ++ volatile struct gdb_exception except; ++ ++ TRY_CATCH (except, RETURN_MASK_ALL) ++ { ++ value = value_copy (value); ++ } ++ GDB_PY_HANDLE_EXCEPTION (except); ++ val_obj = value_to_value_object (value); ++ ++ if (! val_obj) ++ return NULL; ++ ++ printer = gdbpy_instantiate_printer (constructor, val_obj); ++ Py_DECREF (val_obj); ++ return printer; ++#endif ++ return NULL; ++} ++ + /* Set/Get variable object display format */ + + enum varobj_display_formats +@@ -702,7 +768,8 @@ varobj_set_display_format (struct varobj *var, + && var->value && !value_lazy (var->value)) + { + xfree (var->print_value); +- var->print_value = value_get_print_value (var->value, var->format); ++ var->print_value = value_get_print_value (var->value, var->format, ++ var->pretty_printer); + } + + return var->format; +@@ -714,6 +781,21 @@ varobj_get_display_format (struct varobj *var) + return var->format; + } + ++char * ++varobj_get_display_hint (struct varobj *var) ++{ ++ char *result = NULL; ++ ++#if HAVE_PYTHON ++ PyGILState_STATE state = PyGILState_Ensure (); ++ if (var->pretty_printer) ++ result = gdbpy_get_display_hint (var->pretty_printer); ++ PyGILState_Release (state); ++#endif ++ ++ return result; ++} ++ + /* If the variable object is bound to a specific thread, that + is its evaluation can always be done in context of a frame + inside that thread, returns GDB id of the thread -- which +@@ -746,12 +828,141 @@ varobj_get_frozen (struct varobj *var) + return var->frozen; + } + ++static int ++update_dynamic_varobj_children (struct varobj *var, ++ VEC (varobj_p) **changed, ++ VEC (varobj_p) **new_and_unchanged, ++ int *cchanged) ++ ++{ ++#if HAVE_PYTHON ++ /* FIXME: we *might* want to provide this functionality as ++ a standalone function, so that other interested parties ++ than varobj code can benefit for this. */ ++ struct cleanup *back_to; ++ PyObject *children; ++ PyObject *iterator; ++ int i; ++ int children_changed = 0; ++ PyObject *printer = var->pretty_printer; ++ PyGILState_STATE state; ++ ++ state = PyGILState_Ensure (); ++ back_to = make_cleanup_py_restore_gil (&state); ++ ++ *cchanged = 0; ++ if (!PyObject_HasAttr (printer, gdbpy_children_cst)) ++ { ++ do_cleanups (back_to); ++ return 0; ++ } ++ ++ children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, ++ NULL); ++ ++ if (!children) ++ { ++ gdbpy_print_stack (); ++ error ("Null value returned for children"); ++ } ++ ++ make_cleanup_py_decref (children); ++ ++ if (!PyIter_Check (children)) ++ error ("Returned value is not iterable"); ++ ++ iterator = PyObject_GetIter (children); ++ if (!iterator) ++ { ++ gdbpy_print_stack (); ++ error ("Could not get children iterator"); ++ } ++ make_cleanup_py_decref (iterator); ++ ++ for (i = 0; ; ++i) ++ { ++ PyObject *item = PyIter_Next (iterator); ++ PyObject *py_v; ++ struct value *v; ++ char *name; ++ struct cleanup *inner; ++ ++ if (!item) ++ break; ++ inner = make_cleanup_py_decref (item); ++ ++ if (!PyArg_ParseTuple (item, "sO", &name, &py_v)) ++ error ("Invalid item from the child list"); ++ ++ if (PyObject_TypeCheck (py_v, &value_object_type)) ++ { ++ /* If we just call convert_value_from_python for this type, ++ we won't know who owns the result. For this one case we ++ need to copy the resulting value. */ ++ v = value_object_to_value (py_v); ++ v = value_copy (v); ++ } ++ else ++ v = convert_value_from_python (py_v); ++ ++ /* TODO: This assume the name of the i-th child never changes. */ ++ ++ /* Now see what to do here. */ ++ if (VEC_length (varobj_p, var->children) < i + 1) ++ { ++ /* There's no child yet. */ ++ struct varobj *child = varobj_add_child (var, name, v); ++ if (new_and_unchanged) ++ VEC_safe_push (varobj_p, *new_and_unchanged, child); ++ children_changed = 1; ++ } ++ else ++ { ++ varobj_p existing = VEC_index (varobj_p, var->children, i); ++ if (install_new_value (existing, v, 0) && changed) ++ { ++ if (changed) ++ VEC_safe_push (varobj_p, *changed, existing); ++ } ++ else ++ { ++ if (new_and_unchanged) ++ VEC_safe_push (varobj_p, *new_and_unchanged, existing); ++ } ++ } ++ ++ do_cleanups (inner); ++ } ++ ++ if (i < VEC_length (varobj_p, var->children)) ++ { ++ int i; ++ children_changed = 1; ++ for (i = 0; i < VEC_length (varobj_p, var->children); ++i) ++ varobj_delete (VEC_index (varobj_p, var->children, i), NULL, 0); ++ } ++ VEC_truncate (varobj_p, var->children, i); ++ var->num_children = VEC_length (varobj_p, var->children); ++ ++ do_cleanups (back_to); ++ ++ *cchanged = children_changed; ++ return 1; ++#else ++ gdb_assert (0 && "should never be called if Python is not enabled"); ++#endif ++} + + int + varobj_get_num_children (struct varobj *var) + { + if (var->num_children == -1) +- var->num_children = number_of_children (var); ++ { ++ int changed; ++ if (!var->pretty_printer ++ || !update_dynamic_varobj_children (var, NULL, NULL, &changed)) ++ var->num_children = number_of_children (var); ++ } + + return var->num_children; + } +@@ -764,7 +975,16 @@ varobj_list_children (struct varobj *var) + { + struct varobj *child; + char *name; +- int i; ++ int i, children_changed; ++ ++ var->children_requested = 1; ++ ++ if (var->pretty_printer ++ /* This, in theory, can result in the number of children changing without ++ frontend noticing. But well, calling -var-list-children on the same ++ varobj twice is not something a sane frontend would do. */ ++ && update_dynamic_varobj_children (var, NULL, NULL, &children_changed)) ++ return var->children; + + if (var->num_children == -1) + var->num_children = number_of_children (var); +@@ -790,12 +1010,24 @@ varobj_list_children (struct varobj *var) + name = name_of_child (var, i); + existing = create_child (var, i, name); + VEC_replace (varobj_p, var->children, i, existing); ++ install_default_visualizer (existing); + } + } + + return var->children; + } + ++static struct varobj * ++varobj_add_child (struct varobj *var, const char *name, struct value *value) ++{ ++ varobj_p v = create_child_with_value (var, ++ VEC_length (varobj_p, var->children), ++ name, value); ++ VEC_safe_push (varobj_p, var->children, v); ++ install_default_visualizer (v); ++ return v; ++} ++ + /* Obtain the type of an object Variable as a string similar to the one gdb + prints on the console */ + +@@ -1002,6 +1234,13 @@ install_new_value (struct varobj *var, struct value *value, int initial) + a type. */ + gdb_assert (var->type || CPLUS_FAKE_CHILD (var)); + changeable = varobj_value_is_changeable_p (var); ++ ++ /* If the type has custom visualizer, we consider it to be always ++ changeable. FIXME: need to make sure this behaviour will not ++ mess up read-sensitive values. */ ++ if (var->pretty_printer) ++ changeable = 1; ++ + need_to_fetch = changeable; + + /* We are not interested in the address of references, and given +@@ -1053,12 +1292,14 @@ install_new_value (struct varobj *var, struct value *value, int initial) + } + } + ++ + /* Below, we'll be comparing string rendering of old and new + values. Don't get string rendering if the value is + lazy -- if it is, the code above has decided that the value + should not be fetched. */ + if (value && !value_lazy (value)) +- print_value = value_get_print_value (value, var->format); ++ print_value = value_get_print_value (value, var->format, ++ var->pretty_printer); + + /* If the type is changeable, compare the old and the new values. + If this is the initial assignment, we don't have any old value +@@ -1123,6 +1364,150 @@ install_new_value (struct varobj *var, struct value *value, int initial) + return changed; + } + ++/* Return the effective requested range for a varobj. VAR is the ++ varobj. CHILDREN is the computed list of children. FROM and TO ++ are out parameters. If VAR has no bounds selected, *FROM and *TO ++ will be set to the full range of CHILDREN. Otherwise, *FROM and ++ *TO will be set to the selected sub-range of VAR, clipped to be in ++ range of CHILDREN. */ ++void ++varobj_get_child_range (struct varobj *var, VEC (varobj_p) *children, ++ int *from, int *to) ++{ ++ if (var->from < 0 || var->to < 0) ++ { ++ *from = 0; ++ *to = VEC_length (varobj_p, children); ++ } ++ else ++ { ++ *from = var->from; ++ if (*from > VEC_length (varobj_p, children)) ++ *from = VEC_length (varobj_p, children); ++ *to = var->to; ++ if (*to > VEC_length (varobj_p, children)) ++ *to = VEC_length (varobj_p, children); ++ } ++} ++ ++/* Set the selected sub-range of children of VAR to start at index ++ FROM and end at index TO. If either FROM or TO is less than zero, ++ this is interpreted as a request for all children. */ ++void ++varobj_set_child_range (struct varobj *var, int from, int to) ++{ ++ var->from = from; ++ var->to = to; ++} ++ ++static void ++install_visualizer (struct varobj *var, PyObject *visualizer) ++{ ++#if HAVE_PYTHON ++ /* If there are any children now, wipe them. */ ++ varobj_delete (var, NULL, 1 /* children only */); ++ var->num_children = -1; ++ ++ Py_XDECREF (var->pretty_printer); ++ var->pretty_printer = visualizer; ++ ++ install_new_value (var, var->value, 1); ++ ++ /* If we removed the visualizer, and the user ever requested the ++ object's children, then we must compute the list of children. ++ Note that we needn't do this when installing a visualizer, ++ because updating will recompute dynamic children. */ ++ if (!visualizer && var->children_requested) ++ varobj_list_children (var); ++#else ++ error ("Python support required"); ++#endif ++} ++ ++static void ++install_default_visualizer (struct varobj *var) ++{ ++#if HAVE_PYTHON ++ struct cleanup *cleanup; ++ PyGILState_STATE state; ++ PyObject *pretty_printer = NULL; ++ ++ state = PyGILState_Ensure (); ++ cleanup = make_cleanup_py_restore_gil (&state); ++ ++ if (var->value) ++ { ++ pretty_printer = gdbpy_get_varobj_pretty_printer (var->value); ++ if (! pretty_printer) ++ { ++ gdbpy_print_stack (); ++ error (_("Cannot instantiate printer for default visualizer")); ++ } ++ } ++ ++ if (pretty_printer == Py_None) ++ { ++ Py_DECREF (pretty_printer); ++ pretty_printer = NULL; ++ } ++ ++ install_visualizer (var, pretty_printer); ++ do_cleanups (cleanup); ++#else ++ /* No error is right as this function is inserted just as a hook. */ ++#endif ++} ++ ++void ++varobj_set_visualizer (struct varobj *var, const char *visualizer) ++{ ++#if HAVE_PYTHON ++ PyObject *mainmod, *globals, *pretty_printer, *constructor; ++ struct cleanup *back_to, *value; ++ PyGILState_STATE state; ++ ++ ++ state = PyGILState_Ensure (); ++ back_to = make_cleanup_py_restore_gil (&state); ++ ++ mainmod = PyImport_AddModule ("__main__"); ++ globals = PyModule_GetDict (mainmod); ++ Py_INCREF (globals); ++ make_cleanup_py_decref (globals); ++ ++ constructor = PyRun_String (visualizer, Py_eval_input, globals, globals); ++ ++ /* Do not instantiate NoneType. */ ++ if (constructor == Py_None) ++ { ++ pretty_printer = Py_None; ++ Py_INCREF (pretty_printer); ++ } ++ else ++ pretty_printer = instantiate_pretty_printer (constructor, var->value); ++ ++ Py_XDECREF (constructor); ++ ++ if (! pretty_printer) ++ { ++ gdbpy_print_stack (); ++ error ("Could not evaluate visualizer expression: %s", visualizer); ++ } ++ ++ if (pretty_printer == Py_None) ++ { ++ Py_DECREF (pretty_printer); ++ pretty_printer = NULL; ++ } ++ ++ install_visualizer (var, pretty_printer); ++ ++ do_cleanups (back_to); ++#else ++ error ("Python support required"); ++#endif ++} ++ + /* 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 +@@ -1148,7 +1533,7 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) + struct varobj **cv; + struct varobj **templist = NULL; + struct value *new; +- VEC (varobj_p) *stack = NULL; ++ VEC (varobj_update_result) *stack = NULL; + VEC (varobj_update_result) *result = NULL; + struct frame_info *fi; + +@@ -1187,20 +1572,85 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) + + if (new == NULL) + r.status = VAROBJ_NOT_IN_SCOPE; +- +- if (r.type_changed || r.changed) +- VEC_safe_push (varobj_update_result, result, &r); ++ r.value_installed = 1; + + if (r.status == VAROBJ_NOT_IN_SCOPE) +- return result; ++ { ++ VEC_safe_push (varobj_update_result, result, &r); ++ return result; ++ } ++ ++ VEC_safe_push (varobj_update_result, stack, &r); ++ } ++ else ++ { ++ varobj_update_result r = {*varp}; ++ VEC_safe_push (varobj_update_result, stack, &r); + } +- +- VEC_safe_push (varobj_p, stack, *varp); + + /* Walk through the children, reconstructing them all. */ +- while (!VEC_empty (varobj_p, stack)) ++ while (!VEC_empty (varobj_update_result, stack)) + { +- v = VEC_pop (varobj_p, stack); ++ varobj_update_result r = *(VEC_last (varobj_update_result, stack)); ++ struct varobj *v = r.varobj; ++ ++ VEC_pop (varobj_update_result, stack); ++ ++ /* Update this variable, unless it's a root, which is already ++ updated. */ ++ if (!r.value_installed) ++ { ++ new = value_of_child (v->parent, v->index); ++ if (install_new_value (v, new, 0 /* type not changed */)) ++ { ++ r.changed = 1; ++ v->updated = 0; ++ } ++ } ++ ++ /* We probably should not get children of a varobj that has a ++ pretty-printer, but for which -var-list-children was never ++ invoked. Presumably, such varobj is not yet expanded in the ++ UI, so we need not bother getting it. */ ++ if (v->pretty_printer) ++ { ++ VEC (varobj_p) *changed = 0, *new_and_unchanged = 0; ++ int i, children_changed; ++ varobj_p tmp; ++ ++ if (!v->children_requested) ++ continue; ++ ++ if (v->frozen) ++ continue; ++ ++ /* If update_dynamic_varobj_children returns 0, then we have ++ a non-conforming pretty-printer, so we skip it. */ ++ if (update_dynamic_varobj_children (v, &changed, &new_and_unchanged, ++ &children_changed)) ++ { ++ if (children_changed) ++ r.children_changed = 1; ++ for (i = 0; VEC_iterate (varobj_p, changed, i, tmp); ++i) ++ { ++ varobj_update_result r = {tmp}; ++ r.changed = 1; ++ r.value_installed = 1; ++ VEC_safe_push (varobj_update_result, stack, &r); ++ } ++ for (i = 0; ++ VEC_iterate (varobj_p, new_and_unchanged, i, tmp); ++ ++i) ++ { ++ varobj_update_result r = {tmp}; ++ r.value_installed = 1; ++ VEC_safe_push (varobj_update_result, stack, &r); ++ } ++ if (r.changed || r.children_changed) ++ VEC_safe_push (varobj_update_result, result, &r); ++ continue; ++ } ++ } + + /* Push any children. Use reverse order so that the first + child is popped from the work stack first, and so +@@ -1211,26 +1661,18 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) + varobj_p c = VEC_index (varobj_p, v->children, i); + /* Child may be NULL if explicitly deleted by -var-delete. */ + if (c != NULL && !c->frozen) +- VEC_safe_push (varobj_p, stack, c); +- } +- +- /* Update this variable, unless it's a root, which is already +- updated. */ +- if (v->root->rootvar != v) +- { +- new = value_of_child (v->parent, v->index); +- if (install_new_value (v, new, 0 /* type not changed */)) + { +- /* Note that it's changed */ +- varobj_update_result r = {v}; +- r.changed = 1; +- VEC_safe_push (varobj_update_result, result, &r); +- v->updated = 0; ++ varobj_update_result r = {c}; ++ VEC_safe_push (varobj_update_result, stack, &r); + } + } ++ ++ if (r.changed || r.type_changed) ++ VEC_safe_push (varobj_update_result, result, &r); + } + +- VEC_free (varobj_p, stack); ++ VEC_free (varobj_update_result, stack); ++ + return result; + } + +@@ -1429,16 +1871,23 @@ uninstall_variable (struct varobj *var) + static struct varobj * + create_child (struct varobj *parent, int index, char *name) + { ++ return create_child_with_value (parent, index, name, ++ value_of_child (parent, index)); ++} ++ ++static struct varobj * ++create_child_with_value (struct varobj *parent, int index, const char *name, ++ struct value *value) ++{ + struct varobj *child; + char *childs_name; +- struct value *value; + + child = new_variable (); + + /* name is allocated by name_of_child */ +- child->name = name; ++ /* FIXME: xstrdup should not be here. */ ++ child->name = xstrdup (name); + child->index = index; +- value = value_of_child (parent, index); + child->parent = parent; + child->root = parent->root; + childs_name = xstrprintf ("%s.%s", parent->obj_name, name); +@@ -1487,6 +1936,10 @@ new_variable (void) + var->print_value = NULL; + var->frozen = 0; + var->not_fetched = 0; ++ var->children_requested = 0; ++ var->from = -1; ++ var->to = -1; ++ var->pretty_printer = 0; + + return var; + } +@@ -1519,6 +1972,14 @@ free_variable (struct varobj *var) + xfree (var->root); + } + ++#if HAVE_PYTHON ++ { ++ PyGILState_STATE state = PyGILState_Ensure (); ++ Py_XDECREF (var->pretty_printer); ++ PyGILState_Release (state); ++ } ++#endif ++ + xfree (var->name); + xfree (var->obj_name); + xfree (var->print_value); +@@ -1538,6 +1999,18 @@ make_cleanup_free_variable (struct varobj *var) + return make_cleanup (do_free_variable_cleanup, var); + } + ++static void ++do_uninstall_variable_cleanup (void *var) ++{ ++ uninstall_variable (var); ++} ++ ++static struct cleanup * ++make_cleanup_uninstall_variable (struct varobj *var) ++{ ++ return make_cleanup (do_uninstall_variable_cleanup, var); ++} ++ + /* This returns the type of the variable. It also skips past typedefs + to return the real type of the variable. + +@@ -1792,24 +2265,71 @@ my_value_of_variable (struct varobj *var, enum varobj_display_formats format) + return NULL; + } + +-static char * +-value_get_print_value (struct value *value, enum varobj_display_formats format) ++char * ++value_get_print_value (struct value *value, enum varobj_display_formats format, ++ PyObject *value_formatter) + { + long dummy; + struct ui_file *stb; + struct cleanup *old_chain; +- char *thevalue; ++ char *thevalue = NULL; + struct value_print_options opts; + + if (value == NULL) + return NULL; + ++#if HAVE_PYTHON ++ { ++ PyGILState_STATE state = PyGILState_Ensure (); ++ if (value_formatter && PyObject_HasAttr (value_formatter, ++ gdbpy_to_string_cst)) ++ { ++ char *hint; ++ struct value *replacement; ++ int string_print = 0; ++ ++ hint = gdbpy_get_display_hint (value_formatter); ++ if (hint) ++ { ++ if (!strcmp (hint, "string")) ++ string_print = 1; ++ xfree (hint); ++ } ++ ++ thevalue = apply_varobj_pretty_printer (value_formatter, ++ &replacement); ++ if (thevalue && !string_print) ++ { ++ PyGILState_Release (state); ++ return thevalue; ++ } ++ if (replacement) ++ value = replacement; ++ } ++ PyGILState_Release (state); ++ } ++#endif ++ + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + get_formatted_print_options (&opts, format_code[(int) format]); + opts.deref_ref = 0; +- common_val_print (value, stb, 0, &opts, current_language); ++ opts.raw = 1; ++ if (thevalue) ++ { ++ struct type *string_char_type; ++ ++ make_cleanup (xfree, thevalue); ++ ++ /* OUTPUT is already in the hosts's charset. */ ++ string_char_type = language_string_char_type (current_language, ++ current_gdbarch); ++ LA_PRINT_STRING (stb, string_char_type, (gdb_byte *) thevalue, ++ strlen (thevalue), 0, &opts); ++ } ++ else ++ common_val_print (value, stb, 0, &opts, current_language); + thevalue = ui_file_xstrdup (stb, &dummy); + + do_cleanups (old_chain); +@@ -1900,7 +2420,7 @@ varobj_floating_p (struct varobj *var) + value is not known. + + If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1 +- depending on whether pointer was deferenced ++ depending on whether pointer was dereferenced + in this function. */ + static void + adjust_value_for_child_access (struct value **value, +@@ -2269,6 +2789,11 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format) + catch that case explicitly. */ + struct type *type = get_type (var); + ++ /* If we have a custom formatter, return whatever string it has ++ produced. */ ++ if (var->pretty_printer && var->print_value) ++ return xstrdup (var->print_value); ++ + /* Strip top-level references. */ + while (TYPE_CODE (type) == TYPE_CODE_REF) + type = check_typedef (TYPE_TARGET_TYPE (type)); +@@ -2313,7 +2838,8 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format) + if (format == var->format) + return xstrdup (var->print_value); + else +- return value_get_print_value (var->value, format); ++ return value_get_print_value (var->value, format, ++ var->pretty_printer); + } + } + } +diff --git a/gdb/varobj.h b/gdb/varobj.h +index f2cdcf8..10758d6 100644 +--- a/gdb/varobj.h ++++ b/gdb/varobj.h +@@ -72,7 +72,12 @@ typedef struct varobj_update_result_t + struct varobj *varobj; + int type_changed; + int changed; ++ int children_changed; + enum varobj_scope_status status; ++ /* This variable is used internally by varobj_update to indicate if the ++ new value of varobj is already computed and installed, or has to ++ be yet installed. Don't use this outside varobj.c */ ++ int value_installed; + } varobj_update_result; + + DEF_VEC_O (varobj_update_result); +@@ -107,6 +112,14 @@ extern void varobj_set_frozen (struct varobj *var, int frozen); + + extern int varobj_get_frozen (struct varobj *var); + ++extern void varobj_get_child_range (struct varobj *var, ++ VEC (varobj_p) *children, ++ int *from, int *to); ++ ++extern void varobj_set_child_range (struct varobj *var, int from, int to); ++ ++extern char *varobj_get_display_hint (struct varobj *var); ++ + extern int varobj_get_num_children (struct varobj *var); + + /* Return the list of children of VAR. The returned vector +@@ -141,4 +154,13 @@ extern int varobj_editable_p (struct varobj *var); + + extern int varobj_floating_p (struct varobj *var); + ++extern void ++varobj_set_visualizer (struct varobj *var, const char *visualizer); ++ ++extern void ++varobj_clear_type_visualizers (); ++ ++extern void ++varobj_set_visualizer (struct varobj *var, const char *visualizer); ++ + #endif /* VAROBJ_H */ +diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c +index aab3e48..d41738b 100644 +--- a/gdb/xcoffread.c ++++ b/gdb/xcoffread.c +@@ -3021,6 +3021,7 @@ static struct sym_fns xcoff_sym_fns = + xcoff_new_init, /* sym_new_init: init anything gbl to entire symtab */ + xcoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */ + xcoff_initial_scan, /* sym_read: read a symbol file into symtab */ ++ NULL, /* sym_read_psymbols */ + xcoff_symfile_finish, /* sym_finish: finished with file, cleanup */ + xcoff_symfile_offsets, /* sym_offsets: xlate offsets ext->int form */ + default_symfile_segments, /* sym_segments: Get segment information from +diff --git a/gdb/xml-syscall.c b/gdb/xml-syscall.c +new file mode 100644 +index 0000000..498f58a +--- /dev/null ++++ b/gdb/xml-syscall.c +@@ -0,0 +1,423 @@ ++/* Functions that provide the mechanism to parse a syscall XML file ++ and get its values. ++ ++ Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, ++ 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008 ++ 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 3 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, see . */ ++ ++#include "defs.h" ++#include "gdbtypes.h" ++#include "xml-support.h" ++#include "xml-syscall.h" ++ ++#include "filenames.h" ++ ++#include "gdb_assert.h" ++ ++#ifndef HAVE_LIBEXPAT ++ ++/* Dummy functions to indicate that there's no support for fetching ++ syscalls information. */ ++ ++static void ++syscall_warn_user (void) ++{ ++ static int have_warned = 0; ++ if (!have_warned) ++ { ++ have_warned = 1; ++ warning (_("Can not parse XML syscalls information; XML support was " ++ "disabled at compile time")); ++ } ++} ++ ++const struct syscalls_info * ++xml_init_syscalls_info (const char *filename) ++{ ++ syscall_warn_user (); ++ return NULL; ++} ++ ++int ++xml_get_syscall_number (const struct syscalls_info *sysinfo, ++ const char *syscall_name) ++{ ++ syscall_warn_user (); ++ return UNKNOWN_SYSCALL; ++} ++ ++const char * ++xml_get_syscall_name (const struct syscalls_info *sysinfo, ++ int syscall_number) ++{ ++ syscall_warn_user (); ++ return NULL; ++} ++ ++int ++xml_number_of_syscalls (const struct syscalls_info *sysinfo) ++{ ++ syscall_warn_user (); ++ return 0; ++} ++ ++const char ** ++xml_list_of_syscalls (const struct syscalls_info *sysinfo) ++{ ++ syscall_warn_user (); ++ return NULL; ++} ++ ++#else ++ ++/* Structure which describes a syscall. */ ++ ++typedef struct syscall_desc ++{ ++ /* The syscall number. */ ++ ++ int number; ++ ++ /* The syscall name. */ ++ ++ char *name; ++} *syscall_desc_p; ++DEF_VEC_P(syscall_desc_p); ++ ++/* Structure that represents syscalls information. */ ++ ++struct syscalls_info ++{ ++ /* The syscalls. */ ++ ++ VEC(syscall_desc_p) *syscalls; ++}; ++ ++/* Callback data for syscall information parsing. */ ++ ++struct syscall_parsing_data ++{ ++ /* The syscalls_info we are building. */ ++ ++ struct syscalls_info *sysinfo; ++}; ++ ++ ++static struct syscalls_info * ++allocate_syscalls_info (void) ++{ ++ return XZALLOC (struct syscalls_info); ++} ++ ++static void ++sysinfo_free_syscalls_desc (struct syscall_desc *sd) ++{ ++ xfree (sd->name); ++} ++ ++static void ++free_syscalls_info (void *arg) ++{ ++ struct syscalls_info *sysinfo = arg; ++ struct syscall_desc *sysdesc; ++ int i; ++ ++ for (i = 0; ++ VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc); ++ i++) ++ sysinfo_free_syscalls_desc (sysdesc); ++ VEC_free (syscall_desc_p, sysinfo->syscalls); ++ ++ xfree (sysinfo); ++} ++ ++struct cleanup * ++make_cleanup_free_syscalls_info (struct syscalls_info *sysinfo) ++{ ++ return make_cleanup (free_syscalls_info, sysinfo); ++} ++ ++/* Open FILENAME, read all its text into memory, close it, and return ++ the text. If something goes wrong, return NULL and warn. */ ++ ++static char * ++fetch_xml_from_file (const char *filename, void *baton) ++{ ++ const char *dirname = baton; ++ FILE *file; ++ struct cleanup *back_to; ++ char *text; ++ size_t len, offset; ++ ++ if (dirname && *dirname) ++ { ++ char *fullname = concat (dirname, "/", filename, (char *) NULL); ++ if (fullname == NULL) ++ nomem (0); ++ file = fopen (fullname, FOPEN_RT); ++ xfree (fullname); ++ } ++ else ++ file = fopen (filename, FOPEN_RT); ++ ++ if (file == NULL) ++ return NULL; ++ ++ back_to = make_cleanup_fclose (file); ++ ++ /* Read in the whole file, one chunk at a time. */ ++ len = 4096; ++ offset = 0; ++ text = xmalloc (len); ++ make_cleanup (free_current_contents, &text); ++ while (1) ++ { ++ size_t bytes_read; ++ ++ /* Continue reading where the last read left off. Leave at least ++ one byte so that we can NUL-terminate the result. */ ++ bytes_read = fread (text + offset, 1, len - offset - 1, file); ++ if (ferror (file)) ++ { ++ warning (_("Read error from \"%s\""), filename); ++ do_cleanups (back_to); ++ return NULL; ++ } ++ ++ offset += bytes_read; ++ ++ if (feof (file)) ++ break; ++ ++ len = len * 2; ++ text = xrealloc (text, len); ++ } ++ ++ fclose (file); ++ discard_cleanups (back_to); ++ ++ text[offset] = '\0'; ++ return text; ++} ++ ++static void ++syscall_create_syscall_desc (struct syscalls_info *sysinfo, ++ const char *name, int number) ++{ ++ struct syscall_desc *sysdesc = XZALLOC (struct syscall_desc); ++ ++ sysdesc->name = xstrdup (name); ++ sysdesc->number = number; ++ ++ VEC_safe_push (syscall_desc_p, sysinfo->syscalls, sysdesc); ++} ++ ++/* Handle the start of a element. */ ++ ++static void ++syscall_start_syscalls_info (struct gdb_xml_parser *parser, ++ const struct gdb_xml_element *element, ++ void *user_data, ++ VEC(gdb_xml_value_s) *attributes) ++{ ++ struct syscall_parsing_data *data = user_data; ++ struct syscalls_info *sysinfo = data->sysinfo; ++} ++ ++/* Handle the start of a element. */ ++ ++static void ++syscall_start_syscall (struct gdb_xml_parser *parser, ++ const struct gdb_xml_element *element, ++ void *user_data, VEC(gdb_xml_value_s) *attributes) ++{ ++ struct syscall_parsing_data *data = user_data; ++ struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes); ++ int len, i; ++ /* syscall info. */ ++ char *name = NULL; ++ int number = 0; ++ ++ len = VEC_length (gdb_xml_value_s, attributes); ++ ++ for (i = 0; i < len; i++) ++ { ++ if (strcmp (attrs[i].name, "name") == 0) ++ name = attrs[i].value; ++ else if (strcmp (attrs[i].name, "number") == 0) ++ number = * (ULONGEST *) attrs[i].value; ++ else ++ internal_error (__FILE__, __LINE__, ++ _("Unknown attribute name '%s'."), attrs[i].name); ++ } ++ ++ syscall_create_syscall_desc (data->sysinfo, name, number); ++} ++ ++ ++/* The elements and attributes of an XML syscall document. */ ++ ++static const struct gdb_xml_attribute syscall_attr[] = { ++ { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, ++ { "name", GDB_XML_AF_NONE, NULL, NULL }, ++ { NULL, GDB_XML_AF_NONE, NULL, NULL } ++}; ++ ++static const struct gdb_xml_element syscalls_info_children[] = { ++ { "syscall", syscall_attr, NULL, ++ GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, ++ syscall_start_syscall, NULL }, ++ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } ++}; ++ ++static const struct gdb_xml_element syselements[] = { ++ { "syscalls_info", NULL, syscalls_info_children, ++ GDB_XML_EF_NONE, syscall_start_syscalls_info, NULL }, ++ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } ++}; ++ ++static struct syscalls_info * ++syscall_parse_xml (const char *document, xml_fetch_another fetcher, ++ void *fetcher_baton) ++{ ++ struct cleanup *result_cleanup; ++ struct gdb_xml_parser *parser; ++ struct syscall_parsing_data data; ++ char *expanded_text; ++ int i; ++ ++ parser = gdb_xml_create_parser_and_cleanup (_("syscalls info"), ++ syselements, &data); ++ ++ memset (&data, 0, sizeof (struct syscall_parsing_data)); ++ data.sysinfo = allocate_syscalls_info (); ++ result_cleanup = make_cleanup_free_syscalls_info (data.sysinfo); ++ ++ if (gdb_xml_parse (parser, document) == 0) ++ { ++ /* Parsed successfully. */ ++ discard_cleanups (result_cleanup); ++ return data.sysinfo; ++ } ++ else ++ { ++ warning (_("Could not load XML syscalls info; ignoring")); ++ do_cleanups (result_cleanup); ++ return NULL; ++ } ++} ++ ++const struct syscalls_info * ++xml_init_syscalls_info (const char *filename) ++{ ++ char *full_file; ++ char *dirname; ++ struct syscalls_info *sysinfo; ++ struct cleanup *back_to; ++ ++ full_file = fetch_xml_from_file (filename, gdb_datadir); ++ if (full_file == NULL) ++ { ++ warning (_("Could not open \"%s\""), filename); ++ return NULL; ++ } ++ ++ back_to = make_cleanup (xfree, full_file); ++ ++ dirname = ldirname (filename); ++ if (dirname != NULL) ++ make_cleanup (xfree, dirname); ++ ++ sysinfo = syscall_parse_xml (full_file, fetch_xml_from_file, dirname); ++ do_cleanups (back_to); ++ ++ return sysinfo; ++} ++ ++int ++xml_get_syscall_number (const struct syscalls_info *sysinfo, ++ const char *syscall_name) ++{ ++ struct syscall_desc *sysdesc; ++ int i; ++ ++ if (sysinfo == NULL ++ || syscall_name == NULL) ++ return UNKNOWN_SYSCALL; ++ ++ for (i = 0; ++ VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc); ++ i++) ++ if (strcmp (sysdesc->name, syscall_name) == 0) ++ return sysdesc->number; ++ ++ return UNKNOWN_SYSCALL; ++} ++ ++const char * ++xml_get_syscall_name (const struct syscalls_info *sysinfo, ++ int syscall_number) ++{ ++ struct syscall_desc *sysdesc; ++ int i; ++ ++ if (sysinfo == NULL ++ || syscall_number < 0) ++ return NULL; ++ ++ for (i = 0; ++ VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc); ++ i++) ++ if (sysdesc->number == syscall_number) ++ return sysdesc->name; ++ ++ return NULL; ++} ++ ++int ++xml_number_of_syscalls (const struct syscalls_info *sysinfo) ++{ ++ return (sysinfo == NULL ? 0 : VEC_length(syscall_desc_p, ++ sysinfo->syscalls)); ++} ++ ++const char ** ++xml_list_of_syscalls (const struct syscalls_info *sysinfo) ++{ ++ struct syscall_desc *sysdesc; ++ const char **names = NULL; ++ int nsyscalls; ++ int i; ++ ++ if (sysinfo == NULL) ++ return NULL; ++ ++ nsyscalls = VEC_length (syscall_desc_p, sysinfo->syscalls); ++ names = xmalloc ((nsyscalls + 1) * sizeof (char *)); ++ ++ for (i = 0; ++ VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc); ++ i++) ++ names[i] = sysdesc->name; ++ ++ names[i] = NULL; ++ ++ return names; ++} ++ ++#endif /* HAVE_LIBEXPAT */ +diff --git a/gdb/xml-syscall.h b/gdb/xml-syscall.h +new file mode 100644 +index 0000000..ff11f20 +--- /dev/null ++++ b/gdb/xml-syscall.h +@@ -0,0 +1,64 @@ ++/* Functions that provide the mechanism to parse a syscall XML file ++ and get its values. ++ ++ Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, ++ 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008 ++ 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 3 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, see . */ ++ ++#ifndef XML_SYSCALL_H ++#define XML_SYSCALL_H 1 ++ ++/* Structure that stores information about the system's ++ syscalls. */ ++ ++struct syscalls_info; ++ ++ ++/* Function responsible for initializing the information ++ about the syscalls. It reads the XML file and fills the ++ struct syscalls_info with the values. ++ ++ Returns the struct syscalls_info if the file is valid, NULL otherwise. */ ++ ++const struct syscalls_info *xml_init_syscalls_info (const char *); ++ ++/* Function that retrieves the syscall number corresponding to the given ++ name. ++ ++ Returns the syscall number if found, or otherwise. */ ++ ++int xml_get_syscall_number (const struct syscalls_info *, const char *); ++ ++/* Function that retrieves the syscall name corresponding to the given ++ number. ++ ++ Returns the syscall name if found, NULL otherwise. */ ++const char *xml_get_syscall_name (const struct syscalls_info *, int); ++ ++/* Function that returns the number of syscalls defined in the system. ++ ++ Returns the number of syscalls, or zero otherwise. */ ++int xml_number_of_syscalls (const struct syscalls_info *); ++ ++/* Function used to retrieve the list of syscalls in the system. This list ++ is returned as an array of strings. ++ ++ Returns the list of syscalls in the system, or NULL otherwise. */ ++const char **xml_list_of_syscalls (const struct syscalls_info *sysinfo); ++ ++#endif /* XML_SYSCALL_H */ +diff --git a/include/elf/common.h b/include/elf/common.h +index 3ba44d9..764141e 100644 +--- a/include/elf/common.h ++++ b/include/elf/common.h +@@ -803,6 +803,7 @@ + #define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + #define AT_BASE_PLATFORM 24 /* String identifying real platform, + may differ from AT_PLATFORM. */ ++#define AT_RANDOM 25 /* Address of 16 random bytes. */ + #define AT_EXECFN 31 /* Filename of executable. */ + /* Pointer to the global system page used for system calls and other + nice things. */ +diff --git a/include/opcode/ppc.h b/include/opcode/ppc.h +index e45fc58..dc9a7ba 100644 +--- a/include/opcode/ppc.h ++++ b/include/opcode/ppc.h +@@ -1,6 +1,6 @@ + /* ppc.h -- Header file for PowerPC opcode table + Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +- 2007 Free Software Foundation, Inc. ++ 2007, 2008, 2009 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + + This file is part of GDB, GAS, and the GNU binutils. +@@ -351,4 +351,6 @@ struct powerpc_macro + extern const struct powerpc_macro powerpc_macros[]; + extern const int powerpc_num_macros; + ++extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, const char *); ++ + #endif /* PPC_H */ +diff --git a/opcodes/po/es.po b/opcodes/po/es.po +index 873be13..40bea5c 100644 +--- a/opcodes/po/es.po ++++ b/opcodes/po/es.po +@@ -1,13 +1,14 @@ +-# Mensajes en español para opcodes-2.17.90. +-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +-# Cristian Othón Martínez Vera , 2002, 2003, 2004, 2005, 2006, 2007. ++# Mensajes en español para opcodes-2.18.90. ++# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ++# This file is distributed under the same license as the binutils package. ++# Cristian Othón Martínez Vera , 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009. + # + msgid "" + msgstr "" +-"Project-Id-Version: opcodes 2.17.90\n" +-"Report-Msgid-Bugs-To: \n" +-"POT-Creation-Date: 2007-07-05 09:17+0100\n" +-"PO-Revision-Date: 2007-09-08 09:17-0500\n" ++"Project-Id-Version: opcodes 2.18.90\n" ++"Report-Msgid-Bugs-To: bug-binutils@gnu.org\n" ++"POT-Creation-Date: 2008-09-09 15:56+0930\n" ++"PO-Revision-Date: 2009-03-03 21:46-0600\n" + "Last-Translator: Cristian Othón Martínez Vera \n" + "Language-Team: Spanish \n" + "MIME-Version: 1.0\n" +@@ -52,7 +53,7 @@ msgid "too many long constants" + msgstr "demasiadas constantes long" + + #: arc-opc.c:668 +-msgid "to many shimms in load" ++msgid "too many shimms in load" + msgstr "demasiados shimms en load" + + #. Do we have a limm already? +@@ -124,7 +125,7 @@ msgstr "No se reconoce el conjunto de nombres de registro: %s\n" + msgid "Unrecognised disassembler option: %s\n" + msgstr "No se reconoce la opción de desensamblador: %s\n" + +-#: arm-dis.c:4226 ++#: arm-dis.c:4238 + #, c-format + msgid "" + "\n" +@@ -196,14 +197,14 @@ msgstr "La lista de registros no es v + + #: fr30-asm.c:310 frv-asm.c:1263 ip2k-asm.c:511 iq2000-asm.c:459 + #: m32c-asm.c:1589 m32r-asm.c:328 mep-asm.c:1001 mt-asm.c:595 +-#: openrisc-asm.c:241 xc16x-asm.c:375 xstormy16-asm.c:276 ++#: openrisc-asm.c:241 xc16x-asm.c:376 xstormy16-asm.c:276 + #, c-format + msgid "Unrecognized field %d while parsing.\n" + msgstr "No se reconoció el campo %d durante la decodificación.\n" + + #: fr30-asm.c:361 frv-asm.c:1314 ip2k-asm.c:562 iq2000-asm.c:510 + #: m32c-asm.c:1640 m32r-asm.c:379 mep-asm.c:1052 mt-asm.c:646 +-#: openrisc-asm.c:292 xc16x-asm.c:426 xstormy16-asm.c:327 ++#: openrisc-asm.c:292 xc16x-asm.c:427 xstormy16-asm.c:327 + msgid "missing mnemonic in syntax string" + msgstr "falta el mnemónico en la cadena sintáctica" + +@@ -216,7 +217,7 @@ msgstr "falta el mnem + #: m32r-asm.c:605 m32r-asm.c:706 mep-asm.c:1187 mep-asm.c:1191 mep-asm.c:1278 + #: mep-asm.c:1379 mt-asm.c:781 mt-asm.c:785 mt-asm.c:872 mt-asm.c:973 + #: openrisc-asm.c:427 openrisc-asm.c:431 openrisc-asm.c:518 openrisc-asm.c:619 +-#: xc16x-asm.c:561 xc16x-asm.c:565 xc16x-asm.c:652 xc16x-asm.c:753 ++#: xc16x-asm.c:562 xc16x-asm.c:566 xc16x-asm.c:653 xc16x-asm.c:754 + #: xstormy16-asm.c:462 xstormy16-asm.c:466 xstormy16-asm.c:553 + #: xstormy16-asm.c:654 + msgid "unrecognized instruction" +@@ -224,40 +225,40 @@ msgstr "no se reconoce la instrucci + + #: fr30-asm.c:543 frv-asm.c:1496 ip2k-asm.c:744 iq2000-asm.c:692 + #: m32c-asm.c:1822 m32r-asm.c:561 mep-asm.c:1234 mt-asm.c:828 +-#: openrisc-asm.c:474 xc16x-asm.c:608 xstormy16-asm.c:509 ++#: openrisc-asm.c:474 xc16x-asm.c:609 xstormy16-asm.c:509 + #, c-format + msgid "syntax error (expected char `%c', found `%c')" + msgstr "error sintáctico (se esperaba el carácter `%c', se encontró `%c')" + + #: fr30-asm.c:553 frv-asm.c:1506 ip2k-asm.c:754 iq2000-asm.c:702 + #: m32c-asm.c:1832 m32r-asm.c:571 mep-asm.c:1244 mt-asm.c:838 +-#: openrisc-asm.c:484 xc16x-asm.c:618 xstormy16-asm.c:519 ++#: openrisc-asm.c:484 xc16x-asm.c:619 xstormy16-asm.c:519 + #, c-format + msgid "syntax error (expected char `%c', found end of instruction)" + msgstr "error sintáctico (se esperaba el carácter `%c', se encontró el final de la instrucción)" + + #: fr30-asm.c:581 frv-asm.c:1534 ip2k-asm.c:782 iq2000-asm.c:730 + #: m32c-asm.c:1860 m32r-asm.c:599 mep-asm.c:1272 mt-asm.c:866 +-#: openrisc-asm.c:512 xc16x-asm.c:646 xstormy16-asm.c:547 ++#: openrisc-asm.c:512 xc16x-asm.c:647 xstormy16-asm.c:547 + msgid "junk at end of line" + msgstr "basura al final de la línea" + + #: fr30-asm.c:687 frv-asm.c:1640 ip2k-asm.c:888 iq2000-asm.c:836 + #: m32c-asm.c:1966 m32r-asm.c:705 mep-asm.c:1378 mt-asm.c:972 +-#: openrisc-asm.c:618 xc16x-asm.c:752 xstormy16-asm.c:653 ++#: openrisc-asm.c:618 xc16x-asm.c:753 xstormy16-asm.c:653 + msgid "unrecognized form of instruction" + msgstr "no se reconoce la forma de instrucción" + + #: fr30-asm.c:699 frv-asm.c:1652 ip2k-asm.c:900 iq2000-asm.c:848 + #: m32c-asm.c:1978 m32r-asm.c:717 mep-asm.c:1390 mt-asm.c:984 +-#: openrisc-asm.c:630 xc16x-asm.c:764 xstormy16-asm.c:665 ++#: openrisc-asm.c:630 xc16x-asm.c:765 xstormy16-asm.c:665 + #, c-format + msgid "bad instruction `%.50s...'" + msgstr "instrucción errónea `%.50s...'" + + #: fr30-asm.c:702 frv-asm.c:1655 ip2k-asm.c:903 iq2000-asm.c:851 + #: m32c-asm.c:1981 m32r-asm.c:720 mep-asm.c:1393 mt-asm.c:987 +-#: openrisc-asm.c:633 xc16x-asm.c:767 xstormy16-asm.c:668 ++#: openrisc-asm.c:633 xc16x-asm.c:768 xstormy16-asm.c:668 + #, c-format + msgid "bad instruction `%.50s'" + msgstr "instrucción errónea `%.50s'" +@@ -377,11 +378,11 @@ msgstr "no se puede lidiar con insert %d\n" + msgid "%02x\t\t*unknown*" + msgstr "%02x\t\t*desconocido*" + +-#: i386-dis.c:3196 ++#: i386-dis.c:9545 + msgid "" + msgstr "" + +-#: i386-dis.c:3423 ++#: i386-dis.c:9776 + #, c-format + msgid "" + "\n" +@@ -392,79 +393,124 @@ msgstr "" + "Se admiten las siguientes opciones de desensamblador específicas de i386/x86-64\n" + "con el interruptor -M (las opciones múltiples se deben separar con comas):\n" + +-#: i386-dis.c:3427 ++#: i386-dis.c:9780 + #, c-format + msgid " x86-64 Disassemble in 64bit mode\n" + msgstr " x86-64 Desensambla en modo 64bit\n" + +-#: i386-dis.c:3428 ++#: i386-dis.c:9781 + #, c-format + msgid " i386 Disassemble in 32bit mode\n" + msgstr " i386 Desensambla en modo 32bit\n" + +-#: i386-dis.c:3429 ++#: i386-dis.c:9782 + #, c-format + msgid " i8086 Disassemble in 16bit mode\n" + msgstr " i8086 Desensambla en modo 16bit\n" + +-#: i386-dis.c:3430 ++#: i386-dis.c:9783 + #, c-format + msgid " att Display instruction in AT&T syntax\n" + msgstr " att Muestra las instrucciones con sintaxis AT&T\n" + +-#: i386-dis.c:3431 ++#: i386-dis.c:9784 + #, c-format + msgid " intel Display instruction in Intel syntax\n" + msgstr " intel Muestra las instrucciones con sintaxis Intel\n" + +-#: i386-dis.c:3432 ++#: i386-dis.c:9785 ++#, c-format ++msgid "" ++" att-mnemonic\n" ++" Display instruction in AT&T mnemonic\n" ++msgstr "" ++" att-mnemonic\n" ++" Muestra las instrucciones con mnemónicos AT&T\n" ++ ++#: i386-dis.c:9787 ++#, c-format ++msgid "" ++" intel-mnemonic\n" ++" Display instruction in Intel mnemonic\n" ++msgstr "" ++" intel-mnemonic\n" ++" Muestra las instrucciones con mnemónicos Intel\n" ++ ++#: i386-dis.c:9789 + #, c-format + msgid " addr64 Assume 64bit address size\n" + msgstr " addr64 Asume un tamaño de dirección de 64bit\n" + +-#: i386-dis.c:3433 ++#: i386-dis.c:9790 + #, c-format + msgid " addr32 Assume 32bit address size\n" + msgstr " addr32 Asume un tamaño de dirección de 32bit\n" + +-#: i386-dis.c:3434 ++#: i386-dis.c:9791 + #, c-format + msgid " addr16 Assume 16bit address size\n" + msgstr " addr16 Asume un tamaño de dirección de 16bit\n" + +-#: i386-dis.c:3435 ++#: i386-dis.c:9792 + #, c-format + msgid " data32 Assume 32bit data size\n" + msgstr " data32 Asume un tamaño de datos de 32bit\n" + +-#: i386-dis.c:3436 ++#: i386-dis.c:9793 + #, c-format + msgid " data16 Assume 16bit data size\n" + msgstr " data16 Asume un tamaño de datos de 16bit\n" + +-#: i386-dis.c:3437 ++#: i386-dis.c:9794 + #, c-format + msgid " suffix Always display instruction suffix in AT&T syntax\n" + msgstr " suffix Siempre muestra el sufijo de instrucción con sintaxis AT&T\n" + +-#: i386-gen.c:42 ia64-gen.c:307 ++#: i386-gen.c:411 ia64-gen.c:307 + #, c-format + msgid "%s: Error: " + msgstr "%s: Error: " + +-#: i386-gen.c:109 +-msgid "can't find i386-opc.tbl for reading\n" +-msgstr "no se puede encontrar i386-opc.tbl para lectura\n" ++#: i386-gen.c:510 ++#, c-format ++msgid "%s: %d: Unknown bitfield: %s\n" ++msgstr "%s: %d: Campo de bits desconocido: %s\n" ++ ++#: i386-gen.c:674 ++#, c-format ++msgid "can't find i386-opc.tbl for reading, errno = %s\n" ++msgstr "no se puede encontrar i386-opc.tbl para lectura, errno =%s\n" + +-#: i386-gen.c:260 +-msgid "can't find i386-reg.tbl for reading\n" +-msgstr "no se puede encontrar i386-reg.tbl para lectura\n" ++#: i386-gen.c:851 ++#, c-format ++msgid "can't find i386-reg.tbl for reading, errno = %s\n" ++msgstr "no se puede encontrar i386-reg.tbl para lectura, errno = %s\n" ++ ++#: i386-gen.c:943 ++#, c-format ++msgid "can't create i386-init.h, errno = %s\n" ++msgstr "no se puede crear i386-init.h, errno = %s\n" + +-#: i386-gen.c:386 ia64-gen.c:2841 ++#: i386-gen.c:1032 ia64-gen.c:2850 + #, c-format + msgid "unable to change directory to \"%s\", errno = %s\n" + msgstr "no se puede cambiar el directorio a \"%s\", errno = %s\n" + ++#: i386-gen.c:1039 ++#, c-format ++msgid "%d unused bits in i386_cpu_flags.\n" ++msgstr "%d bits sin usar en i386_cpu_flags.\n" ++ ++#: i386-gen.c:1046 ++#, c-format ++msgid "%d unused bits in i386_operand_type.\n" ++msgstr "%d bits sin usar en i386_operand_type.\n" ++ ++#: i386-gen.c:1060 ++#, c-format ++msgid "can't create i386-tbl.h, errno = %s\n" ++msgstr "no se puede crear i386-tbl.h, errno = %s\n" ++ + #: ia64-gen.c:320 + #, c-format + msgid "%s: Warning: " +@@ -503,62 +549,67 @@ msgstr "campo solapado %s->%s\n" + msgid "overwriting note %d with note %d (IC:%s)\n" + msgstr "se sobreescribe la nota %d con la nota %d (IC:%s)\n" + +-#: ia64-gen.c:1455 ++#: ia64-gen.c:1459 + #, c-format + msgid "don't know how to specify %% dependency %s\n" + msgstr "no se sabe cómo especificar la dependencia %% %s\n" + +-#: ia64-gen.c:1477 ++#: ia64-gen.c:1481 + #, c-format + msgid "Don't know how to specify # dependency %s\n" + msgstr "No se sabe cómo especificar la dependencia # %s\n" + +-#: ia64-gen.c:1516 ++#: ia64-gen.c:1520 + #, c-format + msgid "IC:%s [%s] has no terminals or sub-classes\n" + msgstr "IC:%s [%s] no tiene terminales o sub-clases\n" + +-#: ia64-gen.c:1519 ++#: ia64-gen.c:1523 + #, c-format + msgid "IC:%s has no terminals or sub-classes\n" + msgstr "IC:%s no tiene terminales o sub-clases\n" + +-#: ia64-gen.c:1528 ++#: ia64-gen.c:1532 + #, c-format + msgid "no insns mapped directly to terminal IC %s [%s]" + msgstr "no hay insns mapeadas directamente al IC terminal %s [%s]" + +-#: ia64-gen.c:1531 ++#: ia64-gen.c:1535 + #, c-format + msgid "no insns mapped directly to terminal IC %s\n" + msgstr "no hay insns mapeadas directamente al IC terminal %s\n" + +-#: ia64-gen.c:1542 ++#: ia64-gen.c:1546 + #, c-format + msgid "class %s is defined but not used\n" + msgstr "se define la clase %s pero no se utiliza\n" + +-#: ia64-gen.c:1553 ++#: ia64-gen.c:1559 + #, c-format +-msgid "Warning: rsrc %s (%s) has no chks%s\n" +-msgstr "Aviso: el rsrc %s (%s) no tiene chks%s\n" ++msgid "Warning: rsrc %s (%s) has no chks\n" ++msgstr "Aviso: el rsrc %s (%s) no tiene chks\n" + +-#: ia64-gen.c:1557 ++#: ia64-gen.c:1562 ++#, c-format ++msgid "Warning: rsrc %s (%s) has no chks or regs\n" ++msgstr "Aviso: el rsrc %s (%s) no tiene chks o regs\n" ++ ++#: ia64-gen.c:1566 + #, c-format + msgid "rsrc %s (%s) has no regs\n" + msgstr "el rsrc %s (%s) no tiene registros\n" + +-#: ia64-gen.c:2469 ++#: ia64-gen.c:2478 + #, c-format + msgid "IC note %d in opcode %s (IC:%s) conflicts with resource %s note %d\n" + msgstr "la nota IC %d en el código de operación %s (IC:%s) tiene conflictos con el recurso %s nota %d\n" + +-#: ia64-gen.c:2497 ++#: ia64-gen.c:2506 + #, c-format + msgid "IC note %d for opcode %s (IC:%s) conflicts with resource %s note %d\n" + msgstr "la nota IC %d para el código de operación %s (IC:%s) tiene conflictos con el recurso %s nota %d\n" + +-#: ia64-gen.c:2511 ++#: ia64-gen.c:2520 + #, c-format + msgid "opcode %s has no class (ops %d %d %d)\n" + msgstr "el código de operación %s no tiene clase (ops %d %d %d)\n" +@@ -739,26 +790,26 @@ msgstr "S + msgid "invalid %function() here" + msgstr "%funcion() inválida aquí" + +-#: mips-dis.c:745 ++#: mips-dis.c:781 + msgid "# internal error, incomplete extension sequence (+)" + msgstr "# error interno, secuencia de extensión incompleta (+)" + +-#: mips-dis.c:852 ++#: mips-dis.c:915 + #, c-format + msgid "# internal error, undefined extension sequence (+%c)" + msgstr "# error interno, secuencia de extensión sin definir (+%c)" + +-#: mips-dis.c:1211 ++#: mips-dis.c:1274 + #, c-format +-msgid "# internal error, undefined modifier(%c)" +-msgstr "# error interno, modificador(%c) sin definir" ++msgid "# internal error, undefined modifier (%c)" ++msgstr "# error interno, modificador (%c) sin definir" + +-#: mips-dis.c:1818 ++#: mips-dis.c:1881 + #, c-format + msgid "# internal disassembler error, unrecognised modifier (%c)" + msgstr "# error interno del desensamblador, no se reconoce el modificador (%c)" + +-#: mips-dis.c:2049 ++#: mips-dis.c:2112 + #, c-format + msgid "" + "\n" +@@ -769,7 +820,7 @@ msgstr "" + "Las siguientes opciones de desensamblador específicas de MIPS se admiten\n" + "para usarse con el interruptor -M (las opciones múltiples se deben separar con comas):\n" + +-#: mips-dis.c:2053 ++#: mips-dis.c:2116 + #, c-format + msgid "" + "\n" +@@ -780,7 +831,7 @@ msgstr "" + " gpr-names=ABI Muestra los nombres GPR de acuerdo a la ABI especificada.\n" + " Por defecto: basado en el binario a desensamblar.\n" + +-#: mips-dis.c:2057 ++#: mips-dis.c:2120 + #, c-format + msgid "" + "\n" +@@ -791,7 +842,7 @@ msgstr "" + " fpr-names=ABI Muestra los nombres FPR de acuerdo a la ABI especificada.\n" + " Por defecto: numérico.\n" + +-#: mips-dis.c:2061 ++#: mips-dis.c:2124 + #, c-format + msgid "" + "\n" +@@ -804,7 +855,7 @@ msgstr "" + " la arquitectura especificada.\n" + " Por defecto: basado en el binario a desensamblar.\n" + +-#: mips-dis.c:2066 ++#: mips-dis.c:2129 + #, c-format + msgid "" + "\n" +@@ -817,7 +868,7 @@ msgstr "" + " especificada.\n" + " Por defecto: basado en el binario a desensamblar.\n" + +-#: mips-dis.c:2071 ++#: mips-dis.c:2134 + #, c-format + msgid "" + "\n" +@@ -828,7 +879,7 @@ msgstr "" + " reg-names=ABI Muestra los nombres GPR y FPR de acuerdo a\n" + " la ABI especificada.\n" + +-#: mips-dis.c:2075 ++#: mips-dis.c:2138 + #, c-format + msgid "" + "\n" +@@ -839,7 +890,7 @@ msgstr "" + " reg-names=ARCH Muestra el registro CP0 y los nombres HWR de acuerdo a\n" + " la arquitectura especificada.\n" + +-#: mips-dis.c:2079 ++#: mips-dis.c:2142 + #, c-format + msgid "" + "\n" +@@ -850,12 +901,12 @@ msgstr "" + " Para las opciones anteriores, se admiten los siguientes valores de \"ABI\":\n" + " " + +-#: mips-dis.c:2084 mips-dis.c:2092 mips-dis.c:2094 ++#: mips-dis.c:2147 mips-dis.c:2155 mips-dis.c:2157 + #, c-format + msgid "\n" + msgstr "\n" + +-#: mips-dis.c:2086 ++#: mips-dis.c:2149 + #, c-format + msgid "" + "\n" +@@ -894,9 +945,8 @@ msgid "Biiiig Trouble in parse_imm16!" + msgstr "¡Graaaan Problema en parse_imm16!" + + #: mt-asm.c:157 +-#, c-format +-msgid "%operator operand is not a symbol" +-msgstr "el operando %operator no es un símbolo" ++msgid "The percent-operator's operand is not a symbol" ++msgstr "el operando de operador-porcentaje no es un símbolo" + + #: mt-asm.c:395 + msgid "invalid operand. type may have values 0,1,2 only." +@@ -912,42 +962,64 @@ msgstr "operando inv + msgid "$" + msgstr "$" + +-#: ppc-opc.c:782 ppc-opc.c:810 ++#: ppc-opc.c:862 ppc-opc.c:890 + msgid "invalid conditional option" + msgstr "opción condicional inválida" + +-#: ppc-opc.c:812 ++#: ppc-opc.c:892 + msgid "attempt to set y bit when using + or - modifier" + msgstr "intento de establecer el bit y cuando se usaba el modificador + ó -" + +-#: ppc-opc.c:844 ++#: ppc-opc.c:924 + msgid "invalid mask field" + msgstr "campo de máscara inválido" + +-#: ppc-opc.c:870 ++#: ppc-opc.c:950 + msgid "ignoring invalid mfcr mask" + msgstr "se descarta la máscara mfcr inválida" + +-#: ppc-opc.c:920 ppc-opc.c:955 ++#: ppc-opc.c:1000 ppc-opc.c:1035 + msgid "illegal bitmask" + msgstr "máscara de bits ilegal" + +-#: ppc-opc.c:1075 ++#: ppc-opc.c:1155 + msgid "index register in load range" + msgstr "registro índice en el rango de carga" + +-#: ppc-opc.c:1091 ++#: ppc-opc.c:1171 + msgid "source and target register operands must be different" + msgstr "los operandos de registros fuente y objetivo deben ser diferentes" + +-#: ppc-opc.c:1106 ++#: ppc-opc.c:1186 + msgid "invalid register operand when updating" + msgstr "operando de registro inválido mientras se actualizaba" + +-#: ppc-opc.c:1188 ++#: ppc-opc.c:1265 + msgid "invalid sprg number" + msgstr "número sprg inválido" + ++#: s390-dis.c:276 ++#, c-format ++msgid "" ++"\n" ++"The following S/390 specific disassembler options are supported for use\n" ++"with the -M switch (multiple options should be separated by commas):\n" ++msgstr "" ++"\n" ++"Las siguientes opciones de desensamblador específicas de S/390 se admiten\n" ++"para usarse con el interruptor -M (las opciones múltiples se deben\n" ++"separar con comas):\n" ++ ++#: s390-dis.c:280 ++#, c-format ++msgid " esa Disassemble in ESA architecture mode\n" ++msgstr " esa Desensambla en modo de arquitectura ESA\n" ++ ++#: s390-dis.c:281 ++#, c-format ++msgid " zarch Disassemble in z/Architecture mode\n" ++msgstr " zarch Desensambla en modo de z/Architecture\n" ++ + #: score-dis.c:220 score-dis.c:383 + msgid "" + msgstr "" +@@ -1031,27 +1103,27 @@ msgstr "el valor inmediato no est + msgid "immediate value must be even" + msgstr "el valor inmediato debe ser par" + +-#: xc16x-asm.c:65 ++#: xc16x-asm.c:66 + msgid "Missing '#' prefix" + msgstr "Falta el prefijo '#'" + +-#: xc16x-asm.c:81 ++#: xc16x-asm.c:82 + msgid "Missing '.' prefix" + msgstr "Falta el prefijo '.'" + +-#: xc16x-asm.c:97 ++#: xc16x-asm.c:98 + msgid "Missing 'pof:' prefix" + msgstr "Falta el prefijo 'pof:'" + +-#: xc16x-asm.c:113 ++#: xc16x-asm.c:114 + msgid "Missing 'pag:' prefix" + msgstr "Falta el prefijo 'pag:'" + +-#: xc16x-asm.c:129 ++#: xc16x-asm.c:130 + msgid "Missing 'sof:' prefix" + msgstr "Falta el prefijo 'sof:'" + +-#: xc16x-asm.c:145 ++#: xc16x-asm.c:146 + msgid "Missing 'seg:' prefix" + msgstr "Falta el prefijo 'seg:'" + +@@ -1095,6 +1167,9 @@ msgstr "El operando no es un s + msgid "Syntax error: No trailing ')'" + msgstr "Error sintáctico: No hay ')' al final" + ++#~ msgid "%operator operand is not a symbol" ++#~ msgstr "el operando %operator no es un símbolo" ++ + #~ msgid "offset not a multiple of 16" + #~ msgstr "el desplazamiento no es un múltiplo de 16" + +diff --git a/opcodes/po/id.po b/opcodes/po/id.po +index 3edf294..0f6c063 100644 +--- a/opcodes/po/id.po ++++ b/opcodes/po/id.po +@@ -1,46 +1,133 @@ +-# opcodes 2.12.1 (Indonesian) +-# Copyright (C) 2002 Free Software Foundation, Inc. ++# Pesan bahasa indonesia untuk opcodes ++# Copyright (C) 2009 Free Software Foundation, Inc. ++# This file is distributed under the same license as the binutils package. + # Tedi Heriyanto , 2002. ++# Arif E. Nugroho , 2009. + # + msgid "" + msgstr "" +-"Project-Id-Version: opcodes 2.12.1\n" +-"POT-Creation-Date: 2002-02-08 03:24-0200\n" +-"PO-Revision-Date: 2002-07-23 12:35GMT+0700\n" +-"Last-Translator: Tedi Heriyanto \n" ++"Project-Id-Version: opcodes 2.18.90\n" ++"Report-Msgid-Bugs-To: bug-binutils@gnu.org\n" ++"POT-Creation-Date: 2008-09-09 15:56+0930\n" ++"PO-Revision-Date: 2009-03-10 13:30+0700\n" ++"Last-Translator: Arif E. Nugroho \n" + "Language-Team: Indonesian \n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" +-"X-Generator: KBabel 0.9.5\n" + +-#: alpha-opc.c:335 ++#: alpha-opc.c:155 + msgid "branch operand unaligned" + msgstr "operand cabang tidak rata" + +-#: alpha-opc.c:358 alpha-opc.c:380 ++#: alpha-opc.c:171 alpha-opc.c:187 + msgid "jump hint unaligned" + msgstr "petunjuk lompat tidak rata" + +-#: arc-dis.c:52 ++#: arc-dis.c:77 + msgid "Illegal limm reference in last instruction!\n" + msgstr "referensi limm ilegal dalam instruksi terakhir!\n" + +-#: arm-dis.c:502 ++#: arc-opc.c:386 ++msgid "unable to fit different valued constants into instruction" ++msgstr "tidak dapat memasukan nilai konstanta berbeda kedalam instruksi" ++ ++#: arc-opc.c:395 ++msgid "auxiliary register not allowed here" ++msgstr "register tambahan tidak diperbolehkan disini" ++ ++#: arc-opc.c:401 arc-opc.c:418 ++msgid "attempt to set readonly register" ++msgstr "mencoba untuk menset register baca-saja" ++ ++#: arc-opc.c:406 arc-opc.c:423 ++msgid "attempt to read writeonly register" ++msgstr "mencoba untuk membaca register tulis-saja" ++ ++#: arc-opc.c:428 ++#, c-format ++msgid "invalid register number `%d'" ++msgstr "nomor register tidak valid `%d'" ++ ++#: arc-opc.c:594 arc-opc.c:645 arc-opc.c:673 ++msgid "too many long constants" ++msgstr "terlalu banyak konstanta panjang" ++ ++#: arc-opc.c:668 ++msgid "too many shimms in load" ++msgstr "terlalu banyak shimm dalam load" ++ ++#. Do we have a limm already? ++#: arc-opc.c:781 ++msgid "impossible store" ++msgstr "store tidak memungkinkan" ++ ++#: arc-opc.c:814 ++msgid "st operand error" ++msgstr "operand st error" ++ ++#: arc-opc.c:818 arc-opc.c:860 ++msgid "address writeback not allowed" ++msgstr "alamat writeback tidak diijinkan" ++ ++#: arc-opc.c:822 ++msgid "store value must be zero" ++msgstr "nilai simpan harus nol" ++ ++#: arc-opc.c:847 ++msgid "invalid load/shimm insn" ++msgstr "insn load/shimm tidak valid" ++ ++#: arc-opc.c:856 ++msgid "ld operand error" ++msgstr "operand ld error" ++ ++#: arc-opc.c:943 ++msgid "jump flags, but no .f seen" ++msgstr "tanda jump, tetapi tidak ada .f yang terlihat" ++ ++#: arc-opc.c:946 ++msgid "jump flags, but no limm addr" ++msgstr "tanda jump, tetapi tidak ada alamat limm" ++ ++#: arc-opc.c:949 ++msgid "flag bits of jump address limm lost" ++msgstr "tanda bit dari alamat jump limm hilang" ++ ++#: arc-opc.c:952 ++msgid "attempt to set HR bits" ++msgstr "mencoba menset bit HR" ++ ++#: arc-opc.c:955 ++msgid "bad jump flags value" ++msgstr "nilai tanda jump buruk" ++ ++#: arc-opc.c:988 ++msgid "branch address not on 4 byte boundary" ++msgstr "alamat cabang tidak dalam kelipatan 4 byte" ++ ++#: arc-opc.c:1024 ++msgid "must specify .jd or no nullify suffix" ++msgstr "harus menspesifikasikan .jd atau tidak ada akhiran nullify" ++ ++#: arm-dis.c:1808 + msgid "" + msgstr "" + +-#: arm-dis.c:1012 ++#. XXX - should break 'option' at following delimiter. ++#: arm-dis.c:3818 + #, c-format + msgid "Unrecognised register name set: %s\n" + msgstr "Set nama register tidak dikenal: %s\n" + +-#: arm-dis.c:1019 ++#. XXX - should break 'option' at following delimiter. ++#: arm-dis.c:3826 + #, c-format + msgid "Unrecognised disassembler option: %s\n" + msgstr "Option disasembler tidak dikenal: %s\n" + +-#: arm-dis.c:1191 ++#: arm-dis.c:4238 ++#, c-format + msgid "" + "\n" + "The following ARM specific disassembler options are supported for use with\n" +@@ -50,297 +137,919 @@ msgstr "" + "Option disablembler khusus ARM berikut ini didukung untuk digunakan dengan\n" + "switch -M:\n" + +-#: avr-dis.c:118 avr-dis.c:128 ++#: avr-dis.c:115 avr-dis.c:125 ++#, c-format + msgid "undefined" + msgstr "tidak didefinisikan" + +-#: avr-dis.c:180 ++#: avr-dis.c:187 ++#, c-format + msgid "Internal disassembler error" + msgstr "Kesalahan disasembler internal" + +-#: avr-dis.c:228 ++#: avr-dis.c:236 + #, c-format + msgid "unknown constraint `%c'" + msgstr "konstrain tidak dikenal `%c'" + +-#: cgen-asm.c:346 fr30-ibld.c:195 m32r-ibld.c:195 openrisc-ibld.c:195 xstormy16-ibld.c:195 ++#: cgen-asm.c:336 fr30-ibld.c:200 frv-ibld.c:200 ip2k-ibld.c:200 ++#: iq2000-ibld.c:200 m32c-ibld.c:200 m32r-ibld.c:200 mep-ibld.c:200 ++#: mt-ibld.c:200 openrisc-ibld.c:200 xc16x-ibld.c:200 xstormy16-ibld.c:200 + #, c-format + msgid "operand out of range (%ld not between %ld and %ld)" + msgstr "operand keluar batas (%ld tidak antara %ld dan %ld)" + +-#: cgen-asm.c:367 ++#: cgen-asm.c:358 + #, c-format + msgid "operand out of range (%lu not between %lu and %lu)" + msgstr "operand keluar batas (%lu tidak antara %lu dan %lu)" + +-#: d30v-dis.c:312 ++#: d30v-dis.c:255 + #, c-format + msgid "" + msgstr "" + + #. Can't happen. +-#: dis-buf.c:57 ++#: dis-buf.c:59 + #, c-format + msgid "Unknown error %d\n" + msgstr "Kesalahan tidak dikenal %d\n" + +-#: dis-buf.c:62 ++#: dis-buf.c:68 + #, c-format +-msgid "Address 0x%x is out of bounds.\n" +-msgstr "Alamat 0x%x di luar batas.\n" ++msgid "Address 0x%s is out of bounds.\n" ++msgstr "Alamat 0x%s di luar jangkauan.\n" + +-#: fr30-asm.c:323 m32r-asm.c:325 openrisc-asm.c:244 xstormy16-asm.c:231 ++#: fr30-asm.c:93 m32c-asm.c:877 m32c-asm.c:884 ++msgid "Register number is not valid" ++msgstr "Nomor register tidak valid" ++ ++#: fr30-asm.c:95 ++msgid "Register must be between r0 and r7" ++msgstr "Register harus berada diantara r0 dan r7" ++ ++#: fr30-asm.c:97 ++msgid "Register must be between r8 and r15" ++msgstr "Register harus berada diantara r8 dan r15" ++ ++#: fr30-asm.c:116 m32c-asm.c:915 ++msgid "Register list is not valid" ++msgstr "Daftar register tidak valid" ++ ++#: fr30-asm.c:310 frv-asm.c:1263 ip2k-asm.c:511 iq2000-asm.c:459 ++#: m32c-asm.c:1589 m32r-asm.c:328 mep-asm.c:1001 mt-asm.c:595 ++#: openrisc-asm.c:241 xc16x-asm.c:376 xstormy16-asm.c:276 + #, c-format + msgid "Unrecognized field %d while parsing.\n" + msgstr "Field tidak dikenal %d saat parsing.\n" + +-#: fr30-asm.c:373 m32r-asm.c:375 openrisc-asm.c:294 xstormy16-asm.c:281 ++#: fr30-asm.c:361 frv-asm.c:1314 ip2k-asm.c:562 iq2000-asm.c:510 ++#: m32c-asm.c:1640 m32r-asm.c:379 mep-asm.c:1052 mt-asm.c:646 ++#: openrisc-asm.c:292 xc16x-asm.c:427 xstormy16-asm.c:327 + msgid "missing mnemonic in syntax string" + msgstr "mnemonik hilang dalam string sintaks" + + #. We couldn't parse it. +-#: fr30-asm.c:509 fr30-asm.c:513 fr30-asm.c:600 fr30-asm.c:702 m32r-asm.c:511 m32r-asm.c:515 m32r-asm.c:602 m32r-asm.c:704 openrisc-asm.c:430 openrisc-asm.c:434 openrisc-asm.c:521 openrisc-asm.c:623 xstormy16-asm.c:417 xstormy16-asm.c:421 xstormy16-asm.c:508 xstormy16-asm.c:610 ++#: fr30-asm.c:496 fr30-asm.c:500 fr30-asm.c:587 fr30-asm.c:688 frv-asm.c:1449 ++#: frv-asm.c:1453 frv-asm.c:1540 frv-asm.c:1641 ip2k-asm.c:697 ip2k-asm.c:701 ++#: ip2k-asm.c:788 ip2k-asm.c:889 iq2000-asm.c:645 iq2000-asm.c:649 ++#: iq2000-asm.c:736 iq2000-asm.c:837 m32c-asm.c:1775 m32c-asm.c:1779 ++#: m32c-asm.c:1866 m32c-asm.c:1967 m32r-asm.c:514 m32r-asm.c:518 ++#: m32r-asm.c:605 m32r-asm.c:706 mep-asm.c:1187 mep-asm.c:1191 mep-asm.c:1278 ++#: mep-asm.c:1379 mt-asm.c:781 mt-asm.c:785 mt-asm.c:872 mt-asm.c:973 ++#: openrisc-asm.c:427 openrisc-asm.c:431 openrisc-asm.c:518 openrisc-asm.c:619 ++#: xc16x-asm.c:562 xc16x-asm.c:566 xc16x-asm.c:653 xc16x-asm.c:754 ++#: xstormy16-asm.c:462 xstormy16-asm.c:466 xstormy16-asm.c:553 ++#: xstormy16-asm.c:654 + msgid "unrecognized instruction" + msgstr "instruksti tidak dikenal" + +-#: fr30-asm.c:556 m32r-asm.c:558 openrisc-asm.c:477 xstormy16-asm.c:464 ++#: fr30-asm.c:543 frv-asm.c:1496 ip2k-asm.c:744 iq2000-asm.c:692 ++#: m32c-asm.c:1822 m32r-asm.c:561 mep-asm.c:1234 mt-asm.c:828 ++#: openrisc-asm.c:474 xc16x-asm.c:609 xstormy16-asm.c:509 + #, c-format + msgid "syntax error (expected char `%c', found `%c')" + msgstr "kesalahan sintaks (diharapkan karakter `%c', ditemukan `%c')" + +-#: fr30-asm.c:566 m32r-asm.c:568 openrisc-asm.c:487 xstormy16-asm.c:474 ++#: fr30-asm.c:553 frv-asm.c:1506 ip2k-asm.c:754 iq2000-asm.c:702 ++#: m32c-asm.c:1832 m32r-asm.c:571 mep-asm.c:1244 mt-asm.c:838 ++#: openrisc-asm.c:484 xc16x-asm.c:619 xstormy16-asm.c:519 + #, c-format + msgid "syntax error (expected char `%c', found end of instruction)" + msgstr "kesalahan sintaks (diharapkan karakter `%c', ditemukan akhir instruksi)" + +-#: fr30-asm.c:594 m32r-asm.c:596 openrisc-asm.c:515 xstormy16-asm.c:502 ++#: fr30-asm.c:581 frv-asm.c:1534 ip2k-asm.c:782 iq2000-asm.c:730 ++#: m32c-asm.c:1860 m32r-asm.c:599 mep-asm.c:1272 mt-asm.c:866 ++#: openrisc-asm.c:512 xc16x-asm.c:647 xstormy16-asm.c:547 + msgid "junk at end of line" + msgstr "sampah di akhir baris" + +-#: fr30-asm.c:701 m32r-asm.c:703 openrisc-asm.c:622 xstormy16-asm.c:609 ++#: fr30-asm.c:687 frv-asm.c:1640 ip2k-asm.c:888 iq2000-asm.c:836 ++#: m32c-asm.c:1966 m32r-asm.c:705 mep-asm.c:1378 mt-asm.c:972 ++#: openrisc-asm.c:618 xc16x-asm.c:753 xstormy16-asm.c:653 + msgid "unrecognized form of instruction" + msgstr "bentuk instruksi tidak dikenal" + +-#: fr30-asm.c:713 m32r-asm.c:715 openrisc-asm.c:634 xstormy16-asm.c:621 ++#: fr30-asm.c:699 frv-asm.c:1652 ip2k-asm.c:900 iq2000-asm.c:848 ++#: m32c-asm.c:1978 m32r-asm.c:717 mep-asm.c:1390 mt-asm.c:984 ++#: openrisc-asm.c:630 xc16x-asm.c:765 xstormy16-asm.c:665 + #, c-format + msgid "bad instruction `%.50s...'" + msgstr "instruksi buruk `%.50s...'" + +-#: fr30-asm.c:716 m32r-asm.c:718 openrisc-asm.c:637 xstormy16-asm.c:624 ++#: fr30-asm.c:702 frv-asm.c:1655 ip2k-asm.c:903 iq2000-asm.c:851 ++#: m32c-asm.c:1981 m32r-asm.c:720 mep-asm.c:1393 mt-asm.c:987 ++#: openrisc-asm.c:633 xc16x-asm.c:768 xstormy16-asm.c:668 + #, c-format + msgid "bad instruction `%.50s'" + msgstr "instruksi buruk `%.50s'" + + #. Default text to print if an instruction isn't recognized. +-#: fr30-dis.c:39 m32r-dis.c:39 mmix-dis.c:282 openrisc-dis.c:39 xstormy16-dis.c:39 ++#: fr30-dis.c:41 frv-dis.c:41 ip2k-dis.c:41 iq2000-dis.c:41 m32c-dis.c:41 ++#: m32r-dis.c:41 mep-dis.c:41 mmix-dis.c:278 mt-dis.c:41 openrisc-dis.c:41 ++#: xc16x-dis.c:41 xstormy16-dis.c:41 + msgid "*unknown*" + msgstr "*tidak dikenal*" + +-#: fr30-dis.c:318 m32r-dis.c:249 openrisc-dis.c:136 xstormy16-dis.c:169 ++#: fr30-dis.c:299 frv-dis.c:396 ip2k-dis.c:288 iq2000-dis.c:189 m32c-dis.c:891 ++#: m32r-dis.c:256 mep-dis.c:776 mt-dis.c:290 openrisc-dis.c:135 ++#: xc16x-dis.c:375 xstormy16-dis.c:168 + #, c-format + msgid "Unrecognized field %d while printing insn.\n" + msgstr "Field tidak dikenal %d saat mencetak insn.\n" + +-#: fr30-ibld.c:166 m32r-ibld.c:166 openrisc-ibld.c:166 xstormy16-ibld.c:166 ++#: fr30-ibld.c:163 frv-ibld.c:163 ip2k-ibld.c:163 iq2000-ibld.c:163 ++#: m32c-ibld.c:163 m32r-ibld.c:163 mep-ibld.c:163 mt-ibld.c:163 ++#: openrisc-ibld.c:163 xc16x-ibld.c:163 xstormy16-ibld.c:163 + #, c-format + msgid "operand out of range (%ld not between %ld and %lu)" + msgstr "operand di luar batas (%ld tidak antara %ld dan %lu)" + +-#: fr30-ibld.c:179 m32r-ibld.c:179 openrisc-ibld.c:179 xstormy16-ibld.c:179 ++#: fr30-ibld.c:184 frv-ibld.c:184 ip2k-ibld.c:184 iq2000-ibld.c:184 ++#: m32c-ibld.c:184 m32r-ibld.c:184 mep-ibld.c:184 mt-ibld.c:184 ++#: openrisc-ibld.c:184 xc16x-ibld.c:184 xstormy16-ibld.c:184 + #, c-format +-msgid "operand out of range (%lu not between 0 and %lu)" +-msgstr "operand di luar batas (%lu tidak antara 0 dan %lu)" ++msgid "operand out of range (0x%lx not between 0 and 0x%lx)" ++msgstr "operand di luar batas (0x%lx tidak antara 0 dan 0x%lx)" + +-#: fr30-ibld.c:730 m32r-ibld.c:659 openrisc-ibld.c:633 xstormy16-ibld.c:678 ++#: fr30-ibld.c:726 frv-ibld.c:852 ip2k-ibld.c:603 iq2000-ibld.c:709 ++#: m32c-ibld.c:1727 m32r-ibld.c:661 mep-ibld.c:1024 mt-ibld.c:745 ++#: openrisc-ibld.c:629 xc16x-ibld.c:748 xstormy16-ibld.c:674 + #, c-format + msgid "Unrecognized field %d while building insn.\n" + msgstr "Field tidak dikenal %d saat membuild insn.\n" + +-#: fr30-ibld.c:937 m32r-ibld.c:792 openrisc-ibld.c:735 xstormy16-ibld.c:826 ++#: fr30-ibld.c:931 frv-ibld.c:1169 ip2k-ibld.c:678 iq2000-ibld.c:884 ++#: m32c-ibld.c:2888 m32r-ibld.c:798 mep-ibld.c:1444 mt-ibld.c:965 ++#: openrisc-ibld.c:729 xc16x-ibld.c:968 xstormy16-ibld.c:820 + #, c-format + msgid "Unrecognized field %d while decoding insn.\n" + msgstr "Field tidak dikenal %d saat mendekode insn.\n" + +-#: fr30-ibld.c:1086 m32r-ibld.c:902 openrisc-ibld.c:815 xstormy16-ibld.c:939 ++#: fr30-ibld.c:1077 frv-ibld.c:1447 ip2k-ibld.c:752 iq2000-ibld.c:1015 ++#: m32c-ibld.c:3505 m32r-ibld.c:911 mep-ibld.c:1737 mt-ibld.c:1165 ++#: openrisc-ibld.c:806 xc16x-ibld.c:1189 xstormy16-ibld.c:930 + #, c-format + msgid "Unrecognized field %d while getting int operand.\n" + msgstr "Field tidak dikenal %d saat memperoleh operand int.\n" + +-#: fr30-ibld.c:1215 m32r-ibld.c:992 openrisc-ibld.c:875 xstormy16-ibld.c:1032 ++#: fr30-ibld.c:1205 frv-ibld.c:1707 ip2k-ibld.c:808 iq2000-ibld.c:1128 ++#: m32c-ibld.c:4104 m32r-ibld.c:1006 mep-ibld.c:2012 mt-ibld.c:1347 ++#: openrisc-ibld.c:865 xc16x-ibld.c:1392 xstormy16-ibld.c:1022 + #, c-format + msgid "Unrecognized field %d while getting vma operand.\n" + msgstr "Field tidak dikenal %d saat memperoleh operand vma.\n" + +-#: fr30-ibld.c:1349 m32r-ibld.c:1090 openrisc-ibld.c:944 xstormy16-ibld.c:1134 ++#: fr30-ibld.c:1336 frv-ibld.c:1974 ip2k-ibld.c:867 iq2000-ibld.c:1248 ++#: m32c-ibld.c:4691 m32r-ibld.c:1107 mep-ibld.c:2271 mt-ibld.c:1536 ++#: openrisc-ibld.c:931 xc16x-ibld.c:1596 xstormy16-ibld.c:1121 + #, c-format + msgid "Unrecognized field %d while setting int operand.\n" + msgstr "Field tidak dikenal %d saat menset operand int.\n" + +-#: fr30-ibld.c:1471 m32r-ibld.c:1176 openrisc-ibld.c:1001 xstormy16-ibld.c:1224 ++#: fr30-ibld.c:1457 frv-ibld.c:2231 ip2k-ibld.c:916 iq2000-ibld.c:1358 ++#: m32c-ibld.c:5268 m32r-ibld.c:1198 mep-ibld.c:2520 mt-ibld.c:1715 ++#: openrisc-ibld.c:987 xc16x-ibld.c:1790 xstormy16-ibld.c:1210 + #, c-format + msgid "Unrecognized field %d while setting vma operand.\n" + msgstr "Field tidak dikenal %d saat menset operand vma.\n" + +-#: h8300-dis.c:384 ++#: frv-asm.c:608 ++msgid "missing `]'" ++msgstr "hilang `]'" ++ ++#: frv-asm.c:611 frv-asm.c:621 ++msgid "Special purpose register number is out of range" ++msgstr "Nomor register tujuan spesial di luar batas" ++ ++#: frv-asm.c:908 ++msgid "Value of A operand must be 0 or 1" ++msgstr "Nilai dari operand A harus berupa 0 atau 1" ++ ++#: frv-asm.c:944 ++msgid "register number must be even" ++msgstr "nomor register harus genap" ++ ++#. -- assembler routines inserted here. ++#. -- asm.c ++#: frv-asm.c:972 iq2000-asm.c:56 m32c-asm.c:141 m32c-asm.c:237 m32c-asm.c:279 ++#: m32c-asm.c:338 m32c-asm.c:360 m32r-asm.c:53 mep-asm.c:232 mep-asm.c:250 ++#: mep-asm.c:265 mep-asm.c:280 mep-asm.c:292 openrisc-asm.c:54 ++msgid "missing `)'" ++msgstr "hilang `)'" ++ ++#: h8300-dis.c:327 + #, c-format +-msgid "Hmmmm %x" +-msgstr "Hmmmm %x" ++msgid "Hmmmm 0x%x" ++msgstr "Hmmmm 0x%x" + +-#: h8300-dis.c:395 ++#: h8300-dis.c:708 + #, c-format +-msgid "Don't understand %x \n" +-msgstr "Tidak mengerti %x \n" ++msgid "Don't understand 0x%x \n" ++msgstr "Tidak mengerti 0x%x \n" + +-#: h8500-dis.c:143 ++#: h8500-dis.c:124 + #, c-format + msgid "can't cope with insert %d\n" + msgstr "tidak dapat menangani insert %d\n" + + #. Couldn't understand anything. +-#: h8500-dis.c:350 ++#: h8500-dis.c:324 + #, c-format + msgid "%02x\t\t*unknown*" + msgstr "%02x\t\t*tidak dikenal*" + +-#: i386-dis.c:1649 ++#: i386-dis.c:9545 + msgid "" + msgstr "" + +-#: m10200-dis.c:199 ++#: i386-dis.c:9776 ++#, c-format ++msgid "" ++"\n" ++"The following i386/x86-64 specific disassembler options are supported for use\n" ++"with the -M switch (multiple options should be separated by commas):\n" ++msgstr "" ++"\n" ++"Option disablembler khusus i386/x86-64 berikut ini didukung untuk digunakan dengan\n" ++"pilihan -M (pilihan double seharusnya dipisahkan dengan koma):\n" ++ ++#: i386-dis.c:9780 ++#, c-format ++msgid " x86-64 Disassemble in 64bit mode\n" ++msgstr " x86-64 Disasemble dalam mode 64bit\n" ++ ++#: i386-dis.c:9781 ++#, c-format ++msgid " i386 Disassemble in 32bit mode\n" ++msgstr " i386 Disassemble dalam mode 32bit\n" ++ ++#: i386-dis.c:9782 ++#, c-format ++msgid " i8086 Disassemble in 16bit mode\n" ++msgstr " i8086 Disassemble dalam mode 16bit\n" ++ ++#: i386-dis.c:9783 ++#, c-format ++msgid " att Display instruction in AT&T syntax\n" ++msgstr " att Tampilkan instruksi dalam sintaks AT&T\n" ++ ++#: i386-dis.c:9784 ++#, c-format ++msgid " intel Display instruction in Intel syntax\n" ++msgstr " intel Tampilkan instruksi dalam sintaks Intel\n" ++ ++#: i386-dis.c:9785 ++#, c-format ++msgid "" ++" att-mnemonic\n" ++" Display instruction in AT&T mnemonic\n" ++msgstr "" ++" att-mnemonic\n" ++" Tampilkan instruksi dalam mnemonic AT&T\n" ++ ++#: i386-dis.c:9787 ++#, c-format ++msgid "" ++" intel-mnemonic\n" ++" Display instruction in Intel mnemonic\n" ++msgstr "" ++" intel-mnemonic\n" ++" Tampilkan instruksi dalam mnemonic Intel\n" ++ ++#: i386-dis.c:9789 ++#, c-format ++msgid " addr64 Assume 64bit address size\n" ++msgstr " addr64 Asumsikan ukuran alamat 64bit\n" ++ ++#: i386-dis.c:9790 ++#, c-format ++msgid " addr32 Assume 32bit address size\n" ++msgstr " addr32 Asumsikan ukuran alamat 32bit\n" ++ ++#: i386-dis.c:9791 ++#, c-format ++msgid " addr16 Assume 16bit address size\n" ++msgstr " addr16 Asumsikan ukuran alamat 16bit\n" ++ ++#: i386-dis.c:9792 + #, c-format +-msgid "unknown\t0x%02x" +-msgstr "tidak dikenal\t0x%02x" ++msgid " data32 Assume 32bit data size\n" ++msgstr " data32 Asumsikan ukuran data 32bit\n" + +-#: m10200-dis.c:339 ++#: i386-dis.c:9793 ++#, c-format ++msgid " data16 Assume 16bit data size\n" ++msgstr " data16 Asumsikan ukuran data 16bit\n" ++ ++#: i386-dis.c:9794 ++#, c-format ++msgid " suffix Always display instruction suffix in AT&T syntax\n" ++msgstr " akhiran Selalu tampilkan akhiran instruksi dalam sintaks AT&T\n" ++ ++#: i386-gen.c:411 ia64-gen.c:307 ++#, c-format ++msgid "%s: Error: " ++msgstr "%s: Error: " ++ ++#: i386-gen.c:510 ++#, c-format ++msgid "%s: %d: Unknown bitfield: %s\n" ++msgstr "%s: %d: bitfield tidak diketahui: %s\n" ++ ++#: i386-gen.c:674 ++#, c-format ++msgid "can't find i386-opc.tbl for reading, errno = %s\n" ++msgstr "tidak dapat menemukan i386-opc.tbl untuk pembacaan, nomor error = %s\n" ++ ++#: i386-gen.c:851 ++#, c-format ++msgid "can't find i386-reg.tbl for reading, errno = %s\n" ++msgstr "tidak dapat menemukan i386-reg.tbl untuk pembacaan, nomor error = %s\n" ++ ++#: i386-gen.c:943 ++#, c-format ++msgid "can't create i386-init.h, errno = %s\n" ++msgstr "tidak dapat membuat i386-init.h, nomor error = %s\n" ++ ++#: i386-gen.c:1032 ia64-gen.c:2850 ++#, c-format ++msgid "unable to change directory to \"%s\", errno = %s\n" ++msgstr "tidak dapat mengubah direktori ke \"%s\", nomor error = %s\n" ++ ++#: i386-gen.c:1039 ++#, c-format ++msgid "%d unused bits in i386_cpu_flags.\n" ++msgstr "%d bit tidak digunakan dalam i386_cpu_flags.\n" ++ ++#: i386-gen.c:1046 ++#, c-format ++msgid "%d unused bits in i386_operand_type.\n" ++msgstr "%d bit tidak digunakan dalam i386_operand_type.\n" ++ ++#: i386-gen.c:1060 ++#, c-format ++msgid "can't create i386-tbl.h, errno = %s\n" ++msgstr "tidak dapat membuat i386-tbl.h, nomor error = %s\n" ++ ++#: ia64-gen.c:320 ++#, c-format ++msgid "%s: Warning: " ++msgstr "%s: Peringatan: " ++ ++#: ia64-gen.c:506 ia64-gen.c:740 ++#, c-format ++msgid "multiple note %s not handled\n" ++msgstr "catatan ganda %s tidak ditangani\n" ++ ++#: ia64-gen.c:617 ++msgid "can't find ia64-ic.tbl for reading\n" ++msgstr "tidak dapat menemukan ia64-ic.tbl untuk pembacaan\n" ++ ++#: ia64-gen.c:822 ++#, c-format ++msgid "can't find %s for reading\n" ++msgstr "tidak dapat menemukan %s untuk pembacaan\n" ++ ++#: ia64-gen.c:1046 ++#, c-format ++msgid "" ++"most recent format '%s'\n" ++"appears more restrictive than '%s'\n" ++msgstr "" ++"format paling baru '%s'\n" ++"tampak lebih terbatas dari '%s'\n" ++ ++#: ia64-gen.c:1057 ++#, c-format ++msgid "overlapping field %s->%s\n" ++msgstr "daerah saling menimpa %s->%s\n" ++ ++#: ia64-gen.c:1254 ++#, c-format ++msgid "overwriting note %d with note %d (IC:%s)\n" ++msgstr "catatan saling menulis %d dengan catatan %d (IC:%s)\n" ++ ++#: ia64-gen.c:1459 ++#, c-format ++msgid "don't know how to specify %% dependency %s\n" ++msgstr "tidak tahu bagaimana menspesifikasikan %% ketergantungan %s\n" ++ ++#: ia64-gen.c:1481 ++#, c-format ++msgid "Don't know how to specify # dependency %s\n" ++msgstr "Tidak tahu bagaimana menspesifikasikan # ketergantungan %s\n" ++ ++#: ia64-gen.c:1520 ++#, c-format ++msgid "IC:%s [%s] has no terminals or sub-classes\n" ++msgstr "IC:%s [%s] tidak memiliki terminal atau sub-kelas\n" ++ ++#: ia64-gen.c:1523 ++#, c-format ++msgid "IC:%s has no terminals or sub-classes\n" ++msgstr "IC:%s tidak memiliki terminal atau sub-kelas\n" ++ ++#: ia64-gen.c:1532 ++#, c-format ++msgid "no insns mapped directly to terminal IC %s [%s]" ++msgstr "tidak ada insns terpetakan secara langsung ke terminal IC %s [%s]" ++ ++#: ia64-gen.c:1535 ++#, c-format ++msgid "no insns mapped directly to terminal IC %s\n" ++msgstr "tidak ada insns terpetakan langsung ke terminal IC %s\n" ++ ++#: ia64-gen.c:1546 ++#, c-format ++msgid "class %s is defined but not used\n" ++msgstr "kelas %s didefinisikan tetapi tidak digunakan\n" ++ ++#: ia64-gen.c:1559 ++#, c-format ++msgid "Warning: rsrc %s (%s) has no chks\n" ++msgstr "Peringatan: rsrc %s (%s) tidak memiliki chks\n" ++ ++#: ia64-gen.c:1562 ++#, c-format ++msgid "Warning: rsrc %s (%s) has no chks or regs\n" ++msgstr "Peringatan: rsrc %s (%s) tidak memiliki chks atau regs\n" ++ ++#: ia64-gen.c:1566 ++#, c-format ++msgid "rsrc %s (%s) has no regs\n" ++msgstr "rsrc %s (%s) tidak memiliki regs\n" ++ ++#: ia64-gen.c:2478 ++#, c-format ++msgid "IC note %d in opcode %s (IC:%s) conflicts with resource %s note %d\n" ++msgstr "IC catatan %d dalam opcode %s (IC:%s) konflik dengan sumber daya %s catatan %d\n" ++ ++#: ia64-gen.c:2506 ++#, c-format ++msgid "IC note %d for opcode %s (IC:%s) conflicts with resource %s note %d\n" ++msgstr "IC catatan %d untuk opcode %s (IC:%s) konflik dengan sumber data %s catatan %d\n" ++ ++#: ia64-gen.c:2520 ++#, c-format ++msgid "opcode %s has no class (ops %d %d %d)\n" ++msgstr "opcode %s tidak memiliki kelas (ops %d %d %d)\n" ++ ++#. We've been passed a w. Return with an error message so that ++#. cgen will try the next parsing option. ++#: ip2k-asm.c:81 ++msgid "W keyword invalid in FR operand slot." ++msgstr "W kata kunci tidak valid dalam FR operand slot." ++ ++#. Invalid offset present. ++#: ip2k-asm.c:106 ++msgid "offset(IP) is not a valid form" ++msgstr "offset(IP) bukan sebuah bentuk valid" ++ ++#. Found something there in front of (DP) but it's out ++#. of range. ++#: ip2k-asm.c:154 ++msgid "(DP) offset out of range." ++msgstr "(DP) ofset di luar batas." ++ ++#. Found something there in front of (SP) but it's out ++#. of range. ++#: ip2k-asm.c:195 ++msgid "(SP) offset out of range." ++msgstr "(SP) ofset di luar batas." ++ ++#: ip2k-asm.c:211 ++msgid "illegal use of parentheses" ++msgstr "penggunaan tidak legal dari tanda petik" ++ ++#: ip2k-asm.c:218 ++msgid "operand out of range (not between 1 and 255)" ++msgstr "operand di luar batas (tidak antara 1 dan 255)" ++ ++#. Something is very wrong. opindex has to be one of the above. ++#: ip2k-asm.c:242 ++msgid "parse_addr16: invalid opindex." ++msgstr "parse_addr16: opindex tidak valid." ++ ++#: ip2k-asm.c:296 ++msgid "Byte address required. - must be even." ++msgstr "Alamat byte dibutuhkan. - harus genap." ++ ++#: ip2k-asm.c:305 ++msgid "cgen_parse_address returned a symbol. Literal required." ++msgstr "cgen_parse_address mengembalikan sebuah simbol. Literal dibutuhkan." ++ ++#: ip2k-asm.c:360 ++msgid "percent-operator operand is not a symbol" ++msgstr "percent-operator operand bukan sebuah simbol" ++ ++#: ip2k-asm.c:413 ++msgid "Attempt to find bit index of 0" ++msgstr "Mencoba untuk menemukan bit index dari 0" ++ ++#: iq2000-asm.c:112 iq2000-asm.c:142 ++msgid "immediate value cannot be register" ++msgstr "nilai langsung tidak dapat berupa register" ++ ++#: iq2000-asm.c:123 iq2000-asm.c:153 ++msgid "immediate value out of range" ++msgstr "nilai langsung di luar batas" ++ ++#: iq2000-asm.c:182 ++msgid "21-bit offset out of range" ++msgstr "21-bit ofset di luar batas" ++ ++#: m10200-dis.c:158 m10300-dis.c:582 + #, c-format + msgid "unknown\t0x%04lx" + msgstr "tidak dikenal\t0x%04lx" + +-#: m10300-dis.c:685 ++#: m10200-dis.c:328 + #, c-format +-msgid "unknown\t0x%04x" +-msgstr "tidak dikenal\t0x%04x" ++msgid "unknown\t0x%02lx" ++msgstr "tidak dikenal\t0x%02lx" ++ ++#: m32c-asm.c:117 ++msgid "imm:6 immediate is out of range" ++msgstr "imm:6 nilai langsung di luar batas" + +-#: m68k-dis.c:429 ++#: m32c-asm.c:147 + #, c-format +-msgid "\n" +-msgstr "\n" ++msgid "%dsp8() takes a symbolic address, not a number" ++msgstr "%dsp8() mengambil sebuah alamat simbolik, bukan sebuah angka" ++ ++#: m32c-asm.c:160 m32c-asm.c:164 m32c-asm.c:255 ++msgid "dsp:8 immediate is out of range" ++msgstr "dsp:8 nilai langsung di luar batas" ++ ++#: m32c-asm.c:185 m32c-asm.c:189 ++msgid "Immediate is out of range -8 to 7" ++msgstr "nilai langsung di luar dari jangkauan -8 ke 7" ++ ++#: m32c-asm.c:210 m32c-asm.c:214 ++msgid "Immediate is out of range -7 to 8" ++msgstr "nilai langsung di luar dari jangkauan -7 ke 8" ++ ++#: m32c-asm.c:285 ++#, c-format ++msgid "%dsp16() takes a symbolic address, not a number" ++msgstr "%dsp16() mengambil sebuah alamat simbolik, tetapi bukan sebuah angka" ++ ++#: m32c-asm.c:308 m32c-asm.c:315 m32c-asm.c:378 ++msgid "dsp:16 immediate is out of range" ++msgstr "dsp:16 nilai langsung di luar batas" ++ ++#: m32c-asm.c:404 ++msgid "dsp:20 immediate is out of range" ++msgstr "dsp:20 nilai langsung di luar batas" ++ ++#: m32c-asm.c:430 m32c-asm.c:450 ++msgid "dsp:24 immediate is out of range" ++msgstr "dsp:24 nilai langsung di luar batas" ++ ++#: m32c-asm.c:483 ++msgid "immediate is out of range 1-2" ++msgstr "nilai langsung di luar dari jangkauan 1-2" ++ ++#: m32c-asm.c:501 ++msgid "immediate is out of range 1-8" ++msgstr "nilai langsung di luar dari jangkauan 1-8" ++ ++#: m32c-asm.c:519 ++msgid "immediate is out of range 0-7" ++msgstr "nilai langsung di luar dari jangkauan 0-7" ++ ++#: m32c-asm.c:555 ++msgid "immediate is out of range 2-9" ++msgstr "nilai langsung di luar dari jangkauan 2-9" + +-#: m68k-dis.c:1007 ++#: m32c-asm.c:573 ++msgid "Bit number for indexing general register is out of range 0-15" ++msgstr "Nomor bit untuk register umum pengindeksan diluar dari jangkauan 0-15" ++ ++#: m32c-asm.c:611 m32c-asm.c:667 ++msgid "bit,base is out of range" ++msgstr "bit,bas di luar batas" ++ ++#: m32c-asm.c:618 m32c-asm.c:623 m32c-asm.c:671 ++msgid "bit,base out of range for symbol" ++msgstr "bit,base di luar dari jangkauan untuk simbol" ++ ++#: m32c-asm.c:807 ++msgid "not a valid r0l/r0h pair" ++msgstr "bukan sebuah valid pasangan r0l/r0h" ++ ++#: m32c-asm.c:837 ++msgid "Invalid size specifier" ++msgstr "Ukuran penspesifikasi tidak valid" ++ ++#: m68k-dis.c:1163 + #, c-format + msgid "" + msgstr "" + +-#: m88k-dis.c:255 ++#: m68k-dis.c:1320 ++#, c-format ++msgid "\n" ++msgstr "\n" ++ ++#: m88k-dis.c:679 ++#, c-format ++msgid "# " ++msgstr "# " ++ ++#: mep-asm.c:114 ++msgid "Only $tp or $13 allowed for this opcode" ++msgstr "Hanya $tp atau $13 diperbolehkan untuk opcode ini" ++ ++#: mep-asm.c:128 ++msgid "Only $sp or $15 allowed for this opcode" ++msgstr "Hanya $sp atau $15 diperbolehkan untuk opcode ini" ++ ++#: mep-asm.c:299 mep-asm.c:455 ++#, c-format ++msgid "invalid %function() here" ++msgstr "%function disini tidak valid" ++ ++#: mips-dis.c:781 ++msgid "# internal error, incomplete extension sequence (+)" ++msgstr "# internal error, urutan ekstensi (+) tidak lengkap" ++ ++#: mips-dis.c:915 + #, c-format +-msgid "# " +-msgstr "# " ++msgid "# internal error, undefined extension sequence (+%c)" ++msgstr "# kesalahan internal, tidak terdefinisi urutan ekstensi(+%c)" + +-#: mips-dis.c:290 ++#: mips-dis.c:1274 + #, c-format +-msgid "# internal error, undefined modifier(%c)" +-msgstr "# kesalahan internal, modifier tidak didefinisikan(%c)" ++msgid "# internal error, undefined modifier (%c)" ++msgstr "# kesalahan internal, tidak terdefinisi pemodifikasi(%c)" + +-#: mips-dis.c:1154 ++#: mips-dis.c:1881 + #, c-format + msgid "# internal disassembler error, unrecognised modifier (%c)" + msgstr "# kesalahan internal disasembler, modifier tidak dikenal (%c)" + +-#: mmix-dis.c:34 ++#: mips-dis.c:2112 ++#, c-format ++msgid "" ++"\n" ++"The following MIPS specific disassembler options are supported for use\n" ++"with the -M switch (multiple options should be separated by commas):\n" ++msgstr "" ++"\n" ++"Pilihan disablembler khusus MIPS berikut ini didukung untuk digunakan dengan\n" ++"pilihan -M (pilihan ganda seharusnya dipisahkan dengan koma):\n" ++ ++#: mips-dis.c:2116 ++#, c-format ++msgid "" ++"\n" ++" gpr-names=ABI Print GPR names according to specified ABI.\n" ++" Default: based on binary being disassembled.\n" ++msgstr "" ++"\n" ++" gpr-names=ABI Tampilkan nama GPR menurut ABI yang dispesifikasikan.\n" ++" Baku: berdasar dari binari yang sedang diassembled.\n" ++ ++#: mips-dis.c:2120 ++#, c-format ++msgid "" ++"\n" ++" fpr-names=ABI Print FPR names according to specified ABI.\n" ++" Default: numeric.\n" ++msgstr "" ++"\n" ++" fpr-names=ABI Tampilkan nama FPR menurut ABI yang dispesifikasikan.\n" ++" Baku: numerik.\n" ++ ++#: mips-dis.c:2124 ++#, c-format ++msgid "" ++"\n" ++" cp0-names=ARCH Print CP0 register names according to\n" ++" specified architecture.\n" ++" Default: based on binary being disassembled.\n" ++msgstr "" ++"\n" ++" cp0-names=ARCH Tampilkan nama register CP0 menurut arsitektur\n" ++" yang dispesifikasikan.\n" ++" Baku: berdasar dari binari yang sedang diassembled.\n" ++ ++#: mips-dis.c:2129 ++#, c-format ++msgid "" ++"\n" ++" hwr-names=ARCH Print HWR names according to specified \n" ++"\t\t\t architecture.\n" ++" Default: based on binary being disassembled.\n" ++msgstr "" ++"\n" ++" hwr-names=ARCH Tampilkan nama HWR menurut arsitektur\n" ++"\t\t\t yang dispesifikasikan.\n" ++" Baku: berdasar dari binari yang sedang diassembled.\n" ++ ++#: mips-dis.c:2134 ++#, c-format ++msgid "" ++"\n" ++" reg-names=ABI Print GPR and FPR names according to\n" ++" specified ABI.\n" ++msgstr "" ++"\n" ++" reg-names=ABI Tampilkan nama GPR dan FPR menurut ABI yang\n" ++" dispesifikasikan.\n" ++ ++#: mips-dis.c:2138 ++#, c-format ++msgid "" ++"\n" ++" reg-names=ARCH Print CP0 register and HWR names according to\n" ++" specified architecture.\n" ++msgstr "" ++"\n" ++" reg-names=ARCH Tampilkan nama register CP0 dan HWR menurut\n" ++" arsitektur yang dispesifikasikan.\n" ++ ++#: mips-dis.c:2142 ++#, c-format ++msgid "" ++"\n" ++" For the options above, the following values are supported for \"ABI\":\n" ++" " ++msgstr "" ++"\n" ++" Untuk pilihan diatas, nilai berikut didukung untuk \"ABI\":\n" ++" " ++ ++#: mips-dis.c:2147 mips-dis.c:2155 mips-dis.c:2157 ++#, c-format ++msgid "\n" ++msgstr "\n" ++ ++#: mips-dis.c:2149 ++#, c-format ++msgid "" ++"\n" ++" For the options above, The following values are supported for \"ARCH\":\n" ++" " ++msgstr "" ++"\n" ++" Untuk pilihan diatas, nilai berikut didukung untuk \"ARCH\":\n" ++" " ++ ++#: mmix-dis.c:35 + #, c-format + msgid "Bad case %d (%s) in %s:%d\n" + msgstr "Case buruk %d (%s) dalam %s:%d\n" + +-#: mmix-dis.c:44 ++#: mmix-dis.c:45 + #, c-format + msgid "Internal: Non-debugged code (test-case missing): %s:%d" + msgstr "Internal: Kode belum didebug (tidak ada test-case): %s:%d" + +-#: mmix-dis.c:53 ++#: mmix-dis.c:54 + msgid "(unknown)" + msgstr "(tidak dikenal)" + +-#: mmix-dis.c:517 ++#: mmix-dis.c:513 + #, c-format + msgid "*unknown operands type: %d*" + msgstr "*tipe operand tidak dikenal: %d*" + ++#: mt-asm.c:110 mt-asm.c:190 ++msgid "Operand out of range. Must be between -32768 and 32767." ++msgstr "Operand di luar batas. Harus berada diantara -32768 dan 32767." ++ ++#: mt-asm.c:149 ++msgid "Biiiig Trouble in parse_imm16!" ++msgstr "Masalah BESAR dalam parse_imm16!" ++ ++#: mt-asm.c:157 ++msgid "The percent-operator's operand is not a symbol" ++msgstr "Operand percent-operator bukan sebuah simbol" ++ ++#: mt-asm.c:395 ++msgid "invalid operand. type may have values 0,1,2 only." ++msgstr "operand tidak valid. tipe mungkin hanya memiliki nilai 0,1,2." ++ + #. I and Z are output operands and can`t be immediate +-#. * A is an address and we can`t have the address of +-#. * an immediate either. We don't know how much to increase +-#. * aoffsetp by since whatever generated this is broken +-#. * anyway! +-#. +-#: ns32k-dis.c:628 ++#. A is an address and we can`t have the address of ++#. an immediate either. We don't know how much to increase ++#. aoffsetp by since whatever generated this is broken ++#. anyway! ++#: ns32k-dis.c:534 ++#, c-format + msgid "$" + msgstr "$" + +-#: ppc-opc.c:765 ppc-opc.c:798 ++#: ppc-opc.c:862 ppc-opc.c:890 + msgid "invalid conditional option" + msgstr "option kondisional tidak valid" + +-#: ppc-opc.c:800 ++#: ppc-opc.c:892 + msgid "attempt to set y bit when using + or - modifier" + msgstr "berusaha menset bit y saat menggunakan modifier + atau -" + +-#: ppc-opc.c:832 ppc-opc.c:884 +-msgid "offset not a multiple of 4" +-msgstr "offset bukan kelipatan 4" +- +-#: ppc-opc.c:857 +-msgid "offset not between -2048 and 2047" +-msgstr "offset tidak berada antara -2048 dan 2047" +- +-#: ppc-opc.c:882 +-msgid "offset not between -8192 and 8191" +-msgstr "offset tidak berada antara -8192 dan 8191" ++#: ppc-opc.c:924 ++msgid "invalid mask field" ++msgstr "topeng daerah tidak valid" + +-#: ppc-opc.c:910 +-msgid "ignoring least significant bits in branch offset" +-msgstr "mengabaikan least significant bit dalam offset cabang" ++#: ppc-opc.c:950 ++msgid "ignoring invalid mfcr mask" ++msgstr "mengabaikan topeng mfcr tidak valid" + +-#: ppc-opc.c:944 ppc-opc.c:981 ++#: ppc-opc.c:1000 ppc-opc.c:1035 + msgid "illegal bitmask" + msgstr "bitmask ilegal" + +-#: ppc-opc.c:1054 +-msgid "value out of range" +-msgstr "nilai di luar batas" +- +-#: ppc-opc.c:1130 ++#: ppc-opc.c:1155 + msgid "index register in load range" + msgstr "register indeks dalam daerah pemuatan" + +-#: ppc-opc.c:1146 ++#: ppc-opc.c:1171 ++msgid "source and target register operands must be different" ++msgstr "sumber dan target operand register harus berbeda" ++ ++#: ppc-opc.c:1186 + msgid "invalid register operand when updating" + msgstr "operand register tidak valid saat mengupdate" + +-#. Mark as non-valid instruction +-#: sparc-dis.c:750 +-msgid "unknown" +-msgstr "tidak dikenal" ++#: ppc-opc.c:1265 ++msgid "invalid sprg number" ++msgstr "nomor sprg tidak valid" ++ ++#: s390-dis.c:276 ++#, c-format ++msgid "" ++"\n" ++"The following S/390 specific disassembler options are supported for use\n" ++"with the -M switch (multiple options should be separated by commas):\n" ++msgstr "" ++"\n" ++"Pilihan disablembler khusus S/390 berikut ini didukung untuk digunakan dengan\n" ++"pilihan -M (pilihan ganda seharusnya dipisahkan dengan koma):\n" ++ ++#: s390-dis.c:280 ++#, c-format ++msgid " esa Disassemble in ESA architecture mode\n" ++msgstr " esa Disassemble dalam mode arsitektur ESA\n" + +-#: sparc-dis.c:825 ++#: s390-dis.c:281 ++#, c-format ++msgid " zarch Disassemble in z/Architecture mode\n" ++msgstr " zarch Disassemble dalam mode z/Architecture\n" ++ ++#: score-dis.c:220 score-dis.c:383 ++msgid "" ++msgstr "" ++ ++#: sparc-dis.c:282 + #, c-format + msgid "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n" + msgstr "Kesalahan internal: sparc-opcode.h buruk: \"%s\", %#.8lx, %#.8lx\n" + +-#: sparc-dis.c:836 ++#: sparc-dis.c:293 + #, c-format + msgid "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n" + msgstr "Kesalahan internal: sparc-opcode.h buruk: \"%s\", %#.8lx, %#.8lx\n" + +-#: sparc-dis.c:885 ++#: sparc-dis.c:343 + #, c-format + msgid "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n" + msgstr "Kesalahan internal: sparc-opcode.h buruk: \"%s\" == \"%s\"\n" + +-#: v850-dis.c:224 ++#. Mark as non-valid instruction. ++#: sparc-dis.c:1013 ++msgid "unknown" ++msgstr "tidak dikenal" ++ ++#: v850-dis.c:239 + #, c-format + msgid "unknown operand shift: %x\n" + msgstr "shift operand tidak dikenal: %x\n" + +-#: v850-dis.c:236 ++#: v850-dis.c:253 + #, c-format + msgid "unknown pop reg: %d\n" + msgstr "reg pop tidak dikenal: %d\n" +@@ -350,74 +1059,122 @@ msgstr "reg pop tidak dikenal: %d\n" + #. v850_insert_operand() in gas/config/tc-v850.c. Error messages + #. containing the string 'out of range' will be ignored unless a + #. specific command line option is given to GAS. +-#: v850-opc.c:68 ++#: v850-opc.c:48 + msgid "displacement value is not in range and is not aligned" + msgstr "nilai displacement tidak dalam jangkauan dan tidak rata" + +-#: v850-opc.c:69 ++#: v850-opc.c:49 + msgid "displacement value is out of range" + msgstr "nilai displacement di luar batas" + +-#: v850-opc.c:70 ++#: v850-opc.c:50 + msgid "displacement value is not aligned" + msgstr "nilai displacement tidak rata" + +-#: v850-opc.c:72 ++#: v850-opc.c:52 + msgid "immediate value is out of range" + msgstr "nilai langsung di luar batas" + +-#: v850-opc.c:83 ++#: v850-opc.c:60 + msgid "branch value not in range and to odd offset" + msgstr "nilai cabang tidak dalam jangkauan" + +-#: v850-opc.c:85 v850-opc.c:117 ++#: v850-opc.c:62 v850-opc.c:89 + msgid "branch value out of range" + msgstr "nilai cabang di luar jangkauan" + +-#: v850-opc.c:88 v850-opc.c:120 ++#: v850-opc.c:65 v850-opc.c:92 + msgid "branch to odd offset" + msgstr "cabang offset ganjil" + +-#: v850-opc.c:115 ++#: v850-opc.c:87 + msgid "branch value not in range and to an odd offset" + msgstr "nilai cabang di luar jangkauan dan offset ganjil" + +-#: v850-opc.c:346 ++#: v850-opc.c:279 + msgid "invalid register for stack adjustment" + msgstr "register tidak valid untuk penyesuaian stack" + +-#: v850-opc.c:370 ++#: v850-opc.c:299 + msgid "immediate value not in range and not even" + msgstr "nilai langsung tidak dalam jangkauan dan tidak genap" + +-#: v850-opc.c:375 ++#: v850-opc.c:304 + msgid "immediate value must be even" + msgstr "nilai langsung harus genap" + +-#: xstormy16-asm.c:74 ++#: xc16x-asm.c:66 ++msgid "Missing '#' prefix" ++msgstr "Hilang awalan '#'" ++ ++#: xc16x-asm.c:82 ++msgid "Missing '.' prefix" ++msgstr "Hilang awalan '.'" ++ ++#: xc16x-asm.c:98 ++msgid "Missing 'pof:' prefix" ++msgstr "Hilang awalan 'pof:'" ++ ++#: xc16x-asm.c:114 ++msgid "Missing 'pag:' prefix" ++msgstr "Hilang awalan 'pag:'" ++ ++#: xc16x-asm.c:130 ++msgid "Missing 'sof:' prefix" ++msgstr "Hilang awalan 'sof:'" ++ ++#: xc16x-asm.c:146 ++msgid "Missing 'seg:' prefix" ++msgstr "Hilanga awalan 'seg:'" ++ ++#: xstormy16-asm.c:71 + msgid "Bad register in preincrement" + msgstr "register buruk dalam preinkremen" + +-#: xstormy16-asm.c:79 ++#: xstormy16-asm.c:76 + msgid "Bad register in postincrement" + msgstr "Register buruk dalam pascainkremen" + +-#: xstormy16-asm.c:81 ++#: xstormy16-asm.c:78 + msgid "Bad register name" + msgstr "Nama register buruk" + +-#: xstormy16-asm.c:85 ++#: xstormy16-asm.c:82 + msgid "Label conflicts with register name" + msgstr "Label konflik dengan nama register" + +-#: xstormy16-asm.c:89 ++#: xstormy16-asm.c:86 + msgid "Label conflicts with `Rx'" + msgstr "Label konflik dengan `Rx'" + +-#: xstormy16-asm.c:91 ++#: xstormy16-asm.c:88 + msgid "Bad immediate expression" + msgstr "Ekspresi langsung yang buruk" + +-#: xstormy16-asm.c:120 ++#: xstormy16-asm.c:109 ++msgid "No relocation for small immediate" ++msgstr "Tidak ada relokasi untuk immediate kecil" ++ ++#: xstormy16-asm.c:119 + msgid "Small operand was not an immediate number" + msgstr "Operand kecil bukan sebuah angka immediate" ++ ++#: xstormy16-asm.c:157 ++msgid "Operand is not a symbol" ++msgstr "Operand bukan sebuah simbol" ++ ++#: xstormy16-asm.c:165 ++msgid "Syntax error: No trailing ')'" ++msgstr "Sintaks error: Tidak ada akhiran ')'" ++ ++#~ msgid "unknown\t0x%04x" ++#~ msgstr "tidak dikenal\t0x%04x" ++ ++#~ msgid "offset not between -2048 and 2047" ++#~ msgstr "offset tidak berada antara -2048 dan 2047" ++ ++#~ msgid "offset not between -8192 and 8191" ++#~ msgstr "offset tidak berada antara -8192 dan 8191" ++ ++#~ msgid "ignoring least significant bits in branch offset" ++#~ msgstr "mengabaikan least significant bit dalam offset cabang" +diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c +index 9a28338..8511345 100644 +--- a/opcodes/ppc-dis.c ++++ b/opcodes/ppc-dis.c +@@ -1,6 +1,6 @@ + /* ppc-dis.c -- Disassemble PowerPC instructions + Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +- 2008 Free Software Foundation, Inc. ++ 2008, 2009 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + + This file is part of the GNU opcodes library. +@@ -23,6 +23,7 @@ + #include + #include "sysdep.h" + #include "dis-asm.h" ++#include "opintl.h" + #include "opcode/ppc.h" + + /* This file provides several disassembler functions, all of which use +@@ -42,94 +43,198 @@ struct dis_private + #define POWERPC_DIALECT(INFO) \ + (((struct dis_private *) ((INFO)->private_data))->dialect) + +-/* Determine which set of machines to disassemble for. PPC403/601 or +- BookE. For convenience, also disassemble instructions supported +- by the AltiVec vector unit. */ ++struct ppc_mopt { ++ const char *opt; ++ ppc_cpu_t cpu; ++ ppc_cpu_t sticky; ++}; ++ ++struct ppc_mopt ppc_opts[] = { ++ { "403", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_403 ++ | PPC_OPCODE_32), ++ 0 }, ++ { "405", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_403 ++ | PPC_OPCODE_405 | PPC_OPCODE_32), ++ 0 }, ++ { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32 ++ | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI), ++ 0 }, ++ { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32 ++ | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI), ++ 0 }, ++ { "601", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_601 ++ | PPC_OPCODE_32), ++ 0 }, ++ { "603", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32), ++ 0 }, ++ { "604", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32), ++ 0 }, ++ { "620", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64), ++ 0 }, ++ { "7400", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC ++ | PPC_OPCODE_32), ++ 0 }, ++ { "7410", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC ++ | PPC_OPCODE_32), ++ 0 }, ++ { "7450", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC ++ | PPC_OPCODE_32), ++ 0 }, ++ { "7455", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC ++ | PPC_OPCODE_32), ++ 0 }, ++ { "750cl", (PPC_OPCODE_PPC | PPC_OPCODE_PPCPS) ++ , 0 }, ++ { "altivec", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC), ++ PPC_OPCODE_ALTIVEC }, ++ { "any", 0, ++ PPC_OPCODE_ANY }, ++ { "booke", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32), ++ 0 }, ++ { "booke32", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32), ++ 0 }, ++ { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64 ++ | PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC), ++ 0 }, ++ { "com", (PPC_OPCODE_COMMON | PPC_OPCODE_32), ++ 0 }, ++ { "e300", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32 ++ | PPC_OPCODE_E300), ++ 0 }, ++ { "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE ++ | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK ++ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI ++ | PPC_OPCODE_E500MC), ++ 0 }, ++ { "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL ++ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI ++ | PPC_OPCODE_E500MC), ++ 0 }, ++ { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE ++ | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK ++ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI ++ | PPC_OPCODE_E500MC), ++ 0 }, ++ { "efs", (PPC_OPCODE_PPC | PPC_OPCODE_EFS), ++ 0 }, ++ { "power4", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64 ++ | PPC_OPCODE_POWER4), ++ 0 }, ++ { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64 ++ | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5), ++ 0 }, ++ { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64 ++ | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 ++ | PPC_OPCODE_ALTIVEC), ++ 0 }, ++ { "power7", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ISEL ++ | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 ++ | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC ++ | PPC_OPCODE_VSX), ++ 0 }, ++ { "ppc", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32), ++ 0 }, ++ { "ppc32", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32), ++ 0 }, ++ { "ppc64", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64), ++ 0 }, ++ { "ppc64bridge", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64_BRIDGE ++ | PPC_OPCODE_64), ++ 0 }, ++ { "ppcps", (PPC_OPCODE_PPC | PPC_OPCODE_PPCPS), ++ 0 }, ++ { "pwr", (PPC_OPCODE_POWER | PPC_OPCODE_32), ++ 0 }, ++ { "pwr2", (PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32), ++ 0 }, ++ { "pwrx", (PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32), ++ 0 }, ++ { "spe", (PPC_OPCODE_PPC | PPC_OPCODE_EFS), ++ PPC_OPCODE_SPE }, ++ { "vsx", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC), ++ PPC_OPCODE_VSX }, ++}; ++ ++/* Handle -m and -M options that set cpu type, and .machine arg. */ ++ ++ppc_cpu_t ++ppc_parse_cpu (ppc_cpu_t ppc_cpu, const char *arg) ++{ ++ /* Sticky bits. */ ++ ppc_cpu_t retain_flags = ppc_cpu & (PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX ++ | PPC_OPCODE_SPE | PPC_OPCODE_ANY); ++ unsigned int i; ++ ++ for (i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++) ++ if (strcmp (ppc_opts[i].opt, arg) == 0) ++ { ++ if (ppc_opts[i].sticky) ++ { ++ retain_flags |= ppc_opts[i].sticky; ++ if ((ppc_cpu & ~(PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX ++ | PPC_OPCODE_SPE | PPC_OPCODE_ANY)) != 0) ++ break; ++ } ++ ppc_cpu = ppc_opts[i].cpu; ++ break; ++ } ++ if (i >= sizeof (ppc_opts) / sizeof (ppc_opts[0])) ++ return 0; ++ ++ ppc_cpu |= retain_flags; ++ return ppc_cpu; ++} ++ ++/* Determine which set of machines to disassemble for. */ + + static int + powerpc_init_dialect (struct disassemble_info *info) + { +- ppc_cpu_t dialect = PPC_OPCODE_PPC; ++ ppc_cpu_t dialect = 0; ++ char *arg; + struct dis_private *priv = calloc (sizeof (*priv), 1); + + if (priv == NULL) + return FALSE; + +- if (BFD_DEFAULT_TARGET_SIZE == 64) +- dialect |= PPC_OPCODE_64; +- +- if (info->disassembler_options +- && strstr (info->disassembler_options, "ppcps") != NULL) +- dialect |= PPC_OPCODE_PPCPS; +- else if (info->disassembler_options +- && strstr (info->disassembler_options, "booke") != NULL) +- dialect |= PPC_OPCODE_BOOKE; +- else if ((info->mach == bfd_mach_ppc_e500mc) +- || (info->disassembler_options +- && strstr (info->disassembler_options, "e500mc") != NULL)) +- dialect |= (PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL +- | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK +- | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC); +- else if ((info->mach == bfd_mach_ppc_e500) +- || (info->disassembler_options +- && strstr (info->disassembler_options, "e500") != NULL)) +- dialect |= (PPC_OPCODE_BOOKE +- | PPC_OPCODE_SPE | PPC_OPCODE_ISEL +- | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK +- | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK +- | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC); +- else if (info->disassembler_options +- && strstr (info->disassembler_options, "efs") != NULL) +- dialect |= PPC_OPCODE_EFS; +- else if (info->disassembler_options +- && strstr (info->disassembler_options, "e300") != NULL) +- dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON; +- else if (info->disassembler_options +- && (strstr (info->disassembler_options, "440") != NULL +- || strstr (info->disassembler_options, "464") != NULL)) +- dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_32 +- | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI; +- else +- dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC +- | PPC_OPCODE_COMMON | PPC_OPCODE_ALTIVEC); +- +- if (info->disassembler_options +- && strstr (info->disassembler_options, "power4") != NULL) +- dialect |= PPC_OPCODE_POWER4; +- +- if (info->disassembler_options +- && strstr (info->disassembler_options, "power5") != NULL) +- dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5; +- +- if (info->disassembler_options +- && strstr (info->disassembler_options, "cell") != NULL) +- dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC; +- +- if (info->disassembler_options +- && strstr (info->disassembler_options, "power6") != NULL) +- dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 +- | PPC_OPCODE_ALTIVEC; ++ arg = info->disassembler_options; ++ while (arg != NULL) ++ { ++ ppc_cpu_t new_cpu = 0; ++ char *end = strchr (arg, ','); + +- if (info->disassembler_options +- && strstr (info->disassembler_options, "power7") != NULL) +- dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 +- | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 +- | PPC_OPCODE_ISEL | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX; ++ if (end != NULL) ++ *end = 0; + +- if (info->disassembler_options +- && strstr (info->disassembler_options, "vsx") != NULL) +- dialect |= PPC_OPCODE_VSX; ++ if ((new_cpu = ppc_parse_cpu (dialect, arg)) != 0) ++ dialect = new_cpu; ++ else if (strcmp (arg, "32") == 0) ++ { ++ dialect &= ~PPC_OPCODE_64; ++ dialect |= PPC_OPCODE_32; ++ } ++ else if (strcmp (arg, "64") == 0) ++ { ++ dialect |= PPC_OPCODE_64; ++ dialect &= ~PPC_OPCODE_32; ++ } ++ else ++ fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), arg); + +- if (info->disassembler_options +- && strstr (info->disassembler_options, "any") != NULL) +- dialect |= PPC_OPCODE_ANY; ++ if (end != NULL) ++ *end++ = ','; ++ arg = end; ++ } + +- if (info->disassembler_options) ++ if ((dialect & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) == 0) + { +- if (strstr (info->disassembler_options, "32") != NULL) +- dialect &= ~PPC_OPCODE_64; +- else if (strstr (info->disassembler_options, "64") != NULL) ++ if (info->mach == bfd_mach_ppc64) + dialect |= PPC_OPCODE_64; ++ else ++ dialect |= PPC_OPCODE_32; ++ /* Choose a reasonable default. */ ++ dialect |= (PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_CLASSIC ++ | PPC_OPCODE_601 | PPC_OPCODE_ALTIVEC); + } + + info->private_data = priv; +@@ -230,6 +335,7 @@ print_insn_powerpc (bfd_vma memaddr, + const struct powerpc_opcode *opcode; + const struct powerpc_opcode *opcode_end; + unsigned long op; ++ ppc_cpu_t dialect_orig = dialect; + + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) +@@ -268,7 +374,7 @@ print_insn_powerpc (bfd_vma memaddr, + + if ((insn & opcode->mask) != opcode->opcode + || (opcode->flags & dialect) == 0 +- || (opcode->deprecated & dialect) != 0) ++ || (opcode->deprecated & dialect_orig) != 0) + continue; + + /* Make two passes over the operands. First see if any of them +@@ -339,16 +445,14 @@ print_insn_powerpc (bfd_vma memaddr, + (*info->print_address_func) (memaddr + value, info); + else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) + (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); +- else if ((operand->flags & PPC_OPERAND_CR) == 0 +- || (dialect & PPC_OPCODE_PPC) == 0) +- (*info->fprintf_func) (info->stream, "%ld", value); + else if ((operand->flags & PPC_OPERAND_FSL) != 0) + (*info->fprintf_func) (info->stream, "fsl%ld", value); + else if ((operand->flags & PPC_OPERAND_FCR) != 0) + (*info->fprintf_func) (info->stream, "fcr%ld", value); + else if ((operand->flags & PPC_OPERAND_UDI) != 0) + (*info->fprintf_func) (info->stream, "%ld", value); +- else ++ else if ((operand->flags & PPC_OPERAND_CR) != 0 ++ && (dialect & PPC_OPCODE_PPC) != 0) + { + if (operand->bitm == 7) + (*info->fprintf_func) (info->stream, "cr%ld", value); +@@ -365,6 +469,8 @@ print_insn_powerpc (bfd_vma memaddr, + (*info->fprintf_func) (info->stream, "%s", cbnames[cc]); + } + } ++ else ++ (*info->fprintf_func) (info->stream, "%ld", value); + + if (need_paren) + { +@@ -400,23 +506,20 @@ print_insn_powerpc (bfd_vma memaddr, + void + print_ppc_disassembler_options (FILE *stream) + { +- fprintf (stream, "\n\ ++ unsigned int i, col; ++ ++ fprintf (stream, _("\n\ + The following PPC specific disassembler options are supported for use with\n\ +-the -M switch:\n"); +- +- fprintf (stream, " booke Disassemble the BookE instructions\n"); +- fprintf (stream, " e300 Disassemble the e300 instructions\n"); +- fprintf (stream, " e500|e500x2 Disassemble the e500 instructions\n"); +- fprintf (stream, " e500mc Disassemble the e500mc instructions\n"); +- fprintf (stream, " 440 Disassemble the 440 instructions\n"); +- fprintf (stream, " 464 Disassemble the 464 instructions\n"); +- fprintf (stream, " efs Disassemble the EFS instructions\n"); +- fprintf (stream, " ppcps Disassemble the PowerPC paired singles instructions\n"); +- fprintf (stream, " power4 Disassemble the Power4 instructions\n"); +- fprintf (stream, " power5 Disassemble the Power5 instructions\n"); +- fprintf (stream, " power6 Disassemble the Power6 instructions\n"); +- fprintf (stream, " power7 Disassemble the Power7 instructions\n"); +- fprintf (stream, " vsx Disassemble the Vector-Scalar (VSX) instructions\n"); +- fprintf (stream, " 32 Do not disassemble 64-bit instructions\n"); +- fprintf (stream, " 64 Allow disassembly of 64-bit instructions\n"); ++the -M switch:\n")); ++ ++ for (col = 0, i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++) ++ { ++ col += fprintf (stream, " %s,", ppc_opts[i].opt); ++ if (col > 66) ++ { ++ fprintf (stream, "\n"); ++ col = 0; ++ } ++ } ++ fprintf (stream, " 32, 64\n"); + } +diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c +index c872db5..9fac147 100644 +--- a/opcodes/ppc-opc.c ++++ b/opcodes/ppc-opc.c +@@ -3464,8 +3464,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { + + {"isellt", X(31,15), X_MASK, PPCISEL, PPCNONE, {RT, RA, RB}}, + +-{"mfcr", XFXM(31,19,0,0), XRARB_MASK, COM, POWER4, {RT}}, + {"mfcr", XFXM(31,19,0,0), XFXFXM_MASK, POWER4, PPCNONE, {RT, FXM4}}, ++{"mfcr", XFXM(31,19,0,0), XRARB_MASK, COM, POWER4, {RT}}, + {"mfocrf", XFXM(31,19,0,1), XFXFXM_MASK, COM, PPCNONE, {RT, FXM}}, + + {"lwarx", X(31,20), XEH_MASK, PPC, PPCNONE, {RT, RA0, RB, EH}}, +@@ -3726,14 +3726,14 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"mullw.", XO(31,235,0,1), XO_MASK, PPCCOM, PPCNONE, {RT, RA, RB}}, + {"muls.", XO(31,235,0,1), XO_MASK, PWRCOM, PPCNONE, {RT, RA, RB}}, + ++{"icblce", X(31,238), X_MASK, PPCCHLK, E500MC, {CT, RA, RB}}, + {"msgclr", XRTRA(31,238,0,0),XRTRA_MASK,E500MC, PPCNONE, {RB}}, +-{"icblce", X(31,238), X_MASK, PPCCHLK, PPCNONE, {CT, RA, RB}}, + {"mtsrin", X(31,242), XRA_MASK, PPC32, PPCNONE, {RS, RB}}, + {"mtsri", X(31,242), XRA_MASK, POWER32, PPCNONE, {RS, RB}}, + + {"dcbtstt", XRT(31,246,0x10), XRT_MASK, POWER7, PPCNONE, {RA, RB}}, +-{"dcbtst", X(31,246), X_MASK, PPC, POWER4, {CT, RA, RB}}, + {"dcbtst", X(31,246), X_MASK, POWER4, PPCNONE, {RA, RB, CT}}, ++{"dcbtst", X(31,246), X_MASK, PPC, POWER4, {CT, RA, RB}}, + + {"stbux", X(31,247), X_MASK, COM, PPCNONE, {RS, RAS, RB}}, + +@@ -3767,8 +3767,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"lscbx.", XRC(31,277,1), X_MASK, M601, PPCNONE, {RT, RA, RB}}, + + {"dcbtt", XRT(31,278,0x10), XRT_MASK, POWER7, PPCNONE, {RA, RB}}, +-{"dcbt", X(31,278), X_MASK, PPC, POWER4, {CT, RA, RB}}, + {"dcbt", X(31,278), X_MASK, POWER4, PPCNONE, {RA, RB, CT}}, ++{"dcbt", X(31,278), X_MASK, PPC, POWER4, {CT, RA, RB}}, + + {"lhzx", X(31,279), X_MASK, COM, PPCNONE, {RT, RA0, RB}}, + +@@ -4399,16 +4399,16 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"lswi", X(31,597), X_MASK, PPCCOM, PPCNONE, {RT, RA0, NB}}, + {"lsi", X(31,597), X_MASK, PWRCOM, PPCNONE, {RT, RA0, NB}}, + +-{"msync", X(31,598), 0xffffffff, BOOKE, PPCNONE, {0}}, + {"lwsync", XSYNC(31,598,1), 0xffffffff, PPC, PPCNONE, {0}}, + {"ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, PPCNONE, {0}}, +-{"sync", X(31,598), XSYNC_MASK, PPCCOM, PPCNONE, {LS}}, ++{"sync", X(31,598), XSYNC_MASK, PPCCOM, BOOKE, {LS}}, ++{"msync", X(31,598), 0xffffffff, BOOKE, PPCNONE, {0}}, + {"dcs", X(31,598), 0xffffffff, PWRCOM, PPCNONE, {0}}, + + {"lfdx", X(31,599), X_MASK, COM, PPCNONE, {FRT, RA0, RB}}, + +-{"lfdepx", X(31,607), X_MASK, E500MC, PPCNONE, {FRT, RA, RB}}, + {"mffgpr", XRC(31,607,0), XRA_MASK, POWER6, POWER7, {FRT, RB}}, ++{"lfdepx", X(31,607), X_MASK, E500MC, PPCNONE, {FRT, RA, RB}}, + + {"lddx", X(31,611), X_MASK, E500MC, PPCNONE, {RT, RA, RB}}, + +@@ -4502,8 +4502,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"sreq", XRC(31,729,0), X_MASK, M601, PPCNONE, {RA, RS, RB}}, + {"sreq.", XRC(31,729,1), X_MASK, M601, PPCNONE, {RA, RS, RB}}, + +-{"stfdepx", X(31,735), X_MASK, E500MC, PPCNONE, {FRS, RA, RB}}, + {"mftgpr", XRC(31,735,0), XRA_MASK, POWER6, POWER7, {RT, FRB}}, ++{"stfdepx", X(31,735), X_MASK, E500MC, PPCNONE, {FRS, RA, RB}}, + + {"stddx", X(31,739), X_MASK, E500MC, PPCNONE, {RS, RA, RB}}, + +@@ -4560,8 +4560,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { + + {"lhbrx", X(31,790), X_MASK, COM, PPCNONE, {RT, RA0, RB}}, + +-{"lfqx", X(31,791), X_MASK, POWER2, PPCNONE, {FRT, RA, RB}}, + {"lfdpx", X(31,791), X_MASK, POWER6, POWER7, {FRT, RA, RB}}, ++{"lfqx", X(31,791), X_MASK, POWER2, PPCNONE, {FRT, RA, RB}}, + + {"sraw", XRC(31,792,0), X_MASK, PPCCOM, PPCNONE, {RA, RS, RB}}, + {"sra", XRC(31,792,0), X_MASK, PWRCOM, PPCNONE, {RA, RS, RB}}, +@@ -4602,8 +4602,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { + + {"lbzcix", X(31,853), X_MASK, POWER6, PPCNONE, {RT, RA0, RB}}, + ++{"eieio", X(31,854), 0xffffffff, PPC, BOOKE, {0}}, + {"mbar", X(31,854), X_MASK, BOOKE, PPCNONE, {MO}}, +-{"eieio", X(31,854), 0xffffffff, PPC, PPCNONE, {0}}, + + {"lfiwax", X(31,855), X_MASK, POWER6, PPCNONE, {FRT, RA0, RB}}, + +@@ -4638,8 +4638,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { + + {"sthbrx", X(31,918), X_MASK, COM, PPCNONE, {RS, RA0, RB}}, + +-{"stfqx", X(31,919), X_MASK, POWER2, PPCNONE, {FRS, RA, RB}}, + {"stfdpx", X(31,919), X_MASK, POWER6, PPCNONE, {FRS, RA, RB}}, ++{"stfqx", X(31,919), X_MASK, POWER2, PPCNONE, {FRS, RA, RB}}, + + {"sraq", XRC(31,920,0), X_MASK, M601, PPCNONE, {RA, RS, RB}}, + {"sraq.", XRC(31,920,1), X_MASK, M601, PPCNONE, {RA, RS, RB}}, +@@ -4687,10 +4687,10 @@ const struct powerpc_opcode powerpc_opcodes[] = { + + {"stxvd2x", X(31,972), XX1_MASK, PPCVSX, PPCNONE, {XS6, RA, RB}}, + ++{"tlbld", X(31,978), XRTRA_MASK, PPC, PPC403|BOOKE, {RB}}, + {"tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, PPCNONE, {RT, RA}}, + {"tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, PPCNONE, {RT, RA}}, + {"tlbwe", X(31,978), X_MASK, PPC403|BOOKE, PPCNONE, {RSO, RAOPT, SHO}}, +-{"tlbld", X(31,978), XRTRA_MASK, PPC, PPCNONE, {RB}}, + + {"stbcix", X(31,981), X_MASK, POWER6, PPCNONE, {RS, RA0, RB}}, + +@@ -4796,16 +4796,12 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"stfdu", OP(55), OP_MASK, COM, PPCNONE, {FRS, D, RAS}}, + + {"lq", OP(56), OP_MASK, POWER4, PPCNONE, {RTQ, DQ, RAQ}}, +- +-{"lfq", OP(56), OP_MASK, POWER2, PPCNONE, {FRT, D, RA0}}, +- + {"psq_l", OP(56), OP_MASK, PPCPS, PPCNONE, {FRT,PSD,RA,PSW,PSQ}}, +- +-{"lfqu", OP(57), OP_MASK, POWER2, PPCNONE, {FRT, D, RA0}}, +- +-{"psq_lu", OP(57), OP_MASK, PPCPS, PPCNONE, {FRT,PSD,RA,PSW,PSQ}}, ++{"lfq", OP(56), OP_MASK, POWER2, PPCNONE, {FRT, D, RA0}}, + + {"lfdp", OP(57), OP_MASK, POWER6, POWER7, {FRT, D, RA0}}, ++{"psq_lu", OP(57), OP_MASK, PPCPS, PPCNONE, {FRT,PSD,RA,PSW,PSQ}}, ++{"lfqu", OP(57), OP_MASK, POWER2, PPCNONE, {FRT, D, RA0}}, + + {"ld", DSO(58,0), DS_MASK, PPC64, PPCNONE, {RT, DS, RA0}}, + {"ldu", DSO(58,1), DS_MASK, PPC64, PPCNONE, {RT, DS, RAL}}, +@@ -4829,18 +4825,18 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, PPCNONE, {FRT, FRB}}, + {"fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, PPCNONE, {FRT, FRB}}, + +-{"fres", A(59,24,0), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, +-{"fres.", A(59,24,1), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, + {"fres", A(59,24,0), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"fres", A(59,24,0), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, + {"fres.", A(59,24,1), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"fres.", A(59,24,1), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, + + {"fmuls", A(59,25,0), AFRB_MASK, PPC, PPCNONE, {FRT, FRA, FRC}}, + {"fmuls.", A(59,25,1), AFRB_MASK, PPC, PPCNONE, {FRT, FRA, FRC}}, + +-{"frsqrtes", A(59,26,0), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, +-{"frsqrtes.", A(59,26,1), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, + {"frsqrtes", A(59,26,0), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"frsqrtes", A(59,26,0), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, + {"frsqrtes.", A(59,26,1), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"frsqrtes.", A(59,26,1), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, + + {"fmsubs", A(59,28,0), A_MASK, PPC, PPCNONE, {FRT, FRA, FRC, FRB}}, + {"fmsubs.", A(59,28,1), A_MASK, PPC, PPCNONE, {FRT, FRA, FRC, FRB}}, +@@ -4921,10 +4917,6 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"fcfidus", XRC(59,974,0), XRA_MASK, POWER7, PPCNONE, {FRT, FRB}}, + {"fcfidus.", XRC(59,974,1), XRA_MASK, POWER7, PPCNONE, {FRT, FRB}}, + +-{"stfq", OP(60), OP_MASK, POWER2, PPCNONE, {FRS, D, RA}}, +- +-{"psq_st", OP(60), OP_MASK, PPCPS, PPCNONE, {FRS,PSD,RA,PSW,PSQ}}, +- + {"xxsldwi", XX3(60,2), XX3SHW_MASK, PPCVSX, PPCNONE, {XT6, XA6, XB6, SHW}}, + {"xxsel", XX4(60,3), XX4_MASK, PPCVSX, PPCNONE, {XT6, XA6, XB6, XC6}}, + {"xxspltd", XX3(60,10), XX3DM_MASK, PPCVSX, PPCNONE, {XT6, XA6, XB6S, DMEX}}, +@@ -5067,11 +5059,12 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"xvcvsxddp", XX2(60,504), XX2_MASK, PPCVSX, PPCNONE, {XT6, XB6}}, + {"xvnegdp", XX2(60,505), XX2_MASK, PPCVSX, PPCNONE, {XT6, XB6}}, + +-{"psq_stu", OP(61), OP_MASK, PPCPS, PPCNONE, {FRS,PSD,RA,PSW,PSQ}}, +- +-{"stfqu", OP(61), OP_MASK, POWER2, PPCNONE, {FRS, D, RA}}, ++{"psq_st", OP(60), OP_MASK, PPCPS, PPCNONE, {FRS,PSD,RA,PSW,PSQ}}, ++{"stfq", OP(60), OP_MASK, POWER2, PPCNONE, {FRS, D, RA}}, + + {"stfdp", OP(61), OP_MASK, POWER6, PPCNONE, {FRT, D, RA0}}, ++{"psq_stu", OP(61), OP_MASK, PPCPS, PPCNONE, {FRS,PSD,RA,PSW,PSQ}}, ++{"stfqu", OP(61), OP_MASK, POWER2, PPCNONE, {FRS, D, RA}}, + + {"std", DSO(62,0), DS_MASK, PPC64, PPCNONE, {RS, DS, RA0}}, + {"stdu", DSO(62,1), DS_MASK, PPC64, PPCNONE, {RS, DS, RAS}}, +@@ -5122,20 +5115,20 @@ const struct powerpc_opcode powerpc_opcodes[] = { + {"fsel", A(63,23,0), A_MASK, PPC, PPCNONE, {FRT, FRA, FRC, FRB}}, + {"fsel.", A(63,23,1), A_MASK, PPC, PPCNONE, {FRT, FRA, FRC, FRB}}, + +-{"fre", A(63,24,0), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, +-{"fre.", A(63,24,1), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, + {"fre", A(63,24,0), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"fre", A(63,24,0), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, + {"fre.", A(63,24,1), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"fre.", A(63,24,1), AFRALFRC_MASK, POWER5, POWER7, {FRT, FRB, A_L}}, + + {"fmul", A(63,25,0), AFRB_MASK, PPCCOM, PPCNONE, {FRT, FRA, FRC}}, + {"fm", A(63,25,0), AFRB_MASK, PWRCOM, PPCNONE, {FRT, FRA, FRC}}, + {"fmul.", A(63,25,1), AFRB_MASK, PPCCOM, PPCNONE, {FRT, FRA, FRC}}, + {"fm.", A(63,25,1), AFRB_MASK, PWRCOM, PPCNONE, {FRT, FRA, FRC}}, + +-{"frsqrte", A(63,26,0), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, +-{"frsqrte.", A(63,26,1), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, + {"frsqrte", A(63,26,0), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"frsqrte", A(63,26,0), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, + {"frsqrte.", A(63,26,1), AFRAFRC_MASK, POWER7, PPCNONE, {FRT, FRB}}, ++{"frsqrte.", A(63,26,1), AFRALFRC_MASK, PPC, POWER7, {FRT, FRB, A_L}}, + + {"fmsub", A(63,28,0), A_MASK, PPCCOM, PPCNONE, {FRT, FRA, FRC, FRB}}, + {"fms", A(63,28,0), A_MASK, PWRCOM, PPCNONE, {FRT, FRA, FRC, FRB}}, +@@ -5195,10 +5188,10 @@ const struct powerpc_opcode powerpc_opcodes[] = { + + {"dcmpoq", X(63,130), X_MASK, POWER6, PPCNONE, {BF, FRA, FRB}}, + +-{"mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, POWER6, {BFF, U}}, + {"mtfsfi", XRC(63,134,0), XWRA_MASK|(3<<21)|(1<<11), POWER6, PPCNONE, {BFF, U, W}}, +-{"mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, POWER6, {BFF, U}}, ++{"mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, POWER6, {BFF, U}}, + {"mtfsfi.", XRC(63,134,1), XWRA_MASK|(3<<21)|(1<<11), POWER6, PPCNONE, {BFF, U, W}}, ++{"mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, POWER6, {BFF, U}}, + + {"fnabs", XRC(63,136,0), XRA_MASK, COM, PPCNONE, {FRT, FRB}}, + {"fnabs.", XRC(63,136,1), XRA_MASK, COM, PPCNONE, {FRT, FRB}}, +@@ -5254,10 +5247,10 @@ const struct powerpc_opcode powerpc_opcodes[] = { + + {"dtstsfq", X(63,674), X_MASK, POWER6, PPCNONE, {BF, FRA, FRB}}, + +-{"mtfsf", XFL(63,711,0), XFL_MASK, COM, POWER6, {FLM, FRB}}, + {"mtfsf", XFL(63,711,0), XFL_MASK, POWER6, PPCNONE, {FLM, FRB, XFL_L, W}}, +-{"mtfsf.", XFL(63,711,1), XFL_MASK, COM, POWER6, {FLM, FRB}}, ++{"mtfsf", XFL(63,711,0), XFL_MASK, COM, POWER6, {FLM, FRB}}, + {"mtfsf.", XFL(63,711,1), XFL_MASK, POWER6, PPCNONE, {FLM, FRB, XFL_L, W}}, ++{"mtfsf.", XFL(63,711,1), XFL_MASK, COM, POWER6, {FLM, FRB}}, + + {"drdpq", XRC(63,770,0), X_MASK, POWER6, PPCNONE, {FRT, FRB}}, + {"drdpq.", XRC(63,770,1), X_MASK, POWER6, PPCNONE, {FRT, FRB}}, diff --git a/gdb-c_get_string-xfree.patch b/gdb-c_get_string-xfree.patch new file mode 100644 index 0000000..7ff13a7 --- /dev/null +++ b/gdb-c_get_string-xfree.patch @@ -0,0 +1,110 @@ +http://sourceware.org/ml/gdb-patches/2009-04/msg00284.html +http://sourceware.org/ml/gdb-cvs/2009-04/msg00077.html +http://sourceware.org/ml/archer/2009-q2/msg00049.html + +gdb/ +2009-04-14 Jan Kratochvil + + * c-lang.c (c_get_string): Fix xfree crash on a failed string read. + +gdb/testsuite/ +2009-04-14 Jan Kratochvil + + * gdb.python/python-prettyprint.c: Include . + (struct nullstr): New. + (main): New variable `nullstr'. Clear it. + * gdb.python/python-prettyprint.exp (run_lang_tests): Test `nullstr'. + * gdb.python/python-prettyprint.py (class pp_nullstr): New. + (register_pretty_printers): Register `pp_nullstr'. + +--- src/gdb/c-lang.c 2009/03/21 00:46:17 1.63 ++++ src/gdb/c-lang.c 2009/04/14 21:54:33 1.64 +@@ -657,7 +657,7 @@ + buffer, length); + if (err) + { +- xfree (buffer); ++ xfree (*buffer); + error (_("Error reading string from inferior: %s"), + safe_strerror (err)); + } +diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c +index 399be23..0d9110d 100644 +--- a/gdb/testsuite/gdb.python/python-prettyprint.c ++++ b/gdb/testsuite/gdb.python/python-prettyprint.c +@@ -15,6 +15,8 @@ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + ++#include ++ + struct s + { + int a; +@@ -143,6 +145,11 @@ void do_nothing(void) + c = 23; /* Another MI breakpoint */ + } + ++struct nullstr ++{ ++ char *s; ++}; ++ + int + main () + { +@@ -151,10 +158,13 @@ main () + string x = make_string ("this is x"); + zzz_type c = make_container ("container"); + const struct string_repr cstring = { { "const string" } }; ++ /* Clearing by being `static' could invoke an other GDB C++ bug. */ ++ struct nullstr nullstr; + + init_ss(&ss, 1, 2); + init_ss(ssa+0, 3, 4); + init_ss(ssa+1, 5, 6); ++ memset (&nullstr, 0, sizeof nullstr); + + #ifdef __cplusplus + S cps; +diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp +index f83b1cd..907dcfd 100644 +--- a/gdb/testsuite/gdb.python/python-prettyprint.exp ++++ b/gdb/testsuite/gdb.python/python-prettyprint.exp +@@ -85,6 +85,8 @@ proc run_lang_tests {lang} { + + gdb_test "print c" " = container $hex \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}" + ++ gdb_test "print nullstr" "RuntimeError: Error reading string from inferior.*" ++ + gdb_test "continue" "Program exited normally\." + } + +diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py +index a53e412..82e5331 100644 +--- a/gdb/testsuite/gdb.python/python-prettyprint.py ++++ b/gdb/testsuite/gdb.python/python-prettyprint.py +@@ -92,6 +92,13 @@ class pp_vbase1: + def to_string (self): + return "pp class name: " + self.val.type.tag + ++class pp_nullstr: ++ def __init__(self, val): ++ self.val = val ++ ++ def to_string(self): ++ return self.val['s'].string(gdb.parameter('target-charset')) ++ + def lookup_function (val): + "Look-up and return a pretty-printer that can print val." + +@@ -135,6 +142,9 @@ def register_pretty_printers (): + + pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual + pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1 ++ ++ pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr ++ pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr + + # Note that we purposely omit the typedef names here. + # Printer lookup is based on canonical name. diff --git a/gdb-charset-crash.patch b/gdb-charset-crash.patch new file mode 100644 index 0000000..2e0e8ac --- /dev/null +++ b/gdb-charset-crash.patch @@ -0,0 +1,44 @@ +http://sourceware.org/ml/gdb-patches/2009-04/msg00356.html +http://sourceware.org/ml/gdb-cvs/2009-04/msg00081.html + +gdb/ +2009-04-15 Tom Tromey + + * c-lang.c (evaluate_subexp_c): Correctly handle EVAL_SKIP. + +gdb/testsuite/ +2009-04-15 Tom Tromey + + * gdb.base/charset.exp: Add regression test. + +--- src/gdb/c-lang.c 2009/04/14 21:54:33 1.64 ++++ src/gdb/c-lang.c 2009/04/15 21:55:04 1.65 +@@ -941,7 +941,15 @@ + *pos += 2; + + if (noside == EVAL_SKIP) +- return NULL; ++ { ++ /* Return a dummy value of the appropriate type. */ ++ if ((dest_type & C_CHAR) != 0) ++ result = allocate_value (type); ++ else ++ result = value_typed_string ("", 0, type); ++ do_cleanups (cleanup); ++ return result; ++ } + + if ((dest_type & C_CHAR) != 0) + { +--- src/gdb/testsuite/gdb.base/charset.exp 2009/03/25 19:25:49 1.13 ++++ src/gdb/testsuite/gdb.base/charset.exp 2009/04/15 21:55:04 1.14 +@@ -604,4 +604,9 @@ + test_combination u UCS-2 U UCS-4 + } + ++# Regression test for a cleanup bug in the charset code. ++gdb_test "print 'a' == 'a' || 'b' == 'b'" \ ++ ".* = 1" \ ++ "EVAL_SKIP cleanup handling regression test" ++ + gdb_exit diff --git a/gdb-gstack.man b/gdb-gstack.man new file mode 100644 index 0000000..f5bcea6 --- /dev/null +++ b/gdb-gstack.man @@ -0,0 +1,48 @@ +.\" +.\" gstack manual page. +.\" Copyright (c) 1999 Ross Thompson +.\" Copyright (c) 2001, 2002, 2004, 2008 Red Hat, Inc. +.\" +.\" Original author: Ross Thompson +.\" +.\" 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, 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; see the file COPYING. If not, write to +.\" the Free Software Foundation, 59 Temple Place - Suite 330, +.\" Boston, MA 02111-1307, USA. +.\" +.TH GSTACK 1 "Feb 15 2008" "Red Hat Linux" "Linux Programmer's Manual" + +.SH NAME +gstack \- print a stack trace of a running process + +.SH SYNOPSIS +.B gstack +pid + +.SH DESCRIPTION + +\f3gstack\f1 attaches to the active process named by the \f3pid\f1 on +the command line, and prints out an execution stack trace. If ELF +symbols exist in the binary (usually the case unless you have run +strip(1)), then symbolic addresses are printed as well. + +If the process is part of a thread group, then \f3gstack\f1 will print +out a stack trace for each of the threads in the group. + +.SH SEE ALSO +nm(1), ptrace(2), gdb(1) + +.SH AUTHORS +Ross Thompson + +Red Hat, Inc. diff --git a/gdb-orphanripper.c b/gdb-orphanripper.c new file mode 100644 index 0000000..0acd86a --- /dev/null +++ b/gdb-orphanripper.c @@ -0,0 +1,597 @@ +/* + * Copyright 2006-2007 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. + * + * Reap any leftover children possibly holding file descriptors. + * Children are identified by the stale file descriptor or PGID / SID. + * Both can be missed but only the stale file descriptors are important for us. + * PGID / SID may be set by the children on their own. + * If we fine a candidate we kill it will all its process tree (grandchildren). + * The child process is run with `2>&1' redirection (due to forkpty(3)). + * 2007-07-10 Jan Kratochvil + */ + +/* For getpgid(2). */ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LENGTH(x) (sizeof (x) / sizeof (*(x))) + +static const char *progname; + +static volatile int signal_child_hit = 0; + +/* We use it to race-safely emulate ppoll(2) by poll(2). */ +static int pipefd[2]; + +static void signal_child (int signo) +{ + int i; + + signal_child_hit = 1; + + assert (pipefd[1] != -1); + i = close (pipefd[1]); + assert (i == 0); + pipefd[1] = -1; +} + +static char childptyname[LINE_MAX]; +static pid_t child; + +static int spawn (char **argv) +{ + pid_t child_got; + int status, amaster, i; + struct sigaction act; + struct termios termios; + + i = pipe (pipefd); + assert (i == 0); + + /* We do not use signal(2) to be sure we have SA_RESTART set. */ + memset (&act, 0, sizeof (act)); + act.sa_handler = signal_child; + i = sigemptyset (&act.sa_mask); + assert (i == 0); + act.sa_flags = SA_RESTART; + i = sigaction (SIGCHLD, &act, NULL); + assert (i == 0); + + /* With TERMP passed as NULL we get "\n" -> "\r\n". */ + termios.c_iflag = IGNBRK | IGNPAR; + termios.c_oflag = 0; + termios.c_cflag = CS8 | CREAD | CLOCAL | HUPCL | B9600; + termios.c_lflag = IEXTEN | NOFLSH; + memset (termios.c_cc, _POSIX_VDISABLE, sizeof (termios.c_cc)); + termios.c_cc[VTIME] = 0; + termios.c_cc[VMIN ] = 1; + cfmakeraw (&termios); +#ifdef FLUSHO + /* Workaround a readline deadlock bug in _get_tty_settings(). */ + termios.c_lflag &= ~FLUSHO; +#endif + child = forkpty (&amaster, childptyname, &termios, NULL); + switch (child) + { + case -1: + perror ("forkpty(3)"); + exit (EXIT_FAILURE); + case 0: + i = close (pipefd[0]); + assert (i == 0); + i = close (pipefd[1]); + assert (i == 0); + + /* Do not replace STDIN as inferiors query its termios. */ +#if 0 + i = close (STDIN_FILENO); + assert (i == 0); + i = open ("/dev/null", O_RDONLY); + assert (i == STDIN_FILENO); +#endif + + /* Do not setpgrp(2) in the parent process as the process-group + is shared for the whole sh(1) pipeline we could be a part + of. The process-group is set according to PID of the first + command in the pipeline. + We would rip even vi(1) in the case of: + ./orphanripper sh -c 'sleep 1&' | vi - + */ + /* Do not setpgrp(2) as our pty would not be ours and we would + get `SIGSTOP' later, particularly after spawning gdb(1). + setsid(3) was already executed by forkpty(3) and it would fail if + executed again. */ + if (getpid() != getpgrp ()) + { + perror ("getpgrp(2)"); + exit (EXIT_FAILURE); + } + execvp (argv[1], argv + 1); + perror ("execvp(2)"); + exit (EXIT_FAILURE); + default: + break; + } + i = fcntl (amaster, F_SETFL, O_RDWR | O_NONBLOCK); + if (i != 0) + { + perror ("fcntl (amaster, F_SETFL, O_NONBLOCK)"); + exit (EXIT_FAILURE); + } + for (;;) + { + struct pollfd pollfd[2]; + char buf[LINE_MAX]; + ssize_t buf_got; + + pollfd[0].fd = amaster; + pollfd[0].events = POLLIN; + pollfd[1].fd = pipefd[0]; + pollfd[1].events = POLLIN; + i = poll (pollfd, LENGTH (pollfd), -1); + if (i == -1 && errno == EINTR) + { + /* Weird but SA_RESTART sometimes does not work. */ + continue; + } + assert (i >= 1); + /* Data available? Process it first. */ + if (pollfd[0].revents & POLLIN) + { + buf_got = read (amaster, buf, sizeof buf); + if (buf_got <= 0) + { + perror ("read (amaster)"); + exit (EXIT_FAILURE); + } + if (write (STDOUT_FILENO, buf, buf_got) != buf_got) + { + perror ("write(2)"); + exit (EXIT_FAILURE); + } + } + if (pollfd[0].revents & POLLHUP) + break; + if ((pollfd[0].revents &= ~POLLIN) != 0) + { + fprintf (stderr, "%s: ppoll(2): revents 0x%x\n", progname, + (unsigned) pollfd[0].revents); + exit (EXIT_FAILURE); + } + /* Child exited? */ + if (pollfd[1].revents & POLLHUP) + break; + assert (pollfd[1].revents == 0); + } + /* WNOHANG still could fail. */ + child_got = waitpid (child, &status, 0); + if (child != child_got) + { + fprintf (stderr, "waitpid (%d) = %d: %m\n", (int) child, (int) child_got); + exit (EXIT_FAILURE); + } + if (!WIFEXITED (status)) + { + fprintf (stderr, "waitpid (%d): !WIFEXITED (%d)\n", (int) child, status); + exit (EXIT_FAILURE); + } + + assert (signal_child_hit != 0); + assert (pipefd[1] == -1); + i = close (pipefd[0]); + assert (i == 0); + + /* Do not close the master FD as the child would have `/dev/pts/23 (deleted)' + entries which are not expected (and expecting ` (deleted)' would be + a race. */ +#if 0 + i = close (amaster); + if (i != 0) + { + perror ("close (forkpty ()'s amaster)"); + exit (EXIT_FAILURE); + } +#endif + + return WEXITSTATUS (status); +} + +/* Detected commandline may look weird due to a race: + Original command: + ./orphanripper sh -c 'sleep 1&' & + Correct output: + [1] 29610 + ./orphanripper: Killed -9 orphan PID 29612 (PGID 29611): sleep 1 + Raced output (sh(1) child still did not update its argv[]): + [1] 29613 + ./orphanripper: Killed -9 orphan PID 29615 (PGID 29614): sh -c sleep 1& + We could delay a bit before ripping the children. */ +static const char *read_cmdline (pid_t pid) +{ + char cmdline_fname[32]; + static char cmdline[LINE_MAX]; + int fd; + ssize_t got; + char *s; + + if (snprintf (cmdline_fname, sizeof cmdline_fname, "/proc/%d/cmdline", + (int) pid) < 0) + return NULL; + fd = open (cmdline_fname, O_RDONLY); + if (fd == -1) + { + /* It may have already exited - ENOENT. */ +#if 0 + fprintf (stderr, "%s: open (\"%s\"): %m\n", progname, cmdline_fname); +#endif + return NULL; + } + got = read (fd, cmdline, sizeof (cmdline) - 1); + if (got == -1) + fprintf (stderr, "%s: read (\"%s\"): %m\n", progname, + cmdline_fname); + if (close (fd) != 0) + fprintf (stderr, "%s: close (\"%s\"): %m\n", progname, + cmdline_fname); + if (got < 0) + return NULL; + /* Convert '\0' argument delimiters to spaces. */ + for (s = cmdline; s < cmdline + got; s++) + if (!*s) + *s = ' '; + /* Trim the trailing spaces (typically single '\0'->' '). */ + while (s > cmdline && isspace (s[-1])) + s--; + *s = 0; + return cmdline; +} + +static int dir_scan (const char *dirname, + int (*callback) (struct dirent *dirent, const char *pathname)) +{ + DIR *dir; + struct dirent *dirent; + int rc = 0; + + dir = opendir (dirname); + if (dir == NULL) + { + if (errno == EACCES || errno == ENOENT) + return rc; + fprintf (stderr, "%s: opendir (\"%s\"): %m\n", progname, dirname); + exit (EXIT_FAILURE); + } + while ((errno = 0, dirent = readdir (dir))) + { + char pathname[LINE_MAX]; + int pathname_len; + + pathname_len = snprintf (pathname, sizeof pathname, "%s/%s", + dirname, dirent->d_name); + if (pathname_len <= 0 || pathname_len >= sizeof pathname) + { + fprintf (stderr, "entry file name too long: `%s' / `%s'\n", + dirname, dirent->d_name); + continue; + } + /* RHEL-4.5 on s390x never fills in D_TYPE. */ + if (dirent->d_type == DT_UNKNOWN) + { + struct stat statbuf; + int i; + + /* We are not interested in the /proc/PID/fd/ links targets. */ + i = lstat (pathname, &statbuf); + if (i == -1) + { + if (errno == EACCES || errno == ENOENT) + continue; + fprintf (stderr, "%s: stat (\"%s\"): %m\n", progname, pathname); + exit (EXIT_FAILURE); + } + if (S_ISDIR (statbuf.st_mode)) + dirent->d_type = DT_DIR; + if (S_ISLNK (statbuf.st_mode)) + dirent->d_type = DT_LNK; + /* No other D_TYPE types used in this code. */ + } + rc = (*callback) (dirent, pathname); + if (rc != 0) + { + errno = 0; + break; + } + } + if (errno != 0) + { + fprintf (stderr, "%s: readdir (\"%s\"): %m\n", progname, dirname); + exit (EXIT_FAILURE); + } + if (closedir (dir) != 0) + { + fprintf (stderr, "%s: closedir (\"%s\"): %m\n", progname, dirname); + exit (EXIT_FAILURE); + } + return rc; +} + +static int fd_fs_scan (pid_t pid, int (*func) (pid_t pid, const char *link)) +{ + char dirname[64]; + + if (snprintf (dirname, sizeof dirname, "/proc/%d/fd", (int) pid) < 0) + { + perror ("snprintf(3)"); + exit (EXIT_FAILURE); + } + + int callback (struct dirent *dirent, const char *pathname) + { + char buf[LINE_MAX]; + ssize_t buf_len; + + if ((dirent->d_type != DT_DIR && dirent->d_type != DT_LNK) + || (dirent->d_type == DT_DIR && strcmp (dirent->d_name, ".") != 0 + && strcmp (dirent->d_name, "..") != 0) + || (dirent->d_type == DT_LNK && strspn (dirent->d_name, "0123456789") + != strlen (dirent->d_name))) + { + fprintf (stderr, "Unexpected entry \"%s\" (d_type %u)" + " on readdir (\"%s\"): %m\n", + dirent->d_name, (unsigned) dirent->d_type, dirname); + return 0; + } + if (dirent->d_type == DT_DIR) + return 0; + buf_len = readlink (pathname, buf, sizeof buf - 1); + if (buf_len <= 0 || buf_len >= sizeof buf - 1) + { + if (errno != ENOENT && errno != EACCES) + fprintf (stderr, "Error reading link \"%s\": %m\n", pathname); + return 0; + } + buf[buf_len] = 0; + return (*func) (pid, buf); + } + + return dir_scan (dirname, callback); +} + +static void pid_fs_scan (void (*func) (pid_t pid, void *data), void *data) +{ + int callback (struct dirent *dirent, const char *pathname) + { + if (dirent->d_type != DT_DIR + || strspn (dirent->d_name, "0123456789") != strlen (dirent->d_name)) + return 0; + (*func) (atoi (dirent->d_name), data); + return 0; + } + + dir_scan ("/proc", callback); +} + +static int rip_check_ptyname (pid_t pid, const char *link) +{ + assert (pid != getpid ()); + + return strcmp (link, childptyname) == 0; +} + +struct pid + { + struct pid *next; + pid_t pid; + }; +static struct pid *pid_list; + +static int pid_found (pid_t pid) +{ + struct pid *entry; + + for (entry = pid_list; entry != NULL; entry = entry->next) + if (entry->pid == pid) + return 1; + return 0; +} + +/* Single pass is not enough, a (multithreaded) process was seen to survive. + Repeated killing of the same process is not enough, zombies can be killed. + */ +static int cleanup_acted; + +static void pid_record (pid_t pid) +{ + struct pid *entry; + + if (pid_found (pid)) + return; + cleanup_acted = 1; + + entry = malloc (sizeof (*entry)); + if (entry == NULL) + { + fprintf (stderr, "%s: malloc: %m\n", progname); + exit (EXIT_FAILURE); + } + entry->pid = pid; + entry->next = pid_list; + pid_list = entry; +} + +static void pid_forall (void (*func) (pid_t pid)) +{ + struct pid *entry; + + for (entry = pid_list; entry != NULL; entry = entry->next) + (*func) (entry->pid); +} + +/* Returns 0 on failure. */ +static pid_t pid_get_parent (pid_t pid) +{ + char fname[64]; + FILE *f; + char line[LINE_MAX]; + pid_t retval = 0; + + if (snprintf (fname, sizeof fname, "/proc/%d/status", (int) pid) < 0) + { + perror ("snprintf(3)"); + exit (EXIT_FAILURE); + } + f = fopen (fname, "r"); + if (f == NULL) + { + return 0; + } + while (errno = 0, fgets (line, sizeof line, f) == line) + { + if (strncmp (line, "PPid:\t", sizeof "PPid:\t" - 1) != 0) + continue; + retval = atoi (line + sizeof "PPid:\t" - 1); + errno = 0; + break; + } + if (errno != 0) + { + fprintf (stderr, "%s: fgets (\"%s\"): %m\n", progname, fname); + exit (EXIT_FAILURE); + } + if (fclose (f) != 0) + { + fprintf (stderr, "%s: fclose (\"%s\"): %m\n", progname, fname); + exit (EXIT_FAILURE); + } + return retval; +} + +static void killtree (pid_t pid); + +static void killtree_pid_fs_scan (pid_t pid, void *data) +{ + pid_t parent_pid = *(pid_t *) data; + + /* Do not optimize it as we could miss some newly spawned processes. + Always traverse all the leaves. */ +#if 0 + /* Optimization. */ + if (pid_found (pid)) + return; +#endif + + if (pid_get_parent (pid) != parent_pid) + return; + + killtree (pid); +} + +static void killtree (pid_t pid) +{ + pid_record (pid); + pid_fs_scan (killtree_pid_fs_scan, &pid); +} + +static void rip_pid_fs_scan (pid_t pid, void *data) +{ + pid_t pgid; + + /* Shouldn't happen. */ + if (pid == getpid ()) + return; + + /* Check both PGID and the stale file descriptors. */ + pgid = getpgid (pid); + if (pgid == child + || fd_fs_scan (pid, rip_check_ptyname) != 0) + killtree (pid); +} + +static void killproc (pid_t pid) +{ + const char *cmdline; + + cmdline = read_cmdline (pid); + /* Avoid printing the message for already gone processes. */ + if (kill (pid, 0) != 0 && errno == ESRCH) + return; + if (cmdline == NULL) + cmdline = ""; + fprintf (stderr, "%s: Killed -9 orphan PID %d: %s\n", progname, (int) pid, cmdline); + if (kill (pid, SIGKILL) == 0) + cleanup_acted = 1; + else if (errno != ESRCH) + fprintf (stderr, "%s: kill (%d, SIGKILL): %m\n", progname, (int) pid); + /* RHEL-3 kernels cannot SIGKILL a `T (stopped)' process. */ + kill (pid, SIGCONT); + /* Do not waitpid(2) as it cannot be our direct descendant and it gets + cleaned up by init(8). */ +#if 0 + pid_t pid_got; + pid_got = waitpid (pid, NULL, 0); + if (pid != pid_got) + { + fprintf (stderr, "%s: waitpid (%d) != %d: %m\n", progname, + (int) pid, (int) pid_got); + return; + } +#endif +} + +static void rip (void) +{ + cleanup_acted = 0; + do + { + if (cleanup_acted) + usleep (1000000 / 10); + cleanup_acted = 0; + pid_fs_scan (rip_pid_fs_scan, NULL); + pid_forall (killproc); + } + while (cleanup_acted); +} + +int main (int argc, char **argv) +{ + int rc; + + if (argc < 2 || strcmp (argv[1], "-h") == 0 + || strcmp (argv[1], "--help") == 0) + { + fputs ("Syntax: orphanripper \n", stdout); + exit (EXIT_FAILURE); + } + progname = argv[0]; + rc = spawn (argv); + rip (); + return rc; +} diff --git a/gdb.changes b/gdb.changes index 2d307f4..044a078 100644 --- a/gdb.changes +++ b/gdb.changes @@ -1,3 +1,19 @@ +------------------------------------------------------------------- +Wed Apr 29 15:11:15 CEST 2009 - rguenther@suse.de + +- Adjust package name and release to not contain macros. + +------------------------------------------------------------------- +Mon Apr 27 16:18:02 CEST 2009 - rguenther@suse.de + +- Disable rpm support for locating debug info packages. + +------------------------------------------------------------------- +Mon Apr 27 13:33:06 CEST 2009 - rguenther@suse.de + +- Switch to Fedora 11 source RPM. + * includes partially merge from Archer. [bnc#329420, bnc#497141] + ------------------------------------------------------------------- Tue Mar 10 11:14:25 CET 2009 - rguenther@suse.de diff --git a/gdb.spec b/gdb.spec index 730528b..3086c82 100644 --- a/gdb.spec +++ b/gdb.spec @@ -1,5 +1,5 @@ # -# spec file for package gdb (Version 6.8.50.20090216) +# spec file for package gdb (Version 6.8.50.20090302) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -16,54 +16,306 @@ # +Summary: The GNU Debugger Name: gdb -Summary: The GNU Debugger -Version: 6.8.50.20090216 -Release: 3 -BuildRequires: bison dejagnu flex gcc-c++ gcc-fortran gcc-java gcc-objc python-devel readline-devel zlib-devel -%if 0%{?suse_version} > 1020 -BuildRequires: libexpat-devel -%else -BuildRequires: expat -%endif -%ifarch ia64 -BuildRequires: libunwind-devel -%endif -%ifnarch ppc64 s390x -BuildRequires: gcc-ada -%endif -Url: http://www.gnu.org/software/gdb/ +# Set version to contents of gdb/version.in. +# NOTE: the FSF gdb versions are numbered N.M for official releases, like 6.3 +# and, since January 2005, X.Y.Z.date for daily snapshots, like 6.3.50.20050112 # (daily snapshot from mailine), or 6.3.0.20040112 (head of the release branch). +Version: 6.8.50.20090302 +Release: 1 +# The release always contains a leading reserved number, start it at 1. +# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. License: GNU Free Documentation License, Version 1.2 (GFDL 1.2); GPL v2 or later; GPL v3 or later Group: Development/Tools/Debuggers -AutoReqProv: on -%ifarch ppc64 -Obsoletes: gdb-64bit -%endif -PreReq: %{install_info_prereq} -Recommends: python -%define sss -cvs +Source: ftp://sourceware.org/pub/gdb/releases/gdb-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build -Source: gdb-%{version}%{sss}.tar.bz2 -Patch: cell-combined.diff -Patch1: find-pc-sect-line.diff -Patch3: readline-5.1-random.patch -Patch4: readnever.patch -Patch5: gstack.patch -Patch6: sect-index-text.diff -Patch7: pie-relocate.diff -Patch8: find-separate-debug-file.diff -Patch9: fix-gdb-backtrace.diff -Patch10: expand-line-sal-maybe.diff -Patch11: gdb-readline6.patch -# Patches from Fedora -# Fix/implement the Fortran dynamic arrays support (BZ 377541). -# Fix the variable-length-arrays support (BZ 468266, feature BZ 377541). -Patch305: gdb-6.8-bz377541-vla.patch +Url: http://www.gnu.org/software/gdb/ +# For our convenience +%define gdb_src gdb-%{version} +%define gdb_build build-%{_target_platform} +%if 0%{?_with_debug:1} +# Define this if you want to skip the strip step and preserve debug info. +# Useful for testing. +%define __debug_install_post : > %{_builddir}/%{?buildsubdir}/debugfiles.list +%define debug_package %{nil} +%endif +# Make sure we get rid of the old package gdb64, now that we have unified +# support for 32-64 bits in one single 64-bit gdb. +%ifarch ppc64 +Obsoletes: gdb64 < 5.3.91 +%endif +# GDB patches have the format `gdb--bz-.patch'. +# They should be created using patch level 1: diff -up ./gdb (or gdb-6.3/gdb). +# Cleanup any leftover testsuite processes as it may stuck mock(1) builds. +Source2: gdb-orphanripper.c +# Man page for gstack(1). +Source3: gdb-gstack.man +# Work around out-of-date dejagnu that does not have KFAIL +Patch1: gdb-6.3-rh-dummykfail-20041202.patch +# Match the Fedora's version info. +Patch2: gdb-6.3-rh-testversion-20041202.patch +# Check that libunwind works - new test then fix +Patch3: gdb-6.3-rh-testlibunwind-20041202.patch +Patch4: gdb-6.3-rh-testlibunwind1fix-20041202.patch +# Use convert_from_func_ptr_addr on the solib breakpoint address; +# simplifies and makes more consistent the logic. +Patch104: gdb-6.3-ppcdotsolib-20041022.patch +# Better parse 64-bit PPC system call prologues. +Patch105: gdb-6.3-ppc64syscall-20040622.patch +# Stop a backtrace when a zero PC is encountered. +Patch106: gdb-6.3-framepczero-20040927.patch +# Include the pc's section when doing a symbol lookup so that the +# correct symbol is found. +Patch111: gdb-6.3-ppc64displaysymbol-20041124.patch +# Fix upstream `set scheduler-locking step' vs. upstream PPC atomic seqs. +Patch112: gdb-6.6-scheduler_locking-step-sw-watchpoints2.patch +# Make upstream `set scheduler-locking step' as default. +Patch260: gdb-6.6-scheduler_locking-step-is-default.patch +# Fix to display base constructors from list and breakpoint commands +Patch116: gdb-6.3-linespec-20041213.patch +# Continue removing breakpoints even when failure occurs. +Patch117: gdb-6.3-removebp-20041130.patch +# Add a wrapper script to GDB that implements pstack using the +# --readnever option. +Patch118: gdb-6.3-gstack-20050411.patch +# VSYSCALL and PIE +Patch122: gdb-6.3-test-pie-20050107.patch +Patch124: gdb-6.3-pie-20050110.patch +# Get selftest working with sep-debug-info +Patch125: gdb-6.3-test-self-20050110.patch +# Fix for non-threaded watchpoints. +Patch128: gdb-6.3-nonthreaded-wp-20050117.patch +# Fix to support multiple destructors just like multiple constructors +Patch133: gdb-6.3-test-dtorfix-20050121.patch +Patch134: gdb-6.3-dtorfix-20050121.patch +# Fix to support executable moving +Patch136: gdb-6.3-test-movedir-20050125.patch +# Fix to support unwinding syscalls in ia64 corefiles +# Patch138: gdb-6.3-ia64-corefile-fix-20050127.patch +# Fix gcore for threads +Patch140: gdb-6.3-gcore-thread-20050204.patch +# Stop while intentionally stepping and the thread exit is met. +Patch141: gdb-6.6-step-thread-exit.patch +Patch259: gdb-6.3-step-thread-exit-20050211-test.patch +# Prevent gdb from being pushed into background +Patch142: gdb-6.3-terminal-fix-20050214.patch +# Test sibling threads to set threaded watchpoints for x86 and x86-64 +Patch145: gdb-6.3-threaded-watchpoints2-20050225.patch +# Fix printing of inherited members +Patch148: gdb-6.3-inheritance-20050324.patch +# Print a warning when the separate debug info's CRC doesn't match. +Patch150: gdb-6.3-test-sepcrc-20050402.patch +Patch151: gdb-6.3-sepcrc-20050402.patch +# Do not issue warning message about first page of storage for ia64 gcore +Patch153: gdb-6.3-ia64-gcore-page0-20050421.patch +# Security errata for untrusted .gdbinit +Patch157: gdb-6.3-security-errata-20050610.patch +# IA64 sigtramp prev register patch +Patch158: gdb-6.3-ia64-sigtramp-frame-20050708.patch +# IA64 gcore speed-up patch +Patch160: gdb-6.3-ia64-gcore-speedup-20050714.patch +# Notify observers that the inferior has been created +Patch161: gdb-6.3-inferior-notification-20050721.patch +# Fix ia64 info frame bug +Patch162: gdb-6.3-ia64-info-frame-fix-20050725.patch +# Verify printing of inherited members test +Patch163: gdb-6.3-inheritancetest-20050726.patch +# Add readnever option +Patch164: gdb-6.3-readnever-20050907.patch +# Fix frame pointer for ia64 sigtramp frame +Patch166: gdb-6.3-ia64-sigtramp-fp-20050926.patch +# Fix ia64 gdb problem with user-specified SIGILL handling +Patch169: gdb-6.3-ia64-sigill-20051115.patch +# Allow option to continue backtracing past a zero pc value +Patch170: gdb-6.3-bt-past-zero-20051201.patch +# Use bigger numbers than int. +Patch176: gdb-6.3-large-core-20051206.patch +# Hard-code executable names in gstack, such that it can run with a +# corrupted or missing PATH. +Patch177: gdb-6.3-gstack-without-path-20060414.patch +# Fix debuginfo addresses resolving for --emit-relocs Linux kernels (BZ 203661). +Patch188: gdb-6.5-bz203661-emit-relocs.patch +# Security patch: avoid stack overflows in dwarf expression computation. +# CVE-2006-4146 +Patch190: gdb-6.5-dwarf-stack-overflow.patch +# Support TLS symbols (+`errno' suggestion if no pthread is found) (BZ 185337). +Patch194: gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch +# Fix TLS symbols resolving for objects with separate .debug file (-debuginfo). +Patch195: gdb-6.5-tls-of-separate-debuginfo.patch +# Fix TLS symbols resolving for shared libraries with a relative pathname. +# The testsuite needs `gdb-6.5-tls-of-separate-debuginfo.patch'. +Patch196: gdb-6.5-sharedlibrary-path.patch +# Suggest fixing your target architecture for gdbserver(1) (BZ 190810). +# FIXME: It could be autodetected. +Patch199: gdb-6.5-bz190810-gdbserver-arch-advice.patch +# Fix dereferencing registers for 32bit inferiors on 64bit hosts (BZ 181390). +Patch200: gdb-6.5-bz181390-memory-address-width.patch +# Fix `gcore' command for 32bit inferiors on 64bit hosts. +Patch201: gdb-6.5-gcore-i386-on-amd64.patch +# Testcase for deadlocking on last address space byte; for corrupted backtraces. +Patch211: gdb-6.5-last-address-space-byte-test.patch +# Improved testsuite results by the testsuite provided by the courtesy of BEA. +Patch208: gdb-6.5-BEA-testsuite.patch +# Fix readline segfault on excessively long hand-typed lines. +Patch209: gdb-6.5-readline-long-line-crash.patch +Patch213: gdb-6.5-readline-long-line-crash-test.patch +# Fix bogus 0x0 unwind of the thread's topmost function clone(3) (BZ 216711). +Patch214: gdb-6.5-bz216711-clone-is-outermost.patch +# Try to reduce sideeffects of skipping ppc .so libs trampolines (BZ 218379). +Patch215: gdb-6.5-bz218379-ppc-solib-trampoline-fix.patch +Patch216: gdb-6.5-bz218379-ppc-solib-trampoline-test.patch +# Fix lockup on trampoline vs. its function lookup; unreproducible (BZ 218379). +Patch217: gdb-6.5-bz218379-solib-trampoline-lookup-lock-fix.patch +# Find symbols properly at their original (included) file (BZ 109921). +Patch225: gdb-6.5-bz109921-DW_AT_decl_file-test.patch +# Update PPC unwinding patches to their upstream variants (BZ 140532). +Patch229: gdb-6.3-bz140532-ppc-unwinding-test.patch +# Testcase for exec() from threaded program (BZ 202689). +Patch231: gdb-6.3-bz202689-exec-from-pthread-test.patch +# Backported post gdb-6.8 release fixups. +###Patch232: gdb-6.8-upstream.patch +# Testcase for PPC Power6/DFP instructions disassembly (BZ 230000). +Patch234: gdb-6.6-bz230000-power6-disassembly-test.patch +# Temporary support for shared libraries >2GB on 64bit hosts. (BZ 231832) +Patch235: gdb-6.3-bz231832-obstack-2gb.patch +# Fix prelink(8) testcase for non-root $PATH missing `/usr/sbin' (BZ 225783). +Patch240: gdb-6.6-bz225783-prelink-path.patch +# Fix debugging GDB itself - the compiled in source files paths (BZ 225783). +Patch241: gdb-6.6-bz225783-gdb-debuginfo-paths.patch +# Allow running `/usr/bin/gcore' with provided but inaccessible tty (BZ 229517). +Patch245: gdb-6.6-bz229517-gcore-without-terminal.patch +# Notify user of a child forked process being detached (BZ 235197). +Patch247: gdb-6.6-bz235197-fork-detach-info.patch +# New testcase for gcore of 32bit inferiors on 64bit hosts. +Patch249: gdb-6.6-gcore32-test.patch +# Avoid too long timeouts on failing cases of "annota1.exp annota3.exp". +Patch254: gdb-6.6-testsuite-timeouts.patch +# Support for stepping over PPC atomic instruction sequences (BZ 237572). +Patch258: gdb-6.6-bz237572-ppc-atomic-sequence-test.patch +# Link with libreadline provided by the operating system. +Patch261: gdb-6.6-readline-system.patch +# Test kernel VDSO decoding while attaching to an i386 process. +Patch263: gdb-6.3-attach-see-vdso-test.patch +# Do not hang on exit of a thread group leader (BZ 247354). +Patch265: gdb-6.6-bz247354-leader-exit-fix.patch +Patch266: gdb-6.6-bz247354-leader-exit-test.patch +# Test leftover zombie process (BZ 243845). +Patch271: gdb-6.5-bz243845-stale-testing-zombie-test.patch +# New locating of the matching binaries from the pure core file (build-id). +Patch274: gdb-6.6-buildid-locate.patch +Patch353: gdb-6.6-buildid-locate-rpm.patch +# Fix hardware watchpoints after inferior forks-off some process. +# Threaded `set follow-fork-mode child' still not fixed there, glibc fixes reqd. +# `set detach-on-fork off' not fixed there in general - it already assert-fails. +Patch280: gdb-6.6-multifork-debugreg.patch +# Fix displaying of numeric char arrays as strings (BZ 224128). +Patch282: gdb-6.7-charsign-test.patch +# Test PPC hiding of call-volatile parameter register. +Patch284: gdb-6.7-ppc-clobbered-registers-O2-test.patch +# Testsuite fixes for more stable/comparable results. +Patch287: gdb-6.7-testsuite-stable-results.patch +# Test ia64 memory leaks of the code using libunwind. +Patch289: gdb-6.5-ia64-libunwind-leak-test.patch +# Test hiding unexpected breakpoints on intentional step commands. +Patch290: gdb-6.5-missed-trap-on-step-test.patch +# Support DW_TAG_interface_type the same way as DW_TAG_class_type (BZ 426600). +Patch293: gdb-6.7-bz426600-DW_TAG_interface_type-fix.patch +Patch294: gdb-6.7-bz426600-DW_TAG_interface_type-test.patch +# Test gcore memory and time requirements for large inferiors. +Patch296: gdb-6.5-gcore-buffer-limit-test.patch +# Test debugging statically linked threaded inferiors (BZ 239652). +# - It requires recent glibc to work in this case properly. +Patch298: gdb-6.6-threads-static-test.patch +# Fix #include on kernel-headers-2.6.25-0.40.rc1.git2.fc9.x86_64. +Patch304: gdb-6.7-kernel-headers-compat.patch +# Test GCORE for shmid 0 shared memory mappings. +Patch309: gdb-6.3-mapping-zero-inode-test.patch +# Test a crash on `focus cmd', `focus prev' commands. +Patch311: gdb-6.3-focus-cmd-prev-test.patch +# Test crash on a sw watchpoint condition getting out of the scope. +Patch314: gdb-6.3-watchpoint-cond-gone-test.patch +# Test various forms of threads tracking across exec() (BZ 442765). +Patch315: gdb-6.8-bz442765-threaded-exec-test.patch +# Silence memcpy check which returns false positive (sparc64) +Patch317: gdb-6.8-sparc64-silence-memcpy-check.patch +# Fix memory trashing on binaries from GCC Ada (workaround GCC PR 35998). +Patch318: gdb-6.8-gcc35998-ada-memory-trash.patch +# Test a crash on libraries missing the .text section. +Patch320: gdb-6.5-section-num-fixup-test.patch +# Refuse creating watchpoints of an address value, suggested by Martin Stransky. +Patch322: gdb-6.8-constant-watchpoints.patch +# Fix compatibility with recent glibc headers. +Patch324: gdb-6.8-glibc-headers-compat.patch +# Create a single binary `gdb' autodetecting --tui by its argv[0]. +Patch326: gdb-6.8-tui-singlebinary.patch # Support transparent debugging of inlined functions for an optimized code. Patch327: gdb-6.8-inlining.patch Patch350: gdb-6.8-inlining-addon.patch Patch328: gdb-6.8-inlining-by-name.patch +# Fix PRPSINFO in the core files dumped by gcore (BZ 254229). +Patch329: gdb-6.8-bz254229-gcore-prpsinfo.patch +# Fix register assignments with no GDB stack frames (BZ 436037). +Patch330: gdb-6.8-bz436037-reg-no-longer-active.patch +# Make the GDB quit processing non-abortable to cleanup everything properly. +Patch331: gdb-6.8-quit-never-aborts.patch +# Support DW_TAG_constant for Fortran in recent Fedora/RH GCCs. +Patch332: gdb-6.8-fortran-tag-constant.patch +# bare names of constructors and destructors should be unique for GDB-6.8+. +Patch334: gdb-6.8-ctors-dtors-unique.patch +# Fix attaching to stopped processes and/or pending signals. +Patch337: gdb-6.8-attach-signalled-detach-stopped.patch +# Test the watchpoints conditionals works. +Patch343: gdb-6.8-watchpoint-conditionals-test.patch +# Fix resolving of variables at locations lists in prelinked libs (BZ 466901). +Patch348: gdb-6.8-bz466901-backtrace-full-prelinked.patch +# The merged branch `archer' of: http://sourceware.org/gdb/wiki/ProjectArcher +Patch349: gdb-archer.patch +# Fix parsing elf64-i386 files for kdump PAE vmcore dumps (BZ 457187). +# - Turn on 64-bit BFD support, globally enable AC_SYS_LARGEFILE. +Patch352: gdb-6.8-bz457187-largefile.patch +# Fix crash on pretty-printer reading uninitialized std::string (BZ 495781). +Patch357: gdb-c_get_string-xfree.patch +# Fix crash in the charset support. +Patch359: gdb-charset-crash.patch +# Fix readline 5.1 warnings +Patch1000: readline-5.1-random.patch +Patch1001: gdb-readline6.patch +BuildRequires: bison flex gettext glibc-devel libexpat-devel ncurses-devel texinfo zlib-devel +BuildRequires: readline-devel +# dlopen() no longer makes rpm-libs a mandatory dependency. +#Requires: rpm-libs +BuildRequires: rpm-devel +%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +BuildRequires: python-devel +# Temporarily before it gets moved to libstdc++.rpm +BuildRequires: libstdc++ +%if 0%{?_with_testsuite:1} +BuildRequires: dejagnu sharutils +# gcc-objc++ is not covered by the GDB testsuite. +BuildRequires: gcc gcc-c++ gcc-gfortran gcc-java gcc-objc +# Ensure the devel libraries are installed for both multilib arches. +%define multilib_64_archs sparc64 ppc64 s390x x86_64 +# Copied from gcc-4.1.2-32 +%ifarch %{ix86} x86_64 ia64 ppc alpha +BuildRequires: gcc-ada +%ifarch %{multilib_64_archs} ppc +BuildRequires: %{_exec_prefix}/lib/libgnat-4.4.so %{_exec_prefix}/lib64/libgnat-4.4.so +%endif +%endif +%ifarch %{multilib_64_archs} sparc sparcv9 ppc +BuildRequires: %{_exec_prefix}/lib/libc.so %{_exec_prefix}/lib64/libc.so /lib/libc.so.6 /lib64/libc.so.6 +BuildRequires: /lib/libgcc_s.so.1 /lib64/libgcc_s.so.1 +BuildRequires: %{_exec_prefix}/lib/libstdc++.so.6 %{_exec_prefix}/lib64/libstdc++.so.6 +BuildRequires: %{_exec_prefix}/lib/libgcj.so.10 %{_exec_prefix}/lib64/libgcj.so.10 +%endif +%endif +%ifarch ia64 +BuildRequires: libunwind-devel +Requires: libunwind +%endif +Requires(post): /sbin/install-info +Requires(preun): /sbin/install-info %description You can use GDB to debug programs written in C, C++, Ada, and Modula-2. @@ -93,8 +345,6 @@ Authors: License: GPL v2 or later; GPL v3 or later Summary: Remote Server for the GNU Debugger Group: Development/Tools/Debuggers -AutoReqProv: on -Provides: gdb:/usr/bin/gdbserver %description -n gdbserver GDBSERVER is a program that allows you to run GDB on a different @@ -121,98 +371,388 @@ Authors: Stu Grossman %prep -%setup -q -n %{name}-%{version}%{sss} -%patch -%patch1 -%patch3 -%patch4 -%patch5 -%patch6 -%patch7 -%patch8 -%patch9 -%patch10 -%patch11 -%patch305 -p1 +# This allows the tarball name to be different from our +# version-release name. +%setup -q -n %{gdb_src} +# Files have `# ' statements breaking VPATH / find-debuginfo.sh . +rm -f gdb/ada-exp.c gdb/ada-lex.c gdb/c-exp.c gdb/cp-name-parser.c gdb/f-exp.c +rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c +# Apply patches defined above. +# Match the Fedora's version info. +%patch2 -p1 +%if 0%{!?_with_upstream:1} +###patch232 -p1 +%patch349 -p1 +%patch1 -p1 +%patch3 -p1 +%patch4 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch111 -p1 +%patch112 -p1 +%patch116 -p1 +%patch117 -p1 +%patch118 -p1 +%patch122 -p1 +%patch125 -p1 +%patch128 -p1 +%patch133 -p1 +%patch134 -p1 +%patch136 -p1 +%patch140 -p1 +%patch141 -p1 +%patch259 -p1 +%patch142 -p1 +%patch145 -p1 +%patch148 -p1 +%patch150 -p1 +%patch151 -p1 +%patch153 -p1 +%patch157 -p1 +%patch158 -p1 +%patch160 -p1 +%patch161 -p1 +%patch162 -p1 +%patch163 -p1 +%patch164 -p1 +%patch166 -p1 +%patch169 -p1 +%patch170 -p1 +%patch176 -p1 +%patch177 -p1 +%patch188 -p1 +%patch190 -p1 +%patch194 -p1 +%patch195 -p1 +%patch196 -p1 +%patch199 -p1 +%patch200 -p1 +%patch201 -p1 +%patch208 -p1 +%patch209 -p1 +%patch211 -p1 +%patch213 -p1 +%patch214 -p1 +%patch215 -p1 +%patch216 -p1 +%patch217 -p1 +%patch225 -p1 +%patch229 -p1 +%patch231 -p1 +%patch234 -p1 +%patch235 -p1 +%patch240 -p1 +%patch241 -p1 +%patch245 -p1 +%patch247 -p1 +%patch249 -p1 +%patch254 -p1 +%patch258 -p1 +%patch260 -p1 +%patch261 -p1 +%patch263 -p1 +%patch265 -p1 +%patch266 -p1 +%patch271 -p1 +%patch274 -p1 +%patch353 -p1 +%patch280 -p1 +%patch282 -p1 +%patch284 -p1 +%patch287 -p1 +%patch289 -p1 +%patch290 -p1 +%patch293 -p1 +%patch294 -p1 +%patch296 -p1 +%patch298 -p1 +%patch304 -p1 +%patch309 -p1 +%patch311 -p1 +%patch314 -p1 +%patch315 -p1 +%patch317 -p1 +%patch318 -p1 +%patch320 -p1 +%patch322 -p1 +%patch324 -p1 +%patch326 -p1 %patch327 -p1 %patch350 -p1 %patch328 -p1 +%patch329 -p1 +%patch330 -p1 +%patch331 -p1 +%patch332 -p1 +%patch334 -p1 +%patch337 -p1 +%patch343 -p1 +%patch348 -p1 +%patch352 -p1 +%patch357 -p1 +%patch359 -p1 +%patch124 -p1 +%patch1000 +%if %{suse_version} > 1110 +%patch1001 +%endif +find -name "*.orig" | xargs rm -f +! find -name "*.rej" # Should not happen. +%endif # 0%{!?_with_upstream:1} +# Change the version that gets printed at GDB startup, so it is Fedora +# specific. +cat > gdb/version.in << _FOO +Fedora (%{version}-%{release}) +_FOO +# Remove the info and other generated files added by the FSF release +# process. +rm -f libdecnumber/gstdint.h +rm -f bfd/doc/*.info +rm -f bfd/doc/*.info-* +rm -f gdb/doc/*.info +rm -f gdb/doc/*.info-* %build -%ifarch %ix86 ia64 ppc ppc64 s390 s390x x86_64 -%define build_multitarget 1 -%else -%define build_multitarget 0 +# Identify the build directory with the version of gdb as well as the +# architecture, to allow for mutliple versions to be installed and +# built. +# Initially we're in the %{gdb_src} directory. +rm -fr %{gdb_build} +mkdir %{gdb_build} +cd %{gdb_build} +# g77 executable is no longer present in Fedora gcc-4.x+. +g77="`which gfortran 2>/dev/null || true`" +test -z "$g77" || ln -s "$g77" ./g77 +export CFLAGS="$RPM_OPT_FLAGS" +%if 0%{?_with_debug:1} +# --enable-werror could conflict with `-Wall -O0' but this is no longer true +# for recent GCCs. +CFLAGS="$CFLAGS -O0 -ggdb2" %endif -%define target_list i686 ia64 powerpc powerpc64 s390 s390x x86_64 -%define DIST %(echo '%distribution' | sed 's/ (.*)//') -%if %build_multitarget -EXTRA_TARGETS="%(printf ,%%s-suse-linux %target_list)" -EXTRA_TARGETS="$EXTRA_TARGETS,spu-elf" +../configure \ + --prefix=%{_prefix} \ + --libdir=%{_libdir} \ + --sysconfdir=%{_sysconfdir} \ + --mandir=%{_mandir} \ + --infodir=%{_infodir} \ + --with-gdb-datadir=%{_datadir}/gdb \ + --with-pythondir=%{python_sitelib} \ + --enable-gdb-build-warnings=,-Wno-unused \ +%ifnarch %{ix86} alpha ia64 ppc s390 s390x x86_64 ppc64 sparcv9 sparc64 + --disable-werror \ +%else +%if 0%{?_with_upstream:1} + --disable-werror \ %else -EXTRA_TARGETS= + --enable-werror \ %endif -./configure CFLAGS="$RPM_OPT_FLAGS" \ - --prefix=%{_prefix} --libdir=%{_libdir} --infodir=%{_infodir} \ - --mandir=%{_mandir} --with-system-readline \ +%endif + --with-separate-debug-dir=/usr/lib/debug \ + --disable-sim \ + --disable-rpath \ + --with-system-readline \ + --with-expat \ + --enable-tui \ + --with-python \ + --without-rpm \ %ifarch ia64 - --with-libunwind \ + --with-libunwind \ %else - --without-libunwind \ + --without-libunwind \ %endif - --with-separate-debug-dir=%{_prefix}/lib/debug \ - --enable-64-bit-bfd --disable-werror --disable-sim \ - --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion="GDB; %{DIST}" \ - --build=%{_target_cpu}-suse-linux \ - ${EXTRA_TARGETS:+--enable-targets="${EXTRA_TARGETS#,}"} -make %{?jobs:-j%jobs} -make info + --enable-64-bit-bfd \ +%if 0%{?_with_debug:1} + --enable-static --disable-shared --enable-debug \ +%endif +%ifarch sparcv9 + sparc-%{_vendor}-%{_target_os}%{?_gnu} +%else + %{_target_platform} +%endif +make %{?_smp_mflags} +make %{?_smp_mflags} info +# Copy the /gdb/NEWS file to the directory above it. +cp $RPM_BUILD_DIR/%{gdb_src}/gdb/NEWS $RPM_BUILD_DIR/%{gdb_src} %check -ulimit -c $(ulimit -Hc) -TERM=dumb \ -make -k check || : +# Initially we're in the %{gdb_src} directory. +cd %{gdb_build} +%if 0%{!?_with_testsuite:1} +echo ====================TESTSUITE DISABLED========================= +%else +echo ====================TESTING========================= +cd gdb +gcc -o ./orphanripper %{SOURCE2} -Wall -lutil +# Need to use a single --ignore option, second use overrides first. +# No `%{?_smp_mflags}' here as it may race. +# WARNING: can't generate a core file - core tests suppressed - check ulimit +# "readline-overflow.exp" - Testcase is broken, functionality is OK. +( + # ULIMIT required for `gdb.base/auxv.exp'. + ulimit -H -c + ulimit -c unlimited || : + # Setup $CHECK as `check//unix/' or `check//unix/-m64' for explicit bitsize. + # Never use two different bitsizes as it fails on ppc64. + echo 'int main (void) { return 0; }' >biarch.c + CHECK="" + for BI in -m64 -m32 -m31 "" + do + # Do not use size-less options if any of the sizes works. + # On ia64 there is no -m64 flag while we must not leave a bare `check' here + # as it would switch over some testing scripts to the backward compatibility + # mode: when `make check' was executed from inside the testsuite/ directory. + if [ -z "$BI" -a -n "$CHECK" ];then + continue + fi + # Do not use $RPM_OPT_FLAGS as the other non-size options will not be used + # in the real run of the testsuite. + if ! gcc $BI -o biarch biarch.c + then + continue + fi + CHECK="$CHECK check//unix/$BI" + done + # Do not try -m64 inferiors for -m32 GDB as it cannot handle inferiors larger + # than itself. + # s390 -m31 still uses the standard ELF32 binary format. + gcc $RPM_OPT_FLAGS -o biarch biarch.c + RPM_SIZE="$(file ./biarch|sed -n 's/^.*: ELF \(32\|64\)-bit .*$/\1/p')" + if [ "$RPM_SIZE" != "64" ] + then + CHECK="$(echo " $CHECK "|sed 's# check//unix/-m64 # #')" + fi + # Disable some problematic testcases. + # RUNTESTFLAGS='--ignore ...' is not used below as it gets separated by the + # `check//...' target spawn and too much escaping there would be dense. + for test in \ + gdb.base/readline-overflow.exp \ + gdb.base/bigcore.exp \ + ; do + mv -f ../../gdb/testsuite/$test ../gdb/testsuite/$test-DISABLED || : + done +%if 0%{!?_with_upstream:1} + # Run all the scheduled testsuite runs also in the PIE mode. + # Upstream GDB would lock up the testsuite run for too long on its failures. + CHECK="$(echo $CHECK|sed 's#check//unix/[^ ]*#& &/-fPIE/-pie#g')" +%endif # 0%{!?_with_upstream:1} + for CURRENT in $CHECK + do + ./orphanripper make -k $CURRENT || : + done +) +for t in sum log +do + for file in testsuite*/gdb.$t + do + suffix="${file#testsuite.unix.}" + suffix="${suffix%/gdb.$t}" + ln $file gdb-%{_target_platform}$suffix.$t || : + done +done +# `tar | bzip2 | uuencode' may have some piping problems in Brew. +tar cjf gdb-%{_target_platform}.tar.bz2 gdb-%{_target_platform}*.{sum,log} +uuencode gdb-%{_target_platform}.tar.bz2 gdb-%{_target_platform}.tar.bz2 +cd ../.. +echo ====================TESTING END===================== +%endif %install -make install-gdb install-info-gdb DESTDIR="$RPM_BUILD_ROOT" -install -m 755 gdb/gdb_gcore.sh $RPM_BUILD_ROOT%{_bindir}/gcore -rm -f $RPM_BUILD_ROOT%{_bindir}/gdbtui -rm -f $RPM_BUILD_ROOT%{_mandir}/man1/gdbtui.1 -rm -f $RPM_BUILD_ROOT%{_infodir}/stabs.info* +# Initially we're in the %{gdb_src} directory. +cd %{gdb_build} +rm -rf $RPM_BUILD_ROOT +make %{?_smp_mflags} install DESTDIR=$RPM_BUILD_ROOT +# install the gcore script in /usr/bin +cp $RPM_BUILD_DIR/%{gdb_src}/gdb/gdb_gcore.sh $RPM_BUILD_ROOT%{_bindir}/gcore +chmod 755 $RPM_BUILD_ROOT%{_bindir}/gcore +# Remove the gdb/gdbtui binaries duplicity. +test -x $RPM_BUILD_ROOT%{_prefix}/bin/gdbtui +ln -sf gdb $RPM_BUILD_ROOT%{_prefix}/bin/gdbtui +cmp $RPM_BUILD_ROOT%{_mandir}/*/gdb.1 $RPM_BUILD_ROOT%{_mandir}/*/gdbtui.1 +ln -sf gdb.1 $RPM_BUILD_ROOT%{_mandir}/*/gdbtui.1 +# In the future: +#%# A part of the libstdc++ rpm. +#%rm -rf $RPM_BUILD_ROOT%{python_sitelib}/gdb/libstdcxx +# Temporarily now: +for LIB in lib lib64;do + LIBPATH="$RPM_BUILD_ROOT%{_datadir}/gdb/auto-load%{_prefix}/$LIB" + mkdir -p $LIBPATH + # basename is being run only for the native (non-biarch) file. + sed -e 's,@dir@,%{python_sitelib}/gdb,' <$RPM_BUILD_DIR/%{gdb_src}/gdb/python/lib/gdb/libstdcxx/v6/hook.in \ + >$LIBPATH/$(basename %{_prefix}/%{_lib}/libstdc++.so.6.*)-gdb.py +done +# Remove the files that are part of a gdb build but that are owned and +# provided by other packages. +# These are part of binutils +rm -rf $RPM_BUILD_ROOT%{_datadir}/locale/ +rm -f $RPM_BUILD_ROOT%{_infodir}/bfd* +rm -f $RPM_BUILD_ROOT%{_infodir}/standard* +rm -f $RPM_BUILD_ROOT%{_infodir}/mmalloc* +rm -f $RPM_BUILD_ROOT%{_infodir}/configure* +rm -rf $RPM_BUILD_ROOT%{_includedir} +rm -rf $RPM_BUILD_ROOT/%{_libdir}/lib{bfd*,opcodes*,iberty*,mmalloc*} +# Delete this too because the dir file will be updated at rpm install time. +# We don't want a gdb specific one overwriting the system wide one. +rm -f $RPM_BUILD_ROOT%{_infodir}/dir +%if 0%{!?_with_upstream:1} +# pstack obsoletion +cp -p %{SOURCE3} $RPM_BUILD_ROOT%{_mandir}/man1/gstack.1 +%endif # 0%{!?_with_upstream:1} %clean rm -rf $RPM_BUILD_ROOT %post -%install_info --info-dir=%{_infodir} %{_infodir}/annotate.info.gz -%install_info --info-dir=%{_infodir} %{_infodir}/gdb.info.gz -%install_info --info-dir=%{_infodir} %{_infodir}/gdbint.info.gz +# This step is part of the installation of the RPM. Not to be confused +# with the 'make install ' of the build (rpmbuild) process. +/sbin/install-info --info-dir=%{_infodir} %{_infodir}/annotate.info.gz || : +/sbin/install-info --info-dir=%{_infodir} %{_infodir}/gdb.info.gz || : +/sbin/install-info --info-dir=%{_infodir} %{_infodir}/gdbint.info.gz || : +/sbin/install-info --info-dir=%{_infodir} %{_infodir}/stabs.info.gz || : -%postun -%install_info_delete --info-dir=%{_infodir} %{_infodir}/annotate.info.gz -%install_info_delete --info-dir=%{_infodir} %{_infodir}/gdb.info.gz -%install_info_delete --info-dir=%{_infodir} %{_infodir}/gdbint.info.gz +%preun +if [ $1 = 0 ]; then + /sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/annotate.info.gz || : + /sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/gdb.info.gz || : + /sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/gdbint.info.gz || : + /sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/stabs.info.gz || : +fi %files %defattr(-,root,root) -%doc COPYING COPYING.LIB gdb/README gdb/NEWS -%{_bindir}/gdb -%{_bindir}/gstack +%doc COPYING COPYING.LIB README NEWS %{_bindir}/gcore -%{_mandir}/man1/gdb.1.gz -%{_infodir}/annotate.info*.gz -%{_infodir}/gdb.info*.gz -%{_infodir}/gdbint.info*.gz -%ifnarch alpha sparc sparc64 +%{_bindir}/gdb +%{_bindir}/gdbtui +%{_mandir}/*/gdb.1* +%{_mandir}/*/gdbtui.1* +%if 0%{!?_with_upstream:1} +%{_bindir}/gstack +%{_mandir}/*/gstack.1* +%{python_sitelib}/gdb +%{_datadir}/gdb +%endif # 0%{!?_with_upstream:1} +%{_infodir}/annotate.info* +%{_infodir}/gdb.info* +%{_infodir}/gdbint.info* +%{_infodir}/stabs.info* +# don't include the files in include, they are part of binutils +%ifnarch sparcv9 %files -n gdbserver %defattr(-,root,root) -%doc gdb/gdbserver/README %{_bindir}/gdbserver -%{_mandir}/man1/gdbserver.1.gz +%{_mandir}/*/gdbserver.1* %endif %changelog +* Wed Apr 29 2009 rguenther@suse.de +- Adjust package name and release to not contain macros. +* Mon Apr 27 2009 rguenther@suse.de +- Disable rpm support for locating debug info packages. +* Mon Apr 27 2009 rguenther@suse.de +- Switch to Fedora 11 source RPM. + * includes partially merge from Archer. [bnc#329420, bnc#497141] * Tue Mar 10 2009 rguenther@suse.de - Add VLA support patch from Fedora to fix possible dwarf_expr_frame_base NULL checking regression. @@ -642,7 +1182,7 @@ rm -rf $RPM_BUILD_ROOT used it, and only gdbserver implemented it. * Sat Dec 02 2006 schwab@suse.de - Update to gdb 6.5.90. -* Fri Oct 27 2006 schwab@suse.de +* Sat Oct 28 2006 schwab@suse.de - Rename detach-fork to detach fork. * Tue Oct 24 2006 schwab@suse.de - Better fix for function descriptor handling on ppc64. @@ -667,7 +1207,7 @@ rm -rf $RPM_BUILD_ROOT - Fix a parallel build problem. * Tue Apr 04 2006 schwab@suse.de - Relocate PIEs. -* Sun Mar 26 2006 schwab@suse.de +* Mon Mar 27 2006 schwab@suse.de - Handle .eh_frame register encoding that is different from .dwarf_frame. - Remove obsolete patch. * Wed Jan 25 2006 mls@suse.de @@ -942,7 +1482,7 @@ rm -rf $RPM_BUILD_ROOT - add gdb-4.17.0.12 as /usr/bin/gdb-4.17 * Wed Jul 07 1999 kukuk@suse.de - update to 4.18 using diff from jurix -* Mon Feb 22 1999 ro@suse.de +* Tue Feb 23 1999 ro@suse.de - update to 4.17.0.11 using diff from jurix * Thu Jan 21 1999 ro@suse.de - update to 4.17.0.8 diff --git a/pie-relocate.diff b/pie-relocate.diff deleted file mode 100644 index 7e39e3d..0000000 --- a/pie-relocate.diff +++ /dev/null @@ -1,586 +0,0 @@ ---- gdb/breakpoint.c -+++ gdb/breakpoint.c -@@ -3876,6 +3876,7 @@ 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_startup_disabled || - b->enable_state == bp_call_disabled) - ? " (disabled)" - : b->enable_state == bp_permanent -@@ -3947,6 +3948,7 @@ check_duplicates_for (CORE_ADDR address, - ALL_BP_LOCATIONS (b) - if (b->owner->enable_state != bp_disabled - && b->owner->enable_state != bp_call_disabled -+ && b->owner->enable_state != bp_startup_disabled - && b->enabled - && !b->shlib_disabled - && b->address == address /* address / overlay match */ -@@ -3982,6 +3984,7 @@ check_duplicates_for (CORE_ADDR address, - { - if (b->owner->enable_state != bp_disabled - && b->owner->enable_state != bp_call_disabled -+ && b->owner->enable_state != bp_startup_disabled - && b->enabled && !b->shlib_disabled - && b->address == address /* address / overlay match */ - && (!overlay_debugging || b->section == section) -@@ -4707,6 +4710,60 @@ create_catchpoint (int tempflag, char *c - return b; - } - -+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 && !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) -+ { -+ gdb_byte 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) -+ b->enable_state = bp_enabled; -+ } -+ } -+} -+ -+ - static void - create_fork_vfork_event_catchpoint (int tempflag, char *cond_string, - struct breakpoint_ops *ops) -@@ -7435,6 +7492,7 @@ breakpoint_re_set_one (void *bint) - if (not_found - && (b->condition_not_parsed - || (b->loc && b->loc->shlib_disabled) -+ || b->enable_state == bp_startup_disabled - || b->enable_state == bp_disabled)) - not_found_and_ok = 1; - ---- gdb/breakpoint.h -+++ gdb/breakpoint.h -@@ -126,6 +126,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 -@@ -820,6 +821,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 *); - ---- gdb/dwarf2read.c -+++ gdb/dwarf2read.c -@@ -1285,7 +1285,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)) - { ---- gdb/elfread.c -+++ gdb/elfread.c -@@ -680,7 +680,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; ---- gdb/ia64-tdep.c -+++ gdb/ia64-tdep.c -@@ -3361,8 +3361,13 @@ ia64_convert_from_func_ptr_addr (struct - the target address itself points to a section that is executable. */ - if (s && (s->the_bfd_section->flags & SEC_CODE) == 0) - { -- CORE_ADDR pc = read_memory_unsigned_integer (addr, 8); -- struct obj_section *pc_section = find_pc_section (pc); -+ char buf[8]; -+ CORE_ADDR pc; -+ struct obj_section *pc_section; -+ if (target_read_memory (addr, buf, sizeof (buf)) != 0) -+ return addr; -+ pc = extract_unsigned_integer (buf, sizeof (buf)); -+ pc_section = find_pc_section (pc); - - if (pc_section && (pc_section->the_bfd_section->flags & SEC_CODE)) - return pc; ---- gdb/infrun.c -+++ gdb/infrun.c -@@ -2233,6 +2233,11 @@ handle_inferior_event (struct execution_ - #endif - target_terminal_inferior (); - -+ /* For PIE executables, we don't 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 -@@ -3193,6 +3198,11 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( - #endif - target_terminal_inferior (); - -+ /* For PIE executables, we don't 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 ---- gdb/objfiles.c -+++ gdb/objfiles.c -@@ -50,6 +50,8 @@ - #include "addrmap.h" - #include "arch-utils.h" - #include "exec.h" -+#include "auxv.h" -+#include "elf/common.h" - - /* Prototypes for local functions */ - -@@ -271,7 +273,16 @@ 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 (¤t_target, AT_ENTRY, &entry_addr); -+ if (ret > 0) -+ return entry_addr; -+ else -+ return symfile_objfile ? symfile_objfile->ei.entry_point : 0; - } - - /* Create the terminating entry of OBJFILE's minimal symbol table. ---- gdb/solib-svr4.c -+++ gdb/solib-svr4.c -@@ -32,6 +32,7 @@ - #include "gdbcore.h" - #include "target.h" - #include "inferior.h" -+#include "command.h" - #include "gdbthread.h" - - #include "gdb_assert.h" -@@ -287,8 +288,6 @@ static CORE_ADDR main_lm_addr; - - /* Local function prototypes */ - --static int match_main (char *); -- - static CORE_ADDR bfd_lookup_symbol (bfd *, char *); - - /* -@@ -525,6 +524,8 @@ scan_dyntag (int dyntag, bfd *abfd, CORE - Elf32_External_Dyn *x_dynp_32; - Elf64_External_Dyn *x_dynp_64; - struct bfd_section *sect; -+ CORE_ADDR relocated_dyn_addr, entry_addr; -+ int ret; - - if (abfd == NULL) - return 0; -@@ -532,11 +533,20 @@ scan_dyntag (int dyntag, bfd *abfd, CORE - if (arch_size == -1) - return 0; - -+ /* Find the address of the entry point of the program from the -+ auxv vector. */ -+ ret = target_auxv_search (¤t_target, AT_ENTRY, &entry_addr); -+ if (ret <= 0) -+ /* No auxv info, maybe an older kernel. Fake our way through. */ -+ entry_addr = bfd_get_start_address (exec_bfd); -+ - /* Find the start address of the .dynamic section. */ - sect = bfd_get_section_by_name (abfd, ".dynamic"); - if (sect == NULL) - return 0; - dyn_addr = bfd_section_vma (abfd, sect); -+ relocated_dyn_addr -+ = dyn_addr + entry_addr - bfd_get_start_address (exec_bfd); - - /* Read in .dynamic from the BFD. We will get the actual value - from memory later. */ -@@ -578,7 +588,7 @@ scan_dyntag (int dyntag, bfd *abfd, CORE - CORE_ADDR ptr_addr; - - ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; -- ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8; -+ ptr_addr = relocated_dyn_addr + (buf - bufstart) + arch_size / 8; - if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0) - dyn_ptr = extract_typed_address (ptr_buf, ptr_type); - *ptr = dyn_ptr; -@@ -984,11 +994,55 @@ svr4_current_sos (void) - decide when to ignore it. */ - if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0) - { -+ /* It is the first link map entry, i.e. it is the main -+ executable. */ - main_lm_addr = new->lm_info->lm_addr; -- free_so (new); -+ 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; -+ -+ 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_relocated = 0; -+ -+ for (gdb_solib = master_so_list (); -+ gdb_solib != NULL; -+ gdb_solib = gdb_solib->next) -+ if (strcmp (gdb_solib->so_name, new->so_name) == 0 -+ && gdb_solib->main_relocated) -+ break; -+ -+ if (gdb_solib == NULL) -+ { -+ add_to_target_sections (0 /*from_tty*/, ¤t_target, new); -+ new->main_p = 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; -+ } - } - 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; - -@@ -1006,10 +1060,8 @@ svr4_current_sos (void) - } - 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)) -+ /* If this entry has no name, don't include it in the list. */ -+ if (! new->so_name[0]) - free_so (new); - else - { -@@ -1060,24 +1112,6 @@ svr4_fetch_objfile_link_map (struct objf - return 0; - } - --/* 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. */ -- --static int --match_main (char *soname) --{ -- char **mainp; -- -- for (mainp = main_name_list; *mainp != NULL; mainp++) -- { -- if (strcmp (soname, *mainp) == 0) -- return (1); -- } -- -- return (0); --} -- - /* Return 1 if PC lies in the dynamic symbol resolution code of the - SVR4 run time loader. */ - static CORE_ADDR interp_text_sect_low; -@@ -1607,6 +1641,8 @@ svr4_solib_create_inferior_hook (void) - while (tp->stop_signal != TARGET_SIGNAL_TRAP); - inf->stop_soon = NO_STOP_QUIETLY; - #endif /* defined(_SCO_DS) */ -+ -+ disable_breakpoints_at_startup (1); - } - - static void ---- gdb/solib.c -+++ gdb/solib.c -@@ -466,15 +466,37 @@ 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_p) - 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. Therefore 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_p -+ && so->main_relocated) -+ return 1; - } - - sap = build_section_addr_info_from_section_table (so->sections, - so->sections_end); - -- so->objfile = symbol_file_add_from_bfd (so->abfd, so->from_tty, -- sap, 0, OBJF_SHARED | OBJF_KEEPBFD); -+ if (so->main_p) -+ { -+ so->objfile = symbol_file_add_from_bfd (so->abfd, 0, -+ sap, 1, OBJF_KEEPBFD); -+ so->main_relocated = 1; -+ } -+ else -+ so->objfile = symbol_file_add_from_bfd (so->abfd, so->from_tty, -+ sap, 0, OBJF_SHARED | OBJF_KEEPBFD); -+ - free_section_addr_info (sap); - - return (1); -@@ -660,28 +682,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. */ -@@ -777,6 +778,39 @@ 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_p) -+ 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); -+ memcpy (target->to_sections + space, -+ solib->sections, -+ count * sizeof (solib->sections[0])); -+ } -+ } -+} -+ - - /* - ---- gdb/solist.h -+++ gdb/solist.h -@@ -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_p; /* 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; -@@ -142,6 +144,10 @@ extern bfd *solib_bfd_fopen (char *pathn - /* Find solib binary file and open it. */ - extern bfd *solib_bfd_open (char *in_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; - ---- gdb/symfile-mem.c -+++ gdb/symfile-mem.c -@@ -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 (); ---- gdb/symfile.c -+++ gdb/symfile.c -@@ -784,7 +784,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. */ -@@ -812,7 +812,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 (addrs && addrs->other[0].name) - { - asection *lower_sect; - asection *sect; -@@ -914,14 +914,14 @@ 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 (); - } -@@ -967,7 +967,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.")); -@@ -1156,6 +1156,11 @@ 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 -@@ -2442,6 +2447,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. */ diff --git a/readnever.patch b/readnever.patch deleted file mode 100644 index cb66f08..0000000 --- a/readnever.patch +++ /dev/null @@ -1,59 +0,0 @@ -2004-11-18 Andrew Cagney - - * dwarf2read.c: Include "top.c". - (dwarf2_has_info): Check for readnever_symbol_files. - * symfile.c (readnever_symbol_files): Define. - * top.h (readnever_symbol_files): Declare. - * main.c (captured_main): Add --readnever option. - -================================================================================ ---- gdb/dwarf2read.c -+++ gdb/dwarf2read.c -@@ -46,6 +46,7 @@ - #include "command.h" - #include "gdbcmd.h" - #include "addrmap.h" -+#include "top.h" - - #include - #include "gdb_string.h" -@@ -1094,7 +1095,8 @@ dwarf2_has_info (struct objfile *objfile - dwarf_loc_section = 0; - - bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL); -- return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL); -+ return (!readnever_symbol_files -+ && dwarf_info_section != NULL && dwarf_abbrev_section != NULL); - } - - /* When loading sections, we can either look for ".", or for ---- gdb/main.c -+++ gdb/main.c -@@ -295,6 +295,7 @@ captured_main (void *data) - {"xdb", no_argument, &xdb_commands, 1}, - {"dbx", no_argument, &dbx_commands, 1}, - {"readnow", no_argument, &readnow_symbol_files, 1}, -+ {"readnever", no_argument, &readnever_symbol_files, 1}, - {"r", no_argument, &readnow_symbol_files, 1}, - {"quiet", no_argument, &quiet, 1}, - {"q", no_argument, &quiet, 1}, ---- gdb/symfile.c -+++ gdb/symfile.c -@@ -76,6 +76,7 @@ static void clear_symtab_users_cleanup ( - - /* Global variables owned by this file */ - int readnow_symbol_files; /* Read full symbols immediately */ -+int readnever_symbol_files; /* Never read full symbols. */ - - /* External variables and functions referenced. */ - ---- gdb/top.h -+++ gdb/top.h -@@ -59,6 +59,7 @@ extern void set_prompt (char *); - - /* From random places. */ - extern int readnow_symbol_files; -+extern int readnever_symbol_files; - - /* Perform _initialize initialization */ - extern void gdb_init (char *); diff --git a/sect-index-text.diff b/sect-index-text.diff deleted file mode 100644 index f6b33a4..0000000 --- a/sect-index-text.diff +++ /dev/null @@ -1,25 +0,0 @@ ---- gdb/dwarf2read.c.~1.217.~ 2007-04-12 11:24:48.000000000 +0200 -+++ gdb/dwarf2read.c 2007-04-13 15:37:15.000000000 +0200 -@@ -1194,6 +1194,9 @@ dwarf2_locate_sections (bfd *abfd, asect - void - dwarf2_build_psymtabs (struct objfile *objfile, int mainline) - { -+ if (objfile->sect_index_text == -1) -+ return; -+ - /* We definitely need the .debug_info and .debug_abbrev sections */ - - dwarf2_per_objfile->info_buffer = dwarf2_read_section (objfile, dwarf_info_section); ---- gdb/ia64-tdep.c 28 Mar 2007 18:56:06 -0000 1.148 -+++ gdb/ia64-tdep.c 13 Apr 2007 12:30:47 -0000 -@@ -2692,6 +2692,10 @@ ia64_get_dyn_info_list (unw_addr_space_t - { - void *buf = NULL; - -+ if (objfile->sect_index_text == -1) -+ /* No text section. */ -+ continue; -+ - text_sec = objfile->sections + SECT_OFF_TEXT (objfile); - ip = text_sec->addr; - ret = ia64_find_unwind_table (objfile, ip, &di, &buf);