[llvm-dev] Seeking clarification and way forward on limited scope variables.

Sourabh Singh Tomar via llvm-dev llvm-dev at lists.llvm.org
Wed Apr 15 03:14:38 PDT 2020


Hello Everyone,



I need to have your thoughts on this.



Consider the following test case --

-------------------------------------------

 1    int main(int Argc, char **Argv) {
  2         int Local = 6;
  3         printf("%d\n",Local);
  4
  5         {
  6         printf("%d\n",Local);
  7         int Local = 7;
  8         printf("%d\n",Local);
  9         }
 10
 11         return 0;
 12  }

--------------------------------------------

When compiled in debug mode with compilers including (trunk gcc and trunk
clang) and debugging with GDB at Line No.6, the following behavior is
observed

Breakpoint 1, main (Argc=1, Argv=0x7fffffffe458) at MainScope.c:6
6               printf("%d\n",Local);
(gdb) print Local
$1 = 2102704   -- some Garbage value,

(gdb) info addr Local
Symbol "Local" is a variable at frame base reg $rbp offset 0+-24.   -- *This
is location of *Local* declared inside scope, but as you may notice that
the variable being referred here is from the outer scope.*



This problem persists with both GDB and LLDB. Since we have entered the
Lexical Scope and when we try to print value of *Local*,  it will look into
the *current scope* and fetch the value if the variable exists in scope(in
case variable doesn't exist, GDB searches for it in the outer scope).



This is regardless of whether the variable has actually came into scope(or
actually defined) at Line No. 7. Since DWARF already defined the
location(on stack) which will be valid for the lifetime of the variable,
contrary to when the variable is actually defined(or allocated) which is in
this case Line No. 7.

---------------------------------------------

  0x0000006d:     DW_TAG_lexical_block
                  DW_AT_low_pc  (0x00000000002016d1)
                  DW_AT_high_pc (0x000000000020170b)

0x0000007a:       DW_TAG_variable
                    DW_AT_location      (DW_OP_fbreg -24)
                    DW_AT_name  ("Local")
                    DW_AT_decl_file     ("MainScope.c")
                    DW_AT_decl_line     (7)
                    DW_AT_type  (0x0000008a "int")

----------------------------------------------



The DWARF specification provides the DW_AT_start_scope attribute to deal
with this issue (Sec 3.9 Declarations with Reduced Scope DWARFv5). This
attribute aims at limiting the scope of variables within the lexical scope
in which it is defined to from where it has been declared/ defined.



In order to fix this issue, we want to modify llvm so that
DW_AT_start_scope is emitted for the variable in the inner block (in the
above example). This limits the scope of the inner block variable to start
from the point of its declaration.



For POC, we inserted DW_AT_start_scope in this inner *Local* variable,
resultant dwarf after this.

-----------------------------

0x0000006d:     DW_TAG_lexical_block
                  DW_AT_low_pc  (0x00000000002016d1)
                  DW_AT_high_pc (0x000000000020170b)

0x0000007a:       DW_TAG_variable
                    * DW_AT_start_scope   (0x17) -- restricted within a
subset(starting from the point of definition(specified as an offset)) of
entire ranges covered by Lex Block.*
                    DW_AT_location      (DW_OP_fbreg -24)
                    DW_AT_name  ("Local")
                    DW_AT_decl_file     ("MainScope.c")
                    DW_AT_decl_line     (7)
                    DW_AT_type  (0x00000092 "int")

----------------------------





We also modified ‘gdb’ to interpret DW_AT_start_scope so that the scope of
the variable is limited from the PC where the value of DW_AT_start_scope
is. If the debugger is stopped at a point within the same lexical block but
at a PC before DW_AT_start_scope, then gdb follows the normal search
mechanism of searching in consecutive super blocks till it gets a match or
it reaches the global block. After the modification,  GDB is able to
correctly show the value *6* in our example.





After incorporating changes --

  Breakpoint 1, main (Argc=1, Argv=0x7fffffffe458) at MainScope.c:6
6               printf("%d\n",Local);
(gdb) print Local
* $1 = 6 --- Value retrieved from outer scope*

(gdb) info addr Local

Symbol "Local" is a variable at frame base reg $rbp offset 0+-20.



Could you guys please let us know your thoughts or suggestions on this?
Was/ Is there is an existing effort already going on to deal with this
problem?


Even though location lists can be used to deal with this scenario, in my
experience, location lists are emitted at higher optimization levels, and
with the usage of location lists in this example, gdb prints out <optimized
out> (as expected) if it is stopped at a PC in the same lexical block but
before the point of declaration of the local variable.

Thank You,
Sourabh Singh Tomar.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200415/37768838/attachment.html>


More information about the llvm-dev mailing list