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

Michael Eager eager@eagerm.com
Fri Dec 7 16:32:46 GMT 2018


On 12/07/2018 08:26 AM, Cary Coutant wrote:
>> 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.

I think clang is correct.

As I read the loclists, from 0x8 up to but not including 0xf, the
value is in reg0, from 0xf (after the call) up to but not including
0x16, the value is on the stack.

I don't see that this describes the value as live (in a register)
after the call, at PC = 0xf.

-- 
Michael Eager    eager at eagerm.com
1960 Park Blvd., Palo Alto, CA 94306



More information about the Dwarf-discuss mailing list