2006-12-28 Daniel Jacobowitz * ia64-tdep.c (get_kernel_table): Correct signedness in check for a negative return value. --- ./gdb/ia64-tdep.c 12 Jul 2006 18:13:45 -0000 1.140 +++ ./gdb/ia64-tdep.c 28 Dec 2006 23:48:51 -0000 1.141 @@ -2486,13 +2486,14 @@ get_kernel_table (unw_word_t ip, unw_dyn if (!ktab) { gdb_byte *ktab_buf; - size_t size; + LONGEST size; - ktab_size = getunwind_table (&ktab_buf); - if (ktab_size <= 0) + size = getunwind_table (&ktab_buf); + if (size <= 0) return -UNW_ENOINFO; - else - ktab = (struct ia64_table_entry *) ktab_buf; + + ktab = (struct ia64_table_entry *) ktab_buf; + ktab_size = size; for (etab = ktab; etab->start_offset; ++etab) etab->info_offset += KERNEL_START; 2007-01-11 Daniel Jacobowitz * frame.c (get_prev_frame_1): Check PC_REGNUM before using it. --- ./gdb/frame.c 9 Jan 2007 20:19:15 -0000 1.218 +++ ./gdb/frame.c 11 Jan 2007 17:18:22 -0000 1.219 @@ -1221,10 +1221,17 @@ get_prev_frame_1 (struct frame_info *thi have different frame IDs, the new frame will be bogus; two functions can't share a register save slot for the PC. This can happen when the prologue analyzer finds a stack adjustment, but - no PC save. This check does assume that the "PC register" is - roughly a traditional PC, even if the gdbarch_unwind_pc method - frobs it. */ + no PC save. + + This check does assume that the "PC register" is roughly a + traditional PC, even if the gdbarch_unwind_pc method adjusts + it (we do not rely on the value, only on the unwound PC being + dependent on this value). A potential improvement would be + to have the frame prev_pc method and the gdbarch unwind_pc + method set the same lval and location information as + frame_register_unwind. */ if (this_frame->level > 0 + && PC_REGNUM >= 0 && get_frame_type (this_frame) == NORMAL_FRAME && get_frame_type (this_frame->next) == NORMAL_FRAME) { 2007-01-20 Daniel Jacobowitz * arch-utils.c (show_endian): Correct reversed condition. --- ./gdb/arch-utils.c 13 Jan 2007 23:24:43 -0000 1.138 +++ ./gdb/arch-utils.c 20 Jan 2007 18:16:33 -0000 @@ -322,7 +322,7 @@ static void show_endian (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - if (target_byte_order_user != BFD_ENDIAN_UNKNOWN) + if (target_byte_order_user == BFD_ENDIAN_UNKNOWN) if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) fprintf_unfiltered (file, _("The target endianness is set automatically " "(currently big endian)\n")); https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=224128 2007-01-26 Jan Kratochvil * c-valprint.c (c_val_print): Require strings to be of no-signed CHARs. * NEWS: Describe CHAR array vs. string identifcation rules. 2007-01-26 Jan Kratochvil Eli Zaretskii * gdb.texinfo: Describe CHAR array vs. string identifcation rules. 2007-01-25 Jan Kratochvil * gdb.base/charsign.exp, gdb.base/charsign.c: New files. * gdb.arch/i386-sse.exp: Check $xmm.v16_int8 printing as a number array. * gdb.base/printcmds.exp: Sign-provided CHARs now became arrays. * gdb.base/setvar.exp: Likewise. --- ./gdb/NEWS 21 Jan 2007 17:48:53 -0000 1.211 +++ ./gdb/NEWS 26 Jan 2007 10:31:48 -0000 @@ -15,6 +15,9 @@ frequency signals (e.g. SIGALRM) via the target's overall architecture. GDB can read a description from a local file or over the remote serial protocol. +* Arrays of explicitly SIGNED or UNSIGNED CHARs are now printed as arrays + of numbers. + * New commands set mem inaccessible-by-default --- ./gdb/c-valprint.c 9 Jan 2007 17:58:50 -0000 1.41 +++ ./gdb/c-valprint.c 26 Jan 2007 10:31:48 -0000 @@ -96,7 +96,7 @@ c_val_print (struct type *type, const gd } /* For an array of chars, print with string syntax. */ if (eltlen == 1 && - ((TYPE_CODE (elttype) == TYPE_CODE_INT) + ((TYPE_CODE (elttype) == TYPE_CODE_INT && TYPE_NOSIGN (elttype)) || ((current_language->la_language == language_m2) && (TYPE_CODE (elttype) == TYPE_CODE_CHAR))) && (format == 0 || format == 's')) --- ./gdb/doc/gdb.texinfo 26 Jan 2007 08:54:01 -0000 1.380 +++ ./gdb/doc/gdb.texinfo 26 Jan 2007 10:32:00 -0000 @@ -5632,6 +5632,26 @@ If you ask to print an object whose cont by the debug information, @value{GDBN} will say @samp{}. @xref{Symbols, incomplete type}, for more about this. +Strings are identified as arrays of @code{char} values without specified +signedness. Arrays of either @code{signed char} or @code{unsigned char} get +printed as arrays of 1 byte sized integers. @code{-fsigned-char} or +@code{-funsigned-char} @value{NGCC} options have no effect as @value{GDBN} +defines literal string type @code{"char"} as @code{char} without a sign. +For program code + +@smallexample +char var0[] = "A"; +signed char var1[] = "A"; +@end smallexample + +You get during debugging +@smallexample +(gdb) print var0 +$1 = "A" +(gdb) print var1 +$2 = @{65 'A', 0 '\0'@} +@end smallexample + @node Arrays @section Artificial arrays --- ./gdb/testsuite/gdb.arch/i386-sse.exp 9 Jan 2007 17:59:09 -0000 1.5 +++ ./gdb/testsuite/gdb.arch/i386-sse.exp 26 Jan 2007 10:32:00 -0000 @@ -83,7 +83,10 @@ gdb_continue_to_breakpoint "continue to foreach r {0 1 2 3 4 5 6 7} { gdb_test "print \$xmm$r.v4_float" \ ".. = \\{$r, $r.25, $r.5, $r.75\\}.*" \ - "check contents of %xmm$r" + "check float contents of %xmm$r" + gdb_test "print \$xmm$r.v16_int8" \ + ".. = \\{(-?\[0-9\]+ '.*', ){15}-?\[0-9\]+ '.*'\\}.*" \ + "check int8 contents of %xmm$r" } foreach r {0 1 2 3 4 5 6 7} { --- /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} --- ./gdb/testsuite/gdb.base/printcmds.exp 9 Jan 2007 17:59:11 -0000 1.14 +++ ./gdb/testsuite/gdb.base/printcmds.exp 26 Jan 2007 10:32:01 -0000 @@ -590,18 +590,18 @@ proc test_print_char_arrays {} { gdb_test "set print address on" "" gdb_test "p arrays" \ - " = {array1 = \"abc\", array2 = \"d\", array3 = \"e\", array4 = \"fg\", array5 = \"hij\"}" + " = \\{array1 = \\{97 'a', 98 'b', 99 'c', 0 '\\\\0'\\}, array2 = \\{100 'd'\\}, array3 = \\{101 'e'\\}, array4 = \\{102 'f', 103 'g'\\}, array5 = \\{104 'h', 105 'i', 106 'j', 0 '\\\\0'\\}\\}" gdb_test "p parrays" " = \\(struct some_arrays \\*\\) $hex" - gdb_test "p parrays->array1" " = \"abc\"" + gdb_test "p parrays->array1" " = \\{97 'a', 98 'b', 99 'c', 0 '\\\\0'\\}" gdb_test "p &parrays->array1" " = \\(unsigned char \\(\\*\\)\\\[4\\\]\\) $hex" - gdb_test "p parrays->array2" " = \"d\"" + gdb_test "p parrays->array2" " = \\{100 'd'\\}" gdb_test "p &parrays->array2" " = \\(unsigned char \\(\\*\\)\\\[1\\\]\\) $hex" - gdb_test "p parrays->array3" " = \"e\"" + gdb_test "p parrays->array3" " = \\{101 'e'\\}" gdb_test "p &parrays->array3" " = \\(unsigned char \\(\\*\\)\\\[1\\\]\\) $hex" - gdb_test "p parrays->array4" " = \"fg\"" + gdb_test "p parrays->array4" " = \\{102 'f', 103 'g'\\}" gdb_test "p &parrays->array4" " = \\(unsigned char \\(\\*\\)\\\[2\\\]\\) $hex" - gdb_test "p parrays->array5" " = \"hij\"" + gdb_test "p parrays->array5" " = \\{104 'h', 105 'i', 106 'j', 0 '\\\\0'\\}" gdb_test "p &parrays->array5" " = \\(unsigned char \\(\\*\\)\\\[4\\\]\\) $hex" gdb_test "set print address off" "" --- ./gdb/testsuite/gdb.base/setvar.exp 9 Jan 2007 17:59:11 -0000 1.10 +++ ./gdb/testsuite/gdb.base/setvar.exp 26 Jan 2007 10:32:01 -0000 @@ -233,11 +233,11 @@ test_set "set variable v_char_array\[0\] # # test "set variable" for "signed char array[2]" # -test_set "set variable v_signed_char_array\[0\]='h'" "set variable v_signed_char_array\[1\]='i'" "print v_signed_char_array" ".*.\[0-9\]* =.*\"hi\"" "set variable signed char array=\"hi\" (string)" +test_set "set variable v_signed_char_array\[0\]='h'" "set variable v_signed_char_array\[1\]='i'" "print v_signed_char_array" ".*.\[0-9\]* =.*\\{104 'h', 105 'i'\\}" "set variable signed char array=\"hi\" (string)" # # test "set variable" for "unsigned char array[2]" # -test_set "set variable v_unsigned_char_array\[0\]='h'" "set variable v_unsigned_char_array\[1\]='i'" "print v_unsigned_char_array" ".*.\[0-9\]* =.*\"hi\"" "set variable unsigned char array=\"hi\" (string)" +test_set "set variable v_unsigned_char_array\[0\]='h'" "set variable v_unsigned_char_array\[1\]='i'" "print v_unsigned_char_array" ".*.\[0-9\]* =.*\\{104 'h', 105 'i'\\}" "set variable unsigned char array=\"hi\" (string)" # # test "set variable" for "short array[2]" # @@ -289,11 +289,11 @@ test_set "set v_char_pointer=v_char_arra # # test "set variable" for type "signed char *" # -test_set "set v_signed_char_pointer=v_signed_char_array" "set variable *(v_signed_char_pointer)='h'" "set variable *(v_signed_char_pointer+1)='i'" "print v_signed_char_array" ".*.\[0-9\]* =.*\"hi\"" "print *(v_signed_char_pointer+1)" ".*.\[0-9\]* = 105 \'i\'" "set variable signed char pointer=\"hi\" (string)" +test_set "set v_signed_char_pointer=v_signed_char_array" "set variable *(v_signed_char_pointer)='h'" "set variable *(v_signed_char_pointer+1)='i'" "print v_signed_char_array" ".*.\[0-9\]* =.*\\{104 'h', 105 'i'\\}" "print *(v_signed_char_pointer+1)" ".*.\[0-9\]* = 105 \'i\'" "set variable signed char pointer=\"hi\" (string)" # # test "set variable" for type "unsigned char *" # -test_set "set v_unsigned_char_pointer=v_unsigned_char_array" "set variable *(v_unsigned_char_pointer)='h'" "set variable *(v_unsigned_char_pointer+1)='i'" "print v_unsigned_char_array" ".*.\[0-9\]* =.*\"hi\"" "print *(v_unsigned_char_pointer+1)" ".*.\[0-9\]* = 105 \'i\'" "set variable unsigned char pointer=\"hi\" (string)" +test_set "set v_unsigned_char_pointer=v_unsigned_char_array" "set variable *(v_unsigned_char_pointer)='h'" "set variable *(v_unsigned_char_pointer+1)='i'" "print v_unsigned_char_array" ".*.\[0-9\]* =.*\\{104 'h', 105 'i'\\}" "print *(v_unsigned_char_pointer+1)" ".*.\[0-9\]* = 105 \'i\'" "set variable unsigned char pointer=\"hi\" (string)" # # test "set variable" for type "short *" # https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=209445 [ backported ] 2006-12-31 Daniel Jacobowitz * linux-nat.c (lin_lwp_attach_lwp): Return a status. Do not add the LWP to our list until we are attached. Warn instead of erroring if the attach fails. * linux-nat.h (lin_lwp_attach_lwp): New prototype. * linux-thread-db.c (attach_thread): Call lin_lwp_attach_lwp directly. Do not add the thread to our list until we are successfully attached. * config/nm-linux.h (lin_lwp_attach_lwp, ATTACH_LWP): Delete. --- ./gdb/linux-nat.c 20 Nov 2006 21:47:06 -0000 1.51 +++ ./gdb/linux-nat.c 31 Dec 2006 21:04:51 -0000 1.52 @@ -915,12 +915,13 @@ exit_lwp (struct lwp_info *lp) /* Attach to the LWP specified by PID. If VERBOSE is non-zero, print a message telling the user that a new LWP has been added to the - process. */ + process. Return 0 if successful or -1 if the new LWP could not + be attached. */ -void +int lin_lwp_attach_lwp (ptid_t ptid, int verbose) { - struct lwp_info *lp, *found_lp; + struct lwp_info *lp; gdb_assert (is_lwp (ptid)); @@ -932,12 +933,7 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver sigprocmask (SIG_BLOCK, &blocked_mask, NULL); } - if (verbose) - printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid)); - - found_lp = lp = find_lwp_pid (ptid); - if (lp == NULL) - lp = add_lwp (ptid); + lp = find_lwp_pid (ptid); /* We assume that we're already attached to any LWP that has an id equal to the overall process id, and to any LWP that is already @@ -945,14 +941,25 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver and we've had PID wraparound since we last tried to stop all threads, this assumption might be wrong; fortunately, this is very unlikely to happen. */ - if (GET_LWP (ptid) != GET_PID (ptid) && found_lp == NULL) + if (GET_LWP (ptid) != GET_PID (ptid) && lp == NULL) { pid_t pid; int status; if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0) - error (_("Can't attach %s: %s"), target_pid_to_str (ptid), - safe_strerror (errno)); + { + /* If we fail to attach to the thread, issue a warning, + but continue. One way this can happen is if thread + creation is interrupted; as of Linux 2.6.19, a kernel + bug may place threads in the thread list and then fail + to create them. */ + warning (_("Can't attach %s: %s"), target_pid_to_str (ptid), + safe_strerror (errno)); + return -1; + } + + if (lp == NULL) + lp = add_lwp (ptid); if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -990,8 +997,15 @@ lin_lwp_attach_lwp (ptid_t ptid, int ver threads. Note that this won't have already been done since the main thread will have, we assume, been stopped by an attach from a different layer. */ + if (lp == NULL) + lp = add_lwp (ptid); lp->stopped = 1; } + + if (verbose) + printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid)); + + return 0; } static void --- ./gdb/linux-nat.h 20 Nov 2006 21:47:06 -0000 1.13 +++ ./gdb/linux-nat.h 31 Dec 2006 21:04:51 -0000 1.14 @@ -80,6 +80,8 @@ extern void linux_enable_event_reporting extern ptid_t linux_handle_extended_wait (int pid, int status, struct target_waitstatus *ourstatus); +extern int lin_lwp_attach_lwp (ptid_t ptid, int verbose); + /* Iterator function for lin-lwp's lwp list. */ struct lwp_info *iterate_over_lwps (int (*callback) (struct lwp_info *, void *), --- ./gdb/config/nm-linux.h 28 Nov 2006 19:45:07 -0000 1.27 +++ ./gdb/config/nm-linux.h 31 Dec 2006 21:04:51 -0000 1.28 @@ -1,6 +1,6 @@ /* Native support for GNU/Linux. - Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GDB. @@ -25,9 +25,6 @@ struct target_ops; /* GNU/Linux is SVR4-ish but its /proc file system isn't. */ #undef USE_PROC_FS -extern void lin_lwp_attach_lwp (ptid_t ptid, int verbose); -#define ATTACH_LWP(ptid, verbose) lin_lwp_attach_lwp ((ptid), (verbose)) - extern void lin_thread_get_thread_signals (sigset_t *mask); #define GET_THREAD_SIGNALS(mask) lin_thread_get_thread_signals (mask) --- gdb-6.6/gdb-orig/linux-thread-db.c 2007-01-30 14:10:38.000000000 -0500 +++ gdb-6.6/gdb/linux-thread-db.c 2007-01-30 14:16:22.000000000 -0500 @@ -678,6 +678,13 @@ check_thread_signals (); + if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) + return; /* A zombie thread -- do not attach. */ + + /* Under GNU/Linux, we have to attach to each and every thread. */ + if (lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)), 0) < 0) + return; + /* Add the thread to GDB's thread list. */ tp = add_thread (ptid); tp->private = xmalloc (sizeof (struct private_thread_info)); @@ -686,20 +693,10 @@ if (verbose) printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid)); - if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) - return; /* A zombie thread -- do not attach. */ - - new_ptid = BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)); - - /* Under GNU/Linux, we have to attach to each and every thread. */ -#ifdef ATTACH_LWP - ATTACH_LWP (new_ptid, 0); -#endif - /* Notify any observers of a new linux thread. This would include any linux platforms that have to insert hardware watchpoints on every thread. */ - observer_notify_linux_new_thread (new_ptid); + observer_notify_linux_new_thread (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))); /* Enable thread event reporting for this thread. */ err = td_thr_event_enable_p (th_p, 1); https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=230000 2007-02-08 Thiago Jung Bauermann * rs6000-tdep.c (gdb_print_insn_powerpc): Set info->disassembler_options to "any". --- ./gdb/rs6000-tdep.c 8 Feb 2007 14:22:53 -0000 1.261 +++ ./gdb/rs6000-tdep.c 8 Feb 2007 18:05:23 -0000 1.262 @@ -2924,6 +2924,9 @@ find_variant_by_arch (enum bfd_architect static int gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info) { + if (!info->disassembler_options) + info->disassembler_options = "any"; + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) return print_insn_big_powerpc (memaddr, info); else https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=232353 2007-01-27 Daniel Jacobowitz * dwarf2loc.h (struct dwarf2_locexpr_baton): Change size to a long. (struct dwarf2_loclist_baton): Likewise. --- ./gdb/dwarf2loc.h 17 Dec 2005 22:33:59 -0000 1.6 +++ ./gdb/dwarf2loc.h 5 Jan 2007 15:31:17 -0000 @@ -39,7 +39,7 @@ struct dwarf2_locexpr_baton gdb_byte *data; /* Length of the location expression. */ - unsigned short size; + unsigned long size; /* The objfile containing the symbol whose location we're computing. */ struct objfile *objfile; @@ -55,7 +55,7 @@ struct dwarf2_loclist_baton gdb_byte *data; /* Length of the location list. */ - unsigned short size; + unsigned long size; /* The objfile containing the symbol whose location we're computing. */ /* Used (only???) by thread local variables. The objfile in which https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=230000 Fixes embarrassing errors in the ppc dfp instructions committed some time ago. IBM numbers bits in architecture manuals starting from zero in the most signifigant bit. Fields are marked by numbering their most signifigant bit too. This means some translating is required when filling out new powerpc_operand entries. You can't just plug IBM numbers into the shift counts. Also, Z_MASK is too big for instructions that take RMC operands. * ppc-opc.c (DCM, DGM, TE, RMC, R, SP, S): Correct shift. (Z2_MASK): Define. (powerpc_opcodes): Use Z2_MASK in all insns taking RMC operand. --- ./opcodes/ppc-opc.c 19 Apr 2007 01:39:31 -0000 1.91 +++ ./opcodes/ppc-opc.c 20 Apr 2007 09:52:09 -0000 @@ -530,8 +530,9 @@ const struct powerpc_operand powerpc_ope #define SIMM VD + 1 { 5, 16, NULL, NULL, PPC_OPERAND_SIGNED}, - /* The UIMM field in a VX form instruction. */ + /* The UIMM field in a VX form instruction, and TE in Z form. */ #define UIMM SIMM + 1 +#define TE UIMM { 5, 16, NULL, NULL, 0 }, /* The SHB field in a VA form instruction. */ @@ -564,31 +565,23 @@ const struct powerpc_operand powerpc_ope #define A_L MTMSRD_L { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL }, - /* The DCM field in a Z form instruction. */ -#define DCM MTMSRD_L + 1 - { 6, 16, NULL, NULL, 0 }, - - /* Likewise, the DGM field in a Z form instruction. */ -#define DGM DCM + 1 - { 6, 16, NULL, NULL, 0 }, - -#define TE DGM + 1 - { 5, 11, NULL, NULL, 0 }, - -#define RMC TE + 1 - { 2, 21, NULL, NULL, 0 }, +#define RMC A_L + 1 + { 2, 9, NULL, NULL, 0 }, #define R RMC + 1 - { 1, 15, NULL, NULL, 0 }, + { 1, 16, NULL, NULL, 0 }, #define SP R + 1 - { 2, 11, NULL, NULL, 0 }, + { 2, 19, NULL, NULL, 0 }, #define S SP + 1 - { 1, 11, NULL, NULL, 0 }, + { 1, 20, NULL, NULL, 0 }, /* SH field starting at bit position 16. */ #define SH16 S + 1 + /* The DCM and DGM fields in a Z form instruction. */ +#define DCM SH16 +#define DGM DCM { 6, 10, NULL, NULL, 0 }, /* The L field in an X form with the RT field fixed instruction. */ @@ -1683,6 +1676,7 @@ extract_tbr (unsigned long insn, /* The mask for a Z form instruction. */ #define Z_MASK ZRC (0x3f, 0x1ff, 1) +#define Z2_MASK ZRC (0x3f, 0xff, 1) /* An X_MASK with the RA field fixed. */ #define XRA_MASK (X_MASK | RA_MASK) @@ -4639,8 +4633,8 @@ const struct powerpc_opcode powerpc_opco { "dadd", XRC(59,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, { "dadd.", XRC(59,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "dqua", ZRC(59,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "dqua.", ZRC(59,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "dqua", ZRC(59,3,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "dqua.", ZRC(59,3,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, { "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, { "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, @@ -4678,20 +4672,20 @@ const struct powerpc_opcode powerpc_opco { "dmul", XRC(59,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, { "dmul.", XRC(59,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "drrnd", ZRC(59,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "drrnd.", ZRC(59,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "drrnd", ZRC(59,35,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "drrnd.", ZRC(59,35,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, { "dscli", ZRC(59,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, { "dscli.", ZRC(59,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "dquai", ZRC(59,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } }, -{ "dquai.", ZRC(59,67,1), Z_MASK, POWER6, { TE, FRT, FRB, RMC } }, +{ "dquai", ZRC(59,67,0), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, +{ "dquai.", ZRC(59,67,1), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, { "dscri", ZRC(59,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, { "dscri.", ZRC(59,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "drintx", ZRC(59,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintx.", ZRC(59,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintx", ZRC(59,99,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintx.", ZRC(59,99,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, { "dcmpo", X(59,130), X_MASK, POWER6, { BF, FRA, FRB } }, @@ -4699,8 +4693,8 @@ const struct powerpc_opcode powerpc_opco { "dtstdc", Z(59,194), Z_MASK, POWER6, { BF, FRA, DCM } }, { "dtstdg", Z(59,226), Z_MASK, POWER6, { BF, FRA, DGM } }, -{ "drintn", ZRC(59,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintn.", ZRC(59,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintn", ZRC(59,227,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintn.", ZRC(59,227,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, { "dctdp", XRC(59,258,0), X_MASK, POWER6, { FRT, FRB } }, { "dctdp.", XRC(59,258,1), X_MASK, POWER6, { FRT, FRB } }, @@ -4766,8 +4760,8 @@ const struct powerpc_opcode powerpc_opco { "daddq", XRC(63,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, { "daddq.", XRC(63,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "dquaq", ZRC(63,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "dquaq.", ZRC(63,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "dquaq", ZRC(63,3,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "dquaq.", ZRC(63,3,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, { "fcpsgn", XRC(63,8,0), X_MASK, POWER6, { FRT, FRA, FRB } }, { "fcpsgn.", XRC(63,8,1), X_MASK, POWER6, { FRT, FRA, FRB } }, @@ -4842,8 +4836,8 @@ const struct powerpc_opcode powerpc_opco { "dmulq", XRC(63,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, { "dmulq.", XRC(63,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "drrndq", ZRC(63,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "drrndq.", ZRC(63,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "drrndq", ZRC(63,35,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "drrndq.", ZRC(63,35,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, { "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } }, { "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } }, @@ -4856,8 +4850,8 @@ const struct powerpc_opcode powerpc_opco { "dscliq", ZRC(63,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, { "dscliq.", ZRC(63,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "dquaiq", ZRC(63,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } }, -{ "dquaiq.", ZRC(63,67,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "dquaiq", ZRC(63,67,0), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, +{ "dquaiq.", ZRC(63,67,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, { "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } }, { "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } }, @@ -4868,8 +4862,8 @@ const struct powerpc_opcode powerpc_opco { "dscriq", ZRC(63,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, { "dscriq.", ZRC(63,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "drintxq", ZRC(63,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintxq.",ZRC(63,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintxq", ZRC(63,99,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintxq.",ZRC(63,99,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, { "dcmpoq", X(63,130), X_MASK, POWER6, { BF, FRA, FRB } }, @@ -4883,8 +4877,8 @@ const struct powerpc_opcode powerpc_opco { "dtstdcq", Z(63,194), Z_MASK, POWER6, { BF, FRA, DCM } }, { "dtstdgq", Z(63,226), Z_MASK, POWER6, { BF, FRA, DGM } }, -{ "drintnq", ZRC(63,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintnq.",ZRC(63,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintnq", ZRC(63,227,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintnq.",ZRC(63,227,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, { "dctqpq", XRC(63,258,0), X_MASK, POWER6, { FRT, FRB } }, { "dctqpq.", XRC(63,258,1), X_MASK, POWER6, { FRT, FRB } }, -- Alan Modra IBM OzLabs - Linux Technology Centre 2007-05-14 Paul Brook Daniel Jacobowitz * dwarf2read.c (dwarf2_debug_line_missing_file_complaint): New function. (dwarf_decode_lines): Check for line info without a file. --- src/gdb/dwarf2read.c 2007/04/18 13:25:04 1.218 +++ src/gdb/dwarf2read.c 2007/05/14 17:15:20 1.219 @@ -688,6 +688,13 @@ } static void +dwarf2_debug_line_missing_file_complaint (void) +{ + complaint (&symfile_complaints, + _(".debug_line section has line data without a file")); +} + +static void dwarf2_complex_location_expr_complaint (void) { complaint (&symfile_complaints, _("location expression too complex")); @@ -6708,19 +6715,24 @@ address += (adj_opcode / lh->line_range) * lh->minimum_instruction_length; line += lh->line_base + (adj_opcode % lh->line_range); - lh->file_names[file - 1].included_p = 1; - if (!decode_for_pst_p) - { - if (last_subfile != current_subfile) - { - if (last_subfile) - record_line (last_subfile, 0, address); - last_subfile = current_subfile; + if (lh->num_file_names < file) + dwarf2_debug_line_missing_file_complaint (); + else + { + lh->file_names[file - 1].included_p = 1; + if (!decode_for_pst_p) + { + if (last_subfile != current_subfile) + { + if (last_subfile) + record_line (last_subfile, 0, address); + last_subfile = current_subfile; + } + /* Append row to matrix using current values. */ + record_line (current_subfile, line, + check_cu_functions (address, cu)); } - /* Append row to matrix using current values. */ - record_line (current_subfile, line, - check_cu_functions (address, cu)); - } + } basic_block = 1; } else switch (op_code) @@ -6734,9 +6746,15 @@ { case DW_LNE_end_sequence: end_sequence = 1; - lh->file_names[file - 1].included_p = 1; - if (!decode_for_pst_p) - record_line (current_subfile, 0, address); + + if (lh->num_file_names < file) + dwarf2_debug_line_missing_file_complaint (); + else + { + lh->file_names[file - 1].included_p = 1; + if (!decode_for_pst_p) + record_line (current_subfile, 0, address); + } break; case DW_LNE_set_address: address = read_address (abfd, line_ptr, cu, &bytes_read); @@ -6769,17 +6787,22 @@ } break; case DW_LNS_copy: - lh->file_names[file - 1].included_p = 1; - if (!decode_for_pst_p) + if (lh->num_file_names < file) + dwarf2_debug_line_missing_file_complaint (); + else { - if (last_subfile != current_subfile) - { - if (last_subfile) - record_line (last_subfile, 0, address); - last_subfile = current_subfile; - } - record_line (current_subfile, line, - check_cu_functions (address, cu)); + lh->file_names[file - 1].included_p = 1; + if (!decode_for_pst_p) + { + if (last_subfile != current_subfile) + { + if (last_subfile) + record_line (last_subfile, 0, address); + last_subfile = current_subfile; + } + record_line (current_subfile, line, + check_cu_functions (address, cu)); + } } basic_block = 0; break; @@ -6806,15 +6806,19 @@ dwarf_decode_lines (struct line_header * file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - fe = &lh->file_names[file - 1]; - if (fe->dir_index) - dir = lh->include_dirs[fe->dir_index - 1]; - - if (!decode_for_pst_p) - { - last_subfile = current_subfile; - dwarf2_start_subfile (fe->name, dir, comp_dir); - } + if (lh->num_file_names < file) + dwarf2_debug_line_missing_file_complaint (); + else + { + fe = &lh->file_names[file - 1]; + if (fe->dir_index) + dir = lh->include_dirs[fe->dir_index - 1]; + if (!decode_for_pst_p) + { + last_subfile = current_subfile; + dwarf2_start_subfile (fe->name, dir, comp_dir); + } + } } break; case DW_LNS_set_column: http://sourceware.org/ml/binutils/2007-08/msg00296.html [ Backported for GDB-6.6. ] 2007-08-19 Jan Kratochvil * bfd/elf-bfd.h (struct elf_obj_tdata): New build_id_size, build_id. * bfd/elf.c (elfcore_read_notes): Split to ... (elf_read_notes) ... here ... (elf_parse_notes): ... and here. Check `bfd_get_format (abfd)' with the former subfunctions called only for BFD_CORE. Call ELFOBJ_GROK_GNU_NOTE for BFD_OBJECT files with the owner "GNU". (_bfd_elf_make_section_from_shdr): Call ELF_PARSE_NOTES for SHT_NOTEs. (bfd_section_from_phdr): Update the call for renamed ELFCORE_READ_NOTES. (elfobj_grok_gnu_build_id, elfobj_grok_gnu_note): New functions. Code advisory: Roland McGrath --- gdb-6.6/bfd/elf-bfd.h.orig 2006-11-02 16:20:31.000000000 +0100 +++ gdb-6.6/bfd/elf-bfd.h 2007-08-28 15:00:42.000000000 +0200 @@ -1408,6 +1408,10 @@ struct elf_obj_tdata /* Symbol buffer. */ Elf_Internal_Sym *symbuf; + + /* NT_GNU_BUILD_ID note type. */ + bfd_size_type build_id_size; + bfd_byte *build_id; }; #define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) --- ./bfd/elf.c 16 Aug 2007 18:49:42 -0000 1.410 +++ ./bfd/elf.c 19 Aug 2007 20:12:16 -0000 @@ -48,7 +48,9 @@ static int elf_sort_sections (const void static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *); static bfd_boolean prep_headers (bfd *); static bfd_boolean swap_out_syms (bfd *, struct bfd_strtab_hash **, int) ; -static bfd_boolean elfcore_read_notes (bfd *, file_ptr, bfd_size_type) ; +static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ; +static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size, + file_ptr offset); /* Swap version information in and out. The version information is currently size independent. If that ever changes, this code will @@ -899,6 +901,28 @@ _bfd_elf_make_section_from_shdr (bfd *ab if (! bfd_set_section_flags (abfd, newsect, flags)) return FALSE; + /* We do not parse the PT_NOTE segments as we are interested even in the + separate debug info files which may have the segments offsets corrupted. + PT_NOTEs from the core files are currently not parsed using BFD. */ + if (hdr->sh_type == SHT_NOTE) + { + char *contents; + + contents = bfd_malloc (hdr->sh_size); + if (!contents) + return FALSE; + + if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0, + hdr->sh_size) + || !elf_parse_notes (abfd, contents, hdr->sh_size, -1)) + { + free (contents); + return FALSE; + } + + free (contents); + } + if ((flags & SEC_ALLOC) != 0) { Elf_Internal_Phdr *phdr; @@ -2341,7 +2365,7 @@ bfd_section_from_phdr (bfd *abfd, Elf_In case PT_NOTE: if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note")) return FALSE; - if (! elfcore_read_notes (abfd, hdr->p_offset, hdr->p_filesz)) + if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz)) return FALSE; return TRUE; @@ -7713,6 +7737,32 @@ elfcore_grok_note (bfd *abfd, Elf_Intern } static bfd_boolean +elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note) +{ + elf_tdata (abfd)->build_id_size = note->descsz; + elf_tdata (abfd)->build_id = bfd_alloc (abfd, note->descsz); + if (elf_tdata (abfd)->build_id == NULL) + return FALSE; + + memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz); + + return TRUE; +} + +static bfd_boolean +elfobj_grok_gnu_note (bfd *abfd, Elf_Internal_Note *note) +{ + switch (note->type) + { + default: + return TRUE; + + case NT_GNU_BUILD_ID: + return elfobj_grok_gnu_build_id (abfd, note); + } +} + +static bfd_boolean elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp) { char *cp; @@ -8186,28 +8236,10 @@ elfcore_write_prxfpreg (bfd *abfd, } static bfd_boolean -elfcore_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size) +elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset) { - char *buf; char *p; - if (size <= 0) - return TRUE; - - if (bfd_seek (abfd, offset, SEEK_SET) != 0) - return FALSE; - - buf = bfd_malloc (size); - if (buf == NULL) - return FALSE; - - if (bfd_bread (buf, size, abfd) != size) - { - error: - free (buf); - return FALSE; - } - p = buf; while (p < buf + size) { @@ -8312,25 +8344,66 @@ elfcore_read_notes (bfd *abfd, file_ptr in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4); in.descpos = offset + (in.descdata - buf); - if (CONST_STRNEQ (in.namedata, "NetBSD-CORE")) + switch (bfd_get_format (abfd)) { - if (! elfcore_grok_netbsd_note (abfd, &in)) - goto error; - } - else if (CONST_STRNEQ (in.namedata, "QNX")) - { - if (! elfcore_grok_nto_note (abfd, &in)) - goto error; + default: + return TRUE; + + case bfd_core: + if (CONST_STRNEQ (in.namedata, "NetBSD-CORE")) + { + if (! elfcore_grok_netbsd_note (abfd, &in)) + return FALSE; + } + else if (CONST_STRNEQ (in.namedata, "QNX")) + { + if (! elfcore_grok_nto_note (abfd, &in)) + return FALSE; + } + else + { + if (! elfcore_grok_note (abfd, &in)) + return FALSE; + } + break; + + case bfd_object: + if (in.namesz == sizeof "GNU" && strcmp (in.namedata, "GNU") == 0) + { + if (! elfobj_grok_gnu_note (abfd, &in)) + return FALSE; + } + break; } - else - { - if (! elfcore_grok_note (abfd, &in)) - goto error; - } p = in.descdata + BFD_ALIGN (in.descsz, 4); } + return TRUE; +} + +static bfd_boolean +elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size) +{ + char *buf; + + if (size <= 0) + return TRUE; + + if (bfd_seek (abfd, offset, SEEK_SET) != 0) + return FALSE; + + buf = bfd_malloc (size); + if (buf == NULL) + return FALSE; + + if (bfd_bread (buf, size, abfd) != size + || !elf_parse_notes (abfd, buf, size, offset)) + { + free (buf); + return FALSE; + } + free (buf); return TRUE; } 2007-07-09 Roland McGrath * common.h (NT_GNU_HWCAP, NT_GNU_BUILD_ID): New macros. --- ./include/elf/common.h 29 Jun 2007 16:29:16 -0000 1.85 +++ ./include/elf/common.h 9 Jul 2007 21:17:42 -0000 1.86 @@ -413,9 +413,13 @@ #define NT_VERSION 1 /* Contains a version string. */ #define NT_ARCH 2 /* Contains an architecture string. */ -/* Values for GNU .note.ABI-tag notes. Note name is "GNU". */ +/* Values for notes in non-core files using name "GNU". */ #define NT_GNU_ABI_TAG 1 +#define NT_GNU_HWCAP 2 /* Used by ld.so and kernel vDSO. */ +#define NT_GNU_BUILD_ID 3 /* Generated by ld --build-id. */ + +/* Values used in GNU .note.ABI-tag notes (NT_GNU_ABI_TAG). */ #define GNU_ABI_TAG_LINUX 0 #define GNU_ABI_TAG_HURD 1 #define GNU_ABI_TAG_SOLARIS 2 2007-09-15 Alan Modra * configure.ac: Correct makeinfo version check. * configure: Regenerate. #--- ./configure.ac 14 Sep 2007 14:51:36 -0000 1.25 #+++ ./configure.ac 14 Sep 2007 15:47:01 -0000 1.26 #@@ -2462,7 +2462,7 @@ changequote(,) # # For an installed makeinfo, we require it to be from texinfo 4.4 or # # higher, else we use the "missing" dummy. # if ${MAKEINFO} --version \ #- | egrep 'texinfo[^0-9]*([1-3][0-9]|4\.[4-9]|[5-9])' >/dev/null 2>&1; then #+ | egrep 'texinfo[^0-9]*(4\.([4-9]|[1-9][0-9])|[5-9]|[1-9][0-9])' >/dev/null 2>&1; then # : # else # MAKEINFO="$MISSING makeinfo" --- ./configure 14 Sep 2007 14:51:36 -0000 1.277 +++ ./configure 14 Sep 2007 15:47:01 -0000 1.278 @@ -6192,7 +6192,7 @@ case " $build_configdirs " in # For an installed makeinfo, we require it to be from texinfo 4.4 or # higher, else we use the "missing" dummy. if ${MAKEINFO} --version \ - | egrep 'texinfo[^0-9]*([1-3][0-9]|4\.[4-9]|[5-9])' >/dev/null 2>&1; then + | egrep 'texinfo[^0-9]*(4\.([4-9]|[1-9][0-9])|[5-9]|[1-9][0-9])' >/dev/null 2>&1; then : else MAKEINFO="$MISSING makeinfo" gdb/ https://bugzilla.redhat.com/show_bug.cgi?id=314131 gdb/gdbserver/ https://bugzilla.redhat.com/show_bug.cgi?id=328021 http://sourceware.org/ml/gdb-patches/2007-06/msg00479.html http://sourceware.org/ml/gdb-cvs/2007-06/msg00175.html gdb/ 2007-06-27 Daniel Jacobowitz * linux-thread-db.c (thread_db_attach): Delete. (thread_db_detach): Typo fix. Call target_mourn_inferior instead of fixing up proc_handle. (have_threads_callback, have_threads): New functions. (thread_db_wait): Remove dead proc_handle.pid check. Only translate PTIDs if we have registered threads. Check for new threads if we have none. (thread_db_create_inferior, thread_db_post_startup_inferior): Delete. (find_new_threads_callback): Only enable event reporting if TID == 0. (same_ptid_callback): New. (thread_db_get_thread_local_address): Check for new threads. (init_thread_db_ops): Don't set to_attach, to_create_inferior, or to_post_startup_inferior. gdb/gdbserver/ 2007-06-27 Daniel Jacobowitz * thread-db.c (thread_db_find_new_threads): Add prototype. (thread_db_create_event): Check for the main thread before adding a new thread. (maybe_attach_thread): Only enable event reporting if TID == 0. (thread_db_get_tls_address): Check for new threads. --- gdb-6.6/gdb/linux-thread-db.c 2008-01-10 19:38:49.000000000 +0100 +++ gdb-6.6-patched/gdb/linux-thread-db.c 2008-01-10 19:35:58.000000000 +0100 @@ -214,6 +214,21 @@ thread_db_err_str (td_err_e err) } } +/* Return 1 if any threads have been registered. There may be none if + the threading library is not fully initialized yet. */ + +static int +have_threads_callback (struct thread_info *thread, void *dummy) +{ + return 1; +} + +static int +have_threads (void) +{ + return iterate_over_threads (have_threads_callback, NULL) != NULL; +} + /* A callback function for td_ta_thr_iter, which we use to map all threads to LWPs. @@ -706,23 +721,6 @@ attach_thread (ptid_t ptid, const td_thr } static void -thread_db_attach (char *args, int from_tty) -{ - target_beneath->to_attach (args, from_tty); - - /* Destroy thread info; it's no longer valid. */ - init_thread_list (); - - /* The child process is now the actual multi-threaded - program. Snatch its process ID... */ - proc_handle.pid = GET_PID (inferior_ptid); - - /* ...and perform the remaining initialization steps. */ - enable_thread_event_reporting (); - thread_db_find_new_threads (); -} - -static void detach_thread (ptid_t ptid, int verbose) { struct thread_info *thread_info; @@ -748,14 +746,13 @@ thread_db_detach (char *args, int from_t disable_thread_event_reporting (); /* There's no need to save & restore inferior_ptid here, since the - inferior is supposed to be survive this function call. */ + inferior is not supposed to survive this function call. */ inferior_ptid = lwp_from_thread (inferior_ptid); - /* Forget about the child's process ID. We shouldn't need it - anymore. */ - proc_handle.pid = 0; - target_beneath->to_detach (args, from_tty); + + /* Should this be done by detach_command? */ + target_mourn_inferior (); } static void @@ -860,12 +857,6 @@ thread_db_wait (ptid_t ptid, struct targ ptid = target_beneath->to_wait (ptid, ourstatus); - if (proc_handle.pid == 0) - /* The current child process isn't the actual multi-threaded - program yet, so don't try to do any special thread-specific - post-processing and bail out early. */ - return ptid; - if (ourstatus->kind == TARGET_WAITKIND_EXITED || ourstatus->kind == TARGET_WAITKIND_SIGNALLED) return pid_to_ptid (-1); @@ -896,24 +887,33 @@ return pid_to_ptid (GET_PID (ptid)); } + /* If we do not know about the main thread yet, this would be a good time to + find it. */ + if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ()) + thread_db_find_new_threads (); + if (ourstatus->kind == TARGET_WAITKIND_STOPPED && (ourstatus->value.sig == TARGET_SIGNAL_TRAP || ourstatus->value.sig == TARGET_SIGNAL_ILL)) /* Check for a thread event. */ check_event (ptid); - if (!ptid_equal (trap_ptid, null_ptid)) - trap_ptid = thread_from_lwp (trap_ptid); + if (have_threads ()) + { + /* Change ptids back into the higher level PID + TID format. If + the thread is dead and no longer on the thread list, we will + get back a dead ptid. This can occur if the thread death + event gets postponed by other simultaneous events. In such a + case, we want to just ignore the event and continue on. */ + + if (!ptid_equal (trap_ptid, null_ptid)) + trap_ptid = thread_from_lwp (trap_ptid); + + ptid = thread_from_lwp (ptid); + if (GET_PID (ptid) == -1) + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + } - /* Change the ptid back into the higher level PID + TID format. - If the thread is dead and no longer on the thread list, we will - get back a dead ptid. This can occur if the thread death event - gets postponed by other simultaneous events. In such a case, - we want to just ignore the event and continue on. */ - ptid = thread_from_lwp (ptid); - if (GET_PID (ptid) == -1) - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - return ptid; } @@ -935,30 +935,6 @@ thread_db_kill (void) } static void -thread_db_create_inferior (char *exec_file, char *allargs, char **env, - int from_tty) -{ - unpush_target (&thread_db_ops); - using_thread_db = 0; - target_beneath->to_create_inferior (exec_file, allargs, env, from_tty); -} - -static void -thread_db_post_startup_inferior (ptid_t ptid) -{ - if (proc_handle.pid == 0) - { - /* The child process is now the actual multi-threaded - program. Snatch its process ID... */ - proc_handle.pid = GET_PID (ptid); - - /* ...and perform the remaining initialization steps. */ - enable_thread_event_reporting (); - thread_db_find_new_threads (); - } -} - -static void thread_db_mourn_inferior (void) { /* Forget about the child's process ID. We shouldn't need it @@ -993,6 +969,22 @@ find_new_threads_callback (const td_thrh ptid = ptid_build (GET_PID (inferior_ptid), ti.ti_lid, ti.ti_tid); + if (ti.ti_tid == 0) + { + /* A thread ID of zero means that this is the main thread, but + glibc has not yet initialized thread-local storage and the + pthread library. We do not know what the thread's TID will + be yet. Just enable event reporting and otherwise ignore + it. */ + + err = td_thr_event_enable_p (th_p, 1); + if (err != TD_OK) + error (_("Cannot enable thread event reporting for %s: %s"), + target_pid_to_str (ptid), thread_db_err_str (err)); + + return 0; + } + if (!in_thread_list (ptid)) attach_thread (ptid, th_p, &ti, 1); @@ -1049,6 +1041,16 @@ thread_db_extra_thread_info (struct thre return NULL; } +/* Return 1 if this thread has the same LWP as the passed PTID. */ + +static int +same_ptid_callback (struct thread_info *thread, void *arg) +{ + ptid_t *ptid_p = arg; + + return GET_LWP (thread->ptid) == GET_LWP (*ptid_p); +} + /* Get the address of the thread local variable in load module LM which is stored at OFFSET within the thread local storage for thread PTID. */ @@ -1057,6 +1059,21 @@ thread_db_get_thread_local_address (ptid CORE_ADDR lm, CORE_ADDR offset) { + /* If we have not discovered any threads yet, check now. */ + if (!is_thread (ptid) && !have_threads ()) + thread_db_find_new_threads (); + + /* Try to find a matching thread if we still have the LWP ID instead + of the thread ID. */ + if (!is_thread (ptid)) + { + struct thread_info *thread; + + thread = iterate_over_threads (same_ptid_callback, &ptid); + if (thread != NULL) + ptid = thread->ptid; + } + if (is_thread (ptid)) { td_err_e err; @@ -1116,14 +1133,11 @@ init_thread_db_ops (void) thread_db_ops.to_shortname = "multi-thread"; thread_db_ops.to_longname = "multi-threaded child process."; thread_db_ops.to_doc = "Threads and pthreads support."; - thread_db_ops.to_attach = thread_db_attach; thread_db_ops.to_detach = thread_db_detach; thread_db_ops.to_resume = thread_db_resume; thread_db_ops.to_wait = thread_db_wait; thread_db_ops.to_xfer_partial = thread_db_xfer_partial; thread_db_ops.to_kill = thread_db_kill; - thread_db_ops.to_create_inferior = thread_db_create_inferior; - thread_db_ops.to_post_startup_inferior = thread_db_post_startup_inferior; thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior; thread_db_ops.to_find_new_threads = thread_db_find_new_threads; thread_db_ops.to_pid_to_str = thread_db_pid_to_str; --- ./gdb/gdbserver/thread-db.c 9 Jan 2007 17:59:08 -0000 1.9 +++ ./gdb/gdbserver/thread-db.c 27 Jun 2007 11:52:02 -0000 1.10 @@ -41,6 +41,7 @@ static struct ps_prochandle proc_handle; /* Connection to the libthread_db library. */ static td_thragent_t *thread_agent; +static void thread_db_find_new_threads (void); static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data); static char * @@ -135,6 +136,8 @@ thread_db_create_event (CORE_ADDR where) td_event_msg_t msg; td_err_e err; struct inferior_linux_data *tdata; + struct thread_info *inferior; + struct process_info *process; if (debug_threads) fprintf (stderr, "Thread creation event.\n"); @@ -150,6 +153,14 @@ thread_db_create_event (CORE_ADDR where) fprintf (stderr, "thread getmsg err: %s\n", thread_db_err_str (err)); + /* If we do not know about the main thread yet, this would be a good time to + find it. We need to do this to pick up the main thread before any newly + created threads. */ + inferior = (struct thread_info *) all_threads.head; + process = get_thread_process (inferior); + if (process->thread_known == 0) + thread_db_find_new_threads (); + /* msg.event == TD_EVENT_CREATE */ find_new_threads_callback (msg.th_p, NULL); @@ -232,8 +243,24 @@ maybe_attach_thread (const td_thrhandle_ { inferior = (struct thread_info *) all_threads.head; process = get_thread_process (inferior); + if (process->thread_known == 0) { + /* If the new thread ID is zero, a final thread ID will be + available later. Do not enable thread debugging yet. */ + if (ti_p->ti_tid == 0) + { + err = td_thr_event_enable (th_p, 1); + if (err != TD_OK) + error ("Cannot enable thread event reporting for %d: %s", + ti_p->ti_lid, thread_db_err_str (err)); + return; + } + + if (process->lwpid != ti_p->ti_lid) + fatal ("PID mismatch! Expected %ld, got %ld", + (long) process->lwpid, (long) ti_p->ti_lid); + /* Switch to indexing the threads list by TID. */ change_inferior_id (&all_threads, ti_p->ti_tid); goto found; @@ -332,6 +359,8 @@ thread_db_get_tls_address (struct thread process = get_thread_process (thread); if (!process->thread_known) + thread_db_find_new_threads (); + if (!process->thread_known) return TD_NOTHR; /* Note the cast through uintptr_t: this interface only works if http://sources.redhat.com/ml/gdb-patches/2007-07/msg00034.html 2007-07-02 Daniel Jacobowitz * breakpoint.c (reattach_breakpoints): Do not use remove_breakpoint. Call insert_bp_location. [ Backported. ] --- gdb-6.6/gdb/breakpoint.c.orig 2007-10-14 17:42:36.000000000 +0200 +++ gdb-6.6/gdb/breakpoint.c 2007-10-14 17:45:57.000000000 +0200 @@ -1313,20 +1313,19 @@ struct bp_location *b; int val; struct cleanup *old_chain = save_inferior_ptid (); + struct ui_file *tmp_error_stream = mem_fileopen (); + int dummy1 = 0, dummy2 = 0, dummy3 = 0; + + make_cleanup_ui_file_delete (tmp_error_stream); - /* Set inferior_ptid; remove_breakpoint uses this global. */ inferior_ptid = pid_to_ptid (pid); ALL_BP_LOCATIONS (b) { if (b->inserted) { - remove_breakpoint (b, mark_inserted); - if (b->loc_type == bp_loc_hardware_breakpoint) - val = target_insert_hw_breakpoint (&b->target_info); - else - val = target_insert_breakpoint (&b->target_info); - /* FIXME drow/2003-10-07: This doesn't handle any other kinds of - breakpoints. It's wrong for watchpoints, for example. */ + b->inserted = 0; + val = insert_bp_location (b, tmp_error_stream, + &dummy1, &dummy2, &dummy3); if (val != 0) { do_cleanups (old_chain);