diff options
author | Zachary Turner <zturner@google.com> | 2015-01-30 18:07:45 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2015-01-30 18:07:45 +0000 |
commit | 82af9438d0fa27b21f75bdea5832f1baa5450863 (patch) | |
tree | 9e9412193579d574cdeabcd07de3e868795cfd4a /llvm/lib/DebugInfo/DWARFUnit.cpp | |
parent | 51702e6e7539afabe8cf34b11bd6b6974e203054 (diff) | |
download | bcm5719-llvm-82af9438d0fa27b21f75bdea5832f1baa5450863.tar.gz bcm5719-llvm-82af9438d0fa27b21f75bdea5832f1baa5450863.zip |
Move DebugInfo to DebugInfo/DWARF.
In preparation for adding PDB support to LLVM, this moves the
DWARF parsing code to its own subdirectory under DebugInfo, and
renames LLVMDebugInfo to LLVMDebugInfoDWARF.
This is purely a mechanical / build system change.
Differential Revision: http://reviews.llvm.org/D7269
Reviewed by: Eric Christopher
llvm-svn: 227586
Diffstat (limited to 'llvm/lib/DebugInfo/DWARFUnit.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/DWARFUnit.cpp | 377 |
1 files changed, 0 insertions, 377 deletions
diff --git a/llvm/lib/DebugInfo/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARFUnit.cpp deleted file mode 100644 index 395a179f14b..00000000000 --- a/llvm/lib/DebugInfo/DWARFUnit.cpp +++ /dev/null @@ -1,377 +0,0 @@ -//===-- DWARFUnit.cpp -----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/DWARFUnit.h" -#include "llvm/DebugInfo/DWARFContext.h" -#include "llvm/DebugInfo/DWARFFormValue.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/Path.h" -#include <cstdio> - -using namespace llvm; -using namespace dwarf; - -void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { - parseImpl(C, Section, C.getDebugAbbrev(), C.getRangeSection(), - C.getStringSection(), StringRef(), C.getAddrSection(), - C.isLittleEndian()); -} - -void DWARFUnitSectionBase::parseDWO(DWARFContext &C, - const DWARFSection &DWOSection) { - parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(), - C.getStringDWOSection(), C.getStringOffsetDWOSection(), - C.getAddrSection(), C.isLittleEndian()); -} - -DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, - StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection) - : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS), - StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), - isLittleEndian(LE), UnitSection(UnitSection) { - clear(); -} - -DWARFUnit::~DWARFUnit() { -} - -bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, - uint64_t &Result) const { - uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; - if (AddrOffsetSection.size() < Offset + AddrSize) - return false; - DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize); - Result = DA.getAddress(&Offset); - return true; -} - -bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, - uint32_t &Result) const { - // FIXME: string offset section entries are 8-byte for DWARF64. - const uint32_t ItemSize = 4; - uint32_t Offset = Index * ItemSize; - if (StringOffsetSection.size() < Offset + ItemSize) - return false; - DataExtractor DA(StringOffsetSection, isLittleEndian, 0); - Result = DA.getU32(&Offset); - return true; -} - -bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { - Length = debug_info.getU32(offset_ptr); - Version = debug_info.getU16(offset_ptr); - uint64_t AbbrOffset = debug_info.getU32(offset_ptr); - AddrSize = debug_info.getU8(offset_ptr); - - bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); - bool VersionOK = DWARFContext::isSupportedVersion(Version); - bool AddrSizeOK = AddrSize == 4 || AddrSize == 8; - - if (!LengthOK || !VersionOK || !AddrSizeOK) - return false; - - Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); - if (Abbrevs == nullptr) - return false; - - return true; -} - -bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { - clear(); - - Offset = *offset_ptr; - - if (debug_info.isValidOffset(*offset_ptr)) { - if (extractImpl(debug_info, offset_ptr)) - return true; - - // reset the offset to where we tried to parse from if anything went wrong - *offset_ptr = Offset; - } - - return false; -} - -bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, - DWARFDebugRangeList &RangeList) const { - // Require that compile unit is extracted. - assert(DieArray.size() > 0); - DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); - uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; - return RangeList.extract(RangesData, &ActualRangeListOffset); -} - -void DWARFUnit::clear() { - Offset = 0; - Length = 0; - Version = 0; - Abbrevs = nullptr; - AddrSize = 0; - BaseAddr = 0; - RangeSectionBase = 0; - AddrOffsetSectionBase = 0; - clearDIEs(false); - DWO.reset(); -} - -const char *DWARFUnit::getCompilationDir() { - extractDIEsIfNeeded(true); - if (DieArray.empty()) - return nullptr; - return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); -} - -uint64_t DWARFUnit::getDWOId() { - extractDIEsIfNeeded(true); - const uint64_t FailValue = -1ULL; - if (DieArray.empty()) - return FailValue; - return DieArray[0] - .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); -} - -void DWARFUnit::setDIERelations() { - if (DieArray.size() <= 1) - return; - - std::vector<DWARFDebugInfoEntryMinimal *> ParentChain; - DWARFDebugInfoEntryMinimal *SiblingChain = nullptr; - for (auto &DIE : DieArray) { - if (SiblingChain) { - SiblingChain->setSibling(&DIE); - } - if (const DWARFAbbreviationDeclaration *AbbrDecl = - DIE.getAbbreviationDeclarationPtr()) { - // Normal DIE. - if (AbbrDecl->hasChildren()) { - ParentChain.push_back(&DIE); - SiblingChain = nullptr; - } else { - SiblingChain = &DIE; - } - } else { - // NULL entry terminates the sibling chain. - SiblingChain = ParentChain.back(); - ParentChain.pop_back(); - } - } - assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]); - assert(ParentChain.empty()); -} - -void DWARFUnit::extractDIEsToVector( - bool AppendCUDie, bool AppendNonCUDies, - std::vector<DWARFDebugInfoEntryMinimal> &Dies) const { - if (!AppendCUDie && !AppendNonCUDies) - return; - - // Set the offset to that of the first DIE and calculate the start of the - // next compilation unit header. - uint32_t DIEOffset = Offset + getHeaderSize(); - uint32_t NextCUOffset = getNextUnitOffset(); - DWARFDebugInfoEntryMinimal DIE; - uint32_t Depth = 0; - bool IsCUDie = true; - - while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) { - if (IsCUDie) { - if (AppendCUDie) - Dies.push_back(DIE); - if (!AppendNonCUDies) - break; - // The average bytes per DIE entry has been seen to be - // around 14-20 so let's pre-reserve the needed memory for - // our DIE entries accordingly. - Dies.reserve(Dies.size() + getDebugInfoSize() / 14); - IsCUDie = false; - } else { - Dies.push_back(DIE); - } - - if (const DWARFAbbreviationDeclaration *AbbrDecl = - DIE.getAbbreviationDeclarationPtr()) { - // Normal DIE - if (AbbrDecl->hasChildren()) - ++Depth; - } else { - // NULL DIE. - if (Depth > 0) - --Depth; - if (Depth == 0) - break; // We are done with this compile unit! - } - } - - // Give a little bit of info if we encounter corrupt DWARF (our offset - // should always terminate at or before the start of the next compilation - // unit header). - if (DIEOffset > NextCUOffset) - fprintf(stderr, "warning: DWARF compile unit extends beyond its " - "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); -} - -size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { - if ((CUDieOnly && DieArray.size() > 0) || - DieArray.size() > 1) - return 0; // Already parsed. - - bool HasCUDie = DieArray.size() > 0; - extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); - - if (DieArray.empty()) - return 0; - - // If CU DIE was just parsed, copy several attribute values from it. - if (!HasCUDie) { - uint64_t BaseAddr = - DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); - if (BaseAddr == -1ULL) - BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); - setBaseAddress(BaseAddr); - AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( - this, DW_AT_GNU_addr_base, 0); - RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( - this, DW_AT_ranges_base, 0); - // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for - // skeleton CU DIE, so that DWARF users not aware of it are not broken. - } - - setDIERelations(); - return DieArray.size(); -} - -DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) - : DWOFile(), DWOContext(), DWOU(nullptr) { - auto Obj = object::ObjectFile::createObjectFile(DWOPath); - if (!Obj) - return; - DWOFile = std::move(Obj.get()); - DWOContext.reset( - cast<DWARFContext>(DIContext::getDWARFContext(*DWOFile.getBinary()))); - if (DWOContext->getNumDWOCompileUnits() > 0) - DWOU = DWOContext->getDWOCompileUnitAtIndex(0); -} - -bool DWARFUnit::parseDWO() { - if (DWO.get()) - return false; - extractDIEsIfNeeded(true); - if (DieArray.empty()) - return false; - const char *DWOFileName = - DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); - if (!DWOFileName) - return false; - const char *CompilationDir = - DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); - SmallString<16> AbsolutePath; - if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { - sys::path::append(AbsolutePath, CompilationDir); - } - sys::path::append(AbsolutePath, DWOFileName); - DWO = llvm::make_unique<DWOHolder>(AbsolutePath); - DWARFUnit *DWOCU = DWO->getUnit(); - // Verify that compile unit in .dwo file is valid. - if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { - DWO.reset(); - return false; - } - // Share .debug_addr and .debug_ranges section with compile unit in .dwo - DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); - uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); - DWOCU->setRangesSection(RangeSection, DWORangesBase); - return true; -} - -void DWARFUnit::clearDIEs(bool KeepCUDie) { - if (DieArray.size() > (unsigned)KeepCUDie) { - // std::vectors never get any smaller when resized to a smaller size, - // or when clear() or erase() are called, the size will report that it - // is smaller, but the memory allocated remains intact (call capacity() - // to see this). So we need to create a temporary vector and swap the - // contents which will cause just the internal pointers to be swapped - // so that when temporary vector goes out of scope, it will destroy the - // contents. - std::vector<DWARFDebugInfoEntryMinimal> TmpArray; - DieArray.swap(TmpArray); - // Save at least the compile unit DIE - if (KeepCUDie) - DieArray.push_back(TmpArray.front()); - } -} - -void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { - // First, check if CU DIE describes address ranges for the unit. - const auto &CUDIERanges = getCompileUnitDIE()->getAddressRanges(this); - if (!CUDIERanges.empty()) { - CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); - return; - } - - // This function is usually called if there in no .debug_aranges section - // in order to produce a compile unit level set of address ranges that - // is accurate. If the DIEs weren't parsed, then we don't want all dies for - // all compile units to stay loaded when they weren't needed. So we can end - // up parsing the DWARF and then throwing them all away to keep memory usage - // down. - const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; - DieArray[0].collectChildrenAddressRanges(this, CURanges); - - // Collect address ranges from DIEs in .dwo if necessary. - bool DWOCreated = parseDWO(); - if (DWO.get()) - DWO->getUnit()->collectAddressRanges(CURanges); - if (DWOCreated) - DWO.reset(); - - // Keep memory down by clearing DIEs if this generate function - // caused them to be parsed. - if (ClearDIEs) - clearDIEs(true); -} - -const DWARFDebugInfoEntryMinimal * -DWARFUnit::getSubprogramForAddress(uint64_t Address) { - extractDIEsIfNeeded(false); - for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) { - if (DIE.isSubprogramDIE() && - DIE.addressRangeContainsAddress(this, Address)) { - return &DIE; - } - } - return nullptr; -} - -DWARFDebugInfoEntryInlinedChain -DWARFUnit::getInlinedChainForAddress(uint64_t Address) { - // First, find a subprogram that contains the given address (the root - // of inlined chain). - const DWARFUnit *ChainCU = nullptr; - const DWARFDebugInfoEntryMinimal *SubprogramDIE = - getSubprogramForAddress(Address); - if (SubprogramDIE) { - ChainCU = this; - } else { - // Try to look for subprogram DIEs in the DWO file. - parseDWO(); - if (DWO.get()) { - SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); - if (SubprogramDIE) - ChainCU = DWO->getUnit(); - } - } - - // Get inlined chain rooted at this subprogram DIE. - if (!SubprogramDIE) - return DWARFDebugInfoEntryInlinedChain(); - return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); -} |