[net.unix-wizards] for adb hackers only

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