[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