home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / gnu / gdb / bug / 906 < prev    next >
Encoding:
Text File  |  1992-07-27  |  31.7 KB  |  1,049 lines

  1. Newsgroups: gnu.gdb.bug
  2. Path: sparky!uunet!cis.ohio-state.edu!mermaid.micro.umn.edu!daney
  3. From: daney@mermaid.micro.umn.edu (Dave Daney)
  4. Subject: Debug register use for ISC 2.2.1 (Sys v/386 R3.2)
  5. Message-ID: <199207271614.AA07753@mermaid.micro.umn.edu>
  6. Sender: gnulists@ai.mit.edu
  7. Organization: GNUs Not Usenet
  8. Distribution: gnu
  9. Date: Mon, 27 Jul 1992 06:14:50 GMT
  10. Approved: bug-gdb@prep.ai.mit.edu
  11. Lines: 1036
  12.  
  13. I have had several requests for my patches for debug register use for
  14. Interactive 2.2.1 so I am posting the slightly modified for gdb-4.6 version.
  15.  
  16. I think someone told me they work on SCO also but I have not ever seen it
  17. so I make no claims to that, actually I probably shouldn't claim it works
  18. on anything.
  19.  
  20. I have made a few modifications to gdb-4.6 to use the hardware debug
  21. registers on the 386 running Interactive 2.2.1 (Sys V/386 Rel3.2).
  22.  
  23. They are implemented as a new type of breakpoint(I called it an Accesspoint).
  24. I thought that they should be seperate from watchpoints because watchpoints break
  25. on a whole expression changing.  Which  is different than a breakpoint on a memory
  26. access, they (watchpoints) probably are usefull even with accesspoints.  Any how
  27. there are two new commands to implement Accesspoints.
  28.  
  29. wbreak:  Break on a memory write to a location.
  30. abreak:  Break on a memory access (read or write) to a location.
  31.  
  32. They can be set on any expression that evaluates to some thing located in a
  33. memory location.
  34.  
  35. Special note:  To set an access breakpoint on location 0 (good for catching
  36. reads or writes from a NULL pointer).
  37.  
  38. abreak *(int *)0
  39.  
  40. All of the rest of the breakpoint commands work on Accesspoints (info, enable, 
  41. disable, delete, ... .  I haven't had any problems with them, although I have only
  42. had this going on gdb-4.6 for a couple of days.  However I have been using this
  43. with gdb-4.5 ever since it came out.
  44.  
  45. I think It is fairly straight forward.  I didn't make any info files for this.
  46.  
  47.  
  48. I put the machine dependant parts in i386-xdep.c most of the rest of it is
  49. in breakpoint.c.  Several other files just had the
  50. struct target_ops XXXXX_target structures modified.
  51.  
  52. I think(hope) that all of the changes are inside of
  53. #ifdef HAVE_MEM_BEEAKPOINT
  54. #endif
  55. blocks so hopefully this will not break any thing if you don't define
  56. -DHAVE_MEM_BREAKPOINT
  57. not positive about this however.  I hope this addition fits into the
  58. scheme of gdb and does not break things for other systems. Let me know.
  59.  
  60.  
  61. On the 386 there are only four Access breakpoint registers, they can be set
  62. for one, two, and four byte accesses.  The addresses must be properly aligned.
  63. The code in i386-xdep.c takes all of this into account, it will use as many
  64. registers as necessary to cover the requested area.  If the registers are
  65. exausted it will disable the Accesspoint.  There is a bug(feature) here, if
  66. multiple registers are needed and at least one is available it  will fill from
  67. the bottom of the area requested. Then it will report no more registers and disable
  68. the Access point.  It does not deallocate the registers from the failed attempt.
  69. When execution is resumed (continue) the access point is still set on the first
  70. portion of the area.  If it is hit you will get some message about a SIGTRAP, but
  71. the Accesspoint information will not print.  In short, set Accesspoints on
  72. small properly aligned objects.
  73.  
  74.  
  75.  
  76. I configured like this:
  77.  
  78. configure i386-none-sysv32
  79.  
  80. Here is how I made it.  The trad-core things are to get corefiles to read on this
  81. machine, but trad-core.c needs to be patched for it to work (see other posting).
  82. For other 386 systems perhaps just -DHAVE_MEM_BREAKPOINT is sufficient.
  83. I have a feeling that the things in i386-xdep.c might be different for other 
  84. systems.
  85.  
  86. gmake CC=gcc HDEFINES="-D_POSIX_SOURCE -DTRAD_CORE" HDEPFILES=trad-core.o\
  87. READLINE_DEFINES="-D_POSIX_VERSION -D_POSIX_SOURCE" LOADLIBES=-lcposix\
  88. USER_CFLAGS=-DHAVE_MEM_BREAKPOINT CFLAGS="-g -O2"
  89.  
  90.  
  91.  
  92.  
  93. *** breakpoint.c    Mon Jul  6 12:10:37 1992
  94. --- ../../gdb-4.6.new/gdb/breakpoint.c    Fri Jul 24 16:14:04 1992
  95. ***************
  96. *** 133,139 ****
  97. --- 133,152 ----
  98.   static void
  99.   set_breakpoint_count PARAMS ((int));
  100.   
  101. + #ifdef HAVE_MEM_BREAKPOINT
  102.   
  103. + static void
  104. + write_access_breakpoint_command PARAMS ((char *, int));
  105. + static void
  106. + rw_access_breakpoint_command PARAMS ((char *, int));
  107. + static void
  108. + access_breakpoint_command PARAMS ((char *, int, enum access_break_type));
  109. + #endif /* HAVE_MEM_BREAKPOINT */
  110.   extern int addressprint;        /* Print machine addresses? */
  111.   extern int demangle;            /* Print de-mangled symbol names? */
  112.   
  113. ***************
  114. *** 433,438 ****
  115. --- 446,454 ----
  116.   
  117.     ALL_BREAKPOINTS (b)
  118.       if (b->type != bp_watchpoint
  119. + #ifdef HAVE_MEM_BREAKPOINT
  120. +     && b->type != bp_accesspoint
  121. + #endif
  122.       && b->enable != disabled
  123.       && ! b->inserted
  124.       && ! b->duplicate)
  125. ***************
  126. *** 449,455 ****
  127.           if (!disabled_breaks)
  128.             {
  129.               fprintf (stderr,
  130. !              "Cannot insert breakpoint %d:\n", b->number);
  131.               printf_filtered ("Disabling shared library breakpoints:\n");
  132.             }
  133.           disabled_breaks = 1;
  134. --- 465,471 ----
  135.           if (!disabled_breaks)
  136.             {
  137.               fprintf (stderr,
  138. !                  "Cannot insert breakpoint %d:\n", b->number);
  139.               printf_filtered ("Disabling shared library breakpoints:\n");
  140.             }
  141.           disabled_breaks = 1;
  142. ***************
  143. *** 461,467 ****
  144.           fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number);
  145.   #ifdef ONE_PROCESS_WRITETEXT
  146.           fprintf (stderr,
  147. !           "The same program may be running in another process.\n");
  148.   #endif
  149.           memory_error (val, b->address);    /* which bombs us out */
  150.             }
  151. --- 477,483 ----
  152.           fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number);
  153.   #ifdef ONE_PROCESS_WRITETEXT
  154.           fprintf (stderr,
  155. !              "The same program may be running in another process.\n");
  156.   #endif
  157.           memory_error (val, b->address);    /* which bombs us out */
  158.             }
  159. ***************
  160. *** 471,476 ****
  161. --- 487,513 ----
  162.         }
  163.     if (disabled_breaks)
  164.       printf_filtered ("\n");
  165. + #ifdef HAVE_MEM_BREAKPOINT
  166. +   target_init_access_breakpoint();
  167. +   ALL_BREAKPOINTS (b)
  168. +     if (b->type == bp_accesspoint && b->enable != disabled)
  169. +       {
  170. +     int rv;
  171. +     rv = target_insert_access_breakpoint(b->access_break_address,
  172. +                          b->access_break_length,
  173. +                           b->access_break_type, b->number);
  174. +     if (rv)
  175. +       {
  176. +         /* Can't set the breakpoint.  */
  177. +         fprintf(stderr, "Cannot set memory breakpoint %d.  Disableing it.\n", b->number);
  178. +         fprintf(stderr, "It is best to set memory breakpoints on small properly\n");
  179. +         fprintf(stderr, "aligned objects\n");
  180. +         b->enable = disabled;
  181. +       }    
  182. +       }
  183. + #endif /* HAVE_MEM_BREAKPOINT */
  184.     return val;
  185.   }
  186.   
  187. ***************
  188. *** 500,505 ****
  189. --- 537,545 ----
  190.           local_hex_string(b->shadow_contents[1]));
  191.   #endif /* BREAKPOINT_DEBUG */
  192.         }
  193. + #ifdef HAVE_MEM_BREAKPOINT
  194. +   target_init_access_breakpoint();
  195. + #endif /* HAVE_MEM_BREAKPOINT */
  196.   
  197.     return 0;
  198.   }
  199. ***************
  200. *** 707,712 ****
  201. --- 747,755 ----
  202.     if (bs == NULL
  203.         || bs->breakpoint_at == NULL
  204.         || (bs->breakpoint_at->type != bp_breakpoint
  205. + #ifdef HAVE_MEM_BREAKPOINT
  206. +       && bs->breakpoint_at->type != bp_accesspoint
  207. + #endif /* HAVE_MEM_BREAKPOINT */
  208.         && bs->breakpoint_at->type != bp_watchpoint))
  209.       return 0;
  210.     
  211. ***************
  212. *** 742,748 ****
  213.         bs->old_val = NULL;
  214.         return 1;
  215.       }
  216.     /* Maybe another breakpoint in the chain caused us to stop.
  217.        (Currently all watchpoints go on the bpstat whether hit or
  218.        not.  That probably could (should) be changed, provided care is taken
  219. --- 785,808 ----
  220.         bs->old_val = NULL;
  221.         return 1;
  222.       }
  223. ! #ifdef HAVE_MEM_BREAKPOINT
  224. !   if (bs->breakpoint_at->type == bp_accesspoint)
  225. !     {
  226. !       printf_filtered ("\nMemory access breakpoint %d, ", bs->breakpoint_at->number);
  227. !       printf_filtered ("%-10s",
  228. !                local_hex_string(bs->breakpoint_at->access_break_address));
  229. !       printf_filtered ("  ");
  230. !       if(bs->breakpoint_at->access_break_type == access_break_write)
  231. !     printf_filtered ("w  ");
  232. !       else
  233. !     printf_filtered ("r/w");
  234. !       printf_filtered ("  ");
  235. !       printf_filtered ("%d   ", bs->breakpoint_at->access_break_length);
  236. !       print_expression (bs->breakpoint_at->access_break_exp, stdout);
  237. !       printf_filtered ("\n");
  238. !       return 0;
  239. !     }
  240. ! #endif /* HAVE_MEM_BREAKPOINT */
  241.     /* Maybe another breakpoint in the chain caused us to stop.
  242.        (Currently all watchpoints go on the bpstat whether hit or
  243.        not.  That probably could (should) be changed, provided care is taken
  244. ***************
  245. *** 817,822 ****
  246. --- 877,885 ----
  247.     /* True if we've hit a breakpoint (as opposed to a watchpoint).  */
  248.     int real_breakpoint = 0;
  249.   #endif
  250. + #ifdef HAVE_MEM_BREAKPOINT
  251. +   int access_breakpoint = target_get_access_breakpoint_status();
  252. + #endif
  253.     /* Root of the chain of bpstat's */
  254.     struct bpstat root_bs[1];
  255.     /* Pointer to the last thing in the chain currently.  */
  256. ***************
  257. *** 833,841 ****
  258.         if (b->enable == disabled)
  259.       continue;
  260.   
  261. !       if (b->type != bp_watchpoint && b->address != bp_addr)
  262.       continue;
  263.   
  264.         /* Come here if it's a watchpoint, or if the break address matches */
  265.   
  266.         bs = bpstat_alloc (b, bs);    /* Alloc a bpstat to explain stop */
  267. --- 896,912 ----
  268.         if (b->enable == disabled)
  269.       continue;
  270.   
  271. ! #ifdef HAVE_MEM_BREAKPOINT
  272. !       if (b->type != bp_watchpoint && b->address != bp_addr &&
  273. !       b->type != bp_accesspoint)
  274.       continue;
  275.   
  276. +       if(b->type == bp_accesspoint && b->number != access_breakpoint)
  277. +     continue;
  278. + #else
  279. +       if (b->type != bp_watchpoint && b->address != bp_addr)
  280. +     continue;
  281. + #endif /* HAVE_MEM_BREAKPOINT */
  282.         /* Come here if it's a watchpoint, or if the break address matches */
  283.   
  284.         bs = bpstat_alloc (b, bs);    /* Alloc a bpstat to explain stop */
  285. ***************
  286. *** 896,903 ****
  287. --- 967,979 ----
  288.           }
  289.       }
  290.   #if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
  291. + #ifdef HAVE_MEM_BREAKPOINT
  292. +       else if (b->type != bp_accesspoint)
  293. +     real_breakpoint = 1;
  294. + #else
  295.         else
  296.       real_breakpoint = 1;
  297. + #endif /* HAVE_MEM_BREAKPOINT  */
  298.   #endif
  299.   
  300.         if (b->frame && b->frame != frame_address)
  301. ***************
  302. *** 990,998 ****
  303.     return 0;
  304.   }
  305.   
  306. ! /* Print information on breakpoint number BNUM, or -1 if all.
  307. !    If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS
  308. !    is nonzero, process only watchpoints.  */
  309.   
  310.   static void
  311.   breakpoint_1 (bnum, allflag)
  312. --- 1066,1072 ----
  313.     return 0;
  314.   }
  315.   
  316. ! /* Print information on breakpoint number BNUM, or -1 if all. */
  317.   
  318.   static void
  319.   breakpoint_1 (bnum, allflag)
  320. ***************
  321. *** 1005,1011 ****
  322.     CORE_ADDR last_addr = (CORE_ADDR)-1;
  323.     int found_a_breakpoint = 0;
  324.     static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint",
  325. !                   "longjmp", "longjmp resume"};
  326.     static char *bpdisps[] = {"del", "dis", "keep"};
  327.     static char bpenables[] = "ny";
  328.   
  329. --- 1079,1090 ----
  330.     CORE_ADDR last_addr = (CORE_ADDR)-1;
  331.     int found_a_breakpoint = 0;
  332.     static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint",
  333. !                   "longjmp", "longjmp resume"
  334. ! #ifdef HAVE_MEM_BREAKPOINT
  335. !                 ,"accesspoint"
  336. ! #endif /* HAVE_MEM_BREAKPOINT */
  337. !                 };
  338.     static char *bpdisps[] = {"del", "dis", "keep"};
  339.     static char bpenables[] = "ny";
  340.   
  341. ***************
  342. *** 1022,1028 ****
  343.   /*  We only print out user settable breakpoints unless the allflag is set. */
  344.       if (!allflag
  345.           && b->type != bp_breakpoint
  346. !         && b->type != bp_watchpoint)
  347.         continue;
  348.   
  349.       if (!found_a_breakpoint++)
  350. --- 1101,1111 ----
  351.   /*  We only print out user settable breakpoints unless the allflag is set. */
  352.       if (!allflag
  353.           && b->type != bp_breakpoint
  354. !         && b->type != bp_watchpoint
  355. ! #ifdef HAVE_MEM_BREAKPOINT
  356. !         && b->type != bp_accesspoint
  357. ! #endif /* HAVE_MEM_BREAKPOINT */
  358. !         )
  359.         continue;
  360.   
  361.       if (!found_a_breakpoint++)
  362. ***************
  363. *** 1039,1044 ****
  364. --- 1122,1141 ----
  365.         case bp_watchpoint:
  366.           print_expression (b->exp, stdout);
  367.           break;
  368. + #ifdef HAVE_MEM_BREAKPOINT
  369. +       case bp_accesspoint:
  370. +         if (addressprint)
  371. +           printf_filtered ("%s ",
  372. +                    local_hex_string_custom(b->access_break_address,
  373. +                                "08"));
  374. +         if(b->access_break_type == access_break_write)
  375. +            printf_filtered ("(w   ");
  376. +          else
  377. +            printf_filtered ("(r/w ");
  378. +          printf_filtered ("%d) ", b->access_break_length);
  379. +         print_expression (b->access_break_exp, stdout);
  380. +         break;
  381. + #endif /* HAVE_MEM_BREAKPOINT */
  382.         case bp_breakpoint:
  383.         case bp_until:
  384.         case bp_finish:
  385. ***************
  386. *** 1185,1191 ****
  387.     register struct breakpoint *b;
  388.     register int count = 0;
  389.   
  390. !   if (address == 0)        /* Watchpoints are uninteresting */
  391.       return;
  392.   
  393.     ALL_BREAKPOINTS (b)
  394. --- 1282,1288 ----
  395.     register struct breakpoint *b;
  396.     register int count = 0;
  397.   
  398. !   if (address == 0)    /* Watchpoints and access_breakpoints are uninteresting */
  399.       return;
  400.   
  401.     ALL_BREAKPOINTS (b)
  402. ***************
  403. *** 1371,1376 ****
  404. --- 1468,1479 ----
  405.   {
  406.     switch (b->type)
  407.       {
  408. + #ifdef HAVE_MEM_BREAKPOINT
  409. +     case bp_accesspoint:
  410. +       printf_filtered ("Memory accesspoint %d at %s", b->number,
  411. +                local_hex_string_custom(b->access_break_address, "08"));
  412. +       break;
  413. + #endif /* HAVE_MEM_BREAKPOINT  */
  414.       case bp_watchpoint:
  415.         printf_filtered ("Watchpoint %d: ", b->number);
  416.         print_expression (b->exp, stdout);
  417. ***************
  418. *** 1622,1627 ****
  419. --- 1725,1792 ----
  420.     b->cond_string = NULL;
  421.     mention (b);
  422.   }
  423. + #ifdef HAVE_MEM_BREAKPOINT
  424. + /* ARGSUSED */
  425. + static void
  426. + access_breakpoint_command (arg, from_tty, mode)
  427. +      char *arg;
  428. +      int from_tty;
  429. +      enum access_break_type mode;
  430. + {
  431. +   struct breakpoint *b;
  432. +   struct symtab_and_line sal;
  433. +   struct expression *exp;
  434. +   struct block *exp_valid_block;
  435. +   struct value *access_obj;
  436. +   sal.pc = 0;
  437. +   sal.symtab = NULL;
  438. +   sal.line = 0;
  439. +   
  440. +   /* Parse arguments.  */
  441. +   innermost_block = NULL;
  442. +   exp = parse_expression (arg);
  443. +   exp_valid_block = innermost_block;
  444. +   access_obj = evaluate_expression (exp);
  445. +   if(lval_memory != VALUE_LVAL(access_obj))
  446. +     error("requested access breakpoint not in memory.  e.g. register or constant.");
  447. +   /* Now set up the breakpoint.  */
  448. +   b = set_raw_breakpoint (sal);
  449. +   set_breakpoint_count (breakpoint_count + 1);
  450. +   b->number = breakpoint_count;
  451. +   b->type = bp_accesspoint;
  452. +   b->disposition = donttouch;
  453. +   b->exp = 0;
  454. +   b->exp_valid_block = NULL;
  455. +   b->val = NULL;
  456. +   b->cond = 0;
  457. +   b->cond_string = NULL;
  458. +   b->access_break_exp = exp;
  459. +   b->access_break_address = VALUE_ADDRESS(access_obj) + VALUE_OFFSET(access_obj);
  460. +   b->access_break_length = TYPE_LENGTH(VALUE_TYPE(access_obj));
  461. +   b->access_break_type = mode;
  462. +   mention (b);
  463. + }
  464. + static void
  465. + write_access_breakpoint_command (arg, from_tty)
  466. +      char *arg;
  467. +      int from_tty;
  468. + {
  469. +   access_breakpoint_command (arg, from_tty, access_break_write);
  470. + }
  471. + static void
  472. + rw_access_breakpoint_command (arg, from_tty)
  473. +      char *arg;
  474. +      int from_tty;
  475. + {
  476. +   access_breakpoint_command (arg, from_tty, access_break_rw);
  477. + }
  478. + #endif /* HAVE_MEM_BREAKPOINT */
  479.   
  480.   /*
  481.    * Helper routine for the until_command routine in infcmd.c.  Here
  482. ***************
  483. *** 2063,2068 ****
  484. --- 2228,2236 ----
  485.         ALL_BREAKPOINTS (b)
  486.       while (b->next
  487.              && b->next->type != bp_watchpoint
  488. + #ifdef HAVE_MEM_BREAKPOINT
  489. +            && b->next->type != bp_accesspoint
  490. + #endif /* HAVE_MEM_BREAKPOINT */
  491.              && (sal.pc ? b->next->address == sal.pc
  492.              : (b->next->symtab == sal.symtab
  493.                 && b->next->line_number == sal.line)))
  494. ***************
  495. *** 2232,2237 ****
  496. --- 2400,2408 ----
  497.         break;
  498.       default:
  499.         printf_filtered ("Deleting unknown breakpoint type %d\n", b->type);
  500. + #ifdef HAVE_MEM_BREAKPOINT
  501. +     case bp_accesspoint:
  502. + #endif /*HAVE_MEM_BREAKPOINT */
  503.       case bp_until:
  504.       case bp_finish:
  505.       case bp_longjmp:
  506. ***************
  507. *** 2615,2620 ****
  508. --- 2786,2802 ----
  509.   This command may be abbreviated \"delete\".",
  510.          &deletelist);
  511.   
  512. + #ifdef HAVE_MEM_BREAKPOINT
  513. +   add_com ("wbreak", class_breakpoint, write_access_breakpoint_command,
  514. +        "Set a memory write breakpoint at a location.\n\
  515. + A memory write breakpoint stops execution of your program whenever it\n\
  516. + tries to write data at that location.");
  517. +   add_com ("abreak", class_breakpoint, rw_access_breakpoint_command,
  518. +        "Set a memory acsess breakpoint at a location.\n\
  519. + A memory acsess breakpoint stops execution of your program whenever it\n\
  520. + tries to read or write data at that location.");
  521. + #endif /* HAVE_MEM_BREAKPOINT */
  522.     add_com ("clear", class_breakpoint, clear_command,
  523.          "Clear breakpoint at specified line or function.\n\
  524.   Argument may be line number, function name, or \"*\" and an address.\n\
  525. ***************
  526. *** 2643,2648 ****
  527. --- 2825,2850 ----
  528.     add_com_alias ("bre", "break", class_run, 1);
  529.     add_com_alias ("brea", "break", class_run, 1);
  530.   
  531. + #ifdef HAVE_MEM_BREAKPOINT
  532. + #else /* !HAVE_MEM_BREAKPOINT */
  533. +   add_info ("breakpoints", breakpoints_info,
  534. +         "Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
  535. + The \"Type\" column indicates one of:\n\
  536. + \tbreakpoint     - normal breakpoint\n\
  537. + \taccesspoint    - memory access breakpoint\n\
  538. + \twatchpoint     - watchpoint\n\
  539. + The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
  540. + the disposition of the breakpoint after it gets hit.  \"dis\" means that the\n\
  541. + breakpoint will be disabled.  The \"Address\" and \"What\" columns indicate the\n\
  542. + address and file/line number respectively.\n\n\
  543. + Convenience variable \"$_\" and default examine address for \"x\"\n\
  544. + are set to the address of the last breakpoint listed.\n\n\
  545. + Convenience variable \"$bpnum\" contains the number of the last\n\
  546. + breakpoint set.");
  547. + #endif /* !HAVE_MEM_BREAKPOINT */
  548.     add_info ("breakpoints", breakpoints_info,
  549.           "Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
  550.   The \"Type\" column indicates one of:\n\
  551. *** core.c    Mon Jul  6 12:10:41 1992
  552. --- ../../gdb-4.6.new/gdb/core.c    Fri Jul 24 15:32:52 1992
  553. ***************
  554. *** 444,449 ****
  555. --- 444,452 ----
  556.       core_stratum, 0, /* next */
  557.       0, 1, 1, 1, 0,    /* all mem, mem, stack, regs, exec */
  558.       0, 0,            /* section pointers */
  559. + #ifdef HAVE_MEM_BREAKPOINT
  560. +     0, 0, 0, 0,         /* init, insert, get, clear */                    
  561. + #endif
  562.       OPS_MAGIC,        /* Always the last thing */
  563.   };
  564.   
  565. *** exec.c    Tue May 12 20:11:42 1992
  566. --- ../../gdb-4.6.new/gdb/exec.c    Fri Jul 24 15:32:53 1992
  567. ***************
  568. *** 421,426 ****
  569. --- 421,429 ----
  570.       file_stratum, 0, /* next */
  571.       0, 1, 0, 0, 0,    /* all mem, mem, stack, regs, exec */
  572.       0, 0,            /* section pointers */
  573. + #ifdef HAVE_MEM_BREAKPOINT
  574. +     0, 0, 0, 0,         /* init, insert, get, clear */                    
  575. + #endif
  576.       OPS_MAGIC,        /* Always the last thing */
  577.   };
  578.   
  579. *** i386-xdep.c    Wed Jun 24 12:32:49 1992
  580. --- ../../gdb-4.6.new/gdb/i386-xdep.c    Fri Jul 24 17:05:15 1992
  581. ***************
  582. *** 31,36 ****
  583. --- 31,41 ----
  584.   #include <sys/dir.h>
  585.   #include <signal.h>
  586.   #include <sys/user.h>
  587. + #ifdef HAVE_MEM_BREAKPOINT
  588. + #include "breakpoint.h"
  589. + #include <sys/debugreg.h>
  590. + #endif /* HAVE_MEM_BREAKPOINT */
  591.   #include <sys/ioctl.h>
  592.   #include <fcntl.h>
  593.   
  594. ***************
  595. *** 44,49 ****
  596. --- 49,194 ----
  597.   
  598.   extern struct ext_format ext_format_i387;
  599.   
  600. + #ifdef HAVE_MEM_BREAKPOINT
  601. + struct user u;
  602. + #define u_offset(a, b) ((int)((char *)(&(a.b))-(char *)(&a)))
  603. + static int free_debug_register;
  604. + static int debug_control_mirror;
  605. + /* record here which breakpoint associates with which register */
  606. + static int breakpoint_lookup[DR_LASTADDR + 1];
  607. + void clear_access_breakpoint_status()
  608. + {
  609. +   call_ptrace(6, inferior_pid, u_offset(u, u_debugreg[DR_STATUS]), 0);
  610. + }
  611. + int get_access_breakpoint_status()
  612. + {
  613. +   int i;
  614. +   int status;
  615. +   status = call_ptrace(3, inferior_pid, u_offset(u, u_debugreg[DR_STATUS]), 0);
  616. +   for(i = 0; i <= DR_LASTADDR; i++)
  617. +     {
  618. +       if(status & (1 << i))
  619. +     return(breakpoint_lookup[i]);
  620. +     }
  621. +   return 0;
  622. + }
  623. + void init_access_breakpoint()
  624. + {
  625. +   int i;
  626. +   /* Clear the status register so only new status info is shown.
  627. +      Turn off debugging by clearing control register */
  628. +   call_ptrace(6, inferior_pid, u_offset(u, u_debugreg[DR_STATUS]), 0);
  629. +   call_ptrace(6, inferior_pid, u_offset(u, u_debugreg[DR_CONTROL]), 0);
  630. +   debug_control_mirror = 0;
  631. +   free_debug_register = DR_FIRSTADDR;
  632. +   for(i = 0; i <= DR_LASTADDR; i++)
  633. +     breakpoint_lookup[i] = 0;
  634. + }
  635. + static int size_try_array[16] = {
  636. +   1, 1, 1, 1,            /* trying size one */
  637. +   2, 1, 2, 1,            /* trying size two */
  638. +   2, 1, 2, 1,            /* trying size three */
  639. +   4, 1, 2, 1            /* trying size four */
  640. + };
  641. + static int insert_nonaligned_access_breakpoint(addr, length, mode, breakpoint) 
  642. + CORE_ADDR addr;
  643. + int length;
  644. + enum access_break_type mode;
  645. + int breakpoint;
  646. + {
  647. +   int align;
  648. +   int size;
  649. +   int rv;
  650. +   rv = 0;
  651. +   while(length > 0)
  652. +     {
  653. +       align = addr % 4;
  654. +       size = (length > 4) ? 3 : length - 1;    /*four is the maximum length for 386*/
  655. +       size = size_try_array[size * 4 + align];
  656. +       if(rv = insert_access_breakpoint(addr, size, mode, breakpoint))
  657. +     return rv;
  658. +       addr += size;
  659. +       length -= size;
  660. +     }
  661. +   return rv;
  662. + }
  663. + int insert_access_breakpoint(addr, length, mode, breakpoint)
  664. + CORE_ADDR addr;
  665. + int length;
  666. + enum access_break_type mode;
  667. + int breakpoint;
  668. + {
  669. +   int rv;
  670. +   int read_write_bits, len_bits;
  671. +   
  672. +   if(access_break_write == mode)
  673. +     read_write_bits = DR_RW_WRITE;
  674. +   else if(access_break_rw == mode)
  675. +     read_write_bits = DR_RW_READ;
  676. +   else
  677. +     return 1;            /* bad mode! */
  678. +   if(free_debug_register > DR_LASTADDR)
  679. +     return 1;            /* no more debug registers! */
  680. +   if(1 == length)
  681. +     {
  682. +       len_bits = DR_LEN_1;
  683. +     }
  684. +   else if(2 == length)
  685. +     {
  686. +       if(addr % 2)
  687. +     return(insert_nonaligned_access_breakpoint(addr, length, mode,
  688. +                            breakpoint));
  689. +       len_bits = DR_LEN_2;
  690. +     }
  691. +   else if(4 == length)
  692. +     {
  693. +       if(addr % 4)
  694. +     return(insert_nonaligned_access_breakpoint(addr, length, mode,
  695. +                            breakpoint));
  696. +       len_bits = DR_LEN_4;
  697. +     }
  698. +   else
  699. +     {
  700. +       return(insert_nonaligned_access_breakpoint(addr, length, mode,
  701. +                          breakpoint));
  702. +     }
  703. +   
  704. +   debug_control_mirror |= ((read_write_bits | len_bits) << 
  705. +     (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * free_debug_register));
  706. +   debug_control_mirror |= (1 << (DR_LOCAL_ENABLE_SHIFT +
  707. +                  DR_ENABLE_SIZE * free_debug_register));
  708. +   debug_control_mirror |= DR_LOCAL_SLOWDOWN;
  709. +   debug_control_mirror &= ~DR_CONTROL_RESERVED;
  710. +   
  711. +   call_ptrace(6, inferior_pid,
  712. +      u_offset(u, u_debugreg[DR_CONTROL]), debug_control_mirror);
  713. +   call_ptrace(6, inferior_pid, u_offset(u, u_debugreg[free_debug_register]), addr);
  714. +   /* record where we came from */
  715. +   breakpoint_lookup[free_debug_register] = breakpoint;
  716. +   free_debug_register++;
  717. +   return 0;
  718. + }
  719. + #endif /* HAVE_MEM_BREAKPOINT */
  720.   /* this table must line up with REGISTER_NAMES in m-i386.h */
  721.   /* symbols like 'EAX' come from <sys/reg.h> */
  722.   static int regmap[] = 
  723. ***************
  724. *** 194,200 ****
  725.         unsigned int mask;
  726.         
  727.         rounded_addr = uaddr & -sizeof (int);
  728. !       data = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  729.         mask = 0xff << ((uaddr - rounded_addr) * 8);
  730.         
  731.         fpvalid = ((data & mask) != 0);
  732. --- 339,345 ----
  733.         unsigned int mask;
  734.         
  735.         rounded_addr = uaddr & -sizeof (int);
  736. !       data = call_ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  737.         mask = 0xff << ((uaddr - rounded_addr) * 8);
  738.         
  739.         fpvalid = ((data & mask) != 0);
  740. ***************
  741. *** 229,235 ****
  742.         ip = (int *)buf;
  743.         for (i = 0; i < rounded_size; i++) 
  744.       {
  745. !       *ip++ = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  746.         rounded_addr += sizeof (int);
  747.       }
  748.       } 
  749. --- 374,380 ----
  750.         ip = (int *)buf;
  751.         for (i = 0; i < rounded_size; i++) 
  752.       {
  753. !       *ip++ = call_ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
  754.         rounded_addr += sizeof (int);
  755.       }
  756.       } 
  757. *** infrun.c    Mon Jul  6 12:10:54 1992
  758. --- ../../gdb-4.6.new/gdb/infrun.c    Fri Jul 24 15:32:54 1992
  759. ***************
  760. *** 327,332 ****
  761. --- 327,336 ----
  762.     DO_DEFERRED_STORES;
  763.   #endif
  764.   
  765. + #ifdef HAVE_MEM_BREAKPOINT
  766. +   target_clear_access_breakpoint_status();
  767. + #endif    /* HAVE_MEM_BREAKPOINT */
  768.     target_resume (step, sig);
  769.     discard_cleanups (old_cleanups);
  770.   }
  771. ***************
  772. *** 1079,1084 ****
  773. --- 1083,1091 ----
  774.             default:
  775.           fprintf(stderr, "Unknown breakpoint type %d\n",
  776.               stop_bpstat->breakpoint_at->type);
  777. + #ifdef HAVE_MEM_BREAKPOINT
  778. +           case bp_accesspoint:
  779. + #endif /* HAVE_MEM_BREAKPOINT */
  780.             case bp_watchpoint:
  781.             case bp_breakpoint:
  782.             case bp_until:
  783. *** inftarg.c    Sun Mar 29 17:21:27 1992
  784. --- ../../gdb-4.6.new/gdb/inftarg.c    Fri Jul 24 15:32:55 1992
  785. ***************
  786. *** 42,47 ****
  787. --- 42,56 ----
  788.   static void
  789.   child_detach PARAMS ((char *, int));
  790.   
  791. + #ifdef HAVE_MEM_BREAKPOINT
  792. + extern void init_memory_breakpoint();
  793. + extern int insert_memory_breakpoint();
  794. + extern int get_memory_breakpoint_status();
  795. + extern void clear_memory_breakpoint_status();
  796. + #endif /* HAVE_MEM_BREAKPOINT */
  797.   /* Forward declaration */
  798.   extern struct target_ops child_ops;
  799.   
  800. ***************
  801. *** 208,213 ****
  802. --- 217,228 ----
  803.     1,                /* to_has_execution */
  804.     0,                /* sections */
  805.     0,                /* sections_end */
  806. + #ifdef HAVE_MEM_BREAKPOINT
  807. +   init_access_breakpoint,         /* init, insert, get, clear */
  808. +   insert_access_breakpoint,
  809. +   get_access_breakpoint_status,
  810. +   clear_access_breakpoint_status,
  811. + #endif
  812.     OPS_MAGIC            /* to_magic */
  813.   };
  814.   
  815. *** remote.c    Mon Jul  6 12:11:04 1992
  816. --- ../../gdb-4.6.new/gdb/remote.c    Fri Jul 24 15:32:55 1992
  817. ***************
  818. *** 1048,1053 ****
  819. --- 1048,1059 ----
  820.     1,                /* to_has_execution */
  821.     NULL,                /* sections */
  822.     NULL,                /* sections_end */
  823. + #ifdef HAVE_MEM_BREAKPOINT
  824. +   NULL,                         /* accesspoint init */
  825. +   NULL,                         /* accesspoint insert */
  826. +   NULL,                         /* accesspoint get */
  827. +   NULL,                         /* accesspoint clear */
  828. + #endif
  829.     OPS_MAGIC            /* to_magic */
  830.   };
  831.   
  832. *** target.c    Mon Jul  6 12:11:14 1992
  833. --- ../../gdb-4.6.new/gdb/target.c    Fri Jul 24 15:32:56 1992
  834. ***************
  835. *** 88,93 ****
  836. --- 88,96 ----
  837.       dummy_stratum, 0,    /* stratum, next */
  838.       0, 0, 0, 0, 0,    /* all mem, mem, stack, regs, exec */
  839.       0, 0,        /* section pointers */
  840. + #ifdef HAVE_MEM_BREAKPOINT
  841. +     0, 0, 0, 0,         /* init, insert, get, clear */                    
  842. + #endif
  843.       OPS_MAGIC,
  844.   };
  845.   
  846. ***************
  847. *** 331,337 ****
  848.     de_fault (to_has_stack,        0);
  849.     de_fault (to_has_registers,        0);
  850.     de_fault (to_has_execution,        0);
  851.   #undef de_fault
  852.   }
  853.   
  854. --- 334,345 ----
  855.     de_fault (to_has_stack,        0);
  856.     de_fault (to_has_registers,        0);
  857.     de_fault (to_has_execution,        0);
  858. ! #ifdef HAVE_MEM_BREAKPOINT
  859. !   de_fault (to_init_access_breakpoint,    init_access_breakpoint);
  860. !   de_fault (to_insert_access_breakpoint,    insert_access_breakpoint);
  861. !   de_fault (to_get_access_breakpoint_status,    get_access_breakpoint_status);
  862. !   de_fault (to_clear_access_breakpoint_status,    clear_access_breakpoint_status);
  863. ! #endif /* HAVE_MEM_BREAKPOINT */
  864.   #undef de_fault
  865.   }
  866.   
  867. *** breakpoint.h    Wed Apr  1 13:46:00 1992
  868. --- ../../gdb-4.6.new/gdb/breakpoint.h    Fri Jul 24 15:32:52 1992
  869. ***************
  870. *** 23,28 ****
  871. --- 23,29 ----
  872.   #include "frame.h"
  873.   #include "value.h"
  874.   
  875.   /* This is the maximum number of bytes a breakpoint instruction can take.
  876.      Feel free to increase it.  It's just used in a few places to size
  877.      arrays that should be independent of the target architecture.  */
  878. ***************
  879. *** 130,135 ****
  880. --- 131,139 ----
  881.     bp_watchpoint,        /* Watchpoint */
  882.     bp_longjmp,            /* secret breakpoint to find longjmp() */
  883.     bp_longjmp_resume        /* secret breakpoint to escape longjmp() */
  884. + #ifdef HAVE_MEM_BREAKPOINT
  885. +   ,bp_accesspoint        /* Memory access breakpoint */
  886. + #endif /* HAVE_MEM_BREAKPOINT */
  887.   };
  888.   
  889.   /* States of enablement of breakpoint. */
  890. ***************
  891. *** 144,149 ****
  892. --- 148,157 ----
  893.     donttouch            /* Leave it alone */
  894.   };
  895.   
  896. + #ifdef HAVE_MEM_BREAKPOINT
  897. + enum access_break_type {access_break_write, access_break_rw};
  898. + #endif /* HAVE_MEM_BREAKPOINT */
  899.   /* Note that the ->silent field is not currently used by any commands
  900.      (though the code is in there if it was to be, and set_raw_breakpoint
  901.      does set it to 0).  I implemented it because I thought it would be
  902. ***************
  903. *** 210,215 ****
  904. --- 218,234 ----
  905.     struct block *exp_valid_block;
  906.     /* Value of the watchpoint the last time we checked it.  */
  907.     value val;
  908. + #ifdef HAVE_MEM_BREAKPOINT
  909. +    /* Address to memory break at.  */
  910. +    CORE_ADDR access_break_address;
  911. +    /* length of block to look at */
  912. +    int access_break_length;
  913. +    /* expression for address to look at */
  914. +    struct expression *access_break_exp;
  915. +    /* set to mem_break_write, or mem_break_rw if this is a memory breakpoint.*/
  916. +    enum access_break_type access_break_type;
  917. + #endif /* HAVE_MEM_BREAKPOINT */
  918.   };
  919.   
  920.   /* Prototypes for breakpoint-related functions.  */
  921. *** target.h    Fri Feb 21 19:46:03 1992
  922. --- ../../gdb-4.6.new/gdb/target.h    Fri Jul 24 15:32:56 1992
  923. ***************
  924. *** 39,45 ****
  925.      never get to the process target).  So when you push a file target,
  926.      it goes into the file stratum, which is always below the process
  927.      stratum.  */
  928.   #include "bfd.h"
  929.   
  930.   enum strata {
  931. --- 39,45 ----
  932.      never get to the process target).  So when you push a file target,
  933.      it goes into the file stratum, which is always below the process
  934.      stratum.  */
  935. ! #include "breakpoint.h"
  936.   #include "bfd.h"
  937.   
  938.   enum strata {
  939. ***************
  940. *** 94,99 ****
  941. --- 94,106 ----
  942.                  *to_sections;
  943.     struct section_table
  944.              *to_sections_end;
  945. + #ifdef HAVE_MEM_BREAKPOINT
  946. +   void    (* to_init_access_breakpoint) PARAMS ((void));
  947. +   int     (*to_insert_access_breakpoint) PARAMS ((CORE_ADDR, int,
  948. +                      enum access_break_type, int));
  949. +   int     (* to_get_access_breakpoint_status) PARAMS ((void));
  950. +   void    (* to_clear_access_breakpoint_status) PARAMS ((void));
  951. + #endif /* HAVE_MEM_BREAKPOINT */
  952.     int        to_magic;
  953.     /* Need sub-structure for target machine related rather than comm related? */
  954.   };
  955. ***************
  956. *** 222,227 ****
  957. --- 229,266 ----
  958.   
  959.   #define    target_files_info()    \
  960.       (*current_target->to_files_info) (current_target)
  961. + #ifdef HAVE_MEM_BREAKPOINT
  962. + extern void
  963. + init_access_breakpoint PARAMS ((void));
  964. + extern int
  965. + insert_access_breakpoint PARAMS ((CORE_ADDR, int,
  966. +                   enum access_break_type, int));
  967. + extern int
  968. + get_access_breakpoint_status PARAMS ((void));
  969. + extern void
  970. + clear_access_breakpoint_status PARAMS ((void));
  971. + /* Initialize (clear), and set memory access breakpoints.  This is probably
  972. +    done with hardware debug registers in the cpu.  Result is 0 for success,
  973. +    or errno value for failure.  If there is a failure there probably are not
  974. +    any more debug registers left.  */
  975. + #define target_init_access_breakpoint() (*current_target->to_init_access_breakpoint)()
  976. + #define target_insert_access_breakpoint(addr, len, type, bp_num) \
  977. +   (*current_target->to_insert_access_breakpoint)(addr, len, type, bp_num)
  978. + /* Return the breakpoint number that caused the memory access breakpoint.
  979. +    Returns 0 if no memory acess breakpoint */
  980. + #define target_get_access_breakpoint_status() \
  981. +   (*current_target->to_get_access_breakpoint_status)()
  982. + /* Clear the memory breakpoint status.  Called before execution is resumed*/
  983. + #define target_clear_access_breakpoint_status() \
  984. +   (*current_target->to_clear_access_breakpoint_status)()
  985. + #endif /* HAVE_MEM_BREAKPOINT */
  986.   
  987.   /* Insert a breakpoint at address ADDR in the target machine.
  988.      SAVE is a pointer to memory allocated for saving the
  989. ----------------------------------------------------------------
  990. Dave Daney    daney@mermaid.micro.umn.edu
  991.  
  992.  
  993.