[llvm-commits] [llvm] r139627 - in /llvm/trunk: include/llvm/DebugInfo/ lib/ lib/DebugInfo/ tools/ tools/llvm-dwarfdump/
Evan Cheng
evan.cheng at apple.com
Wed Sep 14 11:20:15 PDT 2011
Awesome. Thanks Benjamin!
Evan
On Sep 13, 2011, at 12:42 PM, Benjamin Kramer wrote:
> Author: d0k
> Date: Tue Sep 13 14:42:23 2011
> New Revision: 139627
>
> URL: http://llvm.org/viewvc/llvm-project?rev=139627&view=rev
> Log:
> Sketch out a DWARF parser.
>
> This introduces a new library to LLVM: libDebugInfo. It will provide debug information
> parsing to LLVM. Much of the design and some of the code is taken from the LLDB project.
>
> It also contains an llvm-dwarfdump tool that can dump the abbrevs and DIEs from an
> object file. It can be used to write tests for DWARF input and output easily.
>
> Added:
> llvm/trunk/include/llvm/DebugInfo/
> llvm/trunk/include/llvm/DebugInfo/DIContext.h
> llvm/trunk/lib/DebugInfo/
> llvm/trunk/lib/DebugInfo/CMakeLists.txt
> llvm/trunk/lib/DebugInfo/DIContext.cpp
> llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
> llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.h
> llvm/trunk/lib/DebugInfo/DWARFAttribute.h
> llvm/trunk/lib/DebugInfo/DWARFCompileUnit.cpp
> llvm/trunk/lib/DebugInfo/DWARFCompileUnit.h
> llvm/trunk/lib/DebugInfo/DWARFContext.cpp
> llvm/trunk/lib/DebugInfo/DWARFContext.h
> llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.cpp
> llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.h
> llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp
> llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.h
> llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp
> llvm/trunk/lib/DebugInfo/DWARFFormValue.h
> llvm/trunk/lib/DebugInfo/Makefile
> - copied, changed from r139626, llvm/trunk/lib/Makefile
> llvm/trunk/tools/llvm-dwarfdump/
> llvm/trunk/tools/llvm-dwarfdump/CMakeLists.txt
> llvm/trunk/tools/llvm-dwarfdump/Makefile
> - copied, changed from r139626, llvm/trunk/lib/Makefile
> llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
> Modified:
> llvm/trunk/lib/CMakeLists.txt
> llvm/trunk/lib/Makefile
> llvm/trunk/tools/CMakeLists.txt
> llvm/trunk/tools/Makefile
>
> Added: llvm/trunk/include/llvm/DebugInfo/DIContext.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DIContext.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/DIContext.h (added)
> +++ llvm/trunk/include/llvm/DebugInfo/DIContext.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,42 @@
> +//===-- DIContext.h ---------------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file defines DIContext, and abstract data structure that holds
> +// debug information data.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_DEBUGINFO_DICONTEXT_H
> +#define LLVM_DEBUGINFO_DICONTEXT_H
> +
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/DebugInfo/DILineInfo.h"
> +
> +namespace llvm {
> +
> +class raw_ostream;
> +
> +class DIContext {
> +public:
> + virtual ~DIContext();
> +
> + /// getDWARFContext - get a context for binary DWARF data.
> + static DIContext *getDWARFContext(bool isLittleEndian,
> + StringRef infoSection,
> + StringRef abbrevSection,
> + StringRef aRangeSection = StringRef(),
> + StringRef lineSection = StringRef(),
> + StringRef stringSection = StringRef());
> +
> + virtual void dump(raw_ostream &OS) = 0;
> +};
> +
> +}
> +
> +#endif
>
> Modified: llvm/trunk/lib/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CMakeLists.txt?rev=139627&r1=139626&r2=139627&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CMakeLists.txt (original)
> +++ llvm/trunk/lib/CMakeLists.txt Tue Sep 13 14:42:23 2011
> @@ -9,6 +9,7 @@
> add_subdirectory(MC)
> add_subdirectory(CompilerDriver)
> add_subdirectory(Object)
> +add_subdirectory(DebugInfo)
> add_subdirectory(ExecutionEngine)
> add_subdirectory(Target)
> add_subdirectory(AsmParser)
>
> Added: llvm/trunk/lib/DebugInfo/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CMakeLists.txt?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/CMakeLists.txt (added)
> +++ llvm/trunk/lib/DebugInfo/CMakeLists.txt Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,13 @@
> +add_llvm_library(LLVMMC
> + DIContext.cpp
> + DWARFAbbreviationDeclaration.cpp
> + DWARFCompileUnit.cpp
> + DWARFContext.cpp
> + DWARFDebugAbbrev.cpp
> + DWARFDebugInfoEntry.cpp
> + DWARFFormValue.cpp
> + )
> +
> +add_llvm_library_dependencies(LLVMDebugInfo
> + LLVMSupport
> + )
>
> Added: llvm/trunk/lib/DebugInfo/DIContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DIContext.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DIContext.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DIContext.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,24 @@
> +//===-- DIContext.cpp -----------------------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/DebugInfo/DIContext.h"
> +#include "DWARFContext.h"
> +using namespace llvm;
> +
> +DIContext::~DIContext() {}
> +
> +DIContext *DIContext::getDWARFContext(bool isLittleEndian,
> + StringRef infoSection,
> + StringRef abbrevSection,
> + StringRef aRangeSection,
> + StringRef lineSection,
> + StringRef stringSection) {
> + return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection,
> + aRangeSection, lineSection, stringSection);
> +}
>
> Added: llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,66 @@
> +//===-- DWARFAbbreviationDeclaration.cpp ----------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "DWARFAbbreviationDeclaration.h"
> +#include "llvm/Support/Dwarf.h"
> +#include "llvm/Support/raw_ostream.h"
> +using namespace llvm;
> +using namespace dwarf;
> +
> +bool
> +DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr){
> + return extract(data, offset_ptr, data.getULEB128(offset_ptr));
> +}
> +
> +bool
> +DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr,
> + uint32_t code) {
> + Code = code;
> + Attributes.clear();
> + if (Code) {
> + Tag = data.getULEB128(offset_ptr);
> + HasChildren = data.getU8(offset_ptr);
> +
> + while (data.isValidOffset(*offset_ptr)) {
> + uint16_t attr = data.getULEB128(offset_ptr);
> + uint16_t form = data.getULEB128(offset_ptr);
> +
> + if (attr && form)
> + Attributes.push_back(DWARFAttribute(attr, form));
> + else
> + break;
> + }
> +
> + return Tag != 0;
> + }
> + else {
> + Tag = 0;
> + HasChildren = false;
> + }
> +
> + return false;
> +}
> +
> +void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
> + OS << '[' << getCode() << "] " << TagString(getTag()) << "\tDW_CHILDREN_"
> + << (hasChildren() ? "yes" : "no") << '\n';
> + for (unsigned i = 0, e = Attributes.size(); i != e; ++i)
> + OS << '\t' << AttributeString(Attributes[i].getAttribute())
> + << '\t' << FormEncodingString(Attributes[i].getForm()) << '\n';
> + OS << '\n';
> +}
> +
> +uint32_t
> +DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const {
> + for (uint32_t i = 0, e = Attributes.size(); i != e; ++i) {
> + if (Attributes[i].getAttribute() == attr)
> + return i;
> + }
> + return -1U;
> +}
>
> Added: llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFAbbreviationDeclaration.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,54 @@
> +//===-- DWARFAbbreviationDeclaration.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_DWARFABBREVIATIONDECLARATION_H
> +#define LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
> +
> +#include "DWARFAttribute.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/Support/DataExtractor.h"
> +
> +namespace llvm {
> +
> +class raw_ostream;
> +
> +class DWARFAbbreviationDeclaration {
> + uint32_t Code;
> + uint32_t Tag;
> + bool HasChildren;
> + SmallVector<DWARFAttribute, 8> Attributes;
> +public:
> + enum { InvalidCode = 0 };
> + DWARFAbbreviationDeclaration()
> + : Code(InvalidCode), Tag(0), HasChildren(0) {}
> +
> + uint32_t getCode() const { return Code; }
> + uint32_t getTag() const { return Tag; }
> + bool hasChildren() const { return HasChildren; }
> + uint32_t getNumAttributes() const { return Attributes.size(); }
> + uint16_t getAttrByIndex(uint32_t idx) const {
> + return Attributes.size() > idx ? Attributes[idx].getAttribute() : 0;
> + }
> + uint16_t getFormByIndex(uint32_t idx) const {
> + return Attributes.size() > idx ? Attributes[idx].getForm() : 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; }
> + void dump(raw_ostream &OS) const;
> + const SmallVectorImpl<DWARFAttribute> &getAttributes() const {
> + return Attributes;
> + }
> +};
> +
> +}
> +
> +#endif
>
> Added: llvm/trunk/lib/DebugInfo/DWARFAttribute.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFAttribute.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFAttribute.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFAttribute.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,30 @@
> +//===-- 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
>
> Added: llvm/trunk/lib/DebugInfo/DWARFCompileUnit.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFCompileUnit.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFCompileUnit.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFCompileUnit.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,203 @@
> +//===-- DWARFCompileUnit.cpp ----------------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "DWARFCompileUnit.h"
> +#include "DWARFContext.h"
> +#include "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(Context.getInfoSection(),
> + Context.isLittleEndian(), getAddressByteSize());
> +}
> +
> +bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
> + clear();
> +
> + Offset = *offset_ptr;
> +
> + if (debug_info.isValidOffset(*offset_ptr)) {
> + uint64_t abbrOffset;
> + const DWARFDebugAbbrev *abbr = Context.getDebugAbbrev();
> + 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 = Context.getAbbrevSection().size() > abbrOffset;
> + bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
> +
> + if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && abbr != NULL) {
> + Abbrevs = abbr->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;
> +}
> +
> +void DWARFCompileUnit::clear() {
> + Offset = 0;
> + Length = 0;
> + Version = 0;
> + Abbrevs = 0;
> + AddrSize = 0;
> + BaseAddr = 0;
> + DieArray.clear();
> +}
> +
> +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())
> + << ")\n";
> +
> + extractDIEsIfNeeded(false);
> + for (unsigned i = 0, e = DieArray.size(); i != e; ++i)
> + DieArray[i].dump(OS, this, 10);
> +}
> +
> +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::getFixedFormSizesForAddressSize(getAddressByteSize());
> +
> + 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();
> +}
>
> Added: llvm/trunk/lib/DebugInfo/DWARFCompileUnit.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFCompileUnit.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFCompileUnit.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFCompileUnit.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,98 @@
> +//===-- DWARFCompileUnit.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_DWARFCOMPILEUNIT_H
> +#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
> +
> +#include "DWARFDebugAbbrev.h"
> +#include "DWARFDebugInfoEntry.h"
> +#include <vector>
> +
> +namespace llvm {
> +
> +class DWARFContext;
> +class raw_ostream;
> +
> +class DWARFCompileUnit {
> + DWARFContext &Context;
> +
> + 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;
> +public:
> + DWARFCompileUnit(DWARFContext &context) : Context(context) {
> + clear();
> + }
> +
> + DWARFContext &getContext() const { return Context; }
> + 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.
> + size_t extractDIEsIfNeeded(bool cu_die_only);
> + void clear();
> + 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;
> + }
> +
> + /// 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);
> + }
> +};
> +
> +}
> +
> +#endif
>
> Added: llvm/trunk/lib/DebugInfo/DWARFContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFContext.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFContext.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFContext.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,43 @@
> +//===-- DWARFContext.cpp --------------------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "DWARFContext.h"
> +using namespace llvm;
> +
> +void DWARFContext::dump(raw_ostream &OS) {
> + getDebugAbbrev()->dump(OS);
> + for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
> + getCompileUnitAtIndex(i)->dump(OS);
> +}
> +
> +const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
> + if (Abbrev)
> + return Abbrev.get();
> +
> + DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
> +
> + Abbrev.reset(new DWARFDebugAbbrev());
> + Abbrev->parse(abbrData);
> + return Abbrev.get();
> +}
> +
> +void DWARFContext::parseCompileUnits() {
> + uint32_t offset = 0;
> + const DataExtractor &debug_info_data = DataExtractor(getInfoSection(),
> + isLittleEndian(), 0);
> + while (debug_info_data.isValidOffset(offset)) {
> + CUs.push_back(DWARFCompileUnit(*this));
> + if (!CUs.back().extract(debug_info_data, &offset)) {
> + CUs.pop_back();
> + break;
> + }
> +
> + offset = CUs.back().getNextCompileUnitOffset();
> + }
> +}
>
> Added: llvm/trunk/lib/DebugInfo/DWARFContext.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFContext.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFContext.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFContext.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,104 @@
> +//===-- DWARFContext.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_DWARFCONTEXT_H
> +#define LLVM_DEBUGINFO_DWARFCONTEXT_H
> +
> +#include "DWARFCompileUnit.h"
> +#include "llvm/DebugInfo/DIContext.h"
> +#include "llvm/ADT/OwningPtr.h"
> +#include "llvm/ADT/SmallVector.h"
> +
> +namespace llvm {
> +
> +class DWARFDebugAbbrev;
> +
> +/// DWARFContext
> +/// This data structure is the top level entity that deals with dwarf debug
> +/// information parsing. The actual data is supplied through pure virtual
> +/// methods that a concrete implementation provides.
> +class DWARFContext : public DIContext {
> + bool IsLittleEndian;
> +
> + SmallVector<DWARFCompileUnit, 1> CUs;
> + OwningPtr<DWARFDebugAbbrev> Abbrev;
> +
> + DWARFContext(DWARFContext &); // = delete
> + DWARFContext &operator=(DWARFContext &); // = delete
> +
> + /// Read compile units from the debug_info section and store them in CUs.
> + void parseCompileUnits();
> +protected:
> + DWARFContext(bool isLittleEndian) : IsLittleEndian(isLittleEndian) {}
> +public:
> + virtual void dump(raw_ostream &OS);
> + /// Get the number of compile units in this context.
> + unsigned getNumCompileUnits() {
> + if (CUs.empty())
> + parseCompileUnits();
> + return CUs.size();
> + }
> + /// Get the compile unit at the specified index for this compile unit.
> + DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) {
> + if (CUs.empty())
> + parseCompileUnits();
> + return &CUs[index];
> + }
> +
> + /// Get a pointer to the parsed DebugAbbrev object.
> + const DWARFDebugAbbrev *getDebugAbbrev();
> +
> + bool isLittleEndian() const { return IsLittleEndian; }
> +
> + virtual StringRef getInfoSection() = 0;
> + virtual StringRef getAbbrevSection() = 0;
> + virtual StringRef getARangeSection() = 0;
> + virtual StringRef getLineSection() = 0;
> + virtual StringRef getStringSection() = 0;
> +
> + static bool isSupportedVersion(unsigned version) {
> + return version == 2 || version == 3;
> + }
> +};
> +
> +
> +/// DWARFContextInMemory is the simplest possible implementation of a
> +/// DWARFContext. It assumes all content is available in memory and stores
> +/// pointers to it.
> +class DWARFContextInMemory : public DWARFContext {
> + StringRef InfoSection;
> + StringRef AbbrevSection;
> + StringRef ARangeSection;
> + StringRef LineSection;
> + StringRef StringSection;
> +public:
> + DWARFContextInMemory(bool isLittleEndian,
> + StringRef infoSection,
> + StringRef abbrevSection,
> + StringRef aRangeSection,
> + StringRef lineSection,
> + StringRef stringSection)
> + : DWARFContext(isLittleEndian),
> + InfoSection(infoSection),
> + AbbrevSection(abbrevSection),
> + ARangeSection(aRangeSection),
> + LineSection(lineSection),
> + StringSection(stringSection)
> + {}
> +
> + virtual StringRef getInfoSection() { return InfoSection; }
> + virtual StringRef getAbbrevSection() { return AbbrevSection; }
> + virtual StringRef getARangeSection() { return ARangeSection; }
> + virtual StringRef getLineSection() { return LineSection; }
> + virtual StringRef getStringSection() { return StringSection; }
> +};
> +
> +}
> +
> +#endif
>
> Added: llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,108 @@
> +//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "DWARFDebugAbbrev.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/Support/raw_ostream.h"
> +using namespace llvm;
> +
> +bool DWARFAbbreviationDeclarationSet::extract(DataExtractor data,
> + uint32_t* offset_ptr) {
> + const uint32_t beginOffset = *offset_ptr;
> + Offset = beginOffset;
> + clear();
> + DWARFAbbreviationDeclaration abbrevDeclaration;
> + uint32_t prevAbbrAode = 0;
> + while (abbrevDeclaration.extract(data, offset_ptr)) {
> + Decls.push_back(abbrevDeclaration);
> + if (IdxOffset == 0) {
> + IdxOffset = abbrevDeclaration.getCode();
> + } else {
> + if (prevAbbrAode + 1 != abbrevDeclaration.getCode())
> + IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups
> + }
> + prevAbbrAode = abbrevDeclaration.getCode();
> + }
> + return beginOffset != *offset_ptr;
> +}
> +
> +
> +void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
> + for (unsigned i = 0, e = Decls.size(); i != e; ++i)
> + Decls[i].dump(OS);
> +}
> +
> +
> +const DWARFAbbreviationDeclaration*
> +DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode)
> + const {
> + if (IdxOffset == UINT32_MAX) {
> + DWARFAbbreviationDeclarationCollConstIter pos;
> + DWARFAbbreviationDeclarationCollConstIter end = Decls.end();
> + for (pos = Decls.begin(); pos != end; ++pos) {
> + if (pos->getCode() == abbrCode)
> + return &(*pos);
> + }
> + } else {
> + uint32_t idx = abbrCode - IdxOffset;
> + if (idx < Decls.size())
> + return &Decls[idx];
> + }
> + return NULL;
> +}
> +
> +DWARFDebugAbbrev::DWARFDebugAbbrev() :
> + m_abbrevCollMap(),
> + m_prev_abbr_offset_pos(m_abbrevCollMap.end()) {}
> +
> +
> +void DWARFDebugAbbrev::parse(DataExtractor data) {
> + uint32_t offset = 0;
> +
> + while (data.isValidOffset(offset)) {
> + uint32_t initial_cu_offset = offset;
> + DWARFAbbreviationDeclarationSet abbrevDeclSet;
> +
> + if (abbrevDeclSet.extract(data, &offset))
> + m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet;
> + else
> + break;
> + }
> + m_prev_abbr_offset_pos = m_abbrevCollMap.end();
> +}
> +
> +void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
> + if (m_abbrevCollMap.empty()) {
> + OS << "< EMPTY >\n";
> + return;
> + }
> +
> + DWARFAbbreviationDeclarationCollMapConstIter pos;
> + for (pos = m_abbrevCollMap.begin(); pos != m_abbrevCollMap.end(); ++pos) {
> + OS << format("Abbrev table for offset: 0x%8.8x\n", pos->first);
> + pos->second.dump(OS);
> + }
> +}
> +
> +const DWARFAbbreviationDeclarationSet*
> +DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const {
> + DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end();
> + DWARFAbbreviationDeclarationCollMapConstIter pos;
> + if (m_prev_abbr_offset_pos != end &&
> + m_prev_abbr_offset_pos->first == cu_abbr_offset) {
> + return &(m_prev_abbr_offset_pos->second);
> + } else {
> + pos = m_abbrevCollMap.find(cu_abbr_offset);
> + m_prev_abbr_offset_pos = pos;
> + }
> +
> + if (pos != m_abbrevCollMap.end())
> + return &(pos->second);
> + return NULL;
> +}
>
> Added: llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFDebugAbbrev.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,71 @@
> +//===-- DWARFDebugAbbrev.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_DWARFDEBUGABBREV_H
> +#define LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
> +
> +#include "DWARFAbbreviationDeclaration.h"
> +#include <list>
> +#include <map>
> +#include <vector>
> +
> +namespace llvm {
> +
> +typedef std::vector<DWARFAbbreviationDeclaration>
> + DWARFAbbreviationDeclarationColl;
> +typedef DWARFAbbreviationDeclarationColl::iterator
> + DWARFAbbreviationDeclarationCollIter;
> +typedef DWARFAbbreviationDeclarationColl::const_iterator
> + DWARFAbbreviationDeclarationCollConstIter;
> +
> +class DWARFAbbreviationDeclarationSet {
> + uint64_t Offset;
> + uint32_t IdxOffset;
> + std::vector<DWARFAbbreviationDeclaration> Decls;
> + public:
> + DWARFAbbreviationDeclarationSet()
> + : Offset(0), IdxOffset(0) {}
> +
> + DWARFAbbreviationDeclarationSet(uint64_t offset, uint32_t idxOffset)
> + : Offset(offset), IdxOffset(idxOffset) {}
> +
> + void clear() {
> + IdxOffset = 0;
> + Decls.clear();
> + }
> + uint64_t getOffset() const { return Offset; }
> + void dump(raw_ostream &OS) const;
> + bool extract(DataExtractor data, uint32_t* offset_ptr);
> +
> + const DWARFAbbreviationDeclaration *
> + getAbbreviationDeclaration(uint32_t abbrCode) const;
> +};
> +
> +typedef std::map<uint64_t, DWARFAbbreviationDeclarationSet>
> + DWARFAbbreviationDeclarationCollMap;
> +typedef DWARFAbbreviationDeclarationCollMap::iterator
> + DWARFAbbreviationDeclarationCollMapIter;
> +typedef DWARFAbbreviationDeclarationCollMap::const_iterator
> + DWARFAbbreviationDeclarationCollMapConstIter;
> +
> +class DWARFDebugAbbrev {
> +public:
> + DWARFDebugAbbrev();
> + const DWARFAbbreviationDeclarationSet *
> + getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const;
> + void dump(raw_ostream &OS) const;
> + void parse(DataExtractor data);
> +protected:
> + DWARFAbbreviationDeclarationCollMap m_abbrevCollMap;
> + mutable DWARFAbbreviationDeclarationCollMapConstIter m_prev_abbr_offset_pos;
> +};
> +
> +}
> +
> +#endif
>
> Added: llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,410 @@
> +//===-- DWARFDebugInfoEntry.cpp --------------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "DWARFDebugInfoEntry.h"
> +#include "DWARFCompileUnit.h"
> +#include "DWARFContext.h"
> +#include "DWARFDebugAbbrev.h"
> +#include "DWARFFormValue.h"
> +#include "llvm/Support/Dwarf.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/Support/raw_ostream.h"
> +using namespace llvm;
> +using namespace dwarf;
> +
> +void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
> + const DWARFCompileUnit *cu,
> + unsigned recurseDepth,
> + unsigned indent) const {
> + DataExtractor debug_info_data = cu->getDebugInfoExtractor();
> + uint32_t offset = Offset;
> +
> + if (debug_info_data.isValidOffset(offset)) {
> + uint64_t abbrCode = debug_info_data.getULEB128(&offset);
> +
> + OS.indent(indent) << format("\n0x%8.8x: ", Offset);
> + if (abbrCode) {
> + if (AbbrevDecl) {
> + OS << TagString(AbbrevDecl->getTag())
> + << format(" [%u] %c\n", abbrCode,
> + AbbrevDecl->hasChildren() ? '*': ' ');
> +
> + // Dump all data in the .debug_info for the attributes
> + const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
> + 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);
> + }
> +
> + const DWARFDebugInfoEntryMinimal *child = getFirstChild();
> + if (recurseDepth > 0 && child) {
> + indent += 2;
> + while (child) {
> + child->dump(OS, cu, recurseDepth-1, indent);
> + child = child->getSibling();
> + }
> + indent -= 2;
> + }
> + } else {
> + OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
> + << abbrCode << '\n';
> + }
> + } else {
> + OS << "NULL\n";
> + }
> + }
> +}
> +
> +void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
> + const DWARFCompileUnit *cu,
> + uint32_t* offset_ptr,
> + uint16_t attr,
> + uint16_t form,
> + unsigned indent) const {
> + OS.indent(indent) << format("0x%8.8x: ", *offset_ptr)
> + << AttributeString(attr)
> + << " [" << FormEncodingString(form) << ']';
> +
> + DWARFFormValue formValue(form);
> +
> + if (!formValue.extractValue(cu->getDebugInfoExtractor(), offset_ptr, cu))
> + return;
> +
> + OS << "\t(";
> + formValue.dump(OS, 0, cu);
> + OS << ")\n";
> +}
> +
> +bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
> + const uint8_t *fixed_form_sizes,
> + uint32_t *offset_ptr) {
> + Offset = *offset_ptr;
> +
> + DataExtractor debug_info_data = cu->getDebugInfoExtractor();
> + uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr);
> +
> + assert (fixed_form_sizes); // For best performance this should be specified!
> +
> + if (abbrCode) {
> + uint32_t offset = *offset_ptr;
> +
> + AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);
> +
> + // Skip all data in the .debug_info for the attributes
> + const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
> + uint32_t i;
> + uint16_t form;
> + for (i=0; i<numAttributes; ++i) {
> + form = AbbrevDecl->getFormByIndex(i);
> +
> + const uint8_t fixed_skip_size = fixed_form_sizes[form];
> + if (fixed_skip_size)
> + offset += fixed_skip_size;
> + else {
> + bool form_is_indirect = false;
> + do {
> + form_is_indirect = false;
> + uint32_t form_size = 0;
> + switch (form) {
> + // Blocks if inlined data that have a length field and the data bytes
> + // inlined in the .debug_info.
> + case DW_FORM_block:
> + form_size = debug_info_data.getULEB128(&offset);
> + break;
> + case DW_FORM_block1:
> + form_size = debug_info_data.getU8(&offset);
> + break;
> + case DW_FORM_block2:
> + form_size = debug_info_data.getU16(&offset);
> + break;
> + case DW_FORM_block4:
> + form_size = debug_info_data.getU32(&offset);
> + break;
> +
> + // Inlined NULL terminated C-strings
> + case DW_FORM_string:
> + debug_info_data.getCStr(&offset);
> + break;
> +
> + // Compile unit address sized values
> + case DW_FORM_addr:
> + case DW_FORM_ref_addr:
> + form_size = cu->getAddressByteSize();
> + break;
> +
> + // 1 byte values
> + case DW_FORM_data1:
> + case DW_FORM_flag:
> + case DW_FORM_ref1:
> + form_size = 1;
> + break;
> +
> + // 2 byte values
> + case DW_FORM_data2:
> + case DW_FORM_ref2:
> + form_size = 2;
> + break;
> +
> + // 4 byte values
> + case DW_FORM_strp:
> + case DW_FORM_data4:
> + case DW_FORM_ref4:
> + form_size = 4;
> + break;
> +
> + // 8 byte values
> + case DW_FORM_data8:
> + case DW_FORM_ref8:
> + form_size = 8;
> + break;
> +
> + // signed or unsigned LEB 128 values
> + case DW_FORM_sdata:
> + case DW_FORM_udata:
> + case DW_FORM_ref_udata:
> + debug_info_data.getULEB128(&offset);
> + break;
> +
> + case DW_FORM_indirect:
> + form_is_indirect = true;
> + form = debug_info_data.getULEB128(&offset);
> + break;
> +
> + default:
> + *offset_ptr = Offset;
> + return false;
> + }
> + offset += form_size;
> +
> + } while (form_is_indirect);
> + }
> + }
> + *offset_ptr = offset;
> + return true;
> + } else {
> + AbbrevDecl = NULL;
> + return true; // NULL debug tag entry
> + }
> +
> + return false;
> +}
> +
> +bool
> +DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
> + uint32_t *offset_ptr) {
> + DataExtractor debug_info_data = cu->getDebugInfoExtractor();
> + const uint32_t cu_end_offset = cu->getNextCompileUnitOffset();
> + const uint8_t cu_addr_size = cu->getAddressByteSize();
> + uint32_t offset = *offset_ptr;
> + if ((offset < cu_end_offset) && debug_info_data.isValidOffset(offset)) {
> + Offset = offset;
> +
> + uint64_t abbrCode = debug_info_data.getULEB128(&offset);
> +
> + if (abbrCode) {
> + AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);
> +
> + if (AbbrevDecl) {
> + uint16_t tag = AbbrevDecl->getTag();
> +
> + bool isCompileUnitTag = tag == DW_TAG_compile_unit;
> + if(cu && isCompileUnitTag)
> + const_cast<DWARFCompileUnit*>(cu)->setBaseAddress(0);
> +
> + // Skip all data in the .debug_info for the attributes
> + const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
> + for (uint32_t i = 0; i != numAttributes; ++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 form_value(form);
> + if (form_value.extractValue(debug_info_data, &offset, cu)) {
> + if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
> + const_cast<DWARFCompileUnit*>(cu)
> + ->setBaseAddress(form_value.getUnsigned());
> + }
> + } else {
> + bool form_is_indirect = false;
> + do {
> + form_is_indirect = false;
> + register uint32_t form_size = 0;
> + switch (form) {
> + // Blocks if inlined data that have a length field and the data
> + // bytes // inlined in the .debug_info
> + case DW_FORM_block:
> + form_size = debug_info_data.getULEB128(&offset);
> + break;
> + case DW_FORM_block1:
> + form_size = debug_info_data.getU8(&offset);
> + break;
> + case DW_FORM_block2:
> + form_size = debug_info_data.getU16(&offset);
> + break;
> + case DW_FORM_block4:
> + form_size = debug_info_data.getU32(&offset);
> + break;
> +
> + // Inlined NULL terminated C-strings
> + case DW_FORM_string:
> + debug_info_data.getCStr(&offset);
> + break;
> +
> + // Compile unit address sized values
> + case DW_FORM_addr:
> + case DW_FORM_ref_addr:
> + form_size = cu_addr_size;
> + break;
> +
> + // 1 byte values
> + case DW_FORM_data1:
> + case DW_FORM_flag:
> + case DW_FORM_ref1:
> + form_size = 1;
> + break;
> +
> + // 2 byte values
> + case DW_FORM_data2:
> + case DW_FORM_ref2:
> + form_size = 2;
> + break;
> +
> + // 4 byte values
> + case DW_FORM_strp:
> + form_size = 4;
> + break;
> +
> + case DW_FORM_data4:
> + case DW_FORM_ref4:
> + form_size = 4;
> + break;
> +
> + // 8 byte values
> + case DW_FORM_data8:
> + case DW_FORM_ref8:
> + form_size = 8;
> + break;
> +
> + // signed or unsigned LEB 128 values
> + case DW_FORM_sdata:
> + case DW_FORM_udata:
> + case DW_FORM_ref_udata:
> + debug_info_data.getULEB128(&offset);
> + break;
> +
> + case DW_FORM_indirect:
> + form = debug_info_data.getULEB128(&offset);
> + form_is_indirect = true;
> + break;
> +
> + default:
> + *offset_ptr = offset;
> + return false;
> + }
> +
> + offset += form_size;
> + } while (form_is_indirect);
> + }
> + }
> + *offset_ptr = offset;
> + return true;
> + }
> + } else {
> + AbbrevDecl = NULL;
> + *offset_ptr = offset;
> + return true; // NULL debug tag entry
> + }
> + }
> +
> + return false;
> +}
> +
> +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();
> +
> + DataExtractor debug_info_data = cu->getDebugInfoExtractor();
> +
> + // Skip the abbreviation code so we are at the data for the attributes
> + debug_info_data.getULEB128(&offset);
> +
> + uint32_t idx = 0;
> + while (idx < attr_idx)
> + DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(idx++),
> + debug_info_data, &offset, cu);
> +
> + 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;
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> +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->getContext().getStringSection(),
> + false, 0);
> + return form_value.getAsCString(&stringExtractor);
> + }
> + return fail_value;
> +}
> +
> +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;
> +}
> +
> +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 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;
> +}
>
> Added: llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,131 @@
> +//===-- DWARFDebugInfoEntry.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_DWARFDEBUGINFOENTRY_H
> +#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
> +
> +#include "DWARFAbbreviationDeclaration.h"
> +#include "llvm/Support/DataTypes.h"
> +
> +namespace llvm {
> +
> +class DWARFCompileUnit;
> +class DWARFContext;
> +class DWARFFormValue;
> +
> +/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
> +class DWARFDebugInfoEntryMinimal {
> + /// Offset within the .debug_info of the start of this entry.
> + uint64_t Offset;
> +
> + /// How many to subtract from "this" to get the parent.
> + /// If zero this die has no parent.
> + uint32_t ParentIdx;
> +
> + /// How many to add to "this" to get the sibling.
> + uint32_t SiblingIdx;
> +
> + const DWARFAbbreviationDeclaration *AbbrevDecl;
> +public:
> + 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;
> +
> + bool extractFast(const DWARFCompileUnit *cu, const uint8_t *fixed_form_sizes,
> + uint32_t *offset_ptr);
> +
> + /// Extract a debug info entry for a given compile unit from the
> + /// .debug_info and .debug_abbrev data starting at the given offset.
> + bool extract(const DWARFCompileUnit *cu, uint32_t *offset_ptr);
> +
> + uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
> + bool isNULL() const { return AbbrevDecl == 0; }
> + uint64_t getOffset() const { return Offset; }
> + uint32_t getNumAttributes() const {
> + return !isNULL() ? AbbrevDecl->getNumAttributes() : 0;
> + }
> + bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); }
> +
> + // We know we are kept in a vector of contiguous entries, so we know
> + // our parent will be some index behind "this".
> + DWARFDebugInfoEntryMinimal *getParent() {
> + return ParentIdx > 0 ? this - ParentIdx : 0;
> + }
> + const DWARFDebugInfoEntryMinimal *getParent() const {
> + return ParentIdx > 0 ? this - ParentIdx : 0;
> + }
> + // We know we are kept in a vector of contiguous entries, so we know
> + // our sibling will be some index after "this".
> + DWARFDebugInfoEntryMinimal *getSibling() {
> + return SiblingIdx > 0 ? this + SiblingIdx : 0;
> + }
> + const DWARFDebugInfoEntryMinimal *getSibling() const {
> + return SiblingIdx > 0 ? this + SiblingIdx : 0;
> + }
> + // We know we are kept in a vector of contiguous entries, so we know
> + // we don't need to store our child pointer, if we have a child it will
> + // be the next entry in the list...
> + DWARFDebugInfoEntryMinimal *getFirstChild() {
> + return hasChildren() ? this + 1 : 0;
> + }
> + const DWARFDebugInfoEntryMinimal *getFirstChild() const {
> + return hasChildren() ? this + 1 : 0;
> + }
> +
> + void setParent(DWARFDebugInfoEntryMinimal *parent) {
> + if (parent) {
> + // We know we are kept in a vector of contiguous entries, so we know
> + // our parent will be some index behind "this".
> + ParentIdx = this - parent;
> + }
> + else
> + ParentIdx = 0;
> + }
> + void setSibling(DWARFDebugInfoEntryMinimal *sibling) {
> + if (sibling)
> + {
> + // We know we are kept in a vector of contiguous entries, so we know
> + // our sibling will be some index after "this".
> + SiblingIdx = sibling - this;
> + sibling->setParent(getParent());
> + }
> + else
> + SiblingIdx = 0;
> + }
> +
> + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
> + return AbbrevDecl;
> + }
> +
> + uint32_t getAttributeValue(const DWARFCompileUnit *cu,
> + const uint16_t attr, DWARFFormValue &formValue,
> + uint32_t *end_attr_offset_ptr = 0) const;
> +
> + const char* getAttributeValueAsString(const DWARFCompileUnit* cu,
> + const uint16_t attr,
> + const char *fail_value) const;
> +
> + uint64_t getAttributeValueAsUnsigned(const DWARFCompileUnit *cu,
> + const uint16_t attr,
> + uint64_t fail_value) const;
> +
> + uint64_t getAttributeValueAsReference(const DWARFCompileUnit *cu,
> + const uint16_t attr,
> + uint64_t fail_value) const;
> +
> + int64_t getAttributeValueAsSigned(const DWARFCompileUnit* cu,
> + const uint16_t attr,
> + int64_t fail_value) const;
> +};
> +
> +}
> +
> +#endif
>
> Added: llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,434 @@
> +//===-- DWARFFormValue.cpp ------------------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "DWARFFormValue.h"
> +#include "DWARFCompileUnit.h"
> +#include "llvm/Support/Dwarf.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include <cassert>
> +using namespace llvm;
> +using namespace dwarf;
> +
> +static const uint8_t form_sizes_addr4[] = {
> + 0, // 0x00 unused
> + 4, // 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
> + 4, // 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
> +};
> +
> +static const uint8_t form_sizes_addr8[] = {
> + 0, // 0x00 unused
> + 8, // 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
> + 8, // 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
> +};
> +
> +const uint8_t *
> +DWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) {
> + switch (addr_size) {
> + case 4: return form_sizes_addr4;
> + case 8: return form_sizes_addr8;
> + }
> + return NULL;
> +}
> +
> +bool
> +DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
> + const DWARFCompileUnit* cu) {
> + bool indirect = false;
> + bool is_block = false;
> + Value.data = NULL;
> + // Read the value for the form into value and follow and DW_FORM_indirect
> + // instances we run into
> + do {
> + indirect = false;
> + switch (Form) {
> + case DW_FORM_addr:
> + case DW_FORM_ref_addr:
> + Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
> + break;
> + case DW_FORM_block:
> + Value.uval = data.getULEB128(offset_ptr);
> + is_block = true;
> + break;
> + case DW_FORM_block1:
> + Value.uval = data.getU8(offset_ptr);
> + is_block = true;
> + break;
> + case DW_FORM_block2:
> + Value.uval = data.getU16(offset_ptr);
> + is_block = true;
> + break;
> + case DW_FORM_block4:
> + Value.uval = data.getU32(offset_ptr);
> + is_block = true;
> + break;
> + case DW_FORM_data1:
> + case DW_FORM_ref1:
> + case DW_FORM_flag:
> + Value.uval = data.getU8(offset_ptr);
> + break;
> + case DW_FORM_data2:
> + case DW_FORM_ref2:
> + Value.uval = data.getU16(offset_ptr);
> + break;
> + case DW_FORM_data4:
> + case DW_FORM_ref4:
> + Value.uval = data.getU32(offset_ptr);
> + break;
> + case DW_FORM_data8:
> + case DW_FORM_ref8:
> + Value.uval = data.getU64(offset_ptr);
> + break;
> + case DW_FORM_sdata:
> + Value.sval = data.getSLEB128(offset_ptr);
> + break;
> + case DW_FORM_strp:
> + Value.uval = data.getU32(offset_ptr);
> + break;
> + case DW_FORM_udata:
> + case DW_FORM_ref_udata:
> + Value.uval = data.getULEB128(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 = (uint8_t*)Value.cstr;
> + break;
> + case DW_FORM_indirect:
> + Form = data.getULEB128(offset_ptr);
> + indirect = true;
> + break;
> + default:
> + return false;
> + }
> + } while (indirect);
> +
> + if (is_block) {
> + StringRef str = data.getData().substr(*offset_ptr, Value.uval);
> + Value.data = NULL;
> + if (!str.empty()) {
> + Value.data = reinterpret_cast<const uint8_t *>(str.data());
> + *offset_ptr += Value.uval;
> + }
> + }
> +
> + return true;
> +}
> +
> +bool
> +DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
> + const DWARFCompileUnit* 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) {
> + bool indirect = false;
> + do {
> + indirect = false;
> + switch (form) {
> + // Blocks if inlined data that have a length field and the data bytes
> + // inlined in the .debug_info
> + case DW_FORM_block: {
> + uint64_t size = debug_info_data.getULEB128(offset_ptr);
> + *offset_ptr += size;
> + return true;
> + }
> + case DW_FORM_block1: {
> + uint8_t size = debug_info_data.getU8(offset_ptr);
> + *offset_ptr += size;
> + return true;
> + }
> + case DW_FORM_block2: {
> + uint16_t size = debug_info_data.getU16(offset_ptr);
> + *offset_ptr += size;
> + return true;
> + }
> + case DW_FORM_block4: {
> + uint32_t size = debug_info_data.getU32(offset_ptr);
> + *offset_ptr += size;
> + return true;
> + }
> +
> + // Inlined NULL terminated C-strings
> + case DW_FORM_string:
> + debug_info_data.getCStr(offset_ptr);
> + return true;
> +
> + // Compile unit address sized values
> + case DW_FORM_addr:
> + case DW_FORM_ref_addr:
> + *offset_ptr += cu->getAddressByteSize();
> + return true;
> +
> + // 1 byte values
> + case DW_FORM_data1:
> + case DW_FORM_flag:
> + case DW_FORM_ref1:
> + *offset_ptr += 1;
> + return true;
> +
> + // 2 byte values
> + case DW_FORM_data2:
> + case DW_FORM_ref2:
> + *offset_ptr += 2;
> + return true;
> +
> + // 4 byte values
> + case DW_FORM_strp:
> + case DW_FORM_data4:
> + case DW_FORM_ref4:
> + *offset_ptr += 4;
> + return true;
> +
> + // 8 byte values
> + case DW_FORM_data8:
> + case DW_FORM_ref8:
> + *offset_ptr += 8;
> + return true;
> +
> + // signed or unsigned LEB 128 values
> + // case DW_FORM_APPLE_db_str:
> + case DW_FORM_sdata:
> + case DW_FORM_udata:
> + case DW_FORM_ref_udata:
> + debug_info_data.getULEB128(offset_ptr);
> + return true;
> +
> + case DW_FORM_indirect:
> + indirect = true;
> + form = debug_info_data.getULEB128(offset_ptr);
> + break;
> + default:
> + return false;
> + }
> + } while (indirect);
> + return true;
> +}
> +
> +void
> +DWARFFormValue::dump(raw_ostream &OS, const DataExtractor *debug_str_data,
> + const DWARFCompileUnit *cu) const {
> + uint64_t uvalue = getUnsigned();
> + bool cu_relative_offset = false;
> +
> + switch (Form)
> + {
> + case DW_FORM_addr: OS << format("0x%016x", uvalue); break;
> + case DW_FORM_flag:
> + case DW_FORM_data1: OS << format("0x%02x", uvalue); break;
> + case DW_FORM_data2: OS << format("0x%04x", uvalue); break;
> + case DW_FORM_data4: OS << format("0x%08x", uvalue); break;
> + case DW_FORM_data8: OS << format("0x%016x", uvalue); break;
> + case DW_FORM_string:
> + OS << '"';
> + OS.write_escaped(getAsCString(NULL));
> + OS << '"';
> + break;
> + case DW_FORM_block:
> + case DW_FORM_block1:
> + case DW_FORM_block2:
> + case DW_FORM_block4:
> + if (uvalue > 0) {
> + switch (Form) {
> + case DW_FORM_block: OS << format("<0x%llx> ", uvalue); break;
> + case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break;
> + case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
> + case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
> + default: break;
> + }
> +
> + const uint8_t* data_ptr = Value.data;
> + if (data_ptr) {
> + // uvalue contains size of block
> + const uint8_t* end_data_ptr = data_ptr + uvalue;
> + while (data_ptr < end_data_ptr) {
> + OS << format("%2.2x ", *data_ptr);
> + ++data_ptr;
> + }
> + }
> + else
> + OS << "NULL";
> + }
> + break;
> +
> + case DW_FORM_sdata: OS << getSigned(); break;
> + case DW_FORM_udata: OS << getUnsigned(); break;
> + case DW_FORM_strp:
> + if (debug_str_data) {
> + OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
> + const char* dbg_str = getAsCString(debug_str_data);
> + if (dbg_str) {
> + OS << '"';
> + OS.write_escaped(dbg_str);
> + OS << '"';
> + }
> + } else {
> + OS << format("0x%08x", uvalue);
> + }
> + break;
> + case DW_FORM_ref_addr:
> + OS << format("0x%016x", uvalue);
> + break;
> + case DW_FORM_ref1:
> + cu_relative_offset = true;
> + OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
> + break;
> + case DW_FORM_ref2:
> + cu_relative_offset = true;
> + OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
> + break;
> + case DW_FORM_ref4:
> + cu_relative_offset = true;
> + OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
> + break;
> + case DW_FORM_ref8:
> + cu_relative_offset = true;
> + OS << format("cu + 0x%8.8llx", uvalue);
> + break;
> + case DW_FORM_ref_udata:
> + cu_relative_offset = true;
> + OS << format("cu + 0x%llx", uvalue);
> + break;
> +
> + // All DW_FORM_indirect attributes should be resolved prior to calling
> + // this function
> + case DW_FORM_indirect:
> + OS << "DW_FORM_indirect";
> + break;
> + default:
> + OS << format("DW_FORM(0x%4.4x)", Form);
> + break;
> + }
> +
> + if (cu_relative_offset)
> + OS << format(" => {0x%8.8x}", (uvalue + (cu ? cu->getOffset() : 0)));
> +}
> +
> +const char*
> +DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
> + if (isInlinedCStr()) {
> + return Value.cstr;
> + } else if (debug_str_data_ptr) {
> + uint32_t offset = Value.uval;
> + return debug_str_data_ptr->getCStr(&offset);
> + }
> + return NULL;
> +}
> +
> +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;
> + }
> +
> + return die_offset;
> +}
> +
> +bool
> +DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit* cu) {
> + 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;
> + default:
> + break;
> + }
> +
> + 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_block:
> + case DW_FORM_block1:
> + case DW_FORM_block2:
> + case DW_FORM_block4:
> + return true;
> + }
> + return false;
> +}
> +
> +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;
> +}
>
> Added: llvm/trunk/lib/DebugInfo/DWARFFormValue.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFFormValue.h?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFFormValue.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFFormValue.h Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,79 @@
> +//===-- DWARFFormValue.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_DWARFFORMVALUE_H
> +#define LLVM_DEBUGINFO_DWARFFORMVALUE_H
> +
> +#include "llvm/Support/DataExtractor.h"
> +
> +namespace llvm {
> +
> +class DWARFCompileUnit;
> +class raw_ostream;
> +
> +class DWARFFormValue {
> +public:
> + struct ValueType {
> + ValueType() : data(NULL) {
> + uval = 0;
> + }
> +
> + union {
> + uint64_t uval;
> + int64_t sval;
> + const char* cstr;
> + };
> + const uint8_t* data;
> + };
> +
> + enum {
> + eValueTypeInvalid = 0,
> + eValueTypeUnsigned,
> + eValueTypeSigned,
> + eValueTypeCStr,
> + eValueTypeBlock
> + };
> +
> +private:
> + uint16_t Form; // Form for this value.
> + ValueType Value; // Contains all data for the form.
> +
> +public:
> + DWARFFormValue(uint16_t form = 0) : Form(form) {}
> + uint16_t getForm() const { return Form; }
> + const ValueType& value() const { return Value; }
> + void dump(raw_ostream &OS, const DataExtractor *debug_str_data,
> + const DWARFCompileUnit* cu) const;
> + bool extractValue(DataExtractor data, uint32_t *offset_ptr,
> + const DWARFCompileUnit *cu);
> + bool isInlinedCStr() const {
> + return Value.data != NULL && Value.data == (uint8_t*)Value.cstr;
> + }
> + const uint8_t *BlockData() const;
> + uint64_t getReference(const DWARFCompileUnit* cu) const;
> +
> + /// Resolve any compile unit specific references so that we don't need
> + /// the compile unit at a later time in order to work with the form
> + /// value.
> + bool resolveCompileUnitReferences(const DWARFCompileUnit* cu);
> + uint64_t getUnsigned() const { return Value.uval; }
> + int64_t getSigned() const { return Value.sval; }
> + const char *getAsCString(const DataExtractor *debug_str_data_ptr) const;
> + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
> + const DWARFCompileUnit *cu) const;
> + static bool skipValue(uint16_t form, DataExtractor debug_info_data,
> + uint32_t *offset_ptr, const DWARFCompileUnit *cu);
> + static bool isBlockForm(uint16_t form);
> + static bool isDataForm(uint16_t form);
> + static const uint8_t *getFixedFormSizesForAddressSize(uint8_t addr_size);
> +};
> +
> +}
> +
> +#endif
>
> Copied: llvm/trunk/lib/DebugInfo/Makefile (from r139626, llvm/trunk/lib/Makefile)
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/Makefile?p2=llvm/trunk/lib/DebugInfo/Makefile&p1=llvm/trunk/lib/Makefile&r1=139626&r2=139627&rev=139627&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Makefile (original)
> +++ llvm/trunk/lib/DebugInfo/Makefile Tue Sep 13 14:42:23 2011
> @@ -1,4 +1,4 @@
> -##===- lib/Makefile ----------------------------------------*- Makefile -*-===##
> +##===- lib/DebugInfo/Makefile ------------------------------*- Makefile -*-===##
> #
> # The LLVM Compiler Infrastructure
> #
> @@ -6,12 +6,9 @@
> # License. See LICENSE.TXT for details.
> #
> ##===----------------------------------------------------------------------===##
> -LEVEL = ..
>
> -include $(LEVEL)/Makefile.config
> -
> -PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
> - Target ExecutionEngine Linker MC CompilerDriver Object
> +LEVEL = ../..
> +LIBRARYNAME = LLVMDebugInfo
> +BUILD_ARCHIVE := 1
>
> include $(LEVEL)/Makefile.common
> -
>
> Modified: llvm/trunk/lib/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Makefile?rev=139627&r1=139626&r2=139627&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Makefile (original)
> +++ llvm/trunk/lib/Makefile Tue Sep 13 14:42:23 2011
> @@ -11,7 +11,7 @@
> include $(LEVEL)/Makefile.config
>
> PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
> - Target ExecutionEngine Linker MC CompilerDriver Object
> + Target ExecutionEngine Linker MC CompilerDriver Object DebugInfo
>
> include $(LEVEL)/Makefile.common
>
>
> Modified: llvm/trunk/tools/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/CMakeLists.txt?rev=139627&r1=139626&r2=139627&view=diff
> ==============================================================================
> --- llvm/trunk/tools/CMakeLists.txt (original)
> +++ llvm/trunk/tools/CMakeLists.txt Tue Sep 13 14:42:23 2011
> @@ -39,6 +39,7 @@
> add_subdirectory(macho-dump)
> add_subdirectory(llvm-objdump)
> add_subdirectory(llvm-rtdyld)
> +add_subdirectory(llvm-dwarfdump)
>
> add_subdirectory(bugpoint)
> add_subdirectory(bugpoint-passes)
>
> Modified: llvm/trunk/tools/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=139627&r1=139626&r2=139627&view=diff
> ==============================================================================
> --- llvm/trunk/tools/Makefile (original)
> +++ llvm/trunk/tools/Makefile Tue Sep 13 14:42:23 2011
> @@ -26,7 +26,7 @@
> lli llvm-extract llvm-mc \
> bugpoint llvm-bcanalyzer llvm-stub \
> llvmc llvm-diff macho-dump llvm-objdump \
> - llvm-rtdyld
> + llvm-rtdyld llvm-dwarfdump
>
> # Let users override the set of tools to build from the command line.
> ifdef ONLY_TOOLS
>
> Added: llvm/trunk/tools/llvm-dwarfdump/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/CMakeLists.txt?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/tools/llvm-dwarfdump/CMakeLists.txt (added)
> +++ llvm/trunk/tools/llvm-dwarfdump/CMakeLists.txt Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,8 @@
> +set(LLVM_LINK_COMPONENTS
> + DebugInfo
> + Object
> + )
> +
> +add_llvm_tool(llvm-dwarfdump
> + llvm-dwarfdump.cpp
> + )
>
> Copied: llvm/trunk/tools/llvm-dwarfdump/Makefile (from r139626, llvm/trunk/lib/Makefile)
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/Makefile?p2=llvm/trunk/tools/llvm-dwarfdump/Makefile&p1=llvm/trunk/lib/Makefile&r1=139626&r2=139627&rev=139627&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Makefile (original)
> +++ llvm/trunk/tools/llvm-dwarfdump/Makefile Tue Sep 13 14:42:23 2011
> @@ -1,4 +1,4 @@
> -##===- lib/Makefile ----------------------------------------*- Makefile -*-===##
> +##===- tools/llvm-dwarfdump/Makefile -----------------------*- Makefile -*-===##
> #
> # The LLVM Compiler Infrastructure
> #
> @@ -6,12 +6,12 @@
> # License. See LICENSE.TXT for details.
> #
> ##===----------------------------------------------------------------------===##
> -LEVEL = ..
> +LEVEL = ../..
>
> -include $(LEVEL)/Makefile.config
> +TOOLNAME = llvm-dwarfdump
> +LINK_COMPONENTS = DebugInfo Object
>
> -PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
> - Target ExecutionEngine Linker MC CompilerDriver Object
> +# This tool has no plugins, optimize startup time.
> +TOOL_NO_EXPORTS = 1
>
> include $(LEVEL)/Makefile.common
> -
>
> Added: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp?rev=139627&view=auto
> ==============================================================================
> --- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp (added)
> +++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp Tue Sep 13 14:42:23 2011
> @@ -0,0 +1,93 @@
> +//===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm -----------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This program is a utility that works like "dwarfdump".
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/ADT/OwningPtr.h"
> +#include "llvm/ADT/Triple.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/Object/ObjectFile.h"
> +#include "llvm/DebugInfo/DIContext.h"
> +#include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/Support/ManagedStatic.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/MemoryObject.h"
> +#include "llvm/Support/PrettyStackTrace.h"
> +#include "llvm/Support/Signals.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Support/system_error.h"
> +#include <algorithm>
> +#include <cstring>
> +using namespace llvm;
> +using namespace object;
> +
> +static cl::list<std::string>
> +InputFilenames(cl::Positional, cl::desc("<input object files>"),
> + cl::ZeroOrMore);
> +
> +static void DumpInput(const StringRef &Filename) {
> + OwningPtr<MemoryBuffer> Buff;
> +
> + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
> + errs() << Filename << ": " << ec.message() << "\n";
> + return;
> + }
> +
> + OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
> +
> + outs() << '\n';
> + outs() << Filename
> + << ":\tfile format " << Obj->getFileFormatName() << "\n\n";
> +
> + StringRef DebugInfoSection;
> + StringRef DebugAbbrevSection;
> + StringRef DebugLineSection;
> +
> + error_code ec;
> + for (ObjectFile::section_iterator i = Obj->begin_sections(),
> + e = Obj->end_sections();
> + i != e; i.increment(ec)) {
> + StringRef name;
> + i->getName(name);
> + StringRef data;
> + i->getContents(data);
> + if (name.endswith("debug_info"))
> + DebugInfoSection = data;
> + else if (name.endswith("debug_abbrev"))
> + DebugAbbrevSection = data;
> + else if (name.endswith("debug_line"))
> + DebugLineSection = data;
> + }
> +
> + OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true,
> + DebugInfoSection,
> + DebugAbbrevSection));
> + dictx->dump(outs());
> +}
> +
> +int main(int argc, char **argv) {
> + // Print a stack trace if we signal out.
> + sys::PrintStackTraceOnErrorSignal();
> + PrettyStackTraceProgram X(argc, argv);
> + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
> +
> + cl::ParseCommandLineOptions(argc, argv, "llvm dwarf dumper\n");
> +
> + // Defaults to a.out if no filenames specified.
> + if (InputFilenames.size() == 0)
> + InputFilenames.push_back("a.out");
> +
> + std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput);
> +
> + return 0;
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list