[llvm-commits] [llvm] r139680 - in /llvm/trunk: lib/DebugInfo/CMakeLists.txt lib/DebugInfo/DWARFContext.cpp lib/DebugInfo/DWARFContext.h lib/DebugInfo/DWARFDebugArangeSet.cpp lib/DebugInfo/DWARFDebugArangeSet.h lib/DebugInfo/DWARFDebugAranges.cpp lib/DebugInfo/DWARFDebugAranges.h tools/llvm-dwarfdump/llvm-dwarfdump.cpp

Evan Cheng evan.cheng at apple.com
Wed Sep 14 11:22:47 PDT 2011


On Sep 13, 2011, at 6:09 PM, Benjamin Kramer wrote:

> +
> +class DWARFDebugArangeSet {
> +public:
> +  struct Header {
> +    // The total length of the entries for that set, not including the length
> +    // field itself.
> +    uint32_t Length;
> +    // The DWARF version number.
> +    uint16_t Version;
> +    // The offset from the beginning of the .debug_info section of the
> +    // compilation unit entry referenced by the table.
> +    uint32_t CuOffset;
> +    // The size in bytes of an address on the target architecture. For segmented
> +    // addressing, this is the size of the offset portion of the address.
> +    uint8_t AddrSize;
> +    // The size in bytes of a segment descriptor on the target architecture.
> +    // If the target system uses a flat address space, this value is 0.
> +    uint8_t SegSize;
> +  };

Can you pack this class better to save some space?

Evan

> +
> +  struct Descriptor {
> +    uint64_t Address;
> +    uint64_t Length;
> +    uint64_t getEndAddress() const { return Address + Length; }
> +  };
> +
> +private:
> +  typedef std::vector<Descriptor> DescriptorColl;
> +  typedef DescriptorColl::iterator DescriptorIter;
> +  typedef DescriptorColl::const_iterator DescriptorConstIter;
> +
> +  uint32_t Offset;
> +  Header Header;
> +  DescriptorColl ArangeDescriptors;
> +
> +public:
> +  DWARFDebugArangeSet() { clear(); }
> +  void clear();
> +  void compact();
> +  bool extract(DataExtractor data, uint32_t *offset_ptr);
> +  void dump(raw_ostream &OS) const;
> +
> +  uint32_t getCompileUnitDIEOffset() const { return Header.CuOffset; }
> +  uint32_t getOffsetOfNextEntry() const { return Offset + Header.Length + 4; }
> +  uint32_t findAddress(uint64_t address) const;
> +  uint32_t getNumDescriptors() const { return ArangeDescriptors.size(); }
> +  const struct Header &getHeader() const { return Header; }
> +  const Descriptor *getDescriptor(uint32_t i) const {
> +    if (i < ArangeDescriptors.size())
> +      return &ArangeDescriptors[i];
> +    return NULL;
> +  }
> +};
> +
> +}
> +
> +#endif
> 
> Added: llvm/trunk/lib/DebugInfo/DWARFDebugAranges.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugAranges.cpp?rev=139680&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFDebugAranges.cpp (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFDebugAranges.cpp Tue Sep 13 20:09:52 2011
> @@ -0,0 +1,210 @@
> +//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "DWARFDebugAranges.h"
> +#include "DWARFCompileUnit.h"
> +#include "DWARFContext.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include <algorithm>
> +#include <cassert>
> +using namespace llvm;
> +
> +// Compare function DWARFDebugAranges::Range structures
> +static bool RangeLessThan(const DWARFDebugAranges::Range &range1,
> +                          const DWARFDebugAranges::Range &range2) {
> +  return range1.LoPC < range2.LoPC;
> +}
> +
> +namespace {
> +  class CountArangeDescriptors {
> +  public:
> +    CountArangeDescriptors(uint32_t &count_ref) : Count(count_ref) {}
> +    void operator()(const DWARFDebugArangeSet &set) {
> +      Count += set.getNumDescriptors();
> +    }
> +    uint32_t &Count;
> +  };
> +
> +  class AddArangeDescriptors {
> +  public:
> +    AddArangeDescriptors(DWARFDebugAranges::RangeColl &ranges)
> +      : RangeCollection(ranges) {}
> +    void operator()(const DWARFDebugArangeSet& set) {
> +      const DWARFDebugArangeSet::Descriptor* arange_desc_ptr;
> +      DWARFDebugAranges::Range range;
> +      range.Offset = set.getCompileUnitDIEOffset();
> +
> +      for (uint32_t i=0; (arange_desc_ptr = set.getDescriptor(i)) != NULL; ++i){
> +        range.LoPC = arange_desc_ptr->Address;
> +        range.Length = arange_desc_ptr->Length;
> +
> +        // Insert each item in increasing address order so binary searching
> +        // can later be done!
> +        DWARFDebugAranges::RangeColl::iterator insert_pos =
> +          std::lower_bound(RangeCollection.begin(), RangeCollection.end(),
> +                           range, RangeLessThan);
> +        RangeCollection.insert(insert_pos, range);
> +      }
> +    }
> +    DWARFDebugAranges::RangeColl& RangeCollection;
> +  };
> +}
> +
> +bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) {
> +  if (debug_aranges_data.isValidOffset(0)) {
> +    uint32_t offset = 0;
> +
> +    typedef std::vector<DWARFDebugArangeSet> SetCollection;
> +    typedef SetCollection::const_iterator SetCollectionIter;
> +    SetCollection sets;
> +
> +    DWARFDebugArangeSet set;
> +    Range range;
> +    while (set.extract(debug_aranges_data, &offset))
> +      sets.push_back(set);
> +
> +    uint32_t count = 0;
> +
> +    std::for_each(sets.begin(), sets.end(), CountArangeDescriptors(count));
> +
> +    if (count > 0) {
> +      Aranges.reserve(count);
> +      AddArangeDescriptors range_adder(Aranges);
> +      std::for_each(sets.begin(), sets.end(), range_adder);
> +    }
> +  }
> +  return false;
> +}
> +
> +void DWARFDebugAranges::dump(raw_ostream &OS) const {
> +  const uint32_t num_ranges = getNumRanges();
> +  for (uint32_t i = 0; i < num_ranges; ++i) {
> +    const Range &range = Aranges[i];
> +    OS << format("0x%8.8x: [0x%8.8llx - 0x%8.8llx)", range.Offset,
> +                 (uint64_t)range.LoPC, (uint64_t)range.HiPC());
> +  }
> +}
> +
> +void DWARFDebugAranges::Range::dump(raw_ostream &OS) const {
> +  OS << format("{0x%8.8x}: [0x%8.8llx - 0x%8.8llx)\n", Offset, LoPC, HiPC());
> +}
> +
> +void DWARFDebugAranges::appendRange(uint32_t offset, uint64_t low_pc,
> +                                    uint64_t high_pc) {
> +  if (!Aranges.empty()) {
> +    if (Aranges.back().Offset == offset && Aranges.back().HiPC() == low_pc) {
> +      Aranges.back().setHiPC(high_pc);
> +      return;
> +    }
> +  }
> +  Aranges.push_back(Range(low_pc, high_pc, offset));
> +}
> +
> +void DWARFDebugAranges::sort(bool minimize, uint32_t n) {
> +  const size_t orig_arange_size = Aranges.size();
> +  // Size of one? If so, no sorting is needed
> +  if (orig_arange_size <= 1)
> +    return;
> +  // Sort our address range entries
> +  std::stable_sort(Aranges.begin(), Aranges.end(), RangeLessThan);
> +
> +  if (!minimize)
> +    return;
> +
> +  // Most address ranges are contiguous from function to function
> +  // so our new ranges will likely be smaller. We calculate the size
> +  // of the new ranges since although std::vector objects can be resized,
> +  // the will never reduce their allocated block size and free any excesss
> +  // memory, so we might as well start a brand new collection so it is as
> +  // small as possible.
> +
> +  // First calculate the size of the new minimal arange vector
> +  // so we don't have to do a bunch of re-allocations as we
> +  // copy the new minimal stuff over to the new collection.
> +  size_t minimal_size = 1;
> +  for (size_t i = 1; i < orig_arange_size; ++i) {
> +    if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i], n))
> +      ++minimal_size;
> +  }
> +
> +  // If the sizes are the same, then no consecutive aranges can be
> +  // combined, we are done.
> +  if (minimal_size == orig_arange_size)
> +    return;
> +
> +  // Else, make a new RangeColl that _only_ contains what we need.
> +  RangeColl minimal_aranges;
> +  minimal_aranges.resize(minimal_size);
> +  uint32_t j = 0;
> +  minimal_aranges[j] = Aranges[0];
> +  for (size_t i = 1; i < orig_arange_size; ++i) {
> +    if(Range::SortedOverlapCheck (minimal_aranges[j], Aranges[i], n)) {
> +      minimal_aranges[j].setHiPC (Aranges[i].HiPC());
> +    } else {
> +      // Only increment j if we aren't merging
> +      minimal_aranges[++j] = Aranges[i];
> +    }
> +  }
> +  assert (j+1 == minimal_size);
> +
> +  // Now swap our new minimal aranges into place. The local
> +  // minimal_aranges will then contian the old big collection
> +  // which will get freed.
> +  minimal_aranges.swap(Aranges);
> +}
> +
> +uint32_t DWARFDebugAranges::findAddress(uint64_t address) const {
> +  if (!Aranges.empty()) {
> +    Range range(address);
> +    RangeCollIterator begin = Aranges.begin();
> +    RangeCollIterator end = Aranges.end();
> +    RangeCollIterator pos = lower_bound(begin, end, range, RangeLessThan);
> +
> +    if (pos != end && pos->LoPC <= address && address < pos->HiPC()) {
> +      return pos->Offset;
> +    } else if (pos != begin) {
> +      --pos;
> +      if (pos->LoPC <= address && address < pos->HiPC())
> +        return (*pos).Offset;
> +    }
> +  }
> +  return -1U;
> +}
> +
> +bool
> +DWARFDebugAranges::allRangesAreContiguous(uint64_t &LoPC, uint64_t &HiPC) const{
> +  if (Aranges.empty())
> +    return false;
> +
> +  uint64_t next_addr = 0;
> +  RangeCollIterator begin = Aranges.begin();
> +  for (RangeCollIterator pos = begin, end = Aranges.end(); pos != end;
> +       ++pos) {
> +    if (pos != begin && pos->LoPC != next_addr)
> +      return false;
> +    next_addr = pos->HiPC();
> +  }
> +  // We checked for empty at the start of function so front() will be valid.
> +  LoPC = Aranges.front().LoPC;
> +  // We checked for empty at the start of function so back() will be valid.
> +  HiPC = Aranges.back().HiPC();
> +  return true;
> +}
> +
> +bool DWARFDebugAranges::getMaxRange(uint64_t &LoPC, uint64_t &HiPC) const {
> +  if (Aranges.empty())
> +    return false;
> +  // We checked for empty at the start of function so front() will be valid.
> +  LoPC = Aranges.front().LoPC;
> +  // We checked for empty at the start of function so back() will be valid.
> +  HiPC = Aranges.back().HiPC();
> +  return true;
> +}
> +
> 
> Added: llvm/trunk/lib/DebugInfo/DWARFDebugAranges.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugAranges.h?rev=139680&view=auto
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/DWARFDebugAranges.h (added)
> +++ llvm/trunk/lib/DebugInfo/DWARFDebugAranges.h Tue Sep 13 20:09:52 2011
> @@ -0,0 +1,97 @@
> +//===-- DWARFDebugAranges.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_DWARFDEBUGARANGES_H
> +#define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
> +
> +#include "DWARFDebugArangeSet.h"
> +#include <list>
> +
> +namespace llvm {
> +
> +class DWARFContext;
> +
> +class DWARFDebugAranges {
> +public:
> +  struct Range {
> +    explicit Range(uint64_t lo = -1ULL, uint64_t hi = -1ULL,
> +                   uint32_t off = -1U)
> +      : LoPC(lo), Length(hi-lo), Offset(off) {}
> +
> +    void clear() {
> +      LoPC = -1ULL;
> +      Length = 0;
> +      Offset = -1U;
> +    }
> +
> +    void setHiPC(uint64_t HiPC) {
> +      if (HiPC == -1ULL || HiPC <= LoPC)
> +        Length = 0;
> +      else
> +        Length = HiPC - LoPC;
> +    }
> +    uint64_t HiPC() const {
> +      if (Length)
> +        return LoPC + Length;
> +      return -1ULL;
> +    }
> +    bool isValidRange() const { return Length > 0; }
> +
> +    static bool SortedOverlapCheck(const Range &curr_range,
> +                                   const Range &next_range, uint32_t n) {
> +      if (curr_range.Offset != next_range.Offset)
> +        return false;
> +      return curr_range.HiPC() + n >= next_range.LoPC;
> +    }
> +
> +    bool contains(const Range &range) const {
> +      return LoPC <= range.LoPC && range.HiPC() <= HiPC();
> +    }
> +
> +    void dump(raw_ostream &OS) const;
> +    uint64_t LoPC; // Start of address range
> +    uint32_t Length; // End of address range (not including this address)
> +    uint32_t Offset; // Offset of the compile unit or die
> +  };
> +
> +  void clear() { Aranges.clear(); }
> +  bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const;
> +  bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const;
> +  bool extract(DataExtractor debug_aranges_data);
> +
> +  // Use append range multiple times and then call sort
> +  void appendRange(uint32_t cu_offset, uint64_t low_pc, uint64_t high_pc);
> +  void sort(bool minimize, uint32_t n);
> +
> +  const Range *rangeAtIndex(uint32_t idx) const {
> +    if (idx < Aranges.size())
> +      return &Aranges[idx];
> +    return NULL;
> +  }
> +  void dump(raw_ostream &OS) const;
> +  uint32_t findAddress(uint64_t address) const;
> +  bool isEmpty() const { return Aranges.empty(); }
> +  uint32_t getNumRanges() const { return Aranges.size(); }
> +
> +  uint32_t offsetAtIndex(uint32_t idx) const {
> +    if (idx < Aranges.size())
> +      return Aranges[idx].Offset;
> +    return -1U;
> +  }
> +
> +  typedef std::vector<Range>              RangeColl;
> +  typedef RangeColl::const_iterator       RangeCollIterator;
> +
> +private:
> +  RangeColl Aranges;
> +};
> +
> +}
> +
> +#endif
> 
> Modified: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp?rev=139680&r1=139679&r2=139680&view=diff
> ==============================================================================
> --- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp (original)
> +++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp Tue Sep 13 20:09:52 2011
> @@ -52,6 +52,7 @@
>   StringRef DebugInfoSection;
>   StringRef DebugAbbrevSection;
>   StringRef DebugLineSection;
> +  StringRef DebugArangesSection;
> 
>   error_code ec;
>   for (ObjectFile::section_iterator i = Obj->begin_sections(),
> @@ -67,11 +68,14 @@
>       DebugAbbrevSection = data;
>     else if (name.endswith("debug_line"))
>       DebugLineSection = data;
> +    else if (name.endswith("debug_aranges"))
> +      DebugArangesSection = data;
>   }
> 
>   OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true,
>                                                         DebugInfoSection,
> -                                                        DebugAbbrevSection));
> +                                                        DebugAbbrevSection,
> +                                                        DebugArangesSection));
>   dictx->dump(outs());
> }
> 
> 
> 
> _______________________________________________
> 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