This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
On Sat, Jun 20, 2009 at 4:55 PM, Pedro Alves<pedro@codesourcery.com> wrote: > On Tuesday 02 June 2009 16:36:05, Doug Evans wrote: > >> RCS file: i386-low.c >> diff -N i386-low.c >> --- /dev/null???1 Jan 1970 00:00:00 -0000 >> +++ i386-low.c??1 Jun 2009 22:02:43 -0000 >> @@ -0,0 +1,660 @@ > > >> +/* Support for 8-byte wide hw watchpoints. ?*/ >> +#ifndef TARGET_HAS_DR_LEN_8 >> +#define TARGET_HAS_DR_LEN_8 (sizeof (long) == 8) > > Note: this will be trouble for Win64 (sizeof(long) == 4, sizeof (ptr) == 8) changed to sizeof (void *) >> +/* Set in DR7 the RW and LEN fields for the I'th debug register. ?*/ >> +#define I386_DR_SET_RW_LEN(state, i,rwlen) \ >> + ?do { \ >> + ? ?(state)->dr_control_mirror &= \ >> + ? ? ?~(0x0f << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \ >> + ? ?(state)->dr_control_mirror |= \ >> + ? ? ?((rwlen) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \ >> + ?} while (0) > > Spaces around operators missing, here and several other places. > I realise this is copied from GDB, but IWBN to fix this while we > go. ?Feel free to fix it on GDB as well, as obvious. patch updated. >> +/* Whether or not to print the mirrored debug registers. ?*/ >> +static int maint_show_dr = 0; > > I see nowhere where this can be set. ?There are a few references to > GDB's main show-debug-regs command left behind. ?Could this be set with > a command line option and/or monitor command perhaps? It was useful during debugging, I just hardcoded it to 1. As for how to really enable set it, I wasn't sure. I added a monitor command. > >> + >> +/* Types of operations supported by i386_handle_nonaligned_watchpoint. ?*/ >> +typedef enum { WP_INSERT, WP_REMOVE, WP_COUNT } i386_wp_op_t; >> + >> +/* Internal functions. ?*/ >> + >> +/* Return the value of a 4-bit field for DR7 suitable for watching a >> + ? region of LEN bytes for accesses of type TYPE. ?LEN is assumed to >> + ? have the value of 1, 2, or 4. ?*/ >> +static unsigned i386_length_and_rw_bits (int len, enum target_hw_bp_type type); >> + >> +/* Insert a watchpoint at address ADDR, which is assumed to be aligned >> + ? according to the length of the region to watch. ?LEN_RW_BITS is the >> + ? value of the bit-field from DR7 which describes the length and >> + ? access type of the region to be watched by this watchpoint. ?Return >> + ? 0 on success, -1 on failure. ?*/ >> +static int i386_insert_aligned_watchpoint (struct i386_debug_reg_state *state, >> +??????????????????????????????????????? ? CORE_ADDR addr, >> +??????????????????????????????????????? ? unsigned len_rw_bits); >> + >> +/* Remove a watchpoint at address ADDR, which is assumed to be aligned >> + ? according to the length of the region to watch. ?LEN_RW_BITS is the >> + ? value of the bits from DR7 which describes the length and access >> + ? type of the region watched by this watchpoint. ?Return 0 on >> + ? success, -1 on failure. ?*/ >> +static int i386_remove_aligned_watchpoint (struct i386_debug_reg_state *state, >> +??????????????????????????????????????? ? CORE_ADDR addr, >> +??????????????????????????????????????? ? unsigned len_rw_bits); >> + >> +/* Insert or remove a (possibly non-aligned) watchpoint, or count the >> + ? number of debug registers required to watch a region at address >> + ? ADDR whose length is LEN for accesses of type TYPE. ?Return 0 on >> + ? successful insertion or removal, a positive number when queried >> + ? about the number of registers, or -1 on failure. ?If WHAT is not a >> + ? valid value, bombs through fatal. ?*/ >> +static int i386_handle_nonaligned_watchpoint (struct i386_debug_reg_state *state, >> +??????????????????????????????????????? ? ? ?i386_wp_op_t what, >> +??????????????????????????????????????? ? ? ?CORE_ADDR addr, int len, >> +??????????????????????????????????????? ? ? ?enum target_hw_bp_type type); > > I don't think none of these forward declarations is needed? ok [once upon a time, they were ok. the new rules haven't been locked in memory yet] >> + >> +/* Implementation. ?*/ >> + >> +/* Clear the reference counts and forget everything we knew about the >> + ? debug registers. ?*/ >> + >> +void >> +i386_low_cleanup_dregs (struct i386_debug_reg_state *state) >> +{ >> + ?int i; >> + >> + ?ALL_DEBUG_REGISTERS(i) >> + ? ?{ >> + ? ? ?state->dr_mirror[i] = 0; >> + ? ? ?state->dr_ref_count[i] = 0; >> + ? ?} >> + ?state->dr_control_mirror = 0; >> + ?state->dr_status_mirror ?= 0; >> +} > > This isn't called anywhere? Ah. 'tis now. >> + >> +/* Print the values of the mirrored debug registers. ?This is called >> + ? when maint_show_dr is non-zero. > >> To set that up, type "maint >> + ? show-debug-regs" at GDB's prompt. ?*/ > > Nope, this is a lie. fixed. >> + >> +static void >> +i386_show_dr (struct i386_debug_reg_state *state, >> +??????? ? ? ?const char *func, CORE_ADDR addr, >> +??????? ? ? ?int len, enum target_hw_bp_type type) >> +{ >> + ?int i; >> + >> + ?printf (func); >> + ?if (addr || len) >> + ? ?printf (" (addr=%lx, len=%d, type=%s)", >> +??????????????? ? ? ? (unsigned long) addr, len, >> +??????????????? ? ? ? type == hw_write ? "data-write" >> +??????????????? ? ? ? : (type == hw_read ? "data-read" >> +??????????????????????? ?: (type == hw_access ? "data-read/write" >> +??????????????????????? ? ? : (type == hw_execute ? "instruction-execute" >> +???????????????????????????????/* FIXME: if/when I/O read/write >> +??????????????????????????????? ? watchpoints are supported, add them >> +??????????????????????????????? ? here. ?*/ >> +???????????????????????????????: "??unknown??")))); >> + ?printf (":\n"); >> + ?printf ("\tCONTROL (DR7): %08x ? ? ? ? ?STATUS (DR6): %08x\n", >> +??????????????? ? ? state->dr_control_mirror, state->dr_status_mirror); >> + ?ALL_DEBUG_REGISTERS (i) >> + ? ?{ >> + ? ? ?printf ("\ >> +\tDR%d: addr=0x%s, ref.count=%d ?DR%d: addr=0x%s, ref.count=%d\n", >> +??????????????????????? i, paddr (state->dr_mirror[i]), state->dr_ref_count[i], >> +??????????????????????? i+1, paddr (state->dr_mirror[i+1]), state->dr_ref_count[i+1]); >> + ? ? ?i++; >> + ? ?} >> +} > > These should not go to stdout. ?GDB should be fixed too to make these go to > gdb_stdlog. changed to stderr >> + >> +static int >> +Z_packet_to_hw_type (char type) >> +{ >> + ?switch (type) >> + ? ?{ >> + ? ?case Z_PACKET_WRITE_WP: ?return hw_write; >> + ? ?case Z_PACKET_READ_WP: ? return hw_read; >> + ? ?case Z_PACKET_ACCESS_WP: return hw_access; > > Please don't vertically align. ?Stick to the standards and put > those return statements in their own line. k. >> + ? ?default: >> + ? ? ?error ("Z_packet_to_hw_type: bad watchpoint type %c", type); >> + ? ?} >> +} >> + >> +/* Insert a watchpoint to watch a memory region which starts at >> + ? address ADDR and whose length is LEN bytes. ?Watch memory accesses >> + ? of the type TYPE_FROM_PACKET. ?Return 0 on success, -1 on failure. ?*/ >> + >> +int >> +i386_low_insert_watchpoint (struct i386_debug_reg_state *state, >> +??????????????????????? ? ?char type_from_packet, CORE_ADDR addr, int len) >> +{ >> + ?int retval; >> + ?int type = Z_packet_to_hw_type (type_from_packet); >> + >> + ?if (((len != 1 && len !=2 && len !=4) && !(TARGET_HAS_DR_LEN_8 && len == 8)) > > More examples of missing space around operators coming from GDB. patch updated >> + >> +/* If the inferior has some watchpoint that triggered, set the >> + ? address associated with that watchpoint and return non-zero. >> + ? Otherwise, return zero. ?*/ >> + >> +CORE_ADDR >> +i386_low_stopped_data_address (struct i386_debug_reg_state *state) >> +{ >> + ?CORE_ADDR addr = 0; >> + ?int i; >> + >> + ?/* Get dr_status_mirror for use by I386_DR_WATCH_HIT. ?*/ >> + ?i386_dr_low_get_status (state); >> + >> + ?ALL_DEBUG_REGISTERS(i) >> + ? ?{ >> + ? ? ?if (I386_DR_WATCH_HIT (state, i) >> +??????? ?/* This second condition makes sure DRi is set up for a data >> +??????? ? ? watchpoint, not a hardware breakpoint. ?The reason is >> +??????? ? ? that GDB doesn't call the target_stopped_data_address >> +??????? ? ? method except for data watchpoints. ?In other words, I'm >> +??????? ? ? being paranoiac. ?*/ >> +??????? ?&& I386_DR_GET_RW_LEN (state, i) != 0) >> +???????{ >> +??????? ?addr = state->dr_mirror[i]; >> +??????? ?if (maint_show_dr) >> +??????? ? ?i386_show_dr (state, "watchpoint_hit", addr, -1, hw_write); >> +???????} >> + ? ?} >> + >> + ?if (maint_show_dr && addr == 0) >> + ? ?i386_show_dr (state, "stopped_data_addr", 0, 0, hw_write); >> + > >> + ?/* NOTE: gdb version checks rc != 0 here. ?*/ >> + ?return addr; >> +} > > Indeed. ?GDB's interface was fixed to allow watchpoints at 0. ?I > don't think that matters for any gdbserver target, but it would > be nice to fix the interface anyway... patch updated >> + >> +int >> +i386_low_stopped_by_watchpoint (struct i386_debug_reg_state *state) >> +{ >> + ?CORE_ADDR addr = 0; >> + ?/* NOTE: gdb version passes boolean found/not-found result from >> + ? ? i386_stopped_data_address. ?*/ >> + ?addr = i386_low_stopped_data_address (state); >> + ?return (addr != 0); >> +} > > Same as above. ?You've probably thought about that too... > >> + >> +/* Support for h/w breakpoints. >> + ? This support is not currently used, kept for reference. ?*/ > > Any reason for not using this currently? ?If there's a good reason, > than let's drop it. ?But I'd prefer to have it working. ?:-) deleted. >> Index: utils.c >> =================================================================== > > +char * > +paddr (CORE_ADDR addr) > > This isn't documented in neither server.h or here? Just "going with the flow". > +{ > + ?char *str = get_cell (); > + ?xsnprintf (str, CELLSIZE, "%lx", (long) addr); > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^^^^ > > Note: this will be wrong on Win64... ?BTW, Ulrich > was removing several of these functions from GDB > in the removing-current_gdbarch series. ?Will this one > stay? ?Might be worth it to use the one that is going > to stay in GDB. I think a higher order bit is that gdb and gdbserver cannot share code. Bringing over all the smarts to handle all the different portability issues is painful/depressing. I went with something simple that works for now. IWBN if this kind of thing were in, say, libiberty and tools could just use it. > > + ?return str; > +} > > > >> Index: linux-low.c >> =================================================================== >> RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v >> retrieving revision 1.105 >> diff -u -p -r1.105 linux-low.c >> --- linux-low.c?24 May 2009 17:44:19 -0000??????1.105 >> +++ linux-low.c?1 Jun 2009 22:02:43 -0000 >> @@ -224,6 +224,7 @@ delete_lwp (struct lwp_info *lwp) >> ?{ >> ? ?remove_thread (get_lwp_thread (lwp)); >> ? ?remove_inferior (&all_lwps, &lwp->head); >> + ?free (lwp->arch_private); >> ? ?free (lwp); >> ?} >> >> @@ -242,6 +243,9 @@ linux_add_process (int pid, int attached >> ? ?proc = add_process (pid, attached); >> ? ?proc->private = xcalloc (1, sizeof (*proc->private)); >> >> + ?if (the_low_target.new_process != NULL) >> + ? ?proc->private->arch_private = the_low_target.new_process (pid, attached); > > ( Wouldn't the interface be a bit cleaner if you > passed the 'proc' pointer down to new_process, and have the > callback manage arch_private field itself? ?As is, your passing > some useless parameters down. ?If they end up being needed, > it is likely that an extra look up on pid would be needed to > get at the structure. ?This would also migrate better to a > per-process data mechanism similar to gdb's objfile_data, if > need be. ) args deleted. >> Index: linux-low.h >> =================================================================== >> RCS file: /cvs/src/src/gdb/gdbserver/linux-low.h,v >> retrieving revision 1.30 >> diff -u -p -r1.30 linux-low.h >> --- linux-low.h?12 May 2009 22:25:00 -0000??????1.30 >> +++ linux-low.h?1 Jun 2009 22:02:43 -0000 >> @@ -56,8 +56,13 @@ struct process_info_private >> >> ? ?/* Connection to the libthread_db library. ?*/ >> ? ?td_thragent_t *thread_agent; >> + >> + ?/* Target-specific additions. ?*/ > > Warning: "Target" overload. ?We need to get into the habit > of not doing this --- it makes refering to these things quite > ambiguous. ?Call it "arch" or something else. ?There are other > similar cases. I dunno. there's "the_low_target" in linux-low.h Perhaps we can migrate away but I don't see the above "infraction" as being critical. >> ?#define pid_of(proc) ptid_get_pid ((proc)->head.id) >> ?#define lwpid_of(proc) ptid_get_lwp ((proc)->head.id) >> +#define PIDGET(ptid) ptid_get_pid (ptid) >> +#define TIDGET(ptid) ptid_get_lwp (ptid) > > Why do we need extra ways to do the same thing? ?Let's not > copy GDB's bad habits and legacy code. k. >> --- linux-x86-low.c?????13 May 2009 19:11:04 -0000??????1.2 >> +++ linux-x86-low.c?????1 Jun 2009 22:02:43 -0000 > >> +static unsigned long >> +x86_linux_dr_get (ptid_t ptid, int regnum) >> +{ >> + ?int tid; >> + ?unsigned long value; >> + >> + ?tid = TIDGET (ptid); >> + ?if (tid == 0) >> + ? ?tid = PIDGET (ptid); > > The tid == 0 case is dead code coming from GDB, isn't it? > Likewise in other places. Perhaps. There's similar code in linux-low.c:same_lwp. == 0 code deleted. >> + >> + ?errno = 0; >> + ?value = ptrace (PTRACE_PEEKUSER, tid, >> +??????????????? ?offsetof (struct user, u_debugreg[regnum]), 0); >> + ?if (errno != 0) >> + ? ?error ("Couldn't read debug register"); >> + >> + ?return value; >> +} >> + > >> +/* Update the inferior's debug register REGNUM from STATE. ?*/ >> + >> +void >> +i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum) >> +{ >> + ?struct inferior_list_entry *lp; >> + ?CORE_ADDR addr; >> + >> + ?if (! (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR)) >> + ? ?fatal ("Invalid debug register %d", regnum); >> + >> + ?addr = state->dr_mirror[regnum]; >> + >> + ?/* ??? Will need tweaking for multi-process. ?*/ > > Indeed. ?Why not just set the debug_registers_changed in lwps > of the current process? Are there any existing examples of this? I would have done that had process_info contained the list of its threads (it would have been trivially straightforward). >> + ?for (lp = all_lwps.head; lp; lp = lp->next) >> + ? ?{ >> + ? ? ?struct lwp_info *lwp = (struct lwp_info *) lp; >> + >> + ? ? ?/* The actual update is done later, we just mark that the register >> +??????? needs updating. ?*/ >> + ? ? ?lwp->arch_private->debug_registers_changed = 1; >> + ? ?} > > Thanks, this is likely more non-stop friendly than the win32 version. > We can just send a SIGSTOP to each thread that is stopped, and set > stop_expected. ?Then, the debug register updating just works. ?(we'll > still need to make sure that moribund locations work with watchpoints > though) > > >> Index: utils.c >> =================================================================== >> RCS file: /cvs/src/src/gdb/gdbserver/utils.c,v >> retrieving revision 1.18 >> diff -u -p -r1.18 utils.c >> --- utils.c?????19 Jan 2009 00:16:46 -0000??????1.18 >> +++ utils.c?????1 Jun 2009 22:02:43 -0000 >> @@ -170,3 +170,37 @@ warning (const char *string,...) >> ? ?fprintf (stderr, "\n"); >> ? ?va_end (args); >> ?} >> + >> +/* temporary storage using circular buffer */ > > More bogus formatting copied from GDB. ?Full sentence: capitalize, period, > double space. k. >> +#define NUMCELLS 4 >> +#define CELLSIZE 50 >> +static char * >> +get_cell (void) >> +{ >> + ?static char buf[NUMCELLS][CELLSIZE]; >> + ?static int cell = 0; >> + ?if (++cell >= NUMCELLS) >> + ? ?cell = 0; >> + ?return buf[cell]; >> +} >> + > > > Otherwise, this is looking good to me. ?I still feel that > exposing the debug registers to GDB (as per-process wide > registers), as opposed to using Z packets would be an > alternative worth investigating, that would avoid having > to mostly copy i386-nat.c to gdbserver/i386-low.c. ?But, > the Z packets interface already exists, so, that can > always be investigated at any later time... Setting aside breakpoints+watchpoints -> "points", http://sourceware.org/ml/gdb-patches/2009-06/msg00594.html how about this?
Attachment:
gdb-090622-gdbserver-hw-wp-4.patch.txt
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |