diff options
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFFormValue.cpp')
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFFormValue.cpp | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 7719fea63120..290d35511cdb 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -1,9 +1,8 @@ //===- DWARFFormValue.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -78,6 +77,34 @@ static const DWARFFormValue::FormClass DWARF5FormClasses[] = { }; +DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) { + return DWARFFormValue(F, ValueType(V)); +} + +DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) { + return DWARFFormValue(F, ValueType(V)); +} + +DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) { + return DWARFFormValue(F, ValueType(V)); +} + +DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F, + ArrayRef<uint8_t> D) { + ValueType V; + V.uval = D.size(); + V.data = D.data(); + return DWARFFormValue(F, V); +} + +DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U, + uint32_t *OffsetPtr) { + DWARFFormValue FormValue(F); + FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, + U->getFormParams(), U); + return FormValue; +} + bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, uint32_t *OffsetPtr, const dwarf::FormParams Params) { @@ -193,13 +220,17 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { default: break; } - // 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. Also accept DW_FORM_[line_]strp since these are - // .debug_[line_]str section offsets. - return (Form == DW_FORM_data4 || Form == DW_FORM_data8 || - Form == DW_FORM_strp || Form == DW_FORM_line_strp) && - FC == FC_SectionOffset; + + if (FC == FC_SectionOffset) { + if (Form == DW_FORM_strp || Form == DW_FORM_line_strp) + return true; + // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section + // offset. If we don't have a DWARFUnit, default to the old behavior. + if (Form == DW_FORM_data4 || Form == DW_FORM_data8) + return !U || U->getVersion() <= 3; + } + + return false; } bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, @@ -268,7 +299,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, case DW_FORM_data8: case DW_FORM_ref8: case DW_FORM_ref_sup8: - Value.uval = Data.getU64(OffsetPtr); + Value.uval = Data.getRelocatedValue(8, OffsetPtr); break; case DW_FORM_data16: // Treat this like a 16-byte block. @@ -323,7 +354,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, StringRef Str = Data.getData().substr(*OffsetPtr, Value.uval); Value.data = nullptr; if (!Str.empty()) { - Value.data = reinterpret_cast<const uint8_t *>(Str.data()); + Value.data = Str.bytes_begin(); *OffsetPtr += Value.uval; } } @@ -333,7 +364,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, - SectionedAddress SA) const { + object::SectionedAddress SA) const { OS << format("0x%016" PRIx64, SA.Address); dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, SA.SectionIndex); @@ -370,12 +401,14 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { case DW_FORM_addrx3: case DW_FORM_addrx4: case DW_FORM_GNU_addr_index: { - Optional<SectionedAddress> A = U->getAddrOffsetSectionItem(UValue); + if (U == nullptr) { + OS << "<invalid dwarf unit>"; + break; + } + Optional<object::SectionedAddress> A = U->getAddrOffsetSectionItem(UValue); if (!A || DumpOpts.Verbose) AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); - if (U == nullptr) - OS << "<invalid dwarf unit>"; - else if (A) + if (A) dumpSectionedAddress(AddrOS, DumpOpts, *A); else OS << "<no .debug_addr section>"; @@ -591,14 +624,15 @@ Optional<uint64_t> DWARFFormValue::getAsAddress() const { return SA->Address; return None; } -Optional<SectionedAddress> DWARFFormValue::getAsSectionedAddress() const { +Optional<object::SectionedAddress> +DWARFFormValue::getAsSectionedAddress() const { if (!isFormClass(FC_Address)) return None; if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) { uint32_t Index = Value.uval; if (!U) return None; - Optional<SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); + Optional<object::SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); if (!SA) return None; return SA; @@ -607,6 +641,12 @@ Optional<SectionedAddress> DWARFFormValue::getAsSectionedAddress() const { } Optional<uint64_t> DWARFFormValue::getAsReference() const { + if (auto R = getAsRelativeReference()) + return R->Unit ? R->Unit->getOffset() + R->Offset : R->Offset; + return None; +} + +Optional<DWARFFormValue::UnitOffset> DWARFFormValue::getAsRelativeReference() const { if (!isFormClass(FC_Reference)) return None; switch (Form) { @@ -617,11 +657,11 @@ Optional<uint64_t> DWARFFormValue::getAsReference() const { case DW_FORM_ref_udata: if (!U) return None; - return Value.uval + U->getOffset(); + return UnitOffset{const_cast<DWARFUnit*>(U), Value.uval}; case DW_FORM_ref_addr: case DW_FORM_ref_sig8: case DW_FORM_GNU_ref_alt: - return Value.uval; + return UnitOffset{nullptr, Value.uval}; default: return None; } |