Re: Suspected bug in DW_OP_addr handling
Simon Marchi via Gdb <[email protected]>
| Newsgroups | gmane.comp.gdb.devel |
|---|---|
| Message-ID | <[email protected]> |
On 2022-05-06 23:54, Yichao Yu via Gdb wrote:
> I noticed that gdb unwind failed with read of invalid memory address
> when I used `DW_OP_addr` in my unwind info. Upon checking, it seems
> that the handling of this operation in the dwarf interpreter is very
> suspicious.
>
> The interpreter for the op code has a comment[1] sayijng,
>
>> Some versions of GCC emit DW_OP_addr before
>> DW_OP_GNU_push_tls_address. In this case the value is an
>> index, not an address.
>
> However, the code appears to check for exactly the opposite condition
> `op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address` to decide
> whether the result should be used as index. This was added 12 years
> ago in commit ac56253ddece [2].
>
> Am I missing something or is this a long-standing bug?
My understanding is:
- normally, a value given by DW_OP_addr is an address that should be
relocated with the base address of the objfile
- the DW_OP_GNU_push_tls_address operation (now called
DW_OP_form_tls_address in DWARF 5) expects some kind of value on top
of the stack, identifying the TLS variable to fetch. It's
implementation-defined what this value means, but in practice it
means it's some value that should not be relocated.
- a contemporary version of GCC produces something like this for a TLS
variable's DW_AT_location:
DW_OP_const8u 0x4, DW_OP_form_tls_address
- A version of gcc in the past must have used this instead:
DW_OP_addr 0x4, DW_OP_form_tls_address
The usage of DW_OP_addr was wrong, and it made so GDB had to avoid
relocating the DW_OP_addr value in this particular case. So it is
checking, if we have DW_OP_addr followed by DW_OP_form_tls_address, then
we don't relocate, because we are in this buggy situation.
And so the condition:
if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address)
result += this->m_per_objfile->objfile->text_section_offset ();
looks right to me. It says, only relocate if:
- DW_OP_addr is the last operation of the sequence
- the following op is not DW_OP_form_tls_address / DW_OP_GNU_push_tls_address
Simon