donn@sdchema.UUCP (06/09/84)
Subject: Dbx can't access C functions that have blocks containing declarations Index: ucb/dbx/object.c 4.2BSD Description: Sometimes when debugging with dbx, mysterious functions like '$b4' or '$b23' appear in the stack trace when the 'where' command is given. These functions appear to share lines with the function that appears to call them -- for example, if you are stopped in function 'f' which appears to be called by function '$b4' which is in turn called by function 'g', then 'f' will appear to be called from the same source file and at the same line number in '$b4' as '$b4' is in 'g'. Moreover it is impossible to examine local variables in 'g'. The common feature of all functions 'g' mentioned above is that they contain blocks or compound statements that have their own declarations. If you stop in an inner block with declarations, you can print out that block's local variables (although none of the outer local variables), which is a good indication that they are connected with the bug. Repeat-By: Clip out the following program and compile it with 'cc -g': ---------------------------------------------------------------- #include <stdio.h> int f(); main() { int x; x = 1; if (x > 0) { int y; y = 3; x = f(y); } printf( "%d\n", x ); exit( 0 ); } int f( z ) int z; { z = z + 1; return ( z ); } ---------------------------------------------------------------- Run dbx on the object. If you put a breakpoint anywhere in the program, run it and check the stack when you stop, you will find that there is a mysterious function '$b1' that is always present. The variable 'x' in main() will not be accessible but you can get at 'z' when 'f' is active, and you can get at 'y' at any time (clearly a bug). Fix: Hasn't someone fixed this before? I sure would like to have a good (official?) fix... I won't pretend that my fix is clean or even correct, but it seems to be an improvement. The changes are to enter_nl() and unnamed_block() in object.c: ---------------------------------------------------------------- *** /tmp/,RCSt1021606 Fri Jun 8 14:45:57 1984 --- object.c Fri Jun 8 14:44:26 1984 *************** *** 318,324 break; case N_RBRAC: ! if (addrstk[nesting] == NOADDR) { exitblock(); newfunc(curblock, (linep - 1)->addr); } --- 318,325 ----- break; case N_RBRAC: ! --nesting; ! if (nesting > 0) { exitblock(); newfunc(curblock, (linep - 1)->addr); addrstk[nesting] = (linep - 1)->addr; *************** *** 321,326 if (addrstk[nesting] == NOADDR) { exitblock(); newfunc(curblock, (linep - 1)->addr); } --nesting; break; --- 322,328 ----- if (nesting > 0) { exitblock(); newfunc(curblock, (linep - 1)->addr); + addrstk[nesting] = (linep - 1)->addr; } break; *************** *** 322,328 exitblock(); newfunc(curblock, (linep - 1)->addr); } - --nesting; break; case N_SLINE: --- 324,329 ----- newfunc(curblock, (linep - 1)->addr); addrstk[nesting] = (linep - 1)->addr; } break; case N_SLINE: *************** *** 546,552 ++bnum; sprintf(buf, "$b%d", bnum); s = insert(identname(buf, false)); ! s->class = PROG; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = addrstk[nesting]; --- 547,553 ----- ++bnum; sprintf(buf, "$b%d", bnum); s = insert(identname(buf, false)); ! s->class = PROC; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = (linep - 1)->addr; *************** *** 549,555 s->class = PROG; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; ! s->symvalue.funcv.beginaddr = addrstk[nesting]; enterblock(s); newfunc(s, addrstk[nesting]); addrstk[nesting] = NOADDR; --- 550,556 ----- s->class = PROC; s->symvalue.funcv.src = false; s->symvalue.funcv.inline = true; ! s->symvalue.funcv.beginaddr = (linep - 1)->addr; enterblock(s); newfunc(s, (linep - 1)->addr); addrstk[nesting] = NOADDR; *************** *** 551,557 s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = addrstk[nesting]; enterblock(s); ! newfunc(s, addrstk[nesting]); addrstk[nesting] = NOADDR; } --- 552,558 ----- s->symvalue.funcv.inline = true; s->symvalue.funcv.beginaddr = (linep - 1)->addr; enterblock(s); ! newfunc(s, (linep - 1)->addr); addrstk[nesting] = NOADDR; } ---------------------------------------------------------------- What this fix does for you is that it makes it possible to look at the local variables of a function with an inner block containing declarations, with the caveat that if you are actually IN the inner block, you can see that block's variables but not the outer variables (essentially this reduces the scope of the bug without eliminating it). I am pretty sure that the old code is wrong, but I am not sure that my change is what the author intended. Anyone with a better solution is urged to post it... Donn Seeley UCSD Chemistry Dept. ucbvax!sdcsvax!sdchema!donn 32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn@nosc.ARPA