From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stu Grossman To: gdb-patches@sources.redhat.com Subject: Patches for FreeBSD 4.2 Date: Tue, 10 Jul 2001 23:39:00 -0000 Message-id: <200107110639.f6B6d4K28642@ploor.juniper.net> X-SW-Source: 2001-07/msg00248.html Here is a set of patches that fixes a bunch of problems (and some testsuite failures) for FreeBSD 4.2. Stu Index: gdb/ChangeLog =================================================================== RCS file: /cvs/src/src/gdb/ChangeLog,v retrieving revision 1.1410 diff -c -p -r1.1410 ChangeLog *** ChangeLog 2001/07/04 21:14:05 1.1410 --- ChangeLog 2001/07/11 00:06:34 *************** *** 1,3 **** --- 1,29 ---- + 2001-07-10 Stu Grossman + + * Makefile.in (SUBDIR_MI_INITS): Add $(srcdir) to source file names for + old makes. + * i386-tdep.c (i386_store_return_value): Make sure that floats get + stored at the top of the FP stack. + * infrun.c (handle_inferior_event): Change the way stepping over + signals works. It's much more general, and works for systems that + don't use signal trampolines on entry. + * i386-freebsd-nat.c: New file to support FreeBSD specific stuff. + * config/i386/fbsd.mh (NATDEPFILES): Add i386-freebsd-nat.o. + * config/i386/nm-fbsd.h: Define CHILD_RESUME 'cuz FreeBSD can't use + the stock one. + * config/i386/tm-fbsd.h: Define FRAME_SAVED_PC to use FreeBSD specific + code to extract return PC from signal frames. + * Define FRAME_CHAIN_VALID to use func_frame_chain_valid, since ELF + doesn't generate N_TEXT object file markers. + * Remove SIGTRAMP_START and SIGTRAMP_END. Move all of that logic into + a FreeBSD specific function invoke via IN_SIGTRAMP. + * testsuite/gdb.base/completion.exp: Fix completion test of things + beginning with "a". FreeBSD's libc includes many things beginning with + "a", which confused the test. Fix various other completion tests as + well. + * testsuite/gdb.base/selftest.exp(backtrace through signal handler): + Update expected string to match current reality. + 2001-07-04 Mark Kettenis * i387-tdep.c (print_i387_value): Add extra space after final full Index: gdb/Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.91 diff -c -p -r1.91 Makefile.in *** Makefile.in 2001/06/28 03:33:26 1.91 --- Makefile.in 2001/07/11 00:06:36 *************** SUBDIR_MI_SRCS = \ *** 170,176 **** mi/mi-main.c mi/mi-parse.c mi/mi-getopt.c SUBDIR_MI_DEPS = SUBDIR_MI_INITS = \ ! mi/mi-cmds.c mi/mi-parse.c mi/mi-main.c mi/mi-out.c SUBDIR_MI_LDFLAGS= SUBDIR_MI_CFLAGS= \ -DMI_OUT=1 --- 170,176 ---- mi/mi-main.c mi/mi-parse.c mi/mi-getopt.c SUBDIR_MI_DEPS = SUBDIR_MI_INITS = \ ! $(srcdir)/mi/mi-cmds.c $(srcdir)/mi/mi-parse.c $(srcdir)/mi/mi-main.c $(srcdir)/mi/mi-out.c SUBDIR_MI_LDFLAGS= SUBDIR_MI_CFLAGS= \ -DMI_OUT=1 Index: gdb/i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.31 diff -c -p -r1.31 i386-tdep.c *** i386-tdep.c 2001/05/09 16:16:33 1.31 --- i386-tdep.c 2001/07/11 00:06:36 *************** i386_store_return_value (struct type *ty *** 861,871 **** --- 861,885 ---- if (TYPE_CODE (type) == TYPE_CODE_FLT) { + ULONGEST fstat; + if (NUM_FREGS == 0) { warning ("Cannot set floating-point return value."); return; } + + /* According to the SVR4 x86 ABI, a returned FP value must be at the top + of the FP stack. So we force the FP stack pointer to make it look + like there is one item on the FP stack (at st(0)) which is where we + will store the return value. Failure to do this will result in great + weirdness due to uncaught FP stack overflows. */ + + fstat = read_register (FSTAT_REGNUM); + fstat |= 0x3800; + write_register (FSTAT_REGNUM, fstat); + + write_register (FTAG_REGNUM, 0x3fff); /* Floating-point return values can be found in %st(0). */ if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT Index: gdb/infrun.c =================================================================== RCS file: /cvs/src/src/gdb/infrun.c,v retrieving revision 1.41 diff -c -p -r1.41 infrun.c *** infrun.c 2001/06/28 21:48:41 1.41 --- infrun.c 2001/07/11 00:06:39 *************** handle_inferior_event (struct execution_ *** 2265,2304 **** /* Clear the signal if it should not be passed. */ if (signal_program[stop_signal] == 0) stop_signal = TARGET_SIGNAL_0; ! ! /* I'm not sure whether this needs to be check_sigtramp2 or ! whether it could/should be keep_going. ! ! This used to jump to step_over_function if we are stepping, ! which is wrong. ! ! Suppose the user does a `next' over a function call, and while ! that call is in progress, the inferior receives a signal for ! which GDB does not stop (i.e., signal_stop[SIG] is false). In ! that case, when we reach this point, there is already a ! step-resume breakpoint established, right where it should be: ! immediately after the function call the user is "next"-ing ! over. If we call step_over_function now, two bad things ! happen: ! ! - we'll create a new breakpoint, at wherever the current ! frame's return address happens to be. That could be ! anywhere, depending on what function call happens to be on ! the top of the stack at that point. Point is, it's probably ! not where we need it. ! ! - the existing step-resume breakpoint (which is at the correct ! address) will get orphaned: step_resume_breakpoint will point ! to the new breakpoint, and the old step-resume breakpoint ! will never be cleaned up. ! ! The old behavior was meant to help HP-UX single-step out of ! sigtramps. It would place the new breakpoint at prev_pc, which ! was certainly wrong. I don't know the details there, so fixing ! this probably breaks that. As with anything else, it's up to ! the HP-UX maintainer to furnish a fix that doesn't break other ! platforms. --JimB, 20 May 1999 */ ! check_sigtramp2 (ecs); keep_going (ecs); return; } --- 2265,2294 ---- /* Clear the signal if it should not be passed. */ if (signal_program[stop_signal] == 0) stop_signal = TARGET_SIGNAL_0; ! else ! { ! /* What is happening here is that the inferior is about to have a ! signal delivered. What we will do now is set a step_resume ! breakpoint at the current PC to allow the signal handler to run, ! and then keep on chugging along. */ ! ! if (currently_stepping (ecs)) ! { ! struct symtab_and_line sr_sal; ! ! INIT_SAL (&sr_sal); /* initialize to zeroes */ ! sr_sal.pc = stop_pc; ! sr_sal.section = find_pc_overlay (sr_sal.pc); ! /* We perhaps could set the frame if we kept track of what the ! frame corresponding to prev_pc was. But we don't, so don't. */ ! through_sigtramp_breakpoint = ! set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp); ! insert_breakpoints (); ! ! ecs->remove_breakpoints_on_following_step = 1; ! ecs->another_trap = 1; ! } ! } keep_going (ecs); return; } Index: gdb/config/i386/fbsd.mh =================================================================== RCS file: /cvs/src/src/gdb/config/i386/fbsd.mh,v retrieving revision 1.7 diff -c -p -r1.7 fbsd.mh *** fbsd.mh 2001/04/12 18:44:40 1.7 --- fbsd.mh 2001/07/11 00:06:41 *************** *** 1,6 **** # Host: Intel 386 running FreeBSD XDEPFILES= # NOTE: Do not spread NATDEPFILES over several lines - it hurts BSD make. ! NATDEPFILES= fork-child.o infptrace.o inftarg.o solib.o solib-svr4.o solib-legacy.o corelow.o core-aout.o core-regset.o i387-nat.o i386bsd-nat.o i386-nat.o XM_FILE= xm-fbsd.h NAT_FILE= nm-fbsd.h --- 1,6 ---- # Host: Intel 386 running FreeBSD XDEPFILES= # NOTE: Do not spread NATDEPFILES over several lines - it hurts BSD make. ! NATDEPFILES= fork-child.o infptrace.o inftarg.o solib.o solib-svr4.o solib-legacy.o corelow.o core-aout.o core-regset.o i387-nat.o i386bsd-nat.o i386-nat.o i386-freebsd-nat.o XM_FILE= xm-fbsd.h NAT_FILE= nm-fbsd.h Index: gdb/config/i386/nm-fbsd.h =================================================================== RCS file: /cvs/src/src/gdb/config/i386/nm-fbsd.h,v retrieving revision 1.4 diff -c -p -r1.4 nm-fbsd.h *** nm-fbsd.h 2001/03/31 18:09:03 1.4 --- nm-fbsd.h 2001/07/11 00:06:42 *************** *** 28,33 **** --- 28,36 ---- #include "i386/nm-i386.h" + /* Must use child_resume in i386-freebsd-nat.c to work around OS bug */ + #define CHILD_RESUME + /* Provide access to the i386 hardware debugging registers. */ #define I386_DR_LOW_SET_CONTROL(control) \ Index: gdb/config/i386/tm-fbsd.h =================================================================== RCS file: /cvs/src/src/gdb/config/i386/tm-fbsd.h,v retrieving revision 1.3 diff -c -p -r1.3 tm-fbsd.h *** tm-fbsd.h 2001/03/06 08:21:28 1.3 --- tm-fbsd.h 2001/07/11 00:06:42 *************** *** 24,33 **** --- 24,43 ---- #define HAVE_I387_REGS #include "i386/tm-i386.h" + #undef FRAME_SAVED_PC + #define FRAME_SAVED_PC(FRAME) i386_freebsd_frame_saved_pc(FRAME) + CORE_ADDR i386_freebsd_frame_saved_pc(struct frame_info *frame); + + /* Use the alternate method of determining valid frame chains. */ + + #define FRAME_CHAIN_VALID(fp,fi) func_frame_chain_valid (fp, fi) + /* FreeBSD uses the old gcc convention for struct returns. */ + #if 0 #define USE_STRUCT_CONVENTION(gcc_p, type) \ generic_use_struct_convention (1, type) + #endif /* Support for longjmp. */ *************** extern int get_longjmp_target (CORE_ADDR *** 45,57 **** /* Support for signal handlers. */ - - /* The sigtramp is above the user stack and immediately below - the user area. Using constants here allows for cross debugging. - These are tested for FreeBSD 3.4. */ ! #define SIGTRAMP_START(pc) 0xbfbfdf20 ! #define SIGTRAMP_END(pc) 0xbfbfdff0 /* Offset to saved PC in sigcontext, from . */ #define SIGCONTEXT_PC_OFFSET 20 --- 55,63 ---- /* Support for signal handlers. */ ! extern int i386_freebsd_in_sigtramp (CORE_ADDR pc, char *name); ! #define IN_SIGTRAMP(PC, NAME) i386_freebsd_in_sigtramp (PC, NAME) /* Offset to saved PC in sigcontext, from . */ #define SIGCONTEXT_PC_OFFSET 20 Index: gdb/testsuite/gdb.base/completion.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/completion.exp,v retrieving revision 1.4 diff -c -p -r1.4 completion.exp *** completion.exp 2001/05/30 02:54:41 1.4 --- completion.exp 2001/07/11 00:06:46 *************** gdb_expect { *** 349,368 **** } ! send_gdb "p \"a\t" sleep 1 gdb_expect { ! -re "^p \"a\\\x07$"\ { send_gdb "\n" gdb_expect { -re "Unterminated string in expression\\..*$gdb_prompt $"\ ! { pass "complete 'p a'"} ! -re ".*$gdb_prompt $" { fail "complete 'p a'"} ! timeout {fail "(timeout) complete 'p a'"} } } ! -re ".*$gdb_prompt $" { fail "complete 'p \"a'" } ! timeout { fail "(timeout) complete 'p \"a'" } } send_gdb "p 'a\t" --- 349,370 ---- } ! set unlikely_word abracadubious ! ! send_gdb "p \"$unlikely_word\t" sleep 1 gdb_expect { ! -re "^p \"$unlikely_word\\\x07$"\ { send_gdb "\n" gdb_expect { -re "Unterminated string in expression\\..*$gdb_prompt $"\ ! { pass "complete 'p $unlikely_word'"} ! -re ".*$gdb_prompt $" { fail "complete 'p $unlikely_word'"} ! timeout {fail "(timeout) complete 'p $unlikely_word'"} } } ! -re ".*$gdb_prompt $" { fail "complete 'p \"$unlikely_word'" } ! timeout { fail "(timeout) complete 'p \"$unlikely_word'" } } send_gdb "p 'a\t" *************** gdb_expect { *** 387,393 **** -re "^p 'a\\\x07$" { send_gdb "\t" gdb_expect { ! -re "a64l.*argv.*$gdb_prompt p .a$" { send_gdb "\n" gdb_expect { -re "Invalid character constant\\..*$gdb_prompt $" { --- 389,395 ---- -re "^p 'a\\\x07$" { send_gdb "\t" gdb_expect { ! -re ".*argv.*$gdb_prompt p .a$" { send_gdb "\n" gdb_expect { -re "Invalid character constant\\..*$gdb_prompt $" { *************** gdb_expect { *** 425,487 **** } ! send_gdb "p b-a\t" sleep 1 gdb_expect { ! -re "^p b-a\\\x07$"\ { send_gdb "\n" gdb_expect { -re "No symbol \"b\" in current context\\..*$gdb_prompt $"\ ! { pass "complete 'p b-a'"} ! -re ".*$gdb_prompt $" { fail "complete 'p b-a'"} ! timeout {fail "(timeout) complete 'p b-a'"} } } ! -re ".*$gdb_prompt $" { fail "complete 'p b-a'" } ! timeout { fail "(timeout) complete 'p b-a'" } } ! send_gdb "p b-a\t" sleep 1 gdb_expect { ! -re "^p b-a\\\x07$" { send_gdb "\t" gdb_expect { ! -re "a64l.*argv.*$gdb_prompt p b-a$" { send_gdb "\n" gdb_expect { -re "No symbol \"b\" in current context\\..*$gdb_prompt $" { ! pass "complete (2) 'p b-a'" } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-a'" } ! timeout { fail "(timeout) complete (2) 'p b-a'" } } } -re "(There are $decimal possibilities\\. Do you really\r\nwish to see them all.|Display all $decimal possibilities.) \\(y or n\\)$" { send_gdb "n" gdb_expect { ! -re "\\(gdb\\) p b-a$" { send_gdb "\n" gdb_expect { -re "No symbol \"b\" in current context\\..*$gdb_prompt $" { ! pass "complete (2) 'p b-a'" } -re ".*$gdb_prompt $" { ! fail "complete (2) 'p b-a'" } ! timeout { fail "(timeout) complete (2) 'p b-a'" } } } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-a'" } ! timeout { fail "(timeout) complete (2) 'p b-a'" } } } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-a'" } ! timeout { fail "(timeout) complete (2) 'p b-a'" } } } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-a'" } ! timeout { fail "(timeout) complete (2) 'p b-a'" } } send_gdb "p b-\t" --- 427,489 ---- } ! send_gdb "p b-marker\t" sleep 1 gdb_expect { ! -re "^p b-marker\\\x07$"\ { send_gdb "\n" gdb_expect { -re "No symbol \"b\" in current context\\..*$gdb_prompt $"\ ! { pass "complete 'p b-marker'"} ! -re ".*$gdb_prompt $" { fail "complete 'p b-marker'"} ! timeout {fail "(timeout) complete 'p b-marker'"} } } ! -re ".*$gdb_prompt $" { fail "complete 'p b-marker'" } ! timeout { fail "(timeout) complete 'p b-marker'" } } ! send_gdb "p b-marker\t" sleep 1 gdb_expect { ! -re "^p b-marker\\\x07$" { send_gdb "\t" gdb_expect { ! -re "marker1 *marker2 *marker3 *marker4 *.*$gdb_prompt p b-marker$" { send_gdb "\n" gdb_expect { -re "No symbol \"b\" in current context\\..*$gdb_prompt $" { ! pass "complete (2) 'p b-marker'" } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-marker'" } ! timeout { fail "(timeout) complete (2) 'p b-marker'" } } } -re "(There are $decimal possibilities\\. Do you really\r\nwish to see them all.|Display all $decimal possibilities.) \\(y or n\\)$" { send_gdb "n" gdb_expect { ! -re "\\(gdb\\) p b-marker$" { send_gdb "\n" gdb_expect { -re "No symbol \"b\" in current context\\..*$gdb_prompt $" { ! pass "complete (2) 'p b-marker'" } -re ".*$gdb_prompt $" { ! fail "complete (2) 'p b-marker'" } ! timeout { fail "(timeout) complete (2) 'p b-marker'" } } } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-marker'" } ! timeout { fail "(timeout) complete (2) 'p b-marker'" } } } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-marker'" } ! timeout { fail "(timeout) complete (2) 'p b-marker'" } } } ! -re ".*$gdb_prompt $" { fail "complete (2) 'p b-marker'" } ! timeout { fail "(timeout) complete (2) 'p b-marker'" } } send_gdb "p b-\t" Index: gdb/testsuite/gdb.base/selftest.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/selftest.exp,v retrieving revision 1.2 diff -c -p -r1.2 selftest.exp *** selftest.exp 2001/03/06 08:21:51 1.2 --- selftest.exp 2001/07/11 00:06:46 *************** GDB.*Copyright \[0-9\]+ Free Software Fo *** 376,382 **** set description "backtrace through signal handler" send_gdb "backtrace\n" gdb_expect { ! -re "#0.*read.*in main \\(.*\\) at .*main\\.c.*$gdb_prompt $" { pass "$description" } -re ".*$gdb_prompt $" { --- 376,382 ---- set description "backtrace through signal handler" send_gdb "backtrace\n" gdb_expect { ! -re "#0.*cli_command_loop.*in main \\(.*\\) at .*main\\.c.*$gdb_prompt $" { pass "$description" } -re ".*$gdb_prompt $" { Index: gdb/i386-freebsd-nat.c =================================================================== diff -c -p empty i386-freebsd-nat.c *** Tue Jul 10 17:24:02 2001 --- i386-freebsd-nat.c Tue Jul 10 13:40:10 2001 *************** *** 0 **** --- 1,115 ---- + /* Native-dependent code for FreeBSD Unix running on i386's, for GDB. + Copyright 2000 Free Software Foundation, Inc. + + (This file is derived from i386b-nat.c.) + + 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 "frame.h" + #include "inferior.h" + #include + #include + #include + #include + #include + + /* Return the saved program counter for FRAME. */ + + CORE_ADDR + i386_freebsd_frame_saved_pc (struct frame_info *frame) + { + CORE_ADDR pc; + + if (!frame->signal_handler_caller) + return read_memory_unsigned_integer (frame->frame + 4, 4); + + if (frame->next) + return read_memory_unsigned_integer ((CORE_ADDR)&((struct sigframe *)(frame->next->frame + 8))->sf_uc.uc_mcontext.mc_eip, 4); + else + return 0; + } + + int + i386_freebsd_in_sigtramp (CORE_ADDR pc, char *name) + { + return ((pc >= (CORE_ADDR)PS_STRINGS - 100) + && ((pc) < (CORE_ADDR)PS_STRINGS)); + } + + /* Resume execution of the inferior process. + If STEP is nonzero, single-step it. + If SIGNAL is nonzero, give it that signal. */ + + void + child_resume (ptid_t ptid, int step, enum target_signal signal) + { + int pid = PIDGET (ptid); + + errno = 0; + + if (pid == -1) + /* Resume all threads. */ + /* I think this only gets used in the non-threaded case, where "resume + all threads" and "resume inferior_ptid" are the same. */ + pid = PIDGET (inferior_ptid); + + /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where + it was. (If GDB wanted it to start some other way, we have already + written a new PC value to the child.) + + If this system does not support PT_STEP, a higher level function will + have called single_step() to transmute the step request into a + continue request (by setting breakpoints on all possible successor + instructions), so we don't have to worry about that here. */ + + if (step) + { + if (SOFTWARE_SINGLE_STEP_P ()) + internal_error (__FILE__, __LINE__, "failed internal consistency check"); /* Make sure this doesn't happen. */ + else + ptrace (PT_STEP, pid, (PTRACE_ARG3_TYPE) 1, + target_signal_to_host (signal)); + } + else + { + unsigned int eflags; + + /* Workaround for a bug in FreeBSD. Make sure that the trace flag is off + when doing a continue. There is a code path through the kernel which + can leaves the flag on by the time we get here. If a process has a + signal pending (such as SIGALRM) and we do a PT_STEP, the process + never really has a chance to run because the kernel needs to notify + the debugger that a signal is being sent. Therefore, the process + never goes through the kernel's trap() function which would normally + clear it. */ + + eflags = read_register (PS_REGNUM); + if (eflags & 0x100) + write_register (PS_REGNUM, eflags & ~0x100); + + ptrace (PT_CONTINUE, pid, (PTRACE_ARG3_TYPE) 1, + target_signal_to_host (signal)); + } + + if (errno) + { + perror_with_name ("ptrace"); + } + }