[AMD Official Use Only - Internal Distribution Only]

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.

Reply via email to