berke@csd2.UUCP (Wayne Berke) (04/26/86)
One of the valuable features of adb is the ability to associate count values with breakpoints. Instead of stopping each time we come to a certain spot, we can execute an arbitrary command (e.g. print out a memory location or register). Unfortunately, certain commands do not work in this way. Most notably, try doing a stack trace each time we come to a certain place. The debugger will ignore the count value and stop after hitting the breakpoint once. If you examine the code in runpcs(), you can see that the problem arises because of the return value from command() which, if non-zero, causes adb to decrement the count and return to the debugger only when the count becomes 0 -- on the other hand, if command() returns zero, we immediately return to the main interpretive loop. The exact code (taken from the 4.2 VAX version, all Bourneisms intact) is: IF bkpt->flag==BKPTEXEC ORF ((bkpt->flag=BKPTEXEC) ANDF bkpt->comm[0]!=EOR ANDF command(bkpt->comm,':') ANDF --bkpt->count) THEN execbkpt(bkpt,execsig); execsig=0; loopcnt++; ELSE bkpt->count=bkpt->initcnt; rc=1; FI Note that it is the loopcnt++ instruction which results delaying the return to the debugger. Now if I am using adb and want to print out a stack trace each time I encounter a specific breakpoint, I would want to say: <text_address>,<count_value>:b $c and have adb print out a stack trace the first <count_value> times the process gets to <text_address>. However, the return statement from command() is: return(adrflg ANDF dot != 0); and adrflg==0 for commands like $c and $r. This results in adb performing a single stack trace regardless of the specified <count_value>. Since this return value is only used in the first code segment, I see no reason to change the return statement to: return(dot != 0) Does anyone know why the original return value depended on adrflg, or is it just a bug?
stevesu@copper.UUCP (Steve Summit) (05/07/86)
I don't like to post without having a definitive answer, but Wayne Berke posed an interesting question about adb about which there has been no discussion, so I'd like to toss some information in. Wayne's article pointed out that adb won't automatically continue after a breakpoint unless the internal variable adrflg is set. As I understand the code, adrflg is set if an address expression has been entered in the adb command string ("address" as in "address,count command modifier", the "general form of a request" mentioned on the second page of the adb tutorial). I got bit by this bug when trying to do things like printf+2:b ,3$c;:c I worked around it by doing something like printf+2,-1:b ,3$c;:c;environ/X I am still not sure whether it was setting count to -1, examining a nonzero address to set dot and adrflg, the :c itself, or some combination, that was really getting me the free-running behavior that I wanted. It occurred to me a few days later that adb's testing things before continuing after a breakpoint could be extremely useful if you wanted to arrange that a breakpoint only caused a stop after some complicated condition had been met. For instance, if you wanted to break only when some global variable had reached 0, you could include an expression in your breakpoint action which arranged to set dot to the value of your global variable. If the breakpoint action otherwise tried to continue, it would stop when your variable reached 0. My reason for pointing this out is to make sure, if this feature works and is useful, that nobody inadvertently breaks it (no pun intended) when trying to fix breakpoints. Another piece of information which I don't fully understand is this footnote, from the bottom of page 6 or 7 of the adb tutorial: * Owing to a bug in early versions of ADB (including the version distributed in Generic 3 UNIX) these statements must be written as: settab+4:b settab,5?ia;0 getc+4,3:b main.c?C;0 settab+4:b settab,5?ia; ptab/o;0 Note that ;0 will set dot to zero and stop at the breakpoint. Anyhoo, although I certainly agree that the code looks fishy, let's be careful before changing return(adrflg ANDF dot != 0); to return(dot != 0) One of the problems with these old programs that have twisted control flow and lots of global variables is that it's very hard to be sure that an apparently isolated change will not have far-reaching and unintended effects. Steve Summit tektronix!copper!stevesu