Here are patches for gdb 4.12. We did not write the original patch but we have updated it to recent versions of gdb. You must remember to compile with -DHAVE_MEMORY_BREAKPOINT in your CFLAGS. The commands are 'abreak' and 'wbreak' for access breakpoint and write breakpoint. ----- *** gdb/breakpoint.c-dist Thu Feb 3 11:40:58 1994 --- gdb/breakpoint.c Tue Mar 8 02:05:09 1994 *************** *** 111,117 **** breakpoints_info PARAMS ((char *, int)); static void ! breakpoint_1 PARAMS ((int, int)); static bpstat bpstat_alloc PARAMS ((struct breakpoint *, bpstat)); --- 111,117 ---- breakpoints_info PARAMS ((char *, int)); static void ! breakpoint_1 PARAMS ((int, int, int)); static bpstat bpstat_alloc PARAMS ((struct breakpoint *, bpstat)); *************** *** 475,480 **** --- 475,505 ---- } if (disabled_breaks) printf_filtered ("\n"); + + #ifdef HAVE_MEM_BREAKPOINT + target_init_memory_breakpoint(); + + ALL_BREAKPOINTS (b) + if (b->mem_break_enable != mem_break_disabled && b->enable != disabled) + { + int rv; + + rv = target_insert_memory_breakpoint(b->mem_break_address, + b->mem_break_length, + b->mem_break_enable, b->number); + if (rv) + { + /* Can't set the breakpoint. */ + fprintf_unfiltered (gdb_stderr, + "Cannot set memory breakpoint %d.\n", + b->number); + printf_unfiltered ("Disabling it.\n"); + printf_unfiltered ("It is best to set memory breakpoints on\n"); + printf_unfiltered ("small, properly aligned objects\n"); + b->enable = disabled; + } + } + #endif /* HAVE_MEM_BREAKPOINT */ return val; } *************** *** 504,509 **** --- 529,537 ---- local_hex_string((unsigned long) b->shadow_contents[1])); #endif /* BREAKPOINT_DEBUG */ } + #ifdef HAVE_MEM_BREAKPOINT + target_init_memory_breakpoint(); + #endif /* HAVE_MEM_BREAKPOINT */ return 0; } *************** *** 783,789 **** which has since been deleted. */ if (bs->breakpoint_at == NULL || (bs->breakpoint_at->type != bp_breakpoint ! && bs->breakpoint_at->type != bp_watchpoint)) return 0; if (bs->breakpoint_at->type == bp_breakpoint) --- 811,818 ---- which has since been deleted. */ if (bs->breakpoint_at == NULL || (bs->breakpoint_at->type != bp_breakpoint ! && bs->breakpoint_at->type != bp_watchpoint ! && bs->breakpoint_at->type != bp_memorypoint)) return 0; if (bs->breakpoint_at->type == bp_breakpoint) *************** *** 829,834 **** --- 858,880 ---- if (val >= 0) return val; + #ifdef HAVE_MEM_BREAKPOINT + if (bs->breakpoint_at->mem_break_enable != mem_break_disabled) + { + printf_filtered ("\nMemory breakpoint %d on ", + bs->breakpoint_at->number); + print_expression (bs->breakpoint_at->mem_break_exp, stdout); + printf_filtered (" at %s with length %d: ", + local_hex_string(bs->breakpoint_at->mem_break_address), + bs->breakpoint_at->mem_break_length); + if(bs->breakpoint_at->mem_break_enable == mem_break_write) + printf_filtered ("written.\n"); + else + printf_filtered ("accessed.\n"); + return 1; + } + #endif /* HAVE_MEM_BREAKPOINT */ + /* Maybe another breakpoint in the chain caused us to stop. (Currently all watchpoints go on the bpstat whether hit or not. That probably could (should) be changed, provided care is taken *************** *** 1113,1118 **** --- 1159,1167 ---- /* True if we've hit a breakpoint (as opposed to a watchpoint). */ int real_breakpoint = 0; #endif + #ifdef HAVE_MEM_BREAKPOINT + int memory_breakpoint = target_get_memory_breakpoint_status (); + #endif /* HAVE_MEM_BREAKPOINT */ /* Root of the chain of bpstat's */ struct bpstat root_bs[1]; /* Pointer to the last thing in the chain currently. */ *************** *** 1126,1132 **** if (b->enable == disabled) continue; ! if (b->type != bp_watchpoint && b->address != bp_addr) continue; if (b->type != bp_watchpoint && not_a_breakpoint) --- 1175,1181 ---- if (b->enable == disabled) continue; ! if (b->type != bp_watchpoint && b->type != bp_memorypoint && b->address != bp_addr) continue; if (b->type != bp_watchpoint && not_a_breakpoint) *************** *** 1134,1139 **** --- 1183,1194 ---- /* Come here if it's a watchpoint, or if the break address matches */ + #ifdef HAVE_MEM_BREAKPOINT + if (b->mem_break_enable != mem_break_disabled && + b->number != memory_breakpoint) + continue; + #endif /* HAVE_MEM_BREAKPOINT */ + bs = bpstat_alloc (b, bs); /* Alloc a bpstat to explain stop */ bs->stop = 1; *************** *** 1175,1182 **** --- 1230,1242 ---- } } #if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS) + #ifdef HAVE_MEM_BREAKPOINT + else if (b->mem_break_enable == mem_break_disabled) + real_breakpoint = 1; + #else /* !HAVE_MEM_BREAKPOINT */ else real_breakpoint = 1; + #endif /* !HAVE_MEM_BREAKPOINT */ #endif if (b->frame && b->frame != frame_address) *************** *** 1342,1347 **** --- 1402,1408 ---- case bp_breakpoint: case bp_until: case bp_finish: + case bp_memorypoint: if (bs->stop) { if (bs->print) *************** *** 1419,1437 **** /* Print information on breakpoint number BNUM, or -1 if all. If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS ! is nonzero, process only watchpoints. */ static void ! breakpoint_1 (bnum, allflag) int bnum; int allflag; { register struct breakpoint *b; register struct command_line *l; register struct symbol *sym; CORE_ADDR last_addr = (CORE_ADDR)-1; int found_a_breakpoint = 0; ! static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint", "longjmp", "longjmp resume", "step resume", "call dummy" }; static char *bpdisps[] = {"del", "dis", "keep"}; --- 1480,1501 ---- /* Print information on breakpoint number BNUM, or -1 if all. If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS ! is one, process only watchpoints; if WATCHPOINTS is two, process ! only memory break points. */ static void ! breakpoint_1 (bnum, allflag, watchpoints) int bnum; int allflag; + int watchpoints; { register struct breakpoint *b; register struct command_line *l; register struct symbol *sym; CORE_ADDR last_addr = (CORE_ADDR)-1; int found_a_breakpoint = 0; ! static char *bptypes[] = {"breakpoint", "until", "finish", ! "watchpoint", "memorypoint", "longjmp", "longjmp resume", "step resume", "call dummy" }; static char *bpdisps[] = {"del", "dis", "keep"}; *************** *** 1445,1453 **** /* We only print out user settable breakpoints unless the allflag is set. */ if (!allflag && b->type != bp_breakpoint ! && b->type != bp_watchpoint) continue; if (!found_a_breakpoint++) printf_filtered ("Num Type Disp Enb %sWhat\n", addressprint ? "Address " : ""); --- 1509,1548 ---- /* We only print out user settable breakpoints unless the allflag is set. */ if (!allflag && b->type != bp_breakpoint ! && b->type != bp_watchpoint ! && b->type != bp_memorypoint) continue; + #ifdef HAVE_MEM_BREAKPOINT + if (b->type == bp_watchpoint && !allflag && watchpoints == 2) + { + if (bnum == -1) + continue; + error ("That is a watchpoint, not a memorypoint."); + } + + if (b->type == bp_breakpoint && !allflag && watchpoints == 2) + { + if (bnum == -1) + continue; + error ("That is a breakpoint, not a memorypoint."); + } + + if (b->type == bp_memorypoint && !allflag && watchpoints == 0) + { + if (bnum == -1) + continue; + error ("That is a memorypoint, not a breakpoint."); + } + + if (b->type == bp_memorypoint && !allflag && watchpoints == 1) + { + if (bnum == -1) + continue; + error ("That is a memorypoint, not a watchpoint."); + } + #endif /* HAVE_MEM_BREAKPOINT */ + if (!found_a_breakpoint++) printf_filtered ("Num Type Disp Enb %sWhat\n", addressprint ? "Address " : ""); *************** *** 1466,1471 **** --- 1561,1586 ---- print_expression (b->exp, gdb_stdout); break; + #ifdef HAVE_MEM_BREAKPOINT + case bp_memorypoint: + if(b->mem_break_enable == mem_break_disabled) + print_expression (b->exp, stdout); + else + { + printf_filtered ("%-10s", + local_hex_string(b->mem_break_address)); + printf_filtered (" "); + if(b->mem_break_enable == mem_break_write) + printf_filtered ("w "); + else + printf_filtered ("r/w"); + printf_filtered (" "); + printf_filtered ("%d ", b->mem_break_length); + print_expression (b->mem_break_exp, stdout); + } + break; + #endif /* HAVE_MEM_BREAKPOINT */ + case bp_breakpoint: case bp_until: case bp_finish: *************** *** 1521,1529 **** if (!found_a_breakpoint) { if (bnum == -1) ! printf_filtered ("No breakpoints or watchpoints.\n"); else ! printf_filtered ("No breakpoint or watchpoint number %d.\n", bnum); } else /* Compare against (CORE_ADDR)-1 in case some compiler decides --- 1636,1644 ---- if (!found_a_breakpoint) { if (bnum == -1) ! printf_filtered ("No breakpoints, watchpoints or memorypoints.\n"); else ! printf_filtered ("No breakpoint, watchpoint, or memorypoint number %d.\n", bnum); } else /* Compare against (CORE_ADDR)-1 in case some compiler decides *************** *** 1543,1549 **** if (bnum_exp) bnum = parse_and_eval_address (bnum_exp); ! breakpoint_1 (bnum, 0); } #if MAINTENANCE_CMDS --- 1658,1664 ---- if (bnum_exp) bnum = parse_and_eval_address (bnum_exp); ! breakpoint_1 (bnum, 0, 0); } #if MAINTENANCE_CMDS *************** *** 1559,1569 **** if (bnum_exp) bnum = parse_and_eval_address (bnum_exp); ! breakpoint_1 (bnum, 1); } #endif /* Print a message describing any breakpoints set at PC. */ static void --- 1674,1700 ---- if (bnum_exp) bnum = parse_and_eval_address (bnum_exp); ! breakpoint_1 (bnum, 1, 0); } #endif + #ifdef HAVE_MEM_BREAKPOINT + /* ARGSUSED */ + static void + memory_breakpoint_info (bnum_exp, from_tty) + char *bnum_exp; + int from_tty; + { + int bnum = -1; + + if (bnum_exp) + bnum = parse_and_eval_address (bnum_exp); + + breakpoint_1 (bnum, 0, 2); + } + #endif /* HAVE_MEM_BREAKPOINT */ + /* Print a message describing any breakpoints set at PC. */ static void *************** *** 1817,1822 **** --- 1948,1957 ---- { switch (b->type) { + case bp_memorypoint: + printf_filtered ("Memorypoint %d: ", b->number); + print_expression (b->exp, stdout); + break; case bp_watchpoint: printf_filtered ("Watchpoint %d: ", b->number); print_expression (b->exp, gdb_stdout); *************** *** 2126,2131 **** --- 2261,2329 ---- b->exp_string = savestring (arg, strlen (arg)); mention (b); } + + #ifdef HAVE_MEM_BREAKPOINT + /* ARGSUSED */ + static void + memory_breakpoint_command (arg, from_tty, mode) + char *arg; + int from_tty; + enum mem_break_enable mode; + { + struct breakpoint *b; + struct symtab_and_line sal; + struct expression *exp; + struct block *exp_valid_block; + struct value *watch_obj; + + sal.pc = 0; + sal.symtab = NULL; + sal.line = 0; + + /* Parse arguments. */ + innermost_block = NULL; + exp = parse_expression (arg); + exp_valid_block = innermost_block; + watch_obj = evaluate_expression (exp); + + if (lval_memory != VALUE_LVAL (watch_obj)) + error ("Requested memory break not in memory, e.g. register or constant."); + + /* Now set up the breakpoint. */ + b = set_raw_breakpoint (sal); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->exp = exp; + b->type = bp_memorypoint; + b->disposition = donttouch; + b->exp_valid_block = NULL; + b->val = NULL; + b->cond = 0; + b->cond_string = NULL; + b->mem_break_exp = exp; + b->mem_break_address = VALUE_ADDRESS (watch_obj); + b->mem_break_length = TYPE_LENGTH (VALUE_TYPE (watch_obj)); + b->mem_break_enable = mode; + mention (b); + } + + static void + write_memory_breakpoint_command (arg, from_tty) + char *arg; + int from_tty; + { + memory_breakpoint_command (arg, from_tty, mem_break_write); + } + + static void + access_memory_breakpoint_command (arg, from_tty) + char *arg; + int from_tty; + { + memory_breakpoint_command (arg, from_tty, mem_break_rw); + } + #endif /* HAVE_MEM_BREAKPOINT */ + /* * Helper routine for the until_command routine in infcmd.c. Here *************** *** 3201,3206 **** --- 3399,3422 ---- This command may be abbreviated \"disable\".", &disablelist); + #ifdef HAVE_MEM_BREAKPOINT + add_com ("wbreak", class_breakpoint, write_memory_breakpoint_command, + "Set a memory write breakpoint at a location.\n\ + A memory write breakpoint stops execution of your program whenever it\n\ + tries to write data at that location."); + + add_com ("abreak", class_breakpoint, access_memory_breakpoint_command, + "Set a memory access breakpoint at a location.\n\ + A memory access breakpoint stops execution of your program whenever it\n\ + tries to read or write data at that location."); + + add_info ("memorypoints", memory_breakpoint_info, + "Status of all memory access breakpoints, or memory access\n\ + breakpoint number NUMBER. Second column is \"y\" for enabled memory\n\ + access breakpoints, \"n\" for disabled."); + + #endif /* HAVE_MEM_BREAKPOINT */ + add_prefix_cmd ("delete", class_breakpoint, delete_command, "Delete some breakpoints or auto-display expressions.\n\ Arguments are breakpoint numbers with spaces in between.\n\ *************** *** 3267,3272 **** --- 3483,3489 ---- The \"Type\" column indicates one of:\n\ \tbreakpoint - normal breakpoint\n\ \twatchpoint - watchpoint\n\ + \tmemorypoint -watchpoint using 386 hardware debugging registers\n\ \tlongjmp - internal breakpoint used to step through longjmp()\n\ \tlongjmp resume - internal breakpoint at the target of longjmp()\n\ \tuntil - internal breakpoint used by the \"until\" command\n\ *** gdb/breakpoint.h-dist Thu Feb 3 11:40:59 1994 --- gdb/breakpoint.h Mon Mar 7 20:15:53 1994 *************** *** 23,28 **** --- 23,32 ---- #include "frame.h" #include "value.h" + #ifdef HAVE_MEM_BREAKPOINT + enum mem_break_enable { mem_break_disabled, mem_break_write, mem_break_rw }; + #endif /* HAVE_MEM_BREAKPOINT */ + /* This is the maximum number of bytes a breakpoint instruction can take. Feel free to increase it. It's just used in a few places to size arrays that should be independent of the target architecture. */ *************** *** 42,47 **** --- 46,52 ---- bp_until, /* used by until command */ bp_finish, /* used by finish command */ bp_watchpoint, /* Watchpoint */ + bp_memorypoint, /* Memory breakpoint */ bp_longjmp, /* secret breakpoint to find longjmp() */ bp_longjmp_resume, /* secret breakpoint to escape longjmp() */ *************** *** 130,136 **** struct expression *cond; /* String we used to set the breakpoint (malloc'd). Only matters if ! address is non-NULL. */ char *addr_string; /* String form of the breakpoint condition (malloc'd), or NULL if there is no condition. */ --- 135,141 ---- struct expression *cond; /* String we used to set the breakpoint (malloc'd). Only matters if ! address is non-NULL, or if mem_break_enable is not mem_break_disabled. */ char *addr_string; /* String form of the breakpoint condition (malloc'd), or NULL if there is no condition. */ *************** *** 147,152 **** --- 152,169 ---- value val; /* Thread number for thread-specific breakpoint, or -1 if don't care */ int thread; + + #ifdef HAVE_MEM_BREAKPOINT + /* Address to memory break at. */ + CORE_ADDR mem_break_address; + /* length of block to look at */ + int mem_break_length; + /* expression for address to look at */ + struct expression *mem_break_exp; + /* set to mem_break_read, mem_break_write, or mem_break_rw if this is a + memory breakpoint.*/ + enum mem_break_enable mem_break_enable; + #endif /* HAVE_MEM_BREAKPOINT */ }; /* The following stuff is an abstract data type "bpstat" ("breakpoint status"). *** gdb/corelow.c-dist Thu Feb 3 11:41:07 1994 --- gdb/corelow.c Mon Mar 7 20:40:42 1994 *************** *** 320,325 **** --- 320,328 ---- core_stratum, 0, /* next */ 0, 1, 1, 1, 0, /* all mem, mem, stack, regs, exec */ 0, 0, /* section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/exec.c-dist Thu Feb 3 11:41:14 1994 --- gdb/exec.c Mon Mar 7 20:40:55 1994 *************** *** 458,463 **** --- 458,466 ---- file_stratum, 0, /* next */ 0, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */ 0, 0, /* section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/i386v-nat.c-dist Thu Feb 3 11:41:24 1994 --- gdb/i386v-nat.c Tue Mar 8 01:12:25 1994 *************** *** 31,36 **** --- 31,41 ---- #include #include #include + #ifdef HAVE_MEM_BREAKPOINT + #include "breakpoint.h" + #include + #endif /* HAVE_MEM_BREAKPOINT */ + #include #include *************** *** 47,52 **** --- 52,202 ---- extern struct ext_format ext_format_i387; + + #ifdef HAVE_MEM_BREAKPOINT + + struct user u; + + #define u_offset(a, b) ((int) ((char *) (&(a.b)) - (char *) (&a))) + + static int free_debug_register; + static int debug_control_mirror; + /* Record here which breakpoint associates with which register. */ + static int breakpoint_lookup[DR_LASTADDR - DR_FIRSTADDR + 1]; + + void + clear_memory_breakpoint_status () + { + ptrace (6, inferior_pid, u_offset (u, u_debugreg[DR_STATUS]), 0); + } + + int + get_memory_breakpoint_status () + { + int i; + int status; + + status = ptrace(3, inferior_pid, u_offset (u, u_debugreg[DR_STATUS]), 0); + + for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++) + { + if (status & (1 << (i - DR_FIRSTADDR))) + return breakpoint_lookup[i - DR_FIRSTADDR]; + } + } + + void + init_memory_breakpoint () + { + int i; + + /* Clear the status register so only new status info is shown. + Turn off debugging by clearing control register */ + ptrace (6, inferior_pid, u_offset (u, u_debugreg[DR_STATUS]), 0); + ptrace (6, inferior_pid, u_offset (u, u_debugreg[DR_CONTROL]), 0); + debug_control_mirror = 0; + free_debug_register = DR_FIRSTADDR; + for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++) + breakpoint_lookup[i - DR_FIRSTADDR] = 0; + } + + static int size_try_array[16] = { + 1, 1, 1, 1, /* trying size one */ + 2, 1, 2, 1, /* trying size two */ + 2, 1, 2, 1, /* trying size three */ + 4, 1, 2, 1 /* trying size four */ + }; + + static int + insert_nonaligned_memory_breakpoint (addr, length, mode, breakpoint) + CORE_ADDR addr; + int length; + enum mem_break_enable mode; + int breakpoint; + { + int align; + int size; + int rv; + + rv = 0; + while (length > 0) + { + align = addr % 4; + /* Four is the maximum length for 386. */ + size = (length > 4) ? 3 : length - 1; + size = size_try_array[size * 4 + align]; + + rv = insert_memory_breakpoint(addr, size, mode, breakpoint); + if (rv) + return rv; + addr += size; + length -= size; + } + return rv; + } + + int + insert_memory_breakpoint (addr, length, mode, breakpoint) + CORE_ADDR addr; + int length; + enum mem_break_enable mode; + int breakpoint; + { + int rv; + int read_write_bits, len_bits; + int register_number; + + if (mem_break_write == mode) + read_write_bits = DR_RW_WRITE; + else if (mem_break_rw == mode) + read_write_bits = DR_RW_READ; + else + return 1; + + /* No more debug registers! */ + if (free_debug_register > DR_LASTADDR) + return 1; + + if (1 == length) + len_bits = DR_LEN_1; + else if (2 == length) + { + if (addr % 2) + return insert_nonaligned_memory_breakpoint(addr, length, mode, + breakpoint); + len_bits = DR_LEN_2; + } + + else if (4 == length) + { + if (addr % 4) + return insert_nonaligned_memory_breakpoint(addr, length, mode, + breakpoint); + len_bits = DR_LEN_4; + } + else + return insert_nonaligned_memory_breakpoint(addr, length, mode, breakpoint); + + register_number = free_debug_register - DR_FIRSTADDR; + debug_control_mirror |= + ((read_write_bits | len_bits) + << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number)); + debug_control_mirror |= + (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number)); + debug_control_mirror |= DR_LOCAL_SLOWDOWN; + debug_control_mirror &= ~DR_CONTROL_RESERVED; + + ptrace (6, inferior_pid, + u_offset (u, u_debugreg[DR_CONTROL]), debug_control_mirror); + ptrace (6, inferior_pid, u_offset (u, u_debugreg[free_debug_register]), + addr); + /* Record where we came from. */ + breakpoint_lookup[register_number] = breakpoint; + free_debug_register++; + return 0; + } + #endif /* HAVE_MEM_BREAKPOINT */ + /* this table must line up with REGISTER_NAMES in tm-i386v.h */ /* symbols like 'EAX' come from */ static int regmap[] = *** gdb/infrun.c-dist Thu Feb 3 11:41:26 1994 --- gdb/infrun.c Mon Mar 7 19:40:06 1994 *************** *** 219,224 **** --- 219,228 ---- DO_DEFERRED_STORES; #endif + #ifdef HAVE_MEM_BREAKPOINT + target_clear_memory_breakpoint_status(); + #endif /* HAVE_MEM_BREAKPOINT */ + /* Install inferior's terminal modes. */ target_terminal_inferior (); *** gdb/inftarg.c-dist Thu Feb 3 11:41:27 1994 --- gdb/inftarg.c Mon Mar 7 20:28:15 1994 *************** *** 45,50 **** --- 45,57 ---- static void child_attach PARAMS ((char *, int)); + #ifdef HAVE_MEM_BREAKPOINT + extern void init_memory_breakpoint(); + extern int insert_memory_breakpoint(); + extern int get_memory_breakpoint_status(); + extern void clear_memory_breakpoint_status(); + #endif /* HAVE_MEM_BREAKPOINT */ + static void ptrace_me PARAMS ((void)); *************** *** 314,319 **** --- 321,332 ---- 1, /* to_has_execution */ 0, /* sections */ 0, /* sections_end */ + #ifdef HAVE_MEM_BREAKPOINT + init_memory_breakpoint, /* init, insert, get, clear */ + insert_memory_breakpoint, + get_memory_breakpoint_status, + clear_memory_breakpoint_status, + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC /* to_magic */ }; *** gdb/remote-adapt.c-dist Thu Feb 3 11:41:44 1994 --- gdb/remote-adapt.c Mon Mar 7 20:41:21 1994 *************** *** 1346,1351 **** --- 1346,1354 ---- process_stratum, 0, /* next */ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0,0, /* Section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/remote-eb.c-dist Thu Feb 3 11:41:46 1994 --- gdb/remote-eb.c Mon Mar 7 20:31:40 1994 *************** *** 998,1003 **** --- 998,1006 ---- process_stratum, 0, /* next */ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0, 0, /* Section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/remote-hms.c-dist Thu Feb 3 11:41:47 1994 --- gdb/remote-hms.c Mon Mar 7 20:32:37 1994 *************** *** 1339,1344 **** --- 1339,1347 ---- process_stratum, 0, /* next */ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0, 0, /* Section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/remote-mm.c-dist Thu Feb 3 11:41:47 1994 --- gdb/remote-mm.c Mon Mar 7 20:33:12 1994 *************** *** 1608,1613 **** --- 1608,1616 ---- process_stratum, 0, /* next */ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0,0, /* sections, sections_end */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/remote-nindy.c-dist Thu Feb 3 11:41:48 1994 --- gdb/remote-nindy.c Mon Mar 7 20:33:44 1994 *************** *** 746,751 **** --- 746,754 ---- process_stratum, 0, /* next */ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0, 0, /* Section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/remote-vx.c-dist Thu Feb 3 11:41:55 1994 --- gdb/remote-vx.c Mon Mar 7 20:34:17 1994 *************** *** 1287,1292 **** --- 1287,1295 ---- core_stratum, 0, /* next */ 1, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */ 0, 0, /* Section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ }; *** gdb/remote.c-dist Thu Feb 3 11:41:56 1994 --- gdb/remote.c Mon Mar 7 20:34:49 1994 *************** *** 1344,1349 **** --- 1344,1352 ---- 1, /* to_has_execution */ NULL, /* sections */ NULL, /* sections_end */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC /* to_magic */ }; #endif /* Use remote. */ *** gdb/target.c-dist Thu Feb 3 11:42:27 1994 --- gdb/target.c Mon Mar 7 20:35:27 1994 *************** *** 101,106 **** --- 101,109 ---- dummy_stratum, 0, /* stratum, next */ 0, 0, 0, 0, 0, /* all mem, mem, stack, regs, exec */ 0, 0, /* section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, }; *** gdb/target.h-dist Thu Feb 3 11:42:27 1994 --- gdb/target.h Tue Mar 8 01:20:30 1994 *************** *** 40,45 **** --- 40,46 ---- it goes into the file stratum, which is always below the process stratum. */ + #include "breakpoint.h" #include "bfd.h" enum strata { *************** *** 261,266 **** --- 262,275 ---- *to_sections; struct section_table *to_sections_end; + #ifdef HAVE_MEM_BREAKPOINT + void (*to_init_memory_breakpoint) PARAMS ((void)); + int (*to_insert_memory_breakpoint) PARAMS ((CORE_ADDR addrp, int len, + enum mem_break_enable, + int b)); + int (*to_get_memory_breakpoint_status) PARAMS ((void)); + void (*to_clear_memory_breakpoint_status) PARAMS ((void)); + #endif /* HAVE_MEM_BREAKPOINT */ int to_magic; /* Need sub-structure for target machine related rather than comm related? */ }; *************** *** 390,395 **** --- 399,427 ---- #define target_files_info() \ (*current_target->to_files_info) (current_target) + + #ifdef HAVE_MEM_BREAKPOINT + /* Initialize (clear), and set memory access breakpoints. This is probably + done with hardware debug registers in the cpu. Result is 0 for success, + or errno value for failure. If there is a failure there probably are not + any more debug registers left. */ + + #define target_init_memory_breakpoint() \ + (*current_target->to_init_memory_breakpoint) () + + #define target_insert_memory_breakpoint(addr, len, type, bp_num) \ + (*current_target->to_insert_memory_breakpoint) \ + (addr, len, type, bp_num) + + /* Return the breakpoint number that caused the memory access breakpoint. + Returns 0 if no memory acess breakpoint. */ + #define target_get_memory_breakpoint_status() \ + (*current_target->to_get_memory_breakpoint_status) () + + /* Clear the memory breakpoint status. Called before execution is resumed. */ + #define target_clear_memory_breakpoint_status() \ + (*current_target->to_clear_memory_breakpoint_status) () + #endif /* HAVE_MEM_BREAKPOINT */ /* Insert a breakpoint at address ADDR in the target machine. SAVE is a pointer to memory allocated for saving the *** gdb/xcoffexec.c-dist Thu Feb 3 11:42:33 1994 --- gdb/xcoffexec.c Mon Mar 7 20:40:20 1994 *************** *** 887,892 **** --- 887,895 ---- file_stratum, 0, /* next */ 0, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */ 0, 0, /* section pointers */ + #ifdef HAVE_MEM_BREAKPOINT + 0, 0, 0, 0, /* init, insert, get, clear */ + #endif /* HAVE_MEM_BREAKPOINT */ OPS_MAGIC, /* Always the last thing */ };