On Tue, Jun 9, 2020 at 8:00 AM Tomar, Sourabh Singh
<sourabhsingh.to...@amd.com> wrote:
>
> [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?

There's one or two bugreports about this in bugzilla which has some
extra info.  The issue is that
lexical blocks do not align with variable lifetime.  IIRC I spotted a
DWARF feature that might help
but don't remember (try find the bug).

I'm not aware of anyone actually trying to fix the issue.

Richard.

> 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