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

Adrian McCarthy via llvm-commits llvm-commits at lists.llvm.org
Mon May 2 16:45:03 PDT 2016


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);
+}
+
+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.
   }
 }
 




More information about the llvm-commits mailing list