diff options
author | Alexey Samsonov <vonosmas@gmail.com> | 2015-05-19 20:29:28 +0000 |
---|---|---|
committer | Alexey Samsonov <vonosmas@gmail.com> | 2015-05-19 20:29:28 +0000 |
commit | bf19a578e602d65d6d6ccc58586c41958a29b184 (patch) | |
tree | 8314f6d236a9004d2a7e12aaaf0165bb36205829 /llvm/lib/DebugInfo | |
parent | f999547d11249ff13853683d5ca63383593ef4fd (diff) | |
download | bcm5719-llvm-bf19a578e602d65d6d6ccc58586c41958a29b184.tar.gz bcm5719-llvm-bf19a578e602d65d6d6ccc58586c41958a29b184.zip |
[DWARF parser] Add basic support for DWZ DWARF multifile extensions.
This change implements basic support for DWARF alternate sections
proposal: http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open
LLVM tools now understand new forms: DW_FORM_GNU_ref_alt and
DW_FORM_GNU_strp_alt, which are used as references to .debug_info and
.debug_str sections respectively, stored in a separate file, and
possibly shared between different executables / shared objects.
llvm-dwarfdump and llvm-symbolizer don't yet know how to access this
alternate debug file (usually pointed by .gnu_debugaltlink section),
but they can at lease properly parse and dump regular files, which
refer to it.
This change should fix crashes of llvm-dwarfdump and llvm-symbolizer on
files produced by running "dwz" tool. Such files are already installed
on some modern Linux distributions.
llvm-svn: 237721
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 77 |
2 files changed, 51 insertions, 43 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index e963b7ca6e6..5abbde4ac0f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -161,14 +161,15 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, // We have dumped the attribute raw value. For some attributes // having both the raw value and the pretty-printed value is // interesting. These attributes are handled below. - if ((attr == DW_AT_specification || attr == DW_AT_abstract_origin) && - // The signature references aren't handled. - formValue.getForm() != DW_FORM_ref_sig8) { - uint32_t Ref = formValue.getAsReference(u).getValue(); - DWARFDebugInfoEntryMinimal DIE; - if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &Ref)) - if (const char *Ref = DIE.getName(RefU, DINameKind::LinkageName)) - OS << " \"" << Ref << '\"'; + if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) { + Optional<uint64_t> Ref = formValue.getAsReference(u); + if (Ref.hasValue()) { + uint32_t RefOffset = Ref.getValue(); + DWARFDebugInfoEntryMinimal DIE; + if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &RefOffset)) + if (const char *Name = DIE.getName(RefU, DINameKind::LinkageName)) + OS << " \"" << Name << '\"'; + } } else if (attr == DW_AT_APPLE_property_attribute) { if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) dumpApplePropertyAttribute(OS, *OptVal); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 6946f833424..75ca7622139 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -113,14 +113,17 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { if (Form < ArrayRef<FormClass>(DWARF4FormClasses).size() && DWARF4FormClasses[Form] == FC) return true; - // Check DW_FORM_ref_sig8 from DWARF4. - if (Form == DW_FORM_ref_sig8) + // Check more forms from DWARF4 and DWARF5 proposals. + switch (Form) { + case DW_FORM_ref_sig8: + case DW_FORM_GNU_ref_alt: return (FC == FC_Reference); - // Check for some DWARF5 forms. - if (Form == DW_FORM_GNU_addr_index) + case DW_FORM_GNU_addr_index: return (FC == FC_Address); - if (Form == DW_FORM_GNU_str_index) + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_strp_alt: return (FC == FC_String); + } // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset. // Don't check for DWARF version here, as some producers may still do this // by mistake. @@ -199,15 +202,6 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, case DW_FORM_sdata: Value.sval = data.getSLEB128(offset_ptr); break; - case DW_FORM_strp: { - Value.uval = data.getU32(offset_ptr); - if (!cu) - break; - RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); - if (AI != cu->getRelocMap()->end()) - Value.uval += AI->second.second; - break; - } case DW_FORM_udata: case DW_FORM_ref_udata: Value.uval = data.getULEB128(offset_ptr); @@ -219,14 +213,18 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, Form = data.getULEB128(offset_ptr); indirect = true; break; - case DW_FORM_sec_offset: { + case DW_FORM_sec_offset: + case DW_FORM_strp: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: { // FIXME: This is 64-bit for DWARF64. Value.uval = data.getU32(offset_ptr); if (!cu) break; - RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); + RelocAddrMap::const_iterator AI = + cu->getRelocMap()->find(*offset_ptr - 4); if (AI != cu->getRelocMap()->end()) - Value.uval += AI->second.second; + Value.uval += AI->second.second; break; } case DW_FORM_flag_present: @@ -323,7 +321,6 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, return true; // 4 byte values - case DW_FORM_strp: case DW_FORM_data4: case DW_FORM_ref4: *offset_ptr += 4; @@ -353,6 +350,9 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, // FIXME: 4 for DWARF32, 8 for DWARF64. case DW_FORM_sec_offset: + case DW_FORM_strp: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: *offset_ptr += 4; return true; @@ -424,24 +424,17 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { case DW_FORM_udata: OS << Value.uval; break; case DW_FORM_strp: { OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); - Optional<const char *> DbgStr = getAsCString(cu); - if (DbgStr.hasValue()) { - raw_ostream &COS = WithColor(OS, syntax::String); - COS << '"'; - COS.write_escaped(DbgStr.getValue()); - COS << '"'; - } + dumpString(OS, cu); break; } case DW_FORM_GNU_str_index: { OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); - Optional<const char *> DbgStr = getAsCString(cu); - if (DbgStr.hasValue()) { - raw_ostream &COS = WithColor(OS, syntax::String); - COS << '"'; - COS.write_escaped(DbgStr.getValue()); - COS << '"'; - } + dumpString(OS, cu); + break; + } + case DW_FORM_GNU_strp_alt: { + OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue); + dumpString(OS, cu); break; } case DW_FORM_ref_addr: @@ -467,6 +460,9 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { cu_relative_offset = true; OS << format("cu + 0x%" PRIx64, uvalue); break; + case DW_FORM_GNU_ref_alt: + OS << format("<alt 0x%" PRIx64 ">", uvalue); + break; // All DW_FORM_indirect attributes should be resolved prior to calling // this function @@ -492,12 +488,23 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { } } +void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const { + Optional<const char *> DbgStr = getAsCString(U); + if (DbgStr.hasValue()) { + raw_ostream &COS = WithColor(OS, syntax::String); + COS << '"'; + COS.write_escaped(DbgStr.getValue()); + COS << '"'; + } +} + Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { if (!isFormClass(FC_String)) return None; if (Form == DW_FORM_string) return Value.cstr; - if (!U) + // FIXME: Add support for DW_FORM_GNU_strp_alt + if (Form == DW_FORM_GNU_strp_alt || U == nullptr) return None; uint32_t Offset = Value.uval; if (Form == DW_FORM_GNU_str_index) { @@ -539,9 +546,9 @@ Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { return Value.uval + U->getOffset(); case DW_FORM_ref_addr: return Value.uval; - // FIXME: Add proper support for DW_FORM_ref_sig8 + // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt. default: - return Value.uval; + return None; } } |