[Dwarf-Discuss] Location list entries for caller-saved registers at time of call

Cary Coutant ccoutant at gmail.com
Fri Dec 7 08:26:35 PST 2018


> In the following example I used GCC 7.3.0, and compiled the below
> listed C code using `-O1 -gstrict-dwarf -gdwarf-5'.
>
>   extern int get();
>   extern void set(int);
>
>   int main() {
>     int local = get();
>     set(local);
>     local = 123;
>     return local;
>   }
>
> This produces the following location list for `local':
>
>     0000000c 000000000000000e 0000000000000014 (DW_OP_reg0 (rax))
>     00000011 0000000000000015 000000000000001f (DW_OP_const1u: 123;
>                                                 DW_OP_stack_value)
>
>    9:   e8 00 00 00 00          callq  e <main+0xe>
>    e:   89 c7                   mov    %eax,%edi
>   10:   e8 00 00 00 00          callq  15 <main+0x15>
>   15:   b8 7b 00 00 00          mov    $0x7b,%eax
>
> As seen, there is a one-byte gap at the end of the call instruction to
> set().

This example shows local in %eax, which is a caller-save (i.e.,
scratch) register. GCC is right to show that the value is unknown upon
return from the call, because set() can clobber that register.

Try changing your code so that you use the value of local after the
call to set() -- say, make it "local += 123" -- and see the
difference. My copy of GCC moves local to %ebx, which is a caller-save
register, and the location list shows it live in that register all the
way through the call and return.

> If we instead use Clang, there is no gap in the location list for the
> same code:
>
>     [0x0000000000000008, 0x000000000000000f): DW_OP_reg0 RAX
>     [0x000000000000000f, 0x0000000000000016): DW_OP_consts +123,
>                                               DW_OP_stack_value)
>
>    3:   e8 00 00 00 00          callq  8 <main+0x8>
>    8:   89 c7                   mov    %eax,%edi
>    a:   e8 00 00 00 00          callq  f <main+0xf>
>    f:   b8 7b 00 00 00          mov    $0x7b,%eax
>
> When debugging the Clang-built binary in GDB, when unwinding from set()
> to main(), `local' will be evaluated using the value RAX has in set(),
> rather then being printed as "<optimized out>".

I think clang is wrong here. Because the call can clobber the
register, the compiler should not claim that the value is live upon
return.

-cary


More information about the Dwarf-Discuss mailing list