[llvm] r268334 - NFC: An iterator for stepping through CodeView type stream in llvm-readobj

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon May 2 19:16:59 PDT 2016


On Mon, May 2, 2016 at 4:45 PM, Adrian McCarthy via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: amccarth
> Date: Mon May  2 18:45:03 2016
> New Revision: 268334
>
> URL: http://llvm.org/viewvc/llvm-project?rev=268334&view=rev
> Log:
> NFC: An iterator for stepping through CodeView type stream in llvm-readobj
>
> This is a small refactoring step toward moving CodeView type stream logic
> from llvm-readobj to a library. It abstracts the logic of stepping through
> the stream into an iterator class and updates llvm-readobj to use that
> iterator. This has no functional change; llvm-readobj produces identical
> output.
>
> The next step is to abstract the parsing of the different leaf types and
> then move that and the iterator into a library.
>
> Since this is my first contrib outside LLDB, please let me know if I'm
> messing up on any of the LLVM style guidelines, idioms, or patterns.
>
> Differential Revision: http://reviews.llvm.org/D19746
>
> Modified:
>     llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
>
> Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=268334&r1=268333&r2=268334&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
> +++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Mon May  2 18:45:03 2016
> @@ -1866,19 +1866,9 @@ void COFFDumper::printCodeViewInlineeLin
>    }
>  }
>
> -StringRef getRemainingTypeBytes(const TypeRecordPrefix *Rec, const char
> *Start) {
> -  ptrdiff_t StartOffset = Start - reinterpret_cast<const char *>(Rec);
> -  size_t RecSize = Rec->Len + 2;
> -  assert(StartOffset >= 0 && "negative start-offset!");
> -  assert(static_cast<size_t>(StartOffset) <= RecSize &&
> -         "Start beyond the end of Rec");
> -  return StringRef(Start, RecSize - StartOffset);
> -}
> -
> -StringRef getRemainingBytesAsString(const TypeRecordPrefix *Rec, const
> char *Start) {
> -  StringRef Remaining = getRemainingTypeBytes(Rec, Start);
> -  StringRef Leading, Trailing;
> -  std::tie(Leading, Trailing) = Remaining.split('\0');
> +StringRef getLeafDataBytesAsString(StringRef LeafData) {
> +  StringRef Leading;
> +  std::tie(Leading, std::ignore) = LeafData.split('\0');
>    return Leading;
>  }
>
> @@ -1992,47 +1982,148 @@ static StringRef getLeafTypeName(TypeLea
>    return "UnknownLeaf";
>  }
>
> +// A const input iterator interface to the CodeView type stream.
> +class CodeViewTypeIterator {
> +public:
> +  struct TypeRecord {
> +    std::size_t Length;
> +    TypeLeafKind Leaf;
> +    StringRef LeafData;
> +  };
> +
> +  explicit CodeViewTypeIterator(const StringRef &SectionData)
> +      : Data(SectionData), AtEnd(false) {
> +    if (Data.size() >= 4) {
> +      Magic = *reinterpret_cast<const ulittle32_t *>(Data.data());
> +      Data = Data.drop_front(4);
> +    }
> +    next(); // Prime the pump
> +  }
> +
> +  CodeViewTypeIterator() : AtEnd(true) {}
> +
> +  // For iterators to compare equal, they must both point at the same
> record
> +  // in the same data stream, or they must both be at the end of a stream.
> +  friend bool operator==(const CodeViewTypeIterator &lhs,
> +                         const CodeViewTypeIterator &rhs);
> +
> +  friend bool operator!=(const CodeViewTypeIterator &lhs,
> +                         const CodeViewTypeIterator &rhs);
> +
> +  unsigned getMagic() const { return Magic; }
> +
> +  const TypeRecord &operator*() const {
> +    assert(!AtEnd);
> +    return Current;
> +  }
> +
> +  const TypeRecord *operator->() const {
> +    assert(!AtEnd);
> +    return &Current;
> +  }
> +
> +  CodeViewTypeIterator operator++() {
> +    next();
> +    return *this;
> +  }
> +
> +  CodeViewTypeIterator operator++(int) {
> +    CodeViewTypeIterator Original = *this;
> +    ++*this;
> +    return Original;
> +  }
> +
> +private:
> +  void next() {
> +    assert(!AtEnd && "Attempted to advance more than one past the last
> rec");
> +    if (Data.empty()) {
> +      // We've advanced past the last record.
> +      AtEnd = true;
> +      return;
> +    }
> +
> +    const TypeRecordPrefix *Rec;
> +    if (consumeObject(Data, Rec))
> +      return;
> +    Current.Length = Rec->Len;
> +    Current.Leaf = static_cast<TypeLeafKind>(uint16_t(Rec->Leaf));
> +    Current.LeafData = Data.substr(0, Current.Length - 2);
> +
> +    // The next record starts immediately after this one.
> +    Data = Data.drop_front(Current.LeafData.size());
> +
> +    // FIXME: The stream contains LF_PAD bytes that we need to ignore,
> but those
> +    // are typically included in LeafData. We may need to call
> skipPadding() if
> +    // we ever find a record that doesn't count those bytes.
> +
> +    return;
> +  }
> +
> +  StringRef Data;
> +  unsigned Magic = 0;
> +  TypeRecord Current;
> +  bool AtEnd;
> +};
> +
> +bool operator==(const CodeViewTypeIterator &lhs,
> +                const CodeViewTypeIterator &rhs) {
> +  return (lhs.Data.begin() == rhs.Data.begin()) || (lhs.AtEnd &&
> rhs.AtEnd);
> +}
>

If you like, you can still define these operators inline in the class
definition, even as non-member friends:

  friend bool operator==(...) {
    ...
  }


> +
> +bool operator!=(const CodeViewTypeIterator &lhs,
> +                const CodeViewTypeIterator &rhs) {
> +  return !(lhs == rhs);
> +}
> +
> +struct CodeViewTypeStream {
> +  CodeViewTypeIterator begin;
> +  CodeViewTypeIterator end;
> +  unsigned Magic;
> +};
> +
> +CodeViewTypeStream CreateCodeViewTypeIter(const StringRef &Data) {
> +  CodeViewTypeStream Stream;
> +  Stream.begin = CodeViewTypeIterator(Data);
> +  Stream.end   = CodeViewTypeIterator();
> +  Stream.Magic = Stream.begin.getMagic();
> +
> +  return Stream;
> +}
> +
>  void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
>                                            const SectionRef &Section) {
>    ListScope D(W, "CodeViewTypes");
>    W.printNumber("Section", SectionName, Obj->getSectionID(Section));
> +
>    StringRef Data;
>    error(Section.getContents(Data));
>    if (opts::CodeViewSubsectionBytes)
>      W.printBinaryBlock("Data", Data);
>
> -  unsigned Magic = *reinterpret_cast<const ulittle32_t *>(Data.data());
> -  W.printHex("Magic", Magic);
> -
> -  Data = Data.drop_front(4);
> -
>    CVTD.dump(Data);
>  }
>
>  void CVTypeDumper::dump(StringRef Data) {
> -  while (!Data.empty()) {
> -    const TypeRecordPrefix *Rec;
> -    error(consumeObject(Data, Rec));
> -    auto Leaf = static_cast<TypeLeafKind>(uint16_t(Rec->Leaf));
> +  CodeViewTypeStream Stream = CreateCodeViewTypeIter(Data);
> +  W.printHex("Magic", Stream.Magic);
>
> -    // This record is 'Len - 2' bytes, and the next one starts immediately
> -    // afterwards.
> -    StringRef LeafData = Data.substr(0, Rec->Len - 2);
> -    StringRef RemainingData = Data.drop_front(LeafData.size());
> +  for (auto Iter = Stream.begin; Iter != Stream.end; ++Iter) {
> +    StringRef LeafData = Iter->LeafData;
>
>      // Find the name of this leaf type.
> -    StringRef LeafName = getLeafTypeName(Leaf);
> +    StringRef LeafName = getLeafTypeName(Iter->Leaf);
>      DictScope S(W, LeafName);
>      unsigned NextTypeIndex = 0x1000 + CVUDTNames.size();
> -    W.printEnum("TypeLeafKind", unsigned(Leaf),
> makeArrayRef(LeafTypeNames));
> +    W.printEnum("TypeLeafKind", unsigned(Iter->Leaf),
> +                makeArrayRef(LeafTypeNames));
>      W.printHex("TypeIndex", NextTypeIndex);
>
>      // Fill this in inside the switch to get something in CVUDTNames.
>      StringRef Name;
>
> -    switch (Leaf) {
> +    switch (Iter->Leaf) {
>      default: {
> -      W.printHex("Size", Rec->Len);
> +      W.printHex("Size", Iter->Length);
>        break;
>      }
>
> @@ -2040,7 +2131,7 @@ void CVTypeDumper::dump(StringRef Data)
>        const StringId *String;
>        error(consumeObject(LeafData, String));
>        W.printHex("Id", String->id.getIndex());
> -      StringRef StringData = getRemainingBytesAsString(Rec,
> LeafData.data());
> +      StringRef StringData = getLeafDataBytesAsString(LeafData);
>        W.printString("StringData", StringData);
>        // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
>        Name = StringData;
> @@ -2048,7 +2139,7 @@ void CVTypeDumper::dump(StringRef Data)
>      }
>
>      case LF_FIELDLIST: {
> -      W.printHex("Size", Rec->Len);
> +      W.printHex("Size", Iter->Length);
>        // FieldList has no fixed prefix that can be described with a
> struct. All
>        // the bytes must be interpreted as more records.
>        printCodeViewFieldList(LeafData);
> @@ -2094,7 +2185,7 @@ void CVTypeDumper::dump(StringRef Data)
>        std::tie(Name, LinkageName) = LeafData.split('\0');
>        W.printString("Name", Name);
>        if (Props & uint16_t(ClassOptions::HasUniqueName)) {
> -        LinkageName = getRemainingBytesAsString(Rec, LinkageName.data());
> +        LinkageName = getLeafDataBytesAsString(LinkageName);
>          if (LinkageName.empty())
>            return error(object_error::parse_failed);
>          W.printString("LinkageName", LinkageName);
> @@ -2116,7 +2207,7 @@ void CVTypeDumper::dump(StringRef Data)
>        std::tie(Name, LinkageName) = LeafData.split('\0');
>        W.printString("Name", Name);
>        if (Props & uint16_t(ClassOptions::HasUniqueName)) {
> -        LinkageName = getRemainingBytesAsString(Rec, LinkageName.data());
> +        LinkageName = getLeafDataBytesAsString(LinkageName);
>          if (LinkageName.empty())
>            return error(object_error::parse_failed);
>          W.printString("LinkageName", LinkageName);
> @@ -2371,11 +2462,6 @@ void CVTypeDumper::dump(StringRef Data)
>        W.printBinaryBlock("LeafData", LeafData);
>
>      CVUDTNames.push_back(Name);
> -
> -    Data = RemainingData;
> -    // FIXME: The stream contains LF_PAD bytes that we need to ignore,
> but those
> -    // are typically included in LeafData. We may need to call
> skipPadding() if
> -    // we ever find a record that doesn't count those bytes.
>    }
>  }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160502/5eb67c94/attachment.html>


More information about the llvm-commits mailing list