summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/DebugInfo
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/lib/DebugInfo
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/lib/DebugInfo')
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp76
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h29
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFAttribute.h30
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp258
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h125
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFContext.cpp327
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFContext.h93
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp49
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h5
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp206
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h92
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp311
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h90
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp2
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp74
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h60
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp310
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFTypeUnit.cpp39
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h35
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFUnit.cpp365
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFUnit.h168
21 files changed, 1526 insertions, 1218 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
index 2de62ab..f46fd58 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
@@ -14,37 +14,51 @@
using namespace llvm;
using namespace dwarf;
-bool
-DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr){
- return extract(data, offset_ptr, data.getULEB128(offset_ptr));
+void DWARFAbbreviationDeclaration::clear() {
+ Code = 0;
+ Tag = 0;
+ HasChildren = false;
+ Attributes.clear();
}
-bool
-DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr,
- uint32_t code) {
- Code = code;
- Attribute.clear();
- if (Code) {
- Tag = data.getULEB128(offset_ptr);
- HasChildren = data.getU8(offset_ptr);
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
+ clear();
+}
- while (data.isValidOffset(*offset_ptr)) {
- uint16_t attr = data.getULEB128(offset_ptr);
- uint16_t form = data.getULEB128(offset_ptr);
+bool
+DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint32_t* OffsetPtr) {
+ clear();
+ Code = Data.getULEB128(OffsetPtr);
+ if (Code == 0) {
+ return false;
+ }
+ Tag = Data.getULEB128(OffsetPtr);
+ uint8_t ChildrenByte = Data.getU8(OffsetPtr);
+ HasChildren = (ChildrenByte == DW_CHILDREN_yes);
- if (attr && form)
- Attribute.push_back(DWARFAttribute(attr, form));
- else
- break;
+ while (true) {
+ uint32_t CurOffset = *OffsetPtr;
+ uint16_t Attr = Data.getULEB128(OffsetPtr);
+ if (CurOffset == *OffsetPtr) {
+ clear();
+ return false;
}
-
- return Tag != 0;
- } else {
- Tag = 0;
- HasChildren = false;
+ CurOffset = *OffsetPtr;
+ uint16_t Form = Data.getULEB128(OffsetPtr);
+ if (CurOffset == *OffsetPtr) {
+ clear();
+ return false;
+ }
+ if (Attr == 0 && Form == 0)
+ break;
+ Attributes.push_back(AttributeSpec(Attr, Form));
}
- return false;
+ if (Tag == 0) {
+ clear();
+ return false;
+ }
+ return true;
}
void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
@@ -55,19 +69,19 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
else
OS << format("DW_TAG_Unknown_%x", getTag());
OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
- for (unsigned i = 0, e = Attribute.size(); i != e; ++i) {
+ for (unsigned i = 0, e = Attributes.size(); i != e; ++i) {
OS << '\t';
- const char *attrString = AttributeString(Attribute[i].getAttribute());
+ const char *attrString = AttributeString(Attributes[i].Attr);
if (attrString)
OS << attrString;
else
- OS << format("DW_AT_Unknown_%x", Attribute[i].getAttribute());
+ OS << format("DW_AT_Unknown_%x", Attributes[i].Attr);
OS << '\t';
- const char *formString = FormEncodingString(Attribute[i].getForm());
+ const char *formString = FormEncodingString(Attributes[i].Form);
if (formString)
OS << formString;
else
- OS << format("DW_FORM_Unknown_%x", Attribute[i].getForm());
+ OS << format("DW_FORM_Unknown_%x", Attributes[i].Form);
OS << '\n';
}
OS << '\n';
@@ -75,8 +89,8 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
uint32_t
DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const {
- for (uint32_t i = 0, e = Attribute.size(); i != e; ++i) {
- if (Attribute[i].getAttribute() == attr)
+ for (uint32_t i = 0, e = Attributes.size(); i != e; ++i) {
+ if (Attributes[i].Attr == attr)
return i;
}
return -1U;
diff --git a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h
index 9a3fcd8..e9b072e 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h
@@ -10,7 +10,6 @@
#ifndef LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
#define LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
-#include "DWARFAttribute.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataExtractor.h"
@@ -22,31 +21,33 @@ class DWARFAbbreviationDeclaration {
uint32_t Code;
uint32_t Tag;
bool HasChildren;
- SmallVector<DWARFAttribute, 8> Attribute;
+
+ struct AttributeSpec {
+ AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {}
+ uint16_t Attr;
+ uint16_t Form;
+ };
+ SmallVector<AttributeSpec, 8> Attributes;
public:
- enum { InvalidCode = 0 };
- DWARFAbbreviationDeclaration()
- : Code(InvalidCode), Tag(0), HasChildren(0) {}
+ DWARFAbbreviationDeclaration();
uint32_t getCode() const { return Code; }
uint32_t getTag() const { return Tag; }
bool hasChildren() const { return HasChildren; }
- uint32_t getNumAttributes() const { return Attribute.size(); }
+ uint32_t getNumAttributes() const { return Attributes.size(); }
uint16_t getAttrByIndex(uint32_t idx) const {
- return Attribute.size() > idx ? Attribute[idx].getAttribute() : 0;
+ return idx < Attributes.size() ? Attributes[idx].Attr : 0;
}
uint16_t getFormByIndex(uint32_t idx) const {
- return Attribute.size() > idx ? Attribute[idx].getForm() : 0;
+ return idx < Attributes.size() ? Attributes[idx].Form : 0;
}
uint32_t findAttributeIndex(uint16_t attr) const;
- bool extract(DataExtractor data, uint32_t* offset_ptr);
- bool extract(DataExtractor data, uint32_t* offset_ptr, uint32_t code);
- bool isValid() const { return Code != 0 && Tag != 0; }
+ bool extract(DataExtractor Data, uint32_t* OffsetPtr);
void dump(raw_ostream &OS) const;
- const SmallVectorImpl<DWARFAttribute> &getAttributes() const {
- return Attribute;
- }
+
+private:
+ void clear();
};
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFAttribute.h b/contrib/llvm/lib/DebugInfo/DWARFAttribute.h
deleted file mode 100644
index 6f49b63..0000000
--- a/contrib/llvm/lib/DebugInfo/DWARFAttribute.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===-- DWARFAttribute.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_DWARFATTRIBUTE_H
-#define LLVM_DEBUGINFO_DWARFATTRIBUTE_H
-
-#include "llvm/Support/DataTypes.h"
-
-namespace llvm {
-
-class DWARFAttribute {
- uint16_t Attribute;
- uint16_t Form;
- public:
- DWARFAttribute(uint16_t attr, uint16_t form)
- : Attribute(attr), Form(form) {}
-
- uint16_t getAttribute() const { return Attribute; }
- uint16_t getForm() const { return Form; }
-};
-
-}
-
-#endif
diff --git a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp
index 4f0eed4..33869d8 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp
@@ -8,96 +8,18 @@
//===----------------------------------------------------------------------===//
#include "DWARFCompileUnit.h"
-#include "DWARFContext.h"
-#include "llvm/DebugInfo/DWARFFormValue.h"
-#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-using namespace dwarf;
-
-DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const {
- return DataExtractor(InfoSection, isLittleEndian, AddrSize);
-}
-
-bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
- clear();
-
- Offset = *offset_ptr;
-
- if (debug_info.isValidOffset(*offset_ptr)) {
- uint64_t abbrOffset;
- Length = debug_info.getU32(offset_ptr);
- Version = debug_info.getU16(offset_ptr);
- abbrOffset = debug_info.getU32(offset_ptr);
- AddrSize = debug_info.getU8(offset_ptr);
-
- bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1);
- bool versionOK = DWARFContext::isSupportedVersion(Version);
- bool abbrOffsetOK = AbbrevSection.size() > abbrOffset;
- bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
-
- if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && Abbrev != NULL) {
- Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset);
- return true;
- }
-
- // reset the offset to where we tried to parse from if anything went wrong
- *offset_ptr = Offset;
- }
-
- return false;
-}
-
-uint32_t
-DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data,
- const DWARFAbbreviationDeclarationSet *abbrevs) {
- clear();
- Offset = offset;
-
- if (debug_info_data.isValidOffset(offset)) {
- Length = debug_info_data.getU32(&offset);
- Version = debug_info_data.getU16(&offset);
- bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset();
- Abbrevs = abbrevs;
- AddrSize = debug_info_data.getU8(&offset);
-
- bool versionOK = DWARFContext::isSupportedVersion(Version);
- bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
-
- if (versionOK && addrSizeOK && abbrevsOK &&
- debug_info_data.isValidOffset(offset))
- return offset;
- }
- return 0;
-}
-
-bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset,
- DWARFDebugRangeList &RangeList) const {
- // Require that compile unit is extracted.
- assert(DieArray.size() > 0);
- DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
- return RangeList.extract(RangesData, &RangeListOffset);
-}
-
-void DWARFCompileUnit::clear() {
- Offset = 0;
- Length = 0;
- Version = 0;
- Abbrevs = 0;
- AddrSize = 0;
- BaseAddr = 0;
- clearDIEs(false);
-}
+using namespace llvm;
void DWARFCompileUnit::dump(raw_ostream &OS) {
- OS << format("0x%08x", Offset) << ": Compile Unit:"
- << " length = " << format("0x%08x", Length)
- << " version = " << format("0x%04x", Version)
- << " abbr_offset = " << format("0x%04x", Abbrevs->getOffset())
- << " addr_size = " << format("0x%02x", AddrSize)
- << " (next CU at " << format("0x%08x", getNextCompileUnitOffset())
+ OS << format("0x%08x", getOffset()) << ": Compile Unit:"
+ << " length = " << format("0x%08x", getLength())
+ << " version = " << format("0x%04x", getVersion())
+ << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset())
+ << " addr_size = " << format("0x%02x", getAddressByteSize())
+ << " (next unit at " << format("0x%08x", getNextUnitOffset())
<< ")\n";
const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false);
@@ -105,168 +27,6 @@ void DWARFCompileUnit::dump(raw_ostream &OS) {
CU->dump(OS, this, -1U);
}
-const char *DWARFCompileUnit::getCompilationDir() {
- extractDIEsIfNeeded(true);
- if (DieArray.empty())
- return 0;
- return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
-}
-
-void DWARFCompileUnit::setDIERelations() {
- if (DieArray.empty())
- return;
- DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front();
- DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back();
- DWARFDebugInfoEntryMinimal *curr_die;
- // We purposely are skipping the last element in the array in the loop below
- // so that we can always have a valid next item
- for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) {
- // Since our loop doesn't include the last element, we can always
- // safely access the next die in the array.
- DWARFDebugInfoEntryMinimal *next_die = curr_die + 1;
-
- const DWARFAbbreviationDeclaration *curr_die_abbrev =
- curr_die->getAbbreviationDeclarationPtr();
-
- if (curr_die_abbrev) {
- // Normal DIE
- if (curr_die_abbrev->hasChildren())
- next_die->setParent(curr_die);
- else
- curr_die->setSibling(next_die);
- } else {
- // NULL DIE that terminates a sibling chain
- DWARFDebugInfoEntryMinimal *parent = curr_die->getParent();
- if (parent)
- parent->setSibling(next_die);
- }
- }
-
- // Since we skipped the last element, we need to fix it up!
- if (die_array_begin < die_array_end)
- curr_die->setParent(die_array_begin);
-}
-
-size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
- const size_t initial_die_array_size = DieArray.size();
- if ((cu_die_only && initial_die_array_size > 0) ||
- initial_die_array_size > 1)
- return 0; // Already parsed
-
- // Set the offset to that of the first DIE and calculate the start of the
- // next compilation unit header.
- uint32_t offset = getFirstDIEOffset();
- uint32_t next_cu_offset = getNextCompileUnitOffset();
-
- DWARFDebugInfoEntryMinimal die;
- // Keep a flat array of the DIE for binary lookup by DIE offset
- uint32_t depth = 0;
- // We are in our compile unit, parse starting at the offset
- // we were told to parse
-
- const uint8_t *fixed_form_sizes =
- DWARFFormValue::getFixedFormSizes(getAddressByteSize(), getVersion());
-
- while (offset < next_cu_offset &&
- die.extractFast(this, fixed_form_sizes, &offset)) {
-
- if (depth == 0) {
- uint64_t base_addr =
- die.getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
- if (base_addr == -1U)
- base_addr = die.getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
- setBaseAddress(base_addr);
- }
-
- if (cu_die_only) {
- addDIE(die);
- return 1;
- }
- else if (depth == 0 && initial_die_array_size == 1)
- // Don't append the CU die as we already did that
- ;
- else
- addDIE(die);
-
- const DWARFAbbreviationDeclaration *abbrDecl =
- die.getAbbreviationDeclarationPtr();
- if (abbrDecl) {
- // 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 (offset > next_cu_offset)
- fprintf(stderr, "warning: DWARF compile unit extends beyond its "
- "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset);
-
- setDIERelations();
- return DieArray.size();
-}
-
-void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) {
- if (DieArray.size() > (unsigned)keep_compile_unit_die) {
- // 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 "tmp_array" goes out of scope, it will destroy the
- // contents.
-
- // Save at least the compile unit DIE
- std::vector<DWARFDebugInfoEntryMinimal> tmpArray;
- DieArray.swap(tmpArray);
- if (keep_compile_unit_die)
- DieArray.push_back(tmpArray.front());
- }
-}
-
-void
-DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
- bool clear_dies_if_already_not_parsed){
- // 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 clear_dies = extractDIEsIfNeeded(false) > 1 &&
- clear_dies_if_already_not_parsed;
- DieArray[0].buildAddressRangeTable(this, debug_aranges);
-
- // Keep memory down by clearing DIEs if this generate function
- // caused them to be parsed.
- if (clear_dies)
- clearDIEs(true);
-}
-
-DWARFDebugInfoEntryMinimal::InlinedChain
-DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) {
- // First, find a subprogram that contains the given address (the root
- // of inlined chain).
- extractDIEsIfNeeded(false);
- const DWARFDebugInfoEntryMinimal *SubprogramDIE = 0;
- for (size_t i = 0, n = DieArray.size(); i != n; i++) {
- if (DieArray[i].isSubprogramDIE() &&
- DieArray[i].addressRangeContainsAddress(this, Address)) {
- SubprogramDIE = &DieArray[i];
- break;
- }
- }
- // Get inlined chain rooted at this subprogram DIE.
- if (!SubprogramDIE)
- return DWARFDebugInfoEntryMinimal::InlinedChain();
- return SubprogramDIE->getInlinedChainForAddress(this, Address);
+// VTable anchor.
+DWARFCompileUnit::~DWARFCompileUnit() {
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h
index 2a74605..1c9573b 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h
@@ -10,132 +10,19 @@
#ifndef LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
-#include "DWARFDebugAbbrev.h"
-#include "DWARFDebugInfoEntry.h"
-#include "DWARFDebugRangeList.h"
-#include "DWARFRelocMap.h"
-#include <vector>
+#include "DWARFUnit.h"
namespace llvm {
-class DWARFDebugAbbrev;
-class StringRef;
-class raw_ostream;
-
-class DWARFCompileUnit {
- const DWARFDebugAbbrev *Abbrev;
- StringRef InfoSection;
- StringRef AbbrevSection;
- StringRef RangeSection;
- StringRef StringSection;
- StringRef StringOffsetSection;
- StringRef AddrOffsetSection;
- const RelocAddrMap *RelocMap;
- bool isLittleEndian;
-
- uint32_t Offset;
- uint32_t Length;
- uint16_t Version;
- const DWARFAbbreviationDeclarationSet *Abbrevs;
- uint8_t AddrSize;
- uint64_t BaseAddr;
- // The compile unit debug information entry item.
- std::vector<DWARFDebugInfoEntryMinimal> DieArray;
+class DWARFCompileUnit : public DWARFUnit {
public:
-
DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
- const RelocAddrMap *M, bool LE) :
- Abbrev(DA), InfoSection(IS), AbbrevSection(AS),
- RangeSection(RS), StringSection(SS), StringOffsetSection(SOS),
- AddrOffsetSection(AOS), RelocMap(M), isLittleEndian(LE) {
- clear();
- }
-
- StringRef getStringSection() const { return StringSection; }
- StringRef getStringOffsetSection() const { return StringOffsetSection; }
- StringRef getAddrOffsetSection() const { return AddrOffsetSection; }
- const RelocAddrMap *getRelocMap() const { return RelocMap; }
- DataExtractor getDebugInfoExtractor() const;
-
- bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
- uint32_t extract(uint32_t offset, DataExtractor debug_info_data,
- const DWARFAbbreviationDeclarationSet *abbrevs);
-
- /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
- /// hasn't already been done. Returns the number of DIEs parsed at this call.
- size_t extractDIEsIfNeeded(bool cu_die_only);
- /// extractRangeList - extracts the range list referenced by this compile
- /// unit from .debug_ranges section. Returns true on success.
- /// Requires that compile unit is already extracted.
- bool extractRangeList(uint32_t RangeListOffset,
- DWARFDebugRangeList &RangeList) const;
- void clear();
+ const RelocAddrMap *M, bool LE)
+ : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {}
void dump(raw_ostream &OS);
- uint32_t getOffset() const { return Offset; }
- /// Size in bytes of the compile unit header.
- uint32_t getSize() const { return 11; }
- bool containsDIEOffset(uint32_t die_offset) const {
- return die_offset >= getFirstDIEOffset() &&
- die_offset < getNextCompileUnitOffset();
- }
- uint32_t getFirstDIEOffset() const { return Offset + getSize(); }
- uint32_t getNextCompileUnitOffset() const { return Offset + Length + 4; }
- /// Size in bytes of the .debug_info data associated with this compile unit.
- size_t getDebugInfoSize() const { return Length + 4 - getSize(); }
- uint32_t getLength() const { return Length; }
- uint16_t getVersion() const { return Version; }
- const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
- return Abbrevs;
- }
- uint8_t getAddressByteSize() const { return AddrSize; }
- uint64_t getBaseAddress() const { return BaseAddr; }
-
- void setBaseAddress(uint64_t base_addr) {
- BaseAddr = base_addr;
- }
-
- const DWARFDebugInfoEntryMinimal *
- getCompileUnitDIE(bool extract_cu_die_only = true) {
- extractDIEsIfNeeded(extract_cu_die_only);
- if (DieArray.empty())
- return NULL;
- return &DieArray[0];
- }
-
- const char *getCompilationDir();
-
- /// setDIERelations - We read in all of the DIE entries into our flat list
- /// of DIE entries and now we need to go back through all of them and set the
- /// parent, sibling and child pointers for quick DIE navigation.
- void setDIERelations();
-
- void addDIE(DWARFDebugInfoEntryMinimal &die) {
- // The average bytes per DIE entry has been seen to be
- // around 14-20 so lets pre-reserve the needed memory for
- // our DIE entries accordingly. Search forward for "Compute
- // average bytes per DIE" to see #if'ed out code that does
- // that determination.
-
- // Only reserve the memory if we are adding children of
- // the main compile unit DIE. The compile unit DIE is always
- // the first entry, so if our size is 1, then we are adding
- // the first compile unit child DIE and should reserve
- // the memory.
- if (DieArray.empty())
- DieArray.reserve(getDebugInfoSize() / 14);
- DieArray.push_back(die);
- }
-
- void clearDIEs(bool keep_compile_unit_die);
-
- void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
- bool clear_dies_if_already_not_parsed);
-
- /// getInlinedChainForAddress - fetches inlined chain for a given address.
- /// Returns empty chain if there is no subprogram containing address.
- DWARFDebugInfoEntryMinimal::InlinedChain getInlinedChainForAddress(
- uint64_t Address);
+ // VTable anchor.
+ ~DWARFCompileUnit() LLVM_OVERRIDE;
};
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp
index 9f52133..e477190 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFContext.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp
@@ -19,9 +19,45 @@
#include <algorithm>
using namespace llvm;
using namespace dwarf;
+using namespace object;
typedef DWARFDebugLine::LineTable DWARFLineTable;
+DWARFContext::~DWARFContext() {
+ DeleteContainerPointers(CUs);
+ DeleteContainerPointers(TUs);
+ DeleteContainerPointers(DWOCUs);
+}
+
+static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data,
+ bool LittleEndian, bool GnuStyle) {
+ OS << "\n." << Name << " contents:\n";
+ DataExtractor pubNames(Data, LittleEndian, 0);
+ uint32_t offset = 0;
+ OS << "length = " << format("0x%08x", pubNames.getU32(&offset));
+ OS << " version = " << format("0x%04x", pubNames.getU16(&offset));
+ OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset));
+ OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n';
+ if (GnuStyle)
+ OS << "Offset Linkage Kind Name\n";
+ else
+ OS << "Offset Name\n";
+
+ while (offset < Data.size()) {
+ uint32_t dieRef = pubNames.getU32(&offset);
+ if (dieRef == 0)
+ break;
+ OS << format("0x%8.8x ", dieRef);
+ if (GnuStyle) {
+ PubIndexEntryDescriptor desc(pubNames.getU8(&offset));
+ OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage))
+ << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind))
+ << ' ';
+ }
+ OS << '\"' << pubNames.getCStr(&offset) << "\"\n";
+ }
+}
+
void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
OS << ".debug_abbrev contents:\n";
@@ -34,6 +70,17 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
getCompileUnitAtIndex(i)->dump(OS);
}
+ if (DumpType == DIDT_All || DumpType == DIDT_Types) {
+ OS << "\n.debug_types contents:\n";
+ for (unsigned i = 0, e = getNumTypeUnits(); i != e; ++i)
+ getTypeUnitAtIndex(i)->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
+ OS << "\n.debug_loc contents:\n";
+ getDebugLoc()->dump(OS);
+ }
+
if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
OS << "\n.debug_frame contents:\n";
getDebugFrame()->dump(OS);
@@ -55,13 +102,13 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
savedAddressByteSize = cu->getAddressByteSize();
unsigned stmtOffset =
- cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
- -1U);
+ cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
+ cu, DW_AT_stmt_list, -1U);
if (stmtOffset != -1U) {
- DataExtractor lineData(getLineSection(), isLittleEndian(),
+ DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::DumpingState state(OS);
- DWARFDebugLine::parseStatementTable(lineData, &lineRelocMap(), &stmtOffset, state);
+ DWARFDebugLine::parseStatementTable(lineData, &getLineSection().Relocs, &stmtOffset, state);
}
}
}
@@ -91,23 +138,21 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
rangeList.dump(OS);
}
- if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) {
- OS << "\n.debug_pubnames contents:\n";
- DataExtractor pubNames(getPubNamesSection(), isLittleEndian(), 0);
- offset = 0;
- OS << "Length: " << pubNames.getU32(&offset) << "\n";
- OS << "Version: " << pubNames.getU16(&offset) << "\n";
- OS << "Offset in .debug_info: " << pubNames.getU32(&offset) << "\n";
- OS << "Size: " << pubNames.getU32(&offset) << "\n";
- OS << "\n Offset Name\n";
- while (offset < getPubNamesSection().size()) {
- uint32_t n = pubNames.getU32(&offset);
- if (n == 0)
- break;
- OS << format("%8x ", n);
- OS << pubNames.getCStr(&offset) << "\n";
- }
- }
+ if (DumpType == DIDT_All || DumpType == DIDT_Pubnames)
+ dumpPubSection(OS, "debug_pubnames", getPubNamesSection(),
+ isLittleEndian(), false);
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes)
+ dumpPubSection(OS, "debug_pubtypes", getPubTypesSection(),
+ isLittleEndian(), false);
+
+ if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames)
+ dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(),
+ isLittleEndian(), true /* GnuStyle */);
+
+ if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes)
+ dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(),
+ isLittleEndian(), true /* GnuStyle */);
if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) {
const DWARFDebugAbbrev *D = getDebugAbbrevDWO();
@@ -170,17 +215,23 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
return AbbrevDWO.get();
}
+const DWARFDebugLoc *DWARFContext::getDebugLoc() {
+ if (Loc)
+ return Loc.get();
+
+ DataExtractor LocData(getLocSection().Data, isLittleEndian(), 0);
+ Loc.reset(new DWARFDebugLoc(getLocSection().Relocs));
+ // assume all compile units have the same address byte size
+ if (getNumCompileUnits())
+ Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize());
+ return Loc.get();
+}
+
const DWARFDebugAranges *DWARFContext::getDebugAranges() {
if (Aranges)
return Aranges.get();
- DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
-
Aranges.reset(new DWARFDebugAranges());
- Aranges->extract(arangesData);
- // Generate aranges from DIEs: even if .debug_aranges section is present,
- // it may describe only a small subset of compilation units, so we need to
- // manually build aranges for the rest of them.
Aranges->generate(this);
return Aranges.get();
}
@@ -208,11 +259,11 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() {
const DWARFLineTable *
DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
if (!Line)
- Line.reset(new DWARFDebugLine(&lineRelocMap()));
+ Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
unsigned stmtOffset =
- cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
- -1U);
+ cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
+ cu, DW_AT_stmt_list, -1U);
if (stmtOffset == -1U)
return 0; // No line table for this compile unit.
@@ -221,64 +272,79 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
return lt;
// We have to parse it first.
- DataExtractor lineData(getLineSection(), isLittleEndian(),
+ DataExtractor lineData(getLineSection().Data, isLittleEndian(),
cu->getAddressByteSize());
return Line->getOrParseLineTable(lineData, stmtOffset);
}
void DWARFContext::parseCompileUnits() {
uint32_t offset = 0;
- const DataExtractor &DIData = DataExtractor(getInfoSection(),
+ const DataExtractor &DIData = DataExtractor(getInfoSection().Data,
isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
- CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(),
- getAbbrevSection(), getRangeSection(),
- getStringSection(), StringRef(),
- getAddrSection(),
- &infoRelocMap(),
- isLittleEndian()));
- if (!CUs.back().extract(DIData, &offset)) {
- CUs.pop_back();
+ OwningPtr<DWARFCompileUnit> CU(new DWARFCompileUnit(
+ getDebugAbbrev(), getInfoSection().Data, getAbbrevSection(),
+ getRangeSection(), getStringSection(), StringRef(), getAddrSection(),
+ &getInfoSection().Relocs, isLittleEndian()));
+ if (!CU->extract(DIData, &offset)) {
break;
}
+ CUs.push_back(CU.take());
+ offset = CUs.back()->getNextUnitOffset();
+ }
+}
- offset = CUs.back().getNextCompileUnitOffset();
+void DWARFContext::parseTypeUnits() {
+ const std::map<object::SectionRef, Section> &Sections = getTypesSections();
+ for (std::map<object::SectionRef, Section>::const_iterator
+ I = Sections.begin(),
+ E = Sections.end();
+ I != E; ++I) {
+ uint32_t offset = 0;
+ const DataExtractor &DIData =
+ DataExtractor(I->second.Data, isLittleEndian(), 0);
+ while (DIData.isValidOffset(offset)) {
+ OwningPtr<DWARFTypeUnit> TU(new DWARFTypeUnit(
+ getDebugAbbrev(), I->second.Data, getAbbrevSection(),
+ getRangeSection(), getStringSection(), StringRef(), getAddrSection(),
+ &I->second.Relocs, isLittleEndian()));
+ if (!TU->extract(DIData, &offset))
+ break;
+ TUs.push_back(TU.take());
+ offset = TUs.back()->getNextUnitOffset();
+ }
}
}
void DWARFContext::parseDWOCompileUnits() {
uint32_t offset = 0;
- const DataExtractor &DIData = DataExtractor(getInfoDWOSection(),
- isLittleEndian(), 0);
+ const DataExtractor &DIData =
+ DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
- DWOCUs.push_back(DWARFCompileUnit(getDebugAbbrevDWO(), getInfoDWOSection(),
- getAbbrevDWOSection(),
- getRangeDWOSection(),
- getStringDWOSection(),
- getStringOffsetDWOSection(),
- getAddrSection(),
- &infoDWORelocMap(),
- isLittleEndian()));
- if (!DWOCUs.back().extract(DIData, &offset)) {
- DWOCUs.pop_back();
+ OwningPtr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit(
+ getDebugAbbrevDWO(), getInfoDWOSection().Data, getAbbrevDWOSection(),
+ getRangeDWOSection(), getStringDWOSection(),
+ getStringOffsetDWOSection(), getAddrSection(),
+ &getInfoDWOSection().Relocs, isLittleEndian()));
+ if (!DWOCU->extract(DIData, &offset)) {
break;
}
-
- offset = DWOCUs.back().getNextCompileUnitOffset();
+ DWOCUs.push_back(DWOCU.take());
+ offset = DWOCUs.back()->getNextUnitOffset();
}
}
namespace {
struct OffsetComparator {
- bool operator()(const DWARFCompileUnit &LHS,
- const DWARFCompileUnit &RHS) const {
- return LHS.getOffset() < RHS.getOffset();
+ bool operator()(const DWARFCompileUnit *LHS,
+ const DWARFCompileUnit *RHS) const {
+ return LHS->getOffset() < RHS->getOffset();
}
- bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const {
- return LHS.getOffset() < RHS;
+ bool operator()(const DWARFCompileUnit *LHS, uint32_t RHS) const {
+ return LHS->getOffset() < RHS;
}
- bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const {
- return LHS < RHS.getOffset();
+ bool operator()(uint32_t LHS, const DWARFCompileUnit *RHS) const {
+ return LHS < RHS->getOffset();
}
};
}
@@ -287,10 +353,11 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) {
if (CUs.empty())
parseCompileUnits();
- DWARFCompileUnit *CU = std::lower_bound(CUs.begin(), CUs.end(), Offset,
- OffsetComparator());
- if (CU != CUs.end())
- return &*CU;
+ DWARFCompileUnit **CU =
+ std::lower_bound(CUs.begin(), CUs.end(), Offset, OffsetComparator());
+ if (CU != CUs.end()) {
+ return *CU;
+ }
return 0;
}
@@ -358,11 +425,11 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
// The address may correspond to instruction in some inlined function,
// so we have to build the chain of inlined functions and take the
// name of the topmost function in it.
- const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address);
- if (InlinedChain.size() > 0) {
- const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
- if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
+ if (InlinedChain.DIEs.size() > 0) {
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
+ if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U))
FunctionName = Name;
}
}
@@ -391,23 +458,20 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
// The address may correspond to instruction in some inlined function,
// so we have to build the chain of inlined functions and take the
// name of the topmost function in it.
- const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address);
- if (InlinedChain.size() > 0) {
- const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
- if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
+ if (InlinedChain.DIEs.size() > 0) {
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
+ if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U))
FunctionName = Name;
}
}
- StringRef FuncNameRef = StringRef(FunctionName);
-
// If the Specifier says we don't need FileLineInfo, just
// return the top-most function at the starting address.
if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
- Lines.push_back(std::make_pair(Address,
- DILineInfo(StringRef("<invalid>"),
- FuncNameRef, 0, 0)));
+ Lines.push_back(
+ std::make_pair(Address, DILineInfo("<invalid>", FunctionName, 0, 0)));
return Lines;
}
@@ -428,9 +492,8 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
std::string FileName = "<invalid>";
getFileNameForCompileUnit(CU, LineTable, Row.File,
NeedsAbsoluteFilePath, FileName);
- Lines.push_back(std::make_pair(Row.Address,
- DILineInfo(StringRef(FileName),
- FuncNameRef, Row.Line, Row.Column)));
+ Lines.push_back(std::make_pair(
+ Row.Address, DILineInfo(FileName, FunctionName, Row.Line, Row.Column)));
}
return Lines;
@@ -442,23 +505,23 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
if (!CU)
return DIInliningInfo();
- const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address);
- if (InlinedChain.size() == 0)
+ if (InlinedChain.DIEs.size() == 0)
return DIInliningInfo();
DIInliningInfo InliningInfo;
uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
const DWARFLineTable *LineTable = 0;
- for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
- const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i];
+ for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) {
+ const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i];
std::string FileName = "<invalid>";
std::string FunctionName = "<invalid>";
uint32_t Line = 0;
uint32_t Column = 0;
// Get function name if necessary.
if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
- if (const char *Name = FunctionDIE.getSubroutineName(CU))
+ if (const char *Name = FunctionDIE.getSubroutineName(InlinedChain.U))
FunctionName = Name;
}
if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
@@ -482,7 +545,8 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
}
// Get call file/line/column of a current DIE.
if (i + 1 < n) {
- FunctionDIE.getCallerFrame(CU, CallFile, CallLine, CallColumn);
+ FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine,
+ CallColumn);
}
}
DILineInfo Frame(StringRef(FileName), StringRef(FunctionName),
@@ -538,43 +602,67 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
UncompressedSections.push_back(UncompressedSection.take());
}
- StringRef *Section = StringSwitch<StringRef*>(name)
- .Case("debug_info", &InfoSection)
- .Case("debug_abbrev", &AbbrevSection)
- .Case("debug_line", &LineSection)
- .Case("debug_aranges", &ARangeSection)
- .Case("debug_frame", &DebugFrameSection)
- .Case("debug_str", &StringSection)
- .Case("debug_ranges", &RangeSection)
- .Case("debug_pubnames", &PubNamesSection)
- .Case("debug_info.dwo", &InfoDWOSection)
- .Case("debug_abbrev.dwo", &AbbrevDWOSection)
- .Case("debug_str.dwo", &StringDWOSection)
- .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
- .Case("debug_addr", &AddrSection)
- // Any more debug info sections go here.
- .Default(0);
- if (!Section)
- continue;
- *Section = data;
- if (name == "debug_ranges") {
- // FIXME: Use the other dwo range section when we emit it.
- RangeDWOSection = data;
+ StringRef *Section =
+ StringSwitch<StringRef *>(name)
+ .Case("debug_info", &InfoSection.Data)
+ .Case("debug_abbrev", &AbbrevSection)
+ .Case("debug_loc", &LocSection.Data)
+ .Case("debug_line", &LineSection.Data)
+ .Case("debug_aranges", &ARangeSection)
+ .Case("debug_frame", &DebugFrameSection)
+ .Case("debug_str", &StringSection)
+ .Case("debug_ranges", &RangeSection)
+ .Case("debug_pubnames", &PubNamesSection)
+ .Case("debug_pubtypes", &PubTypesSection)
+ .Case("debug_gnu_pubnames", &GnuPubNamesSection)
+ .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
+ .Case("debug_info.dwo", &InfoDWOSection.Data)
+ .Case("debug_abbrev.dwo", &AbbrevDWOSection)
+ .Case("debug_str.dwo", &StringDWOSection)
+ .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
+ .Case("debug_addr", &AddrSection)
+ // Any more debug info sections go here.
+ .Default(0);
+ if (Section) {
+ *Section = data;
+ if (name == "debug_ranges") {
+ // FIXME: Use the other dwo range section when we emit it.
+ RangeDWOSection = data;
+ }
+ } else if (name == "debug_types") {
+ // Find debug_types data by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ TypesSections[*i].Data = data;
}
+ section_iterator RelocatedSection = i->getRelocatedSection();
+ if (RelocatedSection == Obj->end_sections())
+ continue;
+
+ StringRef RelSecName;
+ RelocatedSection->getName(RelSecName);
+ RelSecName = RelSecName.substr(
+ RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
+
// TODO: Add support for relocations in other sections as needed.
// Record relocations for the debug_info and debug_line sections.
- RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(name)
- .Case("debug_info", &InfoRelocMap)
- .Case("debug_info.dwo", &InfoDWORelocMap)
- .Case("debug_line", &LineRelocMap)
+ RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
+ .Case("debug_info", &InfoSection.Relocs)
+ .Case("debug_loc", &LocSection.Relocs)
+ .Case("debug_info.dwo", &InfoDWOSection.Relocs)
+ .Case("debug_line", &LineSection.Relocs)
.Default(0);
- if (!Map)
- continue;
+ if (!Map) {
+ if (RelSecName != "debug_types")
+ continue;
+ // Find debug_types relocs by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ Map = &TypesSections[*RelocatedSection].Relocs;
+ }
if (i->begin_relocations() != i->end_relocations()) {
uint64_t SectionSize;
- i->getSize(SectionSize);
+ RelocatedSection->getSize(SectionSize);
for (object::relocation_iterator reloc_i = i->begin_relocations(),
reloc_e = i->end_relocations();
reloc_i != reloc_e; reloc_i.increment(ec)) {
@@ -585,9 +673,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
uint64_t SymAddr = 0;
// ELF relocations may need the symbol address
if (Obj->isELF()) {
- object::SymbolRef Sym;
- reloc_i->getSymbol(Sym);
- Sym.getAddress(SymAddr);
+ object::symbol_iterator Sym = reloc_i->getSymbol();
+ Sym->getAddress(SymAddr);
}
object::RelocVisitor V(Obj->getFileFormatName());
diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.h b/contrib/llvm/lib/DebugInfo/DWARFContext.h
index 78c18e6..03863ab 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFContext.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFContext.h
@@ -14,7 +14,9 @@
#include "DWARFDebugAranges.h"
#include "DWARFDebugFrame.h"
#include "DWARFDebugLine.h"
+#include "DWARFDebugLoc.h"
#include "DWARFDebugRangeList.h"
+#include "DWARFTypeUnit.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DIContext.h"
@@ -26,13 +28,15 @@ namespace llvm {
/// information parsing. The actual data is supplied through pure virtual
/// methods that a concrete implementation provides.
class DWARFContext : public DIContext {
- SmallVector<DWARFCompileUnit, 1> CUs;
+ SmallVector<DWARFCompileUnit *, 1> CUs;
+ SmallVector<DWARFTypeUnit *, 1> TUs;
OwningPtr<DWARFDebugAbbrev> Abbrev;
+ OwningPtr<DWARFDebugLoc> Loc;
OwningPtr<DWARFDebugAranges> Aranges;
OwningPtr<DWARFDebugLine> Line;
OwningPtr<DWARFDebugFrame> DebugFrame;
- SmallVector<DWARFCompileUnit, 1> DWOCUs;
+ SmallVector<DWARFCompileUnit *, 1> DWOCUs;
OwningPtr<DWARFDebugAbbrev> AbbrevDWO;
DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION;
@@ -41,12 +45,26 @@ class DWARFContext : public DIContext {
/// Read compile units from the debug_info section and store them in CUs.
void parseCompileUnits();
+ /// Read type units from the debug_types sections and store them in CUs.
+ void parseTypeUnits();
+
/// Read compile units from the debug_info.dwo section and store them in
/// DWOCUs.
void parseDWOCompileUnits();
public:
- DWARFContext() {}
+ struct Section {
+ StringRef Data;
+ RelocAddrMap Relocs;
+ };
+
+ DWARFContext() : DIContext(CK_DWARF) {}
+ virtual ~DWARFContext();
+
+ static bool classof(const DIContext *DICtx) {
+ return DICtx->getKind() == CK_DWARF;
+ }
+
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All);
/// Get the number of compile units in this context.
@@ -56,6 +74,13 @@ public:
return CUs.size();
}
+ /// Get the number of compile units in this context.
+ unsigned getNumTypeUnits() {
+ if (TUs.empty())
+ parseTypeUnits();
+ return TUs.size();
+ }
+
/// Get the number of compile units in the DWO context.
unsigned getNumDWOCompileUnits() {
if (DWOCUs.empty())
@@ -67,19 +92,29 @@ public:
DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) {
if (CUs.empty())
parseCompileUnits();
- return &CUs[index];
+ return CUs[index];
+ }
+
+ /// Get the type unit at the specified index for this compile unit.
+ DWARFTypeUnit *getTypeUnitAtIndex(unsigned index) {
+ if (TUs.empty())
+ parseTypeUnits();
+ return TUs[index];
}
/// Get the compile unit at the specified index for the DWO compile units.
DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) {
if (DWOCUs.empty())
parseDWOCompileUnits();
- return &DWOCUs[index];
+ return DWOCUs[index];
}
/// Get a pointer to the parsed DebugAbbrev object.
const DWARFDebugAbbrev *getDebugAbbrev();
+ /// Get a pointer to the parsed DebugLoc object.
+ const DWARFDebugLoc *getDebugLoc();
+
/// Get a pointer to the parsed dwo abbreviations object.
const DWARFDebugAbbrev *getDebugAbbrevDWO();
@@ -102,28 +137,30 @@ public:
virtual bool isLittleEndian() const = 0;
virtual uint8_t getAddressSize() const = 0;
- virtual const RelocAddrMap &infoRelocMap() const = 0;
- virtual const RelocAddrMap &lineRelocMap() const = 0;
- virtual StringRef getInfoSection() = 0;
+ virtual const Section &getInfoSection() = 0;
+ virtual const std::map<object::SectionRef, Section> &getTypesSections() = 0;
virtual StringRef getAbbrevSection() = 0;
+ virtual const Section &getLocSection() = 0;
virtual StringRef getARangeSection() = 0;
virtual StringRef getDebugFrameSection() = 0;
- virtual StringRef getLineSection() = 0;
+ virtual const Section &getLineSection() = 0;
virtual StringRef getStringSection() = 0;
virtual StringRef getRangeSection() = 0;
virtual StringRef getPubNamesSection() = 0;
+ virtual StringRef getPubTypesSection() = 0;
+ virtual StringRef getGnuPubNamesSection() = 0;
+ virtual StringRef getGnuPubTypesSection() = 0;
// Sections for DWARF5 split dwarf proposal.
- virtual StringRef getInfoDWOSection() = 0;
+ virtual const Section &getInfoDWOSection() = 0;
virtual StringRef getAbbrevDWOSection() = 0;
virtual StringRef getStringDWOSection() = 0;
virtual StringRef getStringOffsetDWOSection() = 0;
virtual StringRef getRangeDWOSection() = 0;
virtual StringRef getAddrSection() = 0;
- virtual const RelocAddrMap &infoDWORelocMap() const = 0;
static bool isSupportedVersion(unsigned version) {
- return version == 2 || version == 3;
+ return version == 2 || version == 3 || version == 4;
}
private:
/// Return the compile unit that includes an offset (relative to .debug_info).
@@ -141,20 +178,22 @@ class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
bool IsLittleEndian;
uint8_t AddressSize;
- RelocAddrMap InfoRelocMap;
- RelocAddrMap LineRelocMap;
- StringRef InfoSection;
+ Section InfoSection;
+ std::map<object::SectionRef, Section> TypesSections;
StringRef AbbrevSection;
+ Section LocSection;
StringRef ARangeSection;
StringRef DebugFrameSection;
- StringRef LineSection;
+ Section LineSection;
StringRef StringSection;
StringRef RangeSection;
StringRef PubNamesSection;
+ StringRef PubTypesSection;
+ StringRef GnuPubNamesSection;
+ StringRef GnuPubTypesSection;
// Sections for DWARF5 split dwarf proposal.
- RelocAddrMap InfoDWORelocMap;
- StringRef InfoDWOSection;
+ Section InfoDWOSection;
StringRef AbbrevDWOSection;
StringRef StringDWOSection;
StringRef StringOffsetDWOSection;
@@ -168,19 +207,24 @@ public:
~DWARFContextInMemory();
virtual bool isLittleEndian() const { return IsLittleEndian; }
virtual uint8_t getAddressSize() const { return AddressSize; }
- virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; }
- virtual const RelocAddrMap &lineRelocMap() const { return LineRelocMap; }
- virtual StringRef getInfoSection() { return InfoSection; }
+ virtual const Section &getInfoSection() { return InfoSection; }
+ virtual const std::map<object::SectionRef, Section> &getTypesSections() {
+ return TypesSections;
+ }
virtual StringRef getAbbrevSection() { return AbbrevSection; }
+ virtual const Section &getLocSection() { return LocSection; }
virtual StringRef getARangeSection() { return ARangeSection; }
virtual StringRef getDebugFrameSection() { return DebugFrameSection; }
- virtual StringRef getLineSection() { return LineSection; }
+ virtual const Section &getLineSection() { return LineSection; }
virtual StringRef getStringSection() { return StringSection; }
virtual StringRef getRangeSection() { return RangeSection; }
virtual StringRef getPubNamesSection() { return PubNamesSection; }
+ virtual StringRef getPubTypesSection() { return PubTypesSection; }
+ virtual StringRef getGnuPubNamesSection() { return GnuPubNamesSection; }
+ virtual StringRef getGnuPubTypesSection() { return GnuPubTypesSection; }
// Sections for DWARF5 split dwarf proposal.
- virtual StringRef getInfoDWOSection() { return InfoDWOSection; }
+ virtual const Section &getInfoDWOSection() { return InfoDWOSection; }
virtual StringRef getAbbrevDWOSection() { return AbbrevDWOSection; }
virtual StringRef getStringDWOSection() { return StringDWOSection; }
virtual StringRef getStringOffsetDWOSection() {
@@ -190,9 +234,6 @@ public:
virtual StringRef getAddrSection() {
return AddrSection;
}
- virtual const RelocAddrMap &infoDWORelocMap() const {
- return InfoDWORelocMap;
- }
};
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp
index 7dff9ff..229376e 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp
@@ -20,32 +20,6 @@ void DWARFDebugArangeSet::clear() {
ArangeDescriptors.clear();
}
-void DWARFDebugArangeSet::compact() {
- if (ArangeDescriptors.empty())
- return;
-
- // Iterate through all arange descriptors and combine any ranges that
- // overlap or have matching boundaries. The ArangeDescriptors are assumed
- // to be in ascending order.
- uint32_t i = 0;
- while (i + 1 < ArangeDescriptors.size()) {
- if (ArangeDescriptors[i].getEndAddress() >= ArangeDescriptors[i+1].Address){
- // The current range ends at or exceeds the start of the next address
- // range. Compute the max end address between the two and use that to
- // make the new length.
- const uint64_t max_end_addr =
- std::max(ArangeDescriptors[i].getEndAddress(),
- ArangeDescriptors[i+1].getEndAddress());
- ArangeDescriptors[i].Length = max_end_addr - ArangeDescriptors[i].Address;
- // Now remove the next entry as it was just combined with the previous one
- ArangeDescriptors.erase(ArangeDescriptors.begin()+i+1);
- } else {
- // Discontiguous address range, just proceed to the next one.
- ++i;
- }
- }
-}
-
bool
DWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) {
if (data.isValidOffset(*offset_ptr)) {
@@ -126,26 +100,3 @@ void DWARFDebugArangeSet::dump(raw_ostream &OS) const {
<< format(" 0x%*.*" PRIx64 ")\n",
hex_width, hex_width, pos->getEndAddress());
}
-
-
-namespace {
- class DescriptorContainsAddress {
- const uint64_t Address;
- public:
- DescriptorContainsAddress(uint64_t address) : Address(address) {}
- bool operator()(const DWARFDebugArangeSet::Descriptor &desc) const {
- return Address >= desc.Address && Address < (desc.Address + desc.Length);
- }
- };
-}
-
-uint32_t DWARFDebugArangeSet::findAddress(uint64_t address) const {
- DescriptorConstIter end = ArangeDescriptors.end();
- DescriptorConstIter pos =
- std::find_if(ArangeDescriptors.begin(), end, // Range
- DescriptorContainsAddress(address)); // Predicate
- if (pos != end)
- return HeaderData.CuOffset;
-
- return -1U;
-}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h
index d768676..49a7132 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h
@@ -44,7 +44,6 @@ public:
private:
typedef std::vector<Descriptor> DescriptorColl;
- typedef DescriptorColl::iterator DescriptorIter;
typedef DescriptorColl::const_iterator DescriptorConstIter;
uint32_t Offset;
@@ -54,15 +53,11 @@ private:
public:
DWARFDebugArangeSet() { clear(); }
void clear();
- void compact();
bool extract(DataExtractor data, uint32_t *offset_ptr);
void dump(raw_ostream &OS) const;
uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; }
- uint32_t getOffsetOfNextEntry() const { return Offset + HeaderData.Length + 4; }
- uint32_t findAddress(uint64_t address) const;
uint32_t getNumDescriptors() const { return ArangeDescriptors.size(); }
- const struct Header &getHeader() const { return HeaderData; }
const Descriptor *getDescriptor(uint32_t i) const {
if (i < ArangeDescriptors.size())
return &ArangeDescriptors[i];
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp
index f79862d..591d4bd 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp
@@ -16,128 +16,79 @@
#include <cassert>
using namespace llvm;
-// Compare function DWARFDebugAranges::Range structures
-static bool RangeLessThan(const DWARFDebugAranges::Range &range1,
- const DWARFDebugAranges::Range &range2) {
- return range1.LoPC < range2.LoPC;
-}
-
-namespace {
- class CountArangeDescriptors {
- public:
- CountArangeDescriptors(uint32_t &count_ref) : Count(count_ref) {}
- void operator()(const DWARFDebugArangeSet &Set) {
- Count += Set.getNumDescriptors();
- }
- uint32_t &Count;
- };
-
- class AddArangeDescriptors {
- public:
- AddArangeDescriptors(DWARFDebugAranges::RangeColl &Ranges,
- DWARFDebugAranges::ParsedCUOffsetColl &CUOffsets)
- : RangeCollection(Ranges),
- CUOffsetCollection(CUOffsets) {}
- void operator()(const DWARFDebugArangeSet &Set) {
- DWARFDebugAranges::Range Range;
- Range.Offset = Set.getCompileUnitDIEOffset();
- CUOffsetCollection.insert(Range.Offset);
-
- for (uint32_t i = 0, n = Set.getNumDescriptors(); i < n; ++i) {
- const DWARFDebugArangeSet::Descriptor *ArangeDescPtr =
- Set.getDescriptor(i);
- Range.LoPC = ArangeDescPtr->Address;
- Range.Length = ArangeDescPtr->Length;
-
- // Insert each item in increasing address order so binary searching
- // can later be done!
- DWARFDebugAranges::RangeColl::iterator InsertPos =
- std::lower_bound(RangeCollection.begin(), RangeCollection.end(),
- Range, RangeLessThan);
- RangeCollection.insert(InsertPos, Range);
- }
-
- }
- DWARFDebugAranges::RangeColl &RangeCollection;
- DWARFDebugAranges::ParsedCUOffsetColl &CUOffsetCollection;
- };
-}
-
-bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) {
- if (debug_aranges_data.isValidOffset(0)) {
- uint32_t offset = 0;
-
- typedef std::vector<DWARFDebugArangeSet> SetCollection;
- SetCollection sets;
-
- DWARFDebugArangeSet set;
- Range range;
- while (set.extract(debug_aranges_data, &offset))
- sets.push_back(set);
-
- uint32_t count = 0;
-
- std::for_each(sets.begin(), sets.end(), CountArangeDescriptors(count));
-
- if (count > 0) {
- Aranges.reserve(count);
- AddArangeDescriptors range_adder(Aranges, ParsedCUOffsets);
- std::for_each(sets.begin(), sets.end(), range_adder);
- }
+void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
+ if (!DebugArangesData.isValidOffset(0))
+ return;
+ uint32_t Offset = 0;
+ typedef std::vector<DWARFDebugArangeSet> RangeSetColl;
+ RangeSetColl Sets;
+ DWARFDebugArangeSet Set;
+ uint32_t TotalRanges = 0;
+
+ while (Set.extract(DebugArangesData, &Offset)) {
+ Sets.push_back(Set);
+ TotalRanges += Set.getNumDescriptors();
}
- return false;
-}
+ if (TotalRanges == 0)
+ return;
-bool DWARFDebugAranges::generate(DWARFContext *ctx) {
- if (ctx) {
- const uint32_t num_compile_units = ctx->getNumCompileUnits();
- for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- if (DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx)) {
- uint32_t CUOffset = cu->getOffset();
- if (ParsedCUOffsets.insert(CUOffset).second)
- cu->buildAddressRangeTable(this, true);
- }
+ Aranges.reserve(TotalRanges);
+ for (RangeSetColl::const_iterator I = Sets.begin(), E = Sets.end(); I != E;
+ ++I) {
+ uint32_t CUOffset = I->getCompileUnitDIEOffset();
+
+ for (uint32_t i = 0, n = I->getNumDescriptors(); i < n; ++i) {
+ const DWARFDebugArangeSet::Descriptor *ArangeDescPtr =
+ I->getDescriptor(i);
+ uint64_t LowPC = ArangeDescPtr->Address;
+ uint64_t HighPC = LowPC + ArangeDescPtr->Length;
+ appendRange(CUOffset, LowPC, HighPC);
}
}
- sort(true, /* overlap size */ 0);
- return !isEmpty();
}
-void DWARFDebugAranges::dump(raw_ostream &OS) const {
- const uint32_t num_ranges = getNumRanges();
- for (uint32_t i = 0; i < num_ranges; ++i) {
- const Range &range = Aranges[i];
- OS << format("0x%8.8x: [0x%8.8" PRIx64 " - 0x%8.8" PRIx64 ")\n",
- range.Offset, (uint64_t)range.LoPC, (uint64_t)range.HiPC());
+void DWARFDebugAranges::generate(DWARFContext *CTX) {
+ clear();
+ if (!CTX)
+ return;
+
+ // Extract aranges from .debug_aranges section.
+ DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
+ extract(ArangesData);
+
+ // Generate aranges from DIEs: even if .debug_aranges section is present,
+ // it may describe only a small subset of compilation units, so we need to
+ // manually build aranges for the rest of them.
+ for (uint32_t i = 0, n = CTX->getNumCompileUnits(); i < n; ++i) {
+ if (DWARFCompileUnit *CU = CTX->getCompileUnitAtIndex(i)) {
+ uint32_t CUOffset = CU->getOffset();
+ if (ParsedCUOffsets.insert(CUOffset).second)
+ CU->buildAddressRangeTable(this, true, CUOffset);
+ }
}
-}
-void DWARFDebugAranges::Range::dump(raw_ostream &OS) const {
- OS << format("{0x%8.8x}: [0x%8.8" PRIx64 " - 0x%8.8" PRIx64 ")\n",
- Offset, LoPC, HiPC());
+ sortAndMinimize();
}
-void DWARFDebugAranges::appendRange(uint32_t offset, uint64_t low_pc,
- uint64_t high_pc) {
+void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
+ uint64_t HighPC) {
if (!Aranges.empty()) {
- if (Aranges.back().Offset == offset && Aranges.back().HiPC() == low_pc) {
- Aranges.back().setHiPC(high_pc);
+ if (Aranges.back().CUOffset == CUOffset &&
+ Aranges.back().HighPC() == LowPC) {
+ Aranges.back().setHighPC(HighPC);
return;
}
}
- Aranges.push_back(Range(low_pc, high_pc, offset));
+ Aranges.push_back(Range(LowPC, HighPC, CUOffset));
}
-void DWARFDebugAranges::sort(bool minimize, uint32_t n) {
+void DWARFDebugAranges::sortAndMinimize() {
const size_t orig_arange_size = Aranges.size();
// Size of one? If so, no sorting is needed
if (orig_arange_size <= 1)
return;
// Sort our address range entries
- std::stable_sort(Aranges.begin(), Aranges.end(), RangeLessThan);
-
- if (!minimize)
- return;
+ std::stable_sort(Aranges.begin(), Aranges.end());
// Most address ranges are contiguous from function to function
// so our new ranges will likely be smaller. We calculate the size
@@ -151,7 +102,7 @@ void DWARFDebugAranges::sort(bool minimize, uint32_t n) {
// copy the new minimal stuff over to the new collection.
size_t minimal_size = 1;
for (size_t i = 1; i < orig_arange_size; ++i) {
- if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i], n))
+ if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i]))
++minimal_size;
}
@@ -166,14 +117,14 @@ void DWARFDebugAranges::sort(bool minimize, uint32_t n) {
uint32_t j = 0;
minimal_aranges[j] = Aranges[0];
for (size_t i = 1; i < orig_arange_size; ++i) {
- if(Range::SortedOverlapCheck (minimal_aranges[j], Aranges[i], n)) {
- minimal_aranges[j].setHiPC (Aranges[i].HiPC());
+ if (Range::SortedOverlapCheck(minimal_aranges[j], Aranges[i])) {
+ minimal_aranges[j].setHighPC(Aranges[i].HighPC());
} else {
// Only increment j if we aren't merging
minimal_aranges[++j] = Aranges[i];
}
}
- assert (j+1 == minimal_size);
+ assert(j+1 == minimal_size);
// Now swap our new minimal aranges into place. The local
// minimal_aranges will then contian the old big collection
@@ -181,50 +132,21 @@ void DWARFDebugAranges::sort(bool minimize, uint32_t n) {
minimal_aranges.swap(Aranges);
}
-uint32_t DWARFDebugAranges::findAddress(uint64_t address) const {
+uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
if (!Aranges.empty()) {
- Range range(address);
+ Range range(Address);
RangeCollIterator begin = Aranges.begin();
RangeCollIterator end = Aranges.end();
- RangeCollIterator pos = std::lower_bound(begin, end, range, RangeLessThan);
+ RangeCollIterator pos =
+ std::lower_bound(begin, end, range);
- if (pos != end && pos->LoPC <= address && address < pos->HiPC()) {
- return pos->Offset;
+ if (pos != end && pos->containsAddress(Address)) {
+ return pos->CUOffset;
} else if (pos != begin) {
--pos;
- if (pos->LoPC <= address && address < pos->HiPC())
- return (*pos).Offset;
+ if (pos->containsAddress(Address))
+ return pos->CUOffset;
}
}
return -1U;
}
-
-bool
-DWARFDebugAranges::allRangesAreContiguous(uint64_t &LoPC, uint64_t &HiPC) const{
- if (Aranges.empty())
- return false;
-
- uint64_t next_addr = 0;
- RangeCollIterator begin = Aranges.begin();
- for (RangeCollIterator pos = begin, end = Aranges.end(); pos != end;
- ++pos) {
- if (pos != begin && pos->LoPC != next_addr)
- return false;
- next_addr = pos->HiPC();
- }
- // We checked for empty at the start of function so front() will be valid.
- LoPC = Aranges.front().LoPC;
- // We checked for empty at the start of function so back() will be valid.
- HiPC = Aranges.back().HiPC();
- return true;
-}
-
-bool DWARFDebugAranges::getMaxRange(uint64_t &LoPC, uint64_t &HiPC) const {
- if (Aranges.empty())
- return false;
- // We checked for empty at the start of function so front() will be valid.
- LoPC = Aranges.front().LoPC;
- // We checked for empty at the start of function so back() will be valid.
- HiPC = Aranges.back().HiPC();
- return true;
-}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h
index 1509ffa..35ad8e5 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h
@@ -20,81 +20,61 @@ class DWARFContext;
class DWARFDebugAranges {
public:
+ void clear() {
+ Aranges.clear();
+ ParsedCUOffsets.clear();
+ }
+
+ void generate(DWARFContext *CTX);
+
+ // Use appendRange multiple times and then call sortAndMinimize.
+ void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC);
+
+ uint32_t findAddress(uint64_t Address) const;
+
+private:
+ void extract(DataExtractor DebugArangesData);
+ void sortAndMinimize();
+
struct Range {
- explicit Range(uint64_t lo = -1ULL, uint64_t hi = -1ULL,
- uint32_t off = -1U)
- : LoPC(lo), Length(hi-lo), Offset(off) {}
-
- void clear() {
- LoPC = -1ULL;
- Length = 0;
- Offset = -1U;
- }
+ explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL,
+ uint32_t CUOffset = -1U)
+ : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {}
- void setHiPC(uint64_t HiPC) {
- if (HiPC == -1ULL || HiPC <= LoPC)
+ void setHighPC(uint64_t HighPC) {
+ if (HighPC == -1ULL || HighPC <= LowPC)
Length = 0;
else
- Length = HiPC - LoPC;
+ Length = HighPC - LowPC;
}
- uint64_t HiPC() const {
+ uint64_t HighPC() const {
if (Length)
- return LoPC + Length;
+ return LowPC + Length;
return -1ULL;
}
- bool isValidRange() const { return Length > 0; }
+ bool containsAddress(uint64_t Address) const {
+ return LowPC <= Address && Address < HighPC();
+ }
- static bool SortedOverlapCheck(const Range &curr_range,
- const Range &next_range, uint32_t n) {
- if (curr_range.Offset != next_range.Offset)
- return false;
- return curr_range.HiPC() + n >= next_range.LoPC;
+ bool operator <(const Range &other) const {
+ return LowPC < other.LowPC;
}
- bool contains(const Range &range) const {
- return LoPC <= range.LoPC && range.HiPC() <= HiPC();
+ static bool SortedOverlapCheck(const Range &Left, const Range &Right) {
+ if (Left.CUOffset != Right.CUOffset)
+ return false;
+ return Left.HighPC() >= Right.LowPC;
}
- void dump(raw_ostream &OS) const;
- uint64_t LoPC; // Start of address range
- uint32_t Length; // End of address range (not including this address)
- uint32_t Offset; // Offset of the compile unit or die
+ uint64_t LowPC; // Start of address range.
+ uint32_t Length; // End of address range (not including this address).
+ uint32_t CUOffset; // Offset of the compile unit or die.
};
- void clear() {
- Aranges.clear();
- ParsedCUOffsets.clear();
- }
- bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const;
- bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const;
- bool extract(DataExtractor debug_aranges_data);
- bool generate(DWARFContext *ctx);
-
- // Use append range multiple times and then call sort
- void appendRange(uint32_t cu_offset, uint64_t low_pc, uint64_t high_pc);
- void sort(bool minimize, uint32_t n);
-
- const Range *rangeAtIndex(uint32_t idx) const {
- if (idx < Aranges.size())
- return &Aranges[idx];
- return NULL;
- }
- void dump(raw_ostream &OS) const;
- uint32_t findAddress(uint64_t address) const;
- bool isEmpty() const { return Aranges.empty(); }
- uint32_t getNumRanges() const { return Aranges.size(); }
-
- uint32_t offsetAtIndex(uint32_t idx) const {
- if (idx < Aranges.size())
- return Aranges[idx].Offset;
- return -1U;
- }
-
typedef std::vector<Range> RangeColl;
typedef RangeColl::const_iterator RangeCollIterator;
typedef DenseSet<uint32_t> ParsedCUOffsetColl;
-private:
RangeColl Aranges;
ParsedCUOffsetColl ParsedCUOffsets;
};
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp
index 10be7b4..babfd2e 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp
@@ -19,11 +19,10 @@
using namespace llvm;
using namespace dwarf;
-void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
- const DWARFCompileUnit *cu,
+void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u,
unsigned recurseDepth,
unsigned indent) const {
- DataExtractor debug_info_data = cu->getDebugInfoExtractor();
+ DataExtractor debug_info_data = u->getDebugInfoExtractor();
uint32_t offset = Offset;
if (debug_info_data.isValidOffset(offset)) {
@@ -45,13 +44,13 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
for (uint32_t i = 0; i != numAttributes; ++i) {
uint16_t attr = AbbrevDecl->getAttrByIndex(i);
uint16_t form = AbbrevDecl->getFormByIndex(i);
- dumpAttribute(OS, cu, &offset, attr, form, indent);
+ dumpAttribute(OS, u, &offset, attr, form, indent);
}
const DWARFDebugInfoEntryMinimal *child = getFirstChild();
if (recurseDepth > 0 && child) {
while (child) {
- child->dump(OS, cu, recurseDepth-1, indent+2);
+ child->dump(OS, u, recurseDepth-1, indent+2);
child = child->getSibling();
}
}
@@ -66,12 +65,11 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
}
void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
- const DWARFCompileUnit *cu,
- uint32_t* offset_ptr,
- uint16_t attr,
- uint16_t form,
+ const DWARFUnit *u,
+ uint32_t *offset_ptr,
+ uint16_t attr, uint16_t form,
unsigned indent) const {
- OS << format("0x%8.8x: ", *offset_ptr);
+ OS << " ";
OS.indent(indent+2);
const char *attrString = AttributeString(attr);
if (attrString)
@@ -86,57 +84,20 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
DWARFFormValue formValue(form);
- if (!formValue.extractValue(cu->getDebugInfoExtractor(), offset_ptr, cu))
+ if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u))
return;
OS << "\t(";
- formValue.dump(OS, cu);
+ formValue.dump(OS, u);
OS << ")\n";
}
-bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *CU,
- const uint8_t *FixedFormSizes,
+bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U,
uint32_t *OffsetPtr) {
Offset = *OffsetPtr;
- DataExtractor DebugInfoData = CU->getDebugInfoExtractor();
- uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
- if (0 == AbbrCode) {
- // NULL debug tag entry.
- AbbrevDecl = NULL;
- return true;
- }
- AbbrevDecl = CU->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
- assert(AbbrevDecl);
- assert(FixedFormSizes); // For best performance this should be specified!
-
- // Skip all data in the .debug_info for the attributes
- for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) {
- uint16_t Form = AbbrevDecl->getFormByIndex(i);
-
- // FIXME: Currently we're checking if this is less than the last
- // entry in the fixed_form_sizes table, but this should be changed
- // to use dynamic dispatch.
- uint8_t FixedFormSize =
- (Form < DW_FORM_ref_sig8) ? FixedFormSizes[Form] : 0;
- if (FixedFormSize)
- *OffsetPtr += FixedFormSize;
- else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr,
- CU)) {
- // Restore the original offset.
- *OffsetPtr = Offset;
- return false;
- }
- }
- return true;
-}
-
-bool
-DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *CU,
- uint32_t *OffsetPtr) {
- DataExtractor DebugInfoData = CU->getDebugInfoExtractor();
- const uint32_t CUEndOffset = CU->getNextCompileUnitOffset();
- Offset = *OffsetPtr;
- if ((Offset >= CUEndOffset) || !DebugInfoData.isValidOffset(Offset))
+ DataExtractor DebugInfoData = U->getDebugInfoExtractor();
+ uint32_t UEndOffset = U->getNextUnitOffset();
+ if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset))
return false;
uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
if (0 == AbbrCode) {
@@ -144,31 +105,25 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *CU,
AbbrevDecl = NULL;
return true;
}
- AbbrevDecl = CU->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
+ AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
if (0 == AbbrevDecl) {
// Restore the original offset.
*OffsetPtr = Offset;
return false;
}
- bool IsCompileUnitTag = (AbbrevDecl->getTag() == DW_TAG_compile_unit);
- if (IsCompileUnitTag)
- const_cast<DWARFCompileUnit*>(CU)->setBaseAddress(0);
+ ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes(
+ U->getAddressByteSize(), U->getVersion());
+ assert(FixedFormSizes.size() > 0);
// Skip all data in the .debug_info for the attributes
for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) {
- uint16_t Attr = AbbrevDecl->getAttrByIndex(i);
uint16_t Form = AbbrevDecl->getFormByIndex(i);
- if (IsCompileUnitTag &&
- ((Attr == DW_AT_entry_pc) || (Attr == DW_AT_low_pc))) {
- DWARFFormValue FormValue(Form);
- if (FormValue.extractValue(DebugInfoData, OffsetPtr, CU)) {
- if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc)
- const_cast<DWARFCompileUnit*>(CU)
- ->setBaseAddress(FormValue.getUnsigned());
- }
- } else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr,
- CU)) {
+ uint8_t FixedFormSize =
+ (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0;
+ if (FixedFormSize)
+ *OffsetPtr += FixedFormSize;
+ else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
// Restore the original offset.
*OffsetPtr = Offset;
return false;
@@ -187,203 +142,191 @@ bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const {
Tag == DW_TAG_inlined_subroutine;
}
-uint32_t
-DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
- const uint16_t attr,
- DWARFFormValue &form_value,
- uint32_t *end_attr_offset_ptr)
- const {
- if (AbbrevDecl) {
- uint32_t attr_idx = AbbrevDecl->findAttributeIndex(attr);
-
- if (attr_idx != -1U) {
- uint32_t offset = getOffset();
+bool DWARFDebugInfoEntryMinimal::getAttributeValue(
+ const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const {
+ if (!AbbrevDecl)
+ return false;
- DataExtractor debug_info_data = cu->getDebugInfoExtractor();
+ uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr);
+ if (AttrIdx == -1U)
+ return false;
- // Skip the abbreviation code so we are at the data for the attributes
- debug_info_data.getULEB128(&offset);
+ DataExtractor DebugInfoData = U->getDebugInfoExtractor();
+ uint32_t DebugInfoOffset = getOffset();
- uint32_t idx = 0;
- while (idx < attr_idx)
- DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(idx++),
- debug_info_data, &offset, cu);
+ // Skip the abbreviation code so we are at the data for the attributes
+ DebugInfoData.getULEB128(&DebugInfoOffset);
- const uint32_t attr_offset = offset;
- form_value = DWARFFormValue(AbbrevDecl->getFormByIndex(idx));
- if (form_value.extractValue(debug_info_data, &offset, cu)) {
- if (end_attr_offset_ptr)
- *end_attr_offset_ptr = offset;
- return attr_offset;
- }
- }
+ // Skip preceding attribute values.
+ for (uint32_t i = 0; i < AttrIdx; ++i) {
+ DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i),
+ DebugInfoData, &DebugInfoOffset, U);
}
- return 0;
+ FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx));
+ return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U);
}
-const char*
-DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- const char* fail_value)
- const {
- DWARFFormValue form_value;
- if (getAttributeValue(cu, attr, form_value)) {
- DataExtractor stringExtractor(cu->getStringSection(), false, 0);
- return form_value.getAsCString(&stringExtractor);
- }
- return fail_value;
+const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
+ const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<const char *> Result = FormValue.getAsCString(U);
+ return Result.hasValue() ? Result.getValue() : FailValue;
+}
+
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsAddress(U);
+ return Result.hasValue() ? Result.getValue() : FailValue;
}
-uint64_t
-DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- uint64_t fail_value) const {
- DWARFFormValue form_value;
- if (getAttributeValue(cu, attr, form_value))
- return form_value.getUnsigned();
- return fail_value;
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsUnsignedConstant();
+ return Result.hasValue() ? Result.getValue() : FailValue;
}
-int64_t
-DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- int64_t fail_value) const {
- DWARFFormValue form_value;
- if (getAttributeValue(cu, attr, form_value))
- return form_value.getSigned();
- return fail_value;
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsReference(U);
+ return Result.hasValue() ? Result.getValue() : FailValue;
}
-uint64_t
-DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- uint64_t fail_value)
- const {
- DWARFFormValue form_value;
- if (getAttributeValue(cu, attr, form_value))
- return form_value.getReference(cu);
- return fail_value;
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsSectionOffset();
+ return Result.hasValue() ? Result.getValue() : FailValue;
}
-bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFCompileUnit *CU,
+bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
uint64_t &LowPC,
uint64_t &HighPC) const {
- HighPC = -1ULL;
- LowPC = getAttributeValueAsUnsigned(CU, DW_AT_low_pc, -1ULL);
- if (LowPC != -1ULL)
- HighPC = getAttributeValueAsUnsigned(CU, DW_AT_high_pc, -1ULL);
+ LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL);
+ if (LowPC == -1ULL)
+ return false;
+ HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL);
+ if (HighPC == -1ULL) {
+ // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
+ // it represents function size.
+ HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL);
+ if (HighPC != -1ULL)
+ HighPC += LowPC;
+ }
return (HighPC != -1ULL);
}
-void
-DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *CU,
- DWARFDebugAranges *DebugAranges)
- const {
+void DWARFDebugInfoEntryMinimal::buildAddressRangeTable(
+ const DWARFUnit *U, DWARFDebugAranges *DebugAranges,
+ uint32_t UOffsetInAranges) const {
if (AbbrevDecl) {
if (isSubprogramDIE()) {
uint64_t LowPC, HighPC;
- if (getLowAndHighPC(CU, LowPC, HighPC)) {
- DebugAranges->appendRange(CU->getOffset(), LowPC, HighPC);
- }
+ if (getLowAndHighPC(U, LowPC, HighPC))
+ DebugAranges->appendRange(UOffsetInAranges, LowPC, HighPC);
// FIXME: try to append ranges from .debug_ranges section.
}
- const DWARFDebugInfoEntryMinimal *child = getFirstChild();
- while (child) {
- child->buildAddressRangeTable(CU, DebugAranges);
- child = child->getSibling();
+ const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
+ while (Child) {
+ Child->buildAddressRangeTable(U, DebugAranges, UOffsetInAranges);
+ Child = Child->getSibling();
}
}
}
-bool
-DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
- const DWARFCompileUnit *CU,
- const uint64_t Address)
- const {
+bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
+ const DWARFUnit *U, const uint64_t Address) const {
if (isNULL())
return false;
uint64_t LowPC, HighPC;
- if (getLowAndHighPC(CU, LowPC, HighPC))
+ if (getLowAndHighPC(U, LowPC, HighPC))
return (LowPC <= Address && Address <= HighPC);
// Try to get address ranges from .debug_ranges section.
- uint32_t RangesOffset = getAttributeValueAsReference(CU, DW_AT_ranges, -1U);
+ uint32_t RangesOffset =
+ getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
if (RangesOffset != -1U) {
DWARFDebugRangeList RangeList;
- if (CU->extractRangeList(RangesOffset, RangeList))
- return RangeList.containsAddress(CU->getBaseAddress(), Address);
+ if (U->extractRangeList(RangesOffset, RangeList))
+ return RangeList.containsAddress(U->getBaseAddress(), Address);
}
return false;
}
-const char*
-DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFCompileUnit *CU)
- const {
+const char *
+DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const {
if (!isSubroutineDIE())
return 0;
// Try to get mangled name if possible.
if (const char *name =
- getAttributeValueAsString(CU, DW_AT_MIPS_linkage_name, 0))
+ getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, 0))
return name;
- if (const char *name = getAttributeValueAsString(CU, DW_AT_linkage_name, 0))
+ if (const char *name = getAttributeValueAsString(U, DW_AT_linkage_name, 0))
return name;
- if (const char *name = getAttributeValueAsString(CU, DW_AT_name, 0))
+ if (const char *name = getAttributeValueAsString(U, DW_AT_name, 0))
return name;
// Try to get name from specification DIE.
uint32_t spec_ref =
- getAttributeValueAsReference(CU, DW_AT_specification, -1U);
+ getAttributeValueAsReference(U, DW_AT_specification, -1U);
if (spec_ref != -1U) {
DWARFDebugInfoEntryMinimal spec_die;
- if (spec_die.extract(CU, &spec_ref)) {
- if (const char *name = spec_die.getSubroutineName(CU))
+ if (spec_die.extractFast(U, &spec_ref)) {
+ if (const char *name = spec_die.getSubroutineName(U))
return name;
}
}
// Try to get name from abstract origin DIE.
uint32_t abs_origin_ref =
- getAttributeValueAsReference(CU, DW_AT_abstract_origin, -1U);
+ getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U);
if (abs_origin_ref != -1U) {
DWARFDebugInfoEntryMinimal abs_origin_die;
- if (abs_origin_die.extract(CU, &abs_origin_ref)) {
- if (const char *name = abs_origin_die.getSubroutineName(CU))
+ if (abs_origin_die.extractFast(U, &abs_origin_ref)) {
+ if (const char *name = abs_origin_die.getSubroutineName(U))
return name;
}
}
return 0;
}
-void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFCompileUnit *CU,
+void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U,
uint32_t &CallFile,
uint32_t &CallLine,
uint32_t &CallColumn) const {
- CallFile = getAttributeValueAsUnsigned(CU, DW_AT_call_file, 0);
- CallLine = getAttributeValueAsUnsigned(CU, DW_AT_call_line, 0);
- CallColumn = getAttributeValueAsUnsigned(CU, DW_AT_call_column, 0);
+ CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0);
+ CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0);
+ CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0);
}
-DWARFDebugInfoEntryMinimal::InlinedChain
+DWARFDebugInfoEntryInlinedChain
DWARFDebugInfoEntryMinimal::getInlinedChainForAddress(
- const DWARFCompileUnit *CU,
- const uint64_t Address)
- const {
- DWARFDebugInfoEntryMinimal::InlinedChain InlinedChain;
+ const DWARFUnit *U, const uint64_t Address) const {
+ DWARFDebugInfoEntryInlinedChain InlinedChain;
+ InlinedChain.U = U;
if (isNULL())
return InlinedChain;
for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) {
// Append current DIE to inlined chain only if it has correct tag
// (e.g. it is not a lexical block).
if (DIE->isSubroutineDIE()) {
- InlinedChain.push_back(*DIE);
+ InlinedChain.DIEs.push_back(*DIE);
}
// Try to get child which also contains provided address.
const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild();
while (Child) {
- if (Child->addressRangeContainsAddress(CU, Address)) {
+ if (Child->addressRangeContainsAddress(U, Address)) {
// Assume there is only one such child.
break;
}
@@ -392,6 +335,6 @@ DWARFDebugInfoEntryMinimal::getInlinedChainForAddress(
DIE = Child;
}
// Reverse the obtained chain to make the root of inlined chain last.
- std::reverse(InlinedChain.begin(), InlinedChain.end());
+ std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end());
return InlinedChain;
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h
index 9003591..aa61056 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h
@@ -18,9 +18,10 @@ namespace llvm {
class DWARFDebugAranges;
class DWARFCompileUnit;
+class DWARFUnit;
class DWARFContext;
class DWARFFormValue;
-class DWARFInlinedSubroutineChain;
+struct DWARFDebugInfoEntryInlinedChain;
/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
class DWARFDebugInfoEntryMinimal {
@@ -39,23 +40,15 @@ public:
DWARFDebugInfoEntryMinimal()
: Offset(0), ParentIdx(0), SiblingIdx(0), AbbrevDecl(0) {}
- void dump(raw_ostream &OS, const DWARFCompileUnit *cu,
- unsigned recurseDepth, unsigned indent = 0) const;
- void dumpAttribute(raw_ostream &OS, const DWARFCompileUnit *cu,
- uint32_t *offset_ptr, uint16_t attr, uint16_t form,
- unsigned indent = 0) const;
+ void dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth,
+ unsigned indent = 0) const;
+ void dumpAttribute(raw_ostream &OS, const DWARFUnit *u, uint32_t *offset_ptr,
+ uint16_t attr, uint16_t form, unsigned indent = 0) const;
- /// Extracts a debug info entry, which is a child of a given compile unit,
+ /// Extracts a debug info entry, which is a child of a given unit,
/// starting at a given offset. If DIE can't be extracted, returns false and
/// doesn't change OffsetPtr.
- bool extractFast(const DWARFCompileUnit *CU, const uint8_t *FixedFormSizes,
- uint32_t *OffsetPtr);
-
- /// Extract a debug info entry for a given compile unit from the
- /// .debug_info and .debug_abbrev data starting at the given offset.
- /// If compile unit can't be parsed, returns false and doesn't change
- /// OffsetPtr.
- bool extract(const DWARFCompileUnit *CU, uint32_t *OffsetPtr);
+ bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr);
uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
bool isNULL() const { return AbbrevDecl == 0; }
@@ -120,60 +113,65 @@ public:
return AbbrevDecl;
}
- uint32_t getAttributeValue(const DWARFCompileUnit *cu,
- const uint16_t attr, DWARFFormValue &formValue,
- uint32_t *end_attr_offset_ptr = 0) const;
+ bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr,
+ DWARFFormValue &FormValue) const;
+
+ const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr,
+ const char *FailValue) const;
- const char* getAttributeValueAsString(const DWARFCompileUnit* cu,
- const uint16_t attr,
- const char *fail_value) const;
+ uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr,
+ uint64_t FailValue) const;
- uint64_t getAttributeValueAsUnsigned(const DWARFCompileUnit *cu,
- const uint16_t attr,
- uint64_t fail_value) const;
+ uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U,
+ const uint16_t Attr,
+ uint64_t FailValue) const;
- uint64_t getAttributeValueAsReference(const DWARFCompileUnit *cu,
- const uint16_t attr,
- uint64_t fail_value) const;
+ uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr,
+ uint64_t FailValue) const;
- int64_t getAttributeValueAsSigned(const DWARFCompileUnit* cu,
- const uint16_t attr,
- int64_t fail_value) const;
+ uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U,
+ const uint16_t Attr,
+ uint64_t FailValue) const;
/// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
/// Returns true if both attributes are present.
- bool getLowAndHighPC(const DWARFCompileUnit *CU,
- uint64_t &LowPC, uint64_t &HighPC) const;
+ bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
+ uint64_t &HighPC) const;
- void buildAddressRangeTable(const DWARFCompileUnit *CU,
- DWARFDebugAranges *DebugAranges) const;
+ void buildAddressRangeTable(const DWARFUnit *U,
+ DWARFDebugAranges *DebugAranges,
+ uint32_t CUOffsetInAranges) const;
- bool addressRangeContainsAddress(const DWARFCompileUnit *CU,
+ bool addressRangeContainsAddress(const DWARFUnit *U,
const uint64_t Address) const;
/// If a DIE represents a subprogram (or inlined subroutine),
/// returns its mangled name (or short name, if mangled is missing).
/// This name may be fetched from specification or abstract origin
/// for this subprogram. Returns null if no name is found.
- const char* getSubroutineName(const DWARFCompileUnit *CU) const;
+ const char *getSubroutineName(const DWARFUnit *U) const;
/// Retrieves values of DW_AT_call_file, DW_AT_call_line and
/// DW_AT_call_column from DIE (or zeroes if they are missing).
- void getCallerFrame(const DWARFCompileUnit *CU, uint32_t &CallFile,
+ void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile,
uint32_t &CallLine, uint32_t &CallColumn) const;
- /// InlinedChain - represents a chain of inlined_subroutine
- /// DIEs, (possibly ending with subprogram DIE), all of which are contained
- /// in some concrete inlined instance tree. Address range for each DIE
- /// (except the last DIE) in this chain is contained in address
- /// range for next DIE in the chain.
- typedef SmallVector<DWARFDebugInfoEntryMinimal, 4> InlinedChain;
-
/// Get inlined chain for a given address, rooted at the current DIE.
/// Returns empty chain if address is not contained in address range
/// of current DIE.
- InlinedChain getInlinedChainForAddress(const DWARFCompileUnit *CU,
- const uint64_t Address) const;
+ DWARFDebugInfoEntryInlinedChain
+ getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const;
+};
+
+/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine
+/// DIEs, (possibly ending with subprogram DIE), all of which are contained
+/// in some concrete inlined instance tree. Address range for each DIE
+/// (except the last DIE) in this chain is contained in address
+/// range for next DIE in the chain.
+struct DWARFDebugInfoEntryInlinedChain {
+ DWARFDebugInfoEntryInlinedChain() : U(0) {}
+ SmallVector<DWARFDebugInfoEntryMinimal, 4> DIEs;
+ const DWARFUnit *U;
};
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp
index 192381c..13d09dd 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp
@@ -211,7 +211,7 @@ DWARFDebugLine::parsePrologue(DataExtractor debug_line_data,
if (*offset_ptr != end_prologue_offset) {
fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should"
- " have ended at 0x%8.8x but it ended ad 0x%8.8x\n",
+ " have ended at 0x%8.8x but it ended at 0x%8.8x\n",
prologue_offset, end_prologue_offset, *offset_ptr);
return false;
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp
new file mode 100644
index 0000000..3895ffa
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp
@@ -0,0 +1,74 @@
+//===-- DWARFDebugLoc.cpp -------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugLoc.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFDebugLoc::dump(raw_ostream &OS) const {
+ for (LocationLists::const_iterator I = Locations.begin(), E = Locations.end(); I != E; ++I) {
+ OS << format("0x%8.8x: ", I->Offset);
+ const unsigned Indent = 12;
+ for (SmallVectorImpl<Entry>::const_iterator I2 = I->Entries.begin(), E2 = I->Entries.end(); I2 != E2; ++I2) {
+ if (I2 != I->Entries.begin())
+ OS.indent(Indent);
+ OS << "Beginning address offset: " << format("0x%016" PRIx64, I2->Begin)
+ << '\n';
+ OS.indent(Indent) << " Ending address offset: "
+ << format("0x%016" PRIx64, I2->End) << '\n';
+ OS.indent(Indent) << " Location description: ";
+ for (SmallVectorImpl<unsigned char>::const_iterator I3 = I2->Loc.begin(), E3 = I2->Loc.end(); I3 != E3; ++I3) {
+ OS << format("%2.2x ", *I3);
+ }
+ OS << "\n\n";
+ }
+ }
+}
+
+void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) {
+ uint32_t Offset = 0;
+ while (data.isValidOffset(Offset)) {
+ Locations.resize(Locations.size() + 1);
+ LocationList &Loc = Locations.back();
+ Loc.Offset = Offset;
+ // 2.6.2 Location Lists
+ // A location list entry consists of:
+ while (true) {
+ Entry E;
+ RelocAddrMap::const_iterator AI = RelocMap.find(Offset);
+ // 1. A beginning address offset. ...
+ E.Begin = data.getUnsigned(&Offset, AddressSize);
+ if (AI != RelocMap.end())
+ E.Begin += AI->second.second;
+
+ AI = RelocMap.find(Offset);
+ // 2. An ending address offset. ...
+ E.End = data.getUnsigned(&Offset, AddressSize);
+ if (AI != RelocMap.end())
+ E.End += AI->second.second;
+
+ // The end of any given location list is marked by an end of list entry,
+ // which consists of a 0 for the beginning address offset and a 0 for the
+ // ending address offset.
+ if (E.Begin == 0 && E.End == 0)
+ break;
+
+ unsigned Bytes = data.getU16(&Offset);
+ // A single location description describing the location of the object...
+ StringRef str = data.getData().substr(Offset, Bytes);
+ Offset += Bytes;
+ E.Loc.reserve(str.size());
+ std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
+ Loc.Entries.push_back(llvm_move(E));
+ }
+ }
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h
new file mode 100644
index 0000000..d31aaaa
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h
@@ -0,0 +1,60 @@
+//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGLOC_H
+#define LLVM_DEBUGINFO_DWARFDEBUGLOC_H
+
+#include "DWARFRelocMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/DataExtractor.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugLoc {
+ /// A single location within a location list.
+ struct Entry {
+ /// The beginning address of the instruction range.
+ uint64_t Begin;
+ /// The ending address of the instruction range.
+ uint64_t End;
+ /// The location of the variable within the specified range.
+ SmallVector<unsigned char, 4> Loc;
+ };
+
+ /// A list of locations that contain one variable.
+ struct LocationList {
+ /// The beginning offset where this location list is stored in the debug_loc
+ /// section.
+ unsigned Offset;
+ /// All the locations in which the variable is stored.
+ SmallVector<Entry, 2> Entries;
+ };
+
+ typedef SmallVector<LocationList, 4> LocationLists;
+
+ /// A list of all the variables in the debug_loc section, each one describing
+ /// the locations in which the variable is stored.
+ LocationLists Locations;
+
+ /// A map used to resolve binary relocations.
+ const RelocAddrMap &RelocMap;
+
+public:
+ DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {}
+ /// Print the location lists found within the debug_loc section.
+ void dump(raw_ostream &OS) const;
+ /// Parse the debug_loc section accessible via the 'data' parameter using the
+ /// specified address size to interpret the address ranges.
+ void parse(DataExtractor data, unsigned AddressSize);
+};
+}
+
+#endif
diff --git a/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp
index c5583f9..da71fb3 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp
@@ -10,6 +10,8 @@
#include "llvm/DebugInfo/DWARFFormValue.h"
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
@@ -19,64 +21,114 @@ using namespace llvm;
using namespace dwarf;
namespace {
-template <uint8_t AddrSize, uint8_t RefAddrSize> struct FixedFormSizes {
- static const uint8_t sizes[];
-};
+uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
+ // FIXME: Support DWARF64.
+ return (Version == 2) ? AddrSize : 4;
}
template <uint8_t AddrSize, uint8_t RefAddrSize>
-const uint8_t FixedFormSizes<AddrSize, RefAddrSize>::sizes[] = {
- 0, // 0x00 unused
- AddrSize, // 0x01 DW_FORM_addr
- 0, // 0x02 unused
- 0, // 0x03 DW_FORM_block2
- 0, // 0x04 DW_FORM_block4
- 2, // 0x05 DW_FORM_data2
- 4, // 0x06 DW_FORM_data4
- 8, // 0x07 DW_FORM_data8
- 0, // 0x08 DW_FORM_string
- 0, // 0x09 DW_FORM_block
- 0, // 0x0a DW_FORM_block1
- 1, // 0x0b DW_FORM_data1
- 1, // 0x0c DW_FORM_flag
- 0, // 0x0d DW_FORM_sdata
- 4, // 0x0e DW_FORM_strp
- 0, // 0x0f DW_FORM_udata
- RefAddrSize, // 0x10 DW_FORM_ref_addr
- 1, // 0x11 DW_FORM_ref1
- 2, // 0x12 DW_FORM_ref2
- 4, // 0x13 DW_FORM_ref4
- 8, // 0x14 DW_FORM_ref8
- 0, // 0x15 DW_FORM_ref_udata
- 0, // 0x16 DW_FORM_indirect
- 4, // 0x17 DW_FORM_sec_offset
- 0, // 0x18 DW_FORM_exprloc
- 0, // 0x19 DW_FORM_flag_present
- 8, // 0x20 DW_FORM_ref_sig8
-};
-
-static uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
- // FIXME: Support DWARF64.
- return (Version == 2) ? AddrSize : 4;
+ArrayRef<uint8_t> makeFixedFormSizesArrayRef() {
+ static const uint8_t sizes[] = {
+ 0, // 0x00 unused
+ AddrSize, // 0x01 DW_FORM_addr
+ 0, // 0x02 unused
+ 0, // 0x03 DW_FORM_block2
+ 0, // 0x04 DW_FORM_block4
+ 2, // 0x05 DW_FORM_data2
+ 4, // 0x06 DW_FORM_data4
+ 8, // 0x07 DW_FORM_data8
+ 0, // 0x08 DW_FORM_string
+ 0, // 0x09 DW_FORM_block
+ 0, // 0x0a DW_FORM_block1
+ 1, // 0x0b DW_FORM_data1
+ 1, // 0x0c DW_FORM_flag
+ 0, // 0x0d DW_FORM_sdata
+ 4, // 0x0e DW_FORM_strp
+ 0, // 0x0f DW_FORM_udata
+ RefAddrSize, // 0x10 DW_FORM_ref_addr
+ 1, // 0x11 DW_FORM_ref1
+ 2, // 0x12 DW_FORM_ref2
+ 4, // 0x13 DW_FORM_ref4
+ 8, // 0x14 DW_FORM_ref8
+ 0, // 0x15 DW_FORM_ref_udata
+ 0, // 0x16 DW_FORM_indirect
+ 4, // 0x17 DW_FORM_sec_offset
+ 0, // 0x18 DW_FORM_exprloc
+ 0, // 0x19 DW_FORM_flag_present
+ };
+ return makeArrayRef(sizes);
+}
}
-const uint8_t *
-DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, uint16_t Version) {
+ArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize,
+ uint16_t Version) {
uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
if (AddrSize == 4 && RefAddrSize == 4)
- return FixedFormSizes<4, 4>::sizes;
+ return makeFixedFormSizesArrayRef<4, 4>();
if (AddrSize == 4 && RefAddrSize == 8)
- return FixedFormSizes<4, 8>::sizes;
+ return makeFixedFormSizesArrayRef<4, 8>();
if (AddrSize == 8 && RefAddrSize == 4)
- return FixedFormSizes<8, 4>::sizes;
+ return makeFixedFormSizesArrayRef<8, 4>();
if (AddrSize == 8 && RefAddrSize == 8)
- return FixedFormSizes<8, 8>::sizes;
- return 0;
+ return makeFixedFormSizesArrayRef<8, 8>();
+ return None;
}
-bool
-DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
- const DWARFCompileUnit *cu) {
+static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
+ DWARFFormValue::FC_Unknown, // 0x0
+ DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr
+ DWARFFormValue::FC_Unknown, // 0x02 unused
+ DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2
+ DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4
+ DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2
+ // --- These can be FC_SectionOffset in DWARF3 and below:
+ DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4
+ DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8
+ // ---
+ DWARFFormValue::FC_String, // 0x08 DW_FORM_string
+ DWARFFormValue::FC_Block, // 0x09 DW_FORM_block
+ DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1
+ DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1
+ DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag
+ DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata
+ DWARFFormValue::FC_String, // 0x0e DW_FORM_strp
+ DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata
+ DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr
+ DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1
+ DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2
+ DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4
+ DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8
+ DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata
+ DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect
+ DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
+ DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc
+ DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present
+};
+
+bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
+ // First, check DWARF4 form classes.
+ if (Form < ArrayRef<FormClass>(DWARF4FormClasses).size() &&
+ DWARF4FormClasses[Form] == FC)
+ return true;
+ // Check DW_FORM_ref_sig8 from DWARF4.
+ if (Form == DW_FORM_ref_sig8)
+ return (FC == FC_Reference);
+ // Check for some DWARF5 forms.
+ if (Form == DW_FORM_GNU_addr_index)
+ return (FC == FC_Address);
+ if (Form == DW_FORM_GNU_str_index)
+ 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.
+ if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
+ FC == FC_SectionOffset)
+ return true;
+ return false;
+}
+
+bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
+ const DWARFUnit *cu) {
bool indirect = false;
bool is_block = false;
Value.data = NULL;
@@ -126,9 +178,13 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
Value.uval = data.getU16(offset_ptr);
break;
case DW_FORM_data4:
- case DW_FORM_ref4:
+ case DW_FORM_ref4: {
+ RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
Value.uval = data.getU32(offset_ptr);
+ if (AI != cu->getRelocMap()->end())
+ Value.uval += AI->second.second;
break;
+ }
case DW_FORM_data8:
case DW_FORM_ref8:
Value.uval = data.getU64(offset_ptr);
@@ -152,10 +208,6 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
break;
case DW_FORM_string:
Value.cstr = data.getCStr(offset_ptr);
- // Set the string value to also be the data for inlined cstr form
- // values only so we can tell the differnence between DW_FORM_string
- // and DW_FORM_strp form values
- Value.data = (const uint8_t*)Value.cstr;
break;
case DW_FORM_indirect:
Form = data.getULEB128(offset_ptr);
@@ -179,8 +231,6 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
Value.uval = data.getU64(offset_ptr);
break;
case DW_FORM_GNU_addr_index:
- Value.uval = data.getULEB128(offset_ptr);
- break;
case DW_FORM_GNU_str_index:
Value.uval = data.getULEB128(offset_ptr);
break;
@@ -203,13 +253,13 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
bool
DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
- const DWARFCompileUnit *cu) const {
+ const DWARFUnit *cu) const {
return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
}
bool
DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
- uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
+ uint32_t *offset_ptr, const DWARFUnit *cu) {
bool indirect = false;
do {
switch (form) {
@@ -309,21 +359,20 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
}
void
-DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
+DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
DataExtractor debug_str_data(cu->getStringSection(), true, 0);
DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
- uint64_t uvalue = getUnsigned();
+ uint64_t uvalue = Value.uval;
bool cu_relative_offset = false;
switch (Form) {
case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break;
case DW_FORM_GNU_addr_index: {
- StringRef AddrOffsetSec = cu->getAddrOffsetSection();
OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
- if (AddrOffsetSec.size() != 0) {
- DataExtractor DA(AddrOffsetSec, true, cu->getAddressByteSize());
- OS << format("0x%016" PRIx64, getIndirectAddress(&DA, cu));
- } else
+ uint64_t Address;
+ if (cu->getAddrOffsetSectionItem(uvalue, Address))
+ OS << format("0x%016" PRIx64, Address);
+ else
OS << "<no .debug_addr section>";
break;
}
@@ -336,7 +385,7 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break;
case DW_FORM_string:
OS << '"';
- OS.write_escaped(getAsCString(NULL));
+ OS.write_escaped(Value.cstr);
OS << '"';
break;
case DW_FORM_exprloc:
@@ -368,25 +417,24 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
}
break;
- case DW_FORM_sdata: OS << getSigned(); break;
- case DW_FORM_udata: OS << getUnsigned(); break;
+ case DW_FORM_sdata: OS << Value.sval; break;
+ case DW_FORM_udata: OS << Value.uval; break;
case DW_FORM_strp: {
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
- const char* dbg_str = getAsCString(&debug_str_data);
- if (dbg_str) {
+ Optional<const char *> DbgStr = getAsCString(cu);
+ if (DbgStr.hasValue()) {
OS << '"';
- OS.write_escaped(dbg_str);
+ OS.write_escaped(DbgStr.getValue());
OS << '"';
}
break;
}
case DW_FORM_GNU_str_index: {
OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
- const char *dbg_str = getIndirectCString(&debug_str_data,
- &debug_str_offset_data);
- if (dbg_str) {
+ Optional<const char *> DbgStr = getAsCString(cu);
+ if (DbgStr.hasValue()) {
OS << '"';
- OS.write_escaped(dbg_str);
+ OS.write_escaped(DbgStr.getValue());
OS << '"';
}
break;
@@ -435,97 +483,67 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
}
-const char*
-DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
- if (isInlinedCStr()) {
+Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
+ if (!isFormClass(FC_String))
+ return None;
+ if (Form == DW_FORM_string)
return Value.cstr;
- } else if (debug_str_data_ptr) {
- uint32_t offset = Value.uval;
- return debug_str_data_ptr->getCStr(&offset);
+ if (U == 0)
+ return None;
+ uint32_t Offset = Value.uval;
+ if (Form == DW_FORM_GNU_str_index) {
+ uint32_t StrOffset;
+ if (!U->getStringOffsetSectionItem(Offset, StrOffset))
+ return None;
+ Offset = StrOffset;
}
- return NULL;
-}
-
-const char*
-DWARFFormValue::getIndirectCString(const DataExtractor *DS,
- const DataExtractor *DSO) const {
- if (!DS || !DSO) return NULL;
-
- uint32_t offset = Value.uval * 4;
- uint32_t soffset = DSO->getU32(&offset);
- return DS->getCStr(&soffset);
-}
-
-uint64_t
-DWARFFormValue::getIndirectAddress(const DataExtractor *DA,
- const DWARFCompileUnit *cu) const {
- if (!DA) return 0;
-
- uint32_t offset = Value.uval * cu->getAddressByteSize();
- return DA->getAddress(&offset);
+ if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
+ return Str;
+ }
+ return None;
}
-uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
- uint64_t die_offset = Value.uval;
- switch (Form) {
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
- case DW_FORM_ref8:
- case DW_FORM_ref_udata:
- die_offset += (cu ? cu->getOffset() : 0);
- break;
- default:
- break;
+Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
+ if (!isFormClass(FC_Address))
+ return None;
+ if (Form == DW_FORM_GNU_addr_index) {
+ uint32_t Index = Value.uval;
+ uint64_t Result;
+ if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result))
+ return None;
+ return Result;
}
-
- return die_offset;
+ return Value.uval;
}
-bool
-DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) {
+Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
+ if (!isFormClass(FC_Reference))
+ return None;
switch (Form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- Value.uval += cu->getOffset();
- Form = DW_FORM_ref_addr;
- return true;
+ if (U == 0)
+ return None;
+ return Value.uval + U->getOffset();
+ case DW_FORM_ref_addr:
+ return Value.uval;
+ // FIXME: Add proper support for DW_FORM_ref_sig8
default:
- break;
+ return Value.uval;
}
- return false;
-}
-
-const uint8_t *DWARFFormValue::BlockData() const {
- if (!isInlinedCStr())
- return Value.data;
- return NULL;
}
-bool DWARFFormValue::isBlockForm(uint16_t form) {
- switch (form) {
- case DW_FORM_exprloc:
- case DW_FORM_block:
- case DW_FORM_block1:
- case DW_FORM_block2:
- case DW_FORM_block4:
- return true;
- }
- return false;
+Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
+ if (!isFormClass(FC_SectionOffset))
+ return None;
+ return Value.uval;
}
-bool DWARFFormValue::isDataForm(uint16_t form) {
- switch (form) {
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_data1:
- case DW_FORM_data2:
- case DW_FORM_data4:
- case DW_FORM_data8:
- return true;
- }
- return false;
+Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
+ if (!isFormClass(FC_Constant) || Form == DW_FORM_sdata)
+ return None;
+ return Value.uval;
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.cpp
new file mode 100644
index 0000000..303bf70
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.cpp
@@ -0,0 +1,39 @@
+//===-- DWARFTypeUnit.cpp -------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFTypeUnit.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+bool DWARFTypeUnit::extractImpl(DataExtractor debug_info,
+ uint32_t *offset_ptr) {
+ if (!DWARFUnit::extractImpl(debug_info, offset_ptr))
+ return false;
+ TypeHash = debug_info.getU64(offset_ptr);
+ TypeOffset = debug_info.getU32(offset_ptr);
+ return TypeOffset < getLength();
+}
+
+void DWARFTypeUnit::dump(raw_ostream &OS) {
+ OS << format("0x%08x", getOffset()) << ": Type Unit:"
+ << " length = " << format("0x%08x", getLength())
+ << " version = " << format("0x%04x", getVersion())
+ << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset())
+ << " addr_size = " << format("0x%02x", getAddressByteSize())
+ << " type_signature = " << format("0x%16" PRIx64, TypeHash)
+ << " type_offset = " << format("0x%04x", TypeOffset)
+ << " (next unit at " << format("0x%08x", getNextUnitOffset())
+ << ")\n";
+
+ const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false);
+ assert(CU && "Null Compile Unit?");
+ CU->dump(OS, this, -1U);
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h b/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h
new file mode 100644
index 0000000..7a0dab2
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h
@@ -0,0 +1,35 @@
+//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFTYPEUNIT_H
+#define LLVM_DEBUGINFO_DWARFTYPEUNIT_H
+
+#include "DWARFUnit.h"
+
+namespace llvm {
+
+class DWARFTypeUnit : public DWARFUnit {
+private:
+ uint64_t TypeHash;
+ uint32_t TypeOffset;
+public:
+ DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
+ StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
+ const RelocAddrMap *M, bool LE)
+ : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {}
+ uint32_t getSize() const LLVM_OVERRIDE { return DWARFUnit::getSize() + 12; }
+ void dump(raw_ostream &OS);
+protected:
+ bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) LLVM_OVERRIDE;
+};
+
+}
+
+#endif
+
diff --git a/contrib/llvm/lib/DebugInfo/DWARFUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARFUnit.cpp
new file mode 100644
index 0000000..5167eb9
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFUnit.cpp
@@ -0,0 +1,365 @@
+//===-- DWARFUnit.cpp -----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFUnit.h"
+#include "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;
+
+DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
+ StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
+ const RelocAddrMap *M, bool LE)
+ : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), RangeSection(RS),
+ StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS),
+ RelocMap(M), isLittleEndian(LE) {
+ 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 abbrOffsetOK = AbbrevSection.size() > abbrOffset;
+ bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
+
+ if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK)
+ return false;
+
+ Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset);
+ 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 = 0;
+ AddrSize = 0;
+ BaseAddr = 0;
+ RangeSectionBase = 0;
+ AddrOffsetSectionBase = 0;
+ clearDIEs(false);
+ DWO.reset();
+}
+
+const char *DWARFUnit::getCompilationDir() {
+ extractDIEsIfNeeded(true);
+ if (DieArray.empty())
+ return 0;
+ return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
+}
+
+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.empty())
+ return;
+ DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front();
+ DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back();
+ DWARFDebugInfoEntryMinimal *curr_die;
+ // We purposely are skipping the last element in the array in the loop below
+ // so that we can always have a valid next item
+ for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) {
+ // Since our loop doesn't include the last element, we can always
+ // safely access the next die in the array.
+ DWARFDebugInfoEntryMinimal *next_die = curr_die + 1;
+
+ const DWARFAbbreviationDeclaration *curr_die_abbrev =
+ curr_die->getAbbreviationDeclarationPtr();
+
+ if (curr_die_abbrev) {
+ // Normal DIE
+ if (curr_die_abbrev->hasChildren())
+ next_die->setParent(curr_die);
+ else
+ curr_die->setSibling(next_die);
+ } else {
+ // NULL DIE that terminates a sibling chain
+ DWARFDebugInfoEntryMinimal *parent = curr_die->getParent();
+ if (parent)
+ parent->setSibling(next_die);
+ }
+ }
+
+ // Since we skipped the last element, we need to fix it up!
+ if (die_array_begin < die_array_end)
+ curr_die->setParent(die_array_begin);
+}
+
+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 Offset = getFirstDIEOffset();
+ uint32_t NextCUOffset = getNextUnitOffset();
+ DWARFDebugInfoEntryMinimal DIE;
+ uint32_t Depth = 0;
+ bool IsCUDie = true;
+
+ while (Offset < NextCUOffset && DIE.extractFast(this, &Offset)) {
+ 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);
+ }
+
+ const DWARFAbbreviationDeclaration *AbbrDecl =
+ DIE.getAbbreviationDeclarationPtr();
+ if (AbbrDecl) {
+ // 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 (Offset > NextCUOffset)
+ fprintf(stderr, "warning: DWARF compile unit extends beyond its "
+ "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset);
+}
+
+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_GNU_ranges_base, 0);
+ }
+
+ setDIERelations();
+ return DieArray.size();
+}
+
+DWARFUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile)
+ : DWOFile(DWOFile),
+ DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))),
+ DWOU(0) {
+ if (DWOContext->getNumDWOCompileUnits() > 0)
+ DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
+}
+
+bool DWARFUnit::parseDWO() {
+ if (DWO.get() != 0)
+ return false;
+ extractDIEsIfNeeded(true);
+ if (DieArray.empty())
+ return false;
+ const char *DWOFileName =
+ DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0);
+ if (DWOFileName == 0)
+ return false;
+ const char *CompilationDir =
+ DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
+ SmallString<16> AbsolutePath;
+ if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) {
+ sys::path::append(AbsolutePath, CompilationDir);
+ }
+ sys::path::append(AbsolutePath, DWOFileName);
+ object::ObjectFile *DWOFile =
+ object::ObjectFile::createObjectFile(AbsolutePath);
+ if (!DWOFile)
+ return false;
+ // Reset DWOHolder.
+ DWO.reset(new DWOHolder(DWOFile));
+ DWARFUnit *DWOCU = DWO->getUnit();
+ // Verify that compile unit in .dwo file is valid.
+ if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) {
+ DWO.reset();
+ return false;
+ }
+ // Share .debug_addr and .debug_ranges section with compile unit in .dwo
+ DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
+ DWOCU->setRangesSection(RangeSection, RangeSectionBase);
+ 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::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
+ bool clear_dies_if_already_not_parsed,
+ uint32_t CUOffsetInAranges) {
+ // 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 clear_dies = extractDIEsIfNeeded(false) > 1 &&
+ clear_dies_if_already_not_parsed;
+ DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges);
+ bool DWOCreated = parseDWO();
+ if (DWO.get()) {
+ // If there is a .dwo file for this compile unit, then skeleton CU DIE
+ // doesn't have children, and we should instead build address range table
+ // from DIEs in the .debug_info.dwo section of .dwo file.
+ DWO->getUnit()->buildAddressRangeTable(
+ debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges);
+ }
+ if (DWOCreated && clear_dies_if_already_not_parsed)
+ DWO.reset();
+
+ // Keep memory down by clearing DIEs if this generate function
+ // caused them to be parsed.
+ if (clear_dies)
+ clearDIEs(true);
+}
+
+const DWARFDebugInfoEntryMinimal *
+DWARFUnit::getSubprogramForAddress(uint64_t Address) {
+ extractDIEsIfNeeded(false);
+ for (size_t i = 0, n = DieArray.size(); i != n; i++)
+ if (DieArray[i].isSubprogramDIE() &&
+ DieArray[i].addressRangeContainsAddress(this, Address)) {
+ return &DieArray[i];
+ }
+ return 0;
+}
+
+DWARFDebugInfoEntryInlinedChain
+DWARFUnit::getInlinedChainForAddress(uint64_t Address) {
+ // First, find a subprogram that contains the given address (the root
+ // of inlined chain).
+ const DWARFUnit *ChainCU = 0;
+ 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);
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFUnit.h b/contrib/llvm/lib/DebugInfo/DWARFUnit.h
new file mode 100644
index 0000000..bd768a6
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFUnit.h
@@ -0,0 +1,168 @@
+//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFUNIT_H
+#define LLVM_DEBUGINFO_DWARFUNIT_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFDebugRangeList.h"
+#include "DWARFRelocMap.h"
+#include <vector>
+
+namespace llvm {
+
+namespace object {
+class ObjectFile;
+}
+
+class DWARFDebugAbbrev;
+class StringRef;
+class raw_ostream;
+
+class DWARFUnit {
+ const DWARFDebugAbbrev *Abbrev;
+ StringRef InfoSection;
+ StringRef AbbrevSection;
+ StringRef RangeSection;
+ uint32_t RangeSectionBase;
+ StringRef StringSection;
+ StringRef StringOffsetSection;
+ StringRef AddrOffsetSection;
+ uint32_t AddrOffsetSectionBase;
+ const RelocAddrMap *RelocMap;
+ bool isLittleEndian;
+
+ uint32_t Offset;
+ uint32_t Length;
+ uint16_t Version;
+ const DWARFAbbreviationDeclarationSet *Abbrevs;
+ uint8_t AddrSize;
+ uint64_t BaseAddr;
+ // The compile unit debug information entry items.
+ std::vector<DWARFDebugInfoEntryMinimal> DieArray;
+
+ class DWOHolder {
+ OwningPtr<object::ObjectFile> DWOFile;
+ OwningPtr<DWARFContext> DWOContext;
+ DWARFUnit *DWOU;
+ public:
+ DWOHolder(object::ObjectFile *DWOFile);
+ DWARFUnit *getUnit() const { return DWOU; }
+ };
+ OwningPtr<DWOHolder> DWO;
+
+protected:
+ virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
+
+public:
+
+ DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
+ StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
+ const RelocAddrMap *M, bool LE);
+
+ virtual ~DWARFUnit();
+
+ StringRef getStringSection() const { return StringSection; }
+ StringRef getStringOffsetSection() const { return StringOffsetSection; }
+ void setAddrOffsetSection(StringRef AOS, uint32_t Base) {
+ AddrOffsetSection = AOS;
+ AddrOffsetSectionBase = Base;
+ }
+ void setRangesSection(StringRef RS, uint32_t Base) {
+ RangeSection = RS;
+ RangeSectionBase = Base;
+ }
+
+ bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
+ // FIXME: Result should be uint64_t in DWARF64.
+ bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const;
+
+ DataExtractor getDebugInfoExtractor() const {
+ return DataExtractor(InfoSection, isLittleEndian, AddrSize);
+ }
+ DataExtractor getStringExtractor() const {
+ return DataExtractor(StringSection, false, 0);
+ }
+
+ const RelocAddrMap *getRelocMap() const { return RelocMap; }
+
+ bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
+
+ /// extractRangeList - extracts the range list referenced by this compile
+ /// unit from .debug_ranges section. Returns true on success.
+ /// Requires that compile unit is already extracted.
+ bool extractRangeList(uint32_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const;
+ void clear();
+ uint32_t getOffset() const { return Offset; }
+ /// Size in bytes of the compile unit header.
+ virtual uint32_t getSize() const { return 11; }
+ uint32_t getFirstDIEOffset() const { return Offset + getSize(); }
+ uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
+ /// Size in bytes of the .debug_info data associated with this compile unit.
+ size_t getDebugInfoSize() const { return Length + 4 - getSize(); }
+ uint32_t getLength() const { return Length; }
+ uint16_t getVersion() const { return Version; }
+ const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
+ return Abbrevs;
+ }
+ uint8_t getAddressByteSize() const { return AddrSize; }
+ uint64_t getBaseAddress() const { return BaseAddr; }
+
+ void setBaseAddress(uint64_t base_addr) {
+ BaseAddr = base_addr;
+ }
+
+ const DWARFDebugInfoEntryMinimal *
+ getCompileUnitDIE(bool extract_cu_die_only = true) {
+ extractDIEsIfNeeded(extract_cu_die_only);
+ return DieArray.empty() ? NULL : &DieArray[0];
+ }
+
+ const char *getCompilationDir();
+ uint64_t getDWOId();
+
+ void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
+ bool clear_dies_if_already_not_parsed,
+ uint32_t CUOffsetInAranges);
+
+ /// getInlinedChainForAddress - fetches inlined chain for a given address.
+ /// Returns empty chain if there is no subprogram containing address. The
+ /// chain is valid as long as parsed compile unit DIEs are not cleared.
+ DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address);
+
+private:
+ /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
+ /// hasn't already been done. Returns the number of DIEs parsed at this call.
+ size_t extractDIEsIfNeeded(bool CUDieOnly);
+ /// extractDIEsToVector - Appends all parsed DIEs to a vector.
+ void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
+ std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const;
+ /// setDIERelations - We read in all of the DIE entries into our flat list
+ /// of DIE entries and now we need to go back through all of them and set the
+ /// parent, sibling and child pointers for quick DIE navigation.
+ void setDIERelations();
+ /// clearDIEs - Clear parsed DIEs to keep memory usage low.
+ void clearDIEs(bool KeepCUDie);
+
+ /// parseDWO - Parses .dwo file for current compile unit. Returns true if
+ /// it was actually constructed.
+ bool parseDWO();
+
+ /// getSubprogramForAddress - Returns subprogram DIE with address range
+ /// encompassing the provided address. The pointer is alive as long as parsed
+ /// compile unit DIEs are not cleared.
+ const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address);
+};
+
+}
+
+#endif
OpenPOWER on IntegriCloud