[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