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.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
LGTM
(Next time please upload the diff with full context because it is easier to review that way)
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; }
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?
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.