This is an archive of the discontinued LLVM Phabricator instance.

[dwarf] Handle DWARF forms for address other than DW_FORM_GNU_addr_index and DW_FORM_addr.
AbandonedPublic

Authored by dawn on Nov 12 2015, 6:20 PM.

Details

Summary

Other compilers (and older Clang compilers) use data4/data8 forms to specify addresses in DWARF. This patch fixes lldb to correctly read the addresses in DWARF generated by those compilers.

Diff Detail

Repository
rL LLVM

Event Timeline

dawn updated this revision to Diff 40102.Nov 12 2015, 6:20 PM
dawn retitled this revision from to [dwarf] Handle DWARF forms for address other than DW_FORM_GNU_addr_index and DW_FORM_addr..
dawn updated this object.
dawn added reviewers: tberghammer, clayborg, tfiala.
dawn set the repository for this revision to rL LLVM.
dawn added a subscriber: lldb-commits.
tberghammer accepted this revision.Nov 13 2015, 2:21 AM
tberghammer edited edge metadata.

LGTM

(Next time please upload the diff with full context because it is easier to review that way)

This revision is now accepted and ready to land.Nov 13 2015, 2:21 AM
clayborg requested changes to this revision.Nov 13 2015, 9:58 AM
clayborg edited edge metadata.

This is not the right fix. Compilers that emit addresses with DW_FORM_data* forms are saying that this address is an offset from the DW_AT_low_pc so this function will not return a valid address, but it will now return an offset. If you have a compiler that is actually emitting addresses incorrectly using DW_FORM_data* when the values are not offsets, the compiler should be fixed.

There are two solutions to this:
1 - modify DWARFFormValue::Address() to return LLDB_INVALID_ADDRESS if the form is not DW_FORM_addr or DW_FORM_GNU_addr_index.
2 - modify DWARFFormValue::Address() to take an lldb::addr_t that is the base address that the DW_FORM_data* would be relative to. This argument could be defaulted:

dw_addr_t
DWARFFormValue::Address(lldb::addr_t base_addr = LLDB_INVALID_ADDRESS) const

Then in the code we would do:

dw_addr_t
DWARFFormValue::Address(lldb::addr_t base_addr) const
{
    switch (m_form)
    {
    case DW_FORM_addr:
        return Unsigned();
    case DW_FORM_GNU_addr_index:
        if (m_cu)
        {
            SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF();
            if (symbol_file)
            {
                uint32_t index_size = m_cu->GetAddressByteSize();
                dw_offset_t addr_base = m_cu->GetAddrBase();
                lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
                return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);
            }
        }
        break;
     case DW_FORM_data1:
     case DW_FORM_data2:
     case DW_FORM_data4:
     case DW_FORM_data8:
     case DW_FORM_sdata:
     case DW_FORM_udata:
         if (base_addr != LLDB_INVALID_ADDRESS)
            return base_addr + Unsigned();
    default:
        break;
    }
    return LLDB_INVALID_ADDRESS;
}
This revision now requires changes to proceed.Nov 13 2015, 9:58 AM
dawn abandoned this revision.Nov 13 2015, 12:53 PM

If you have a compiler that is actually emitting addresses incorrectly using DW_FORM_data* when the values are not offsets, the compiler should be fixed.

Thanks Greg! In this case it indeed appears to be a compiler bug (we are getting relocations emitted for them). But I like your suggestion of how to rewrite the Address function. If any valid cases arise, I will use your idea, but instead create an overload which takes a parameter (that way only the DWARF contexts in which addresses are represented using data4/data8 will have to pay the cost of the added code).

The feature Greg mentioned is already implemented in DWARFDebugInfoEntry::GetAttributeHighPC and we shouldn't move it to DWARFFormValue::Address because it is only needed for DW_AT_high_pc but DWARFFormValue::Address used for other places as well (e.g. DW_AT_low_pc).

I think what we are seeing isn't a compiler bug, but I need a little bit more information to be sure.

How you end up in calling DWARFFormValue::Address() with a value what have a form type other then DW_FORM_addr and DW_FORM_GNU_addr_index? What is the attribute tag and the form type used? Can you post a call stack for the case when you hit this issue?

dawn added a comment.EditedNov 16 2015, 11:25 AM

How you end up in calling DWARFFormValue::Address() with a value what have a form type other then DW_FORM_addr and DW_FORM_GNU_addr_index? What is the attribute tag and the form type used? Can you post a call stack for the case when you hit this issue?

We see it in the comp unit's low_pc:

0x000b:  DW_TAG_compile_unit    : abbrev_num=1
0x000c:  DW_AT_producer         : DW_FORM_strp       string=Embarcadero Technologies Inc. clang version 3.1 (33931.6d56f68.9eae00b) (based on LLVM 3.3svn)
0x0010:  DW_AT_language         : DW_FORM_data2      uval=0x4
         language=DW_LANG_C_plus_plus
0x0012:  DW_AT_name             : DW_FORM_strp       string=cprops.cpp
0x0016:  DW_AT_low_pc           : DW_FORM_data4      uval=0x0

Address is called at the beginning of reading the CU's DIE.

So yes this is a compiler bug where the compiler is producing invalid DWARF.