Support skewed stream arrays.
authorZachary Turner <zturner@google.com>
Thu, 6 Dec 2018 16:55:00 +0000 (16:55 +0000)
committerZachary Turner <zturner@google.com>
Thu, 6 Dec 2018 16:55:00 +0000 (16:55 +0000)
VarStreamArray was built on the assumption that it is backed by a
StreamRef, and offset 0 of that StreamRef is the first byte of the first
record in the array.

This is a logical and intuitive assumption, but unfortunately we have
use cases where it doesn't hold. Specifically, a PDB module's symbol
stream is prefixed by 4 bytes containing a magic value, and the first
byte of record data in the array is actually at offset 4 of this byte
sequence.

Previously, we would just truncate the first 4 bytes and then construct
the VarStreamArray with the resulting StreamRef, so that offset 0 of the
underlying stream did correspond to the first byte of the first record,
but this is problematic, because symbol records reference other symbol
records by the absolute offset including that initial magic 4 bytes. So
if another record wants to refer to the first record in the array, it
would say "the record at offset 4".

This led to extremely confusing hacks and semantics in loading code, and
after spending 30 minutes trying to get some math right and failing, I
decided to fix this in the underlying implementation of VarStreamArray.
Now, we can say that a stream is skewed by a particular amount. This
way, when we access a record by absolute offset, we can use the same
values that the records themselves contain, instead of having to do
fixups.

Differential Revision: https://reviews.llvm.org/D55344

llvm-svn: 348499

lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
llvm/include/llvm/Support/BinaryStreamArray.h
llvm/include/llvm/Support/BinaryStreamReader.h
llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
llvm/test/DebugInfo/PDB/module-bytes.test

index 7aa656a..20bea85 100644 (file)
@@ -131,10 +131,7 @@ void PdbIndex::BuildAddrToSymbolMap(CompilandIndexItem &cci) {
     SegmentOffset so = GetSegmentAndOffset(*iter);
     lldb::addr_t va = MakeVirtualAddress(so);
 
-    // We need to add 4 here to adjust for the codeview debug magic
-    // at the beginning of the debug info stream.
-    uint32_t sym_offset = iter.offset() + 4;
-    PdbCompilandSymId cu_sym_id(modi, sym_offset);
+    PdbCompilandSymId cu_sym_id(modi, iter.offset());
 
     // If the debug info is incorrect, we could have multiple symbols with the
     // same address.  So use try_emplace instead of insert, and the first one
@@ -201,7 +198,7 @@ CVSymbol PdbIndex::ReadSymbolRecord(PdbCompilandSymId cu_sym) const {
   // We need to subtract 4 here to adjust for the codeview debug magic
   // at the beginning of the debug info stream.
   const CompilandIndexItem *cci = compilands().GetCompiland(cu_sym.modi);
-  auto iter = cci->m_debug_stream.getSymbolArray().at(cu_sym.offset - 4);
+  auto iter = cci->m_debug_stream.getSymbolArray().at(cu_sym.offset);
   lldbassert(iter != cci->m_debug_stream.getSymbolArray().end());
   return *iter;
 }
index 7b8a95b..78e3c06 100644 (file)
@@ -96,17 +96,19 @@ public:
 
   explicit VarStreamArray(const Extractor &E) : E(E) {}
 
-  explicit VarStreamArray(BinaryStreamRef Stream) : Stream(Stream) {}
+  explicit VarStreamArray(BinaryStreamRef Stream, uint32_t Skew = 0)
+      : Stream(Stream), Skew(Skew) {}
 
-  VarStreamArray(BinaryStreamRef Stream, const Extractor &E)
-      : Stream(Stream), E(E) {}
+  VarStreamArray(BinaryStreamRef Stream, const Extractor &E, uint32_t Skew = 0)
+      : Stream(Stream), E(E), Skew(Skew) {}
 
   Iterator begin(bool *HadError = nullptr) const {
-    return Iterator(*this, E, HadError);
+    return Iterator(*this, E, Skew, nullptr);
   }
 
   bool valid() const { return Stream.valid(); }
 
+  uint32_t skew() const { return Skew; }
   Iterator end() const { return Iterator(E); }
 
   bool empty() const { return Stream.getLength() == 0; }
@@ -123,13 +125,17 @@ public:
   Extractor &getExtractor() { return E; }
 
   BinaryStreamRef getUnderlyingStream() const { return Stream; }
-  void setUnderlyingStream(BinaryStreamRef S) { Stream = S; }
+  void setUnderlyingStream(BinaryStreamRef S, uint32_t Skew = 0) {
+    Stream = S;
+    this->Skew = Skew;
+  }
 
   void drop_front() { Stream = Stream.drop_front(begin()->length()); }
 
 private:
   BinaryStreamRef Stream;
   Extractor E;
+  uint32_t Skew;
 };
 
 template <typename ValueType, typename Extractor>
@@ -141,10 +147,6 @@ class VarStreamArrayIterator
 
 public:
   VarStreamArrayIterator(const ArrayType &Array, const Extractor &E,
-                         bool *HadError)
-      : VarStreamArrayIterator(Array, E, 0, HadError) {}
-
-  VarStreamArrayIterator(const ArrayType &Array, const Extractor &E,
                          uint32_t Offset, bool *HadError)
       : IterRef(Array.Stream.drop_front(Offset)), Extract(E),
         Array(&Array), AbsOffset(Offset), HadError(HadError) {
index fe77b55..392958d 100644 (file)
@@ -203,11 +203,12 @@ public:
   /// \returns a success error code if the data was successfully read, otherwise
   /// returns an appropriate error code.
   template <typename T, typename U>
-  Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
+  Error readArray(VarStreamArray<T, U> &Array, uint32_t Size,
+                  uint32_t Skew = 0) {
     BinaryStreamRef S;
     if (auto EC = readStreamRef(S, Size))
       return EC;
-    Array.setUnderlyingStream(S);
+    Array.setUnderlyingStream(S, Skew);
     return Error::success();
   }
 
index 44a6774..cbcaa56 100644 (file)
@@ -75,7 +75,7 @@ Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
 Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,
                                          uint32_t InitialOffset) {
   for (auto I : Symbols) {
-    if (auto EC = visitSymbolRecord(I, InitialOffset))
+    if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew()))
       return EC;
     InitialOffset += I.length();
   }
index 6464b85..5ff7c15 100644 (file)
@@ -47,7 +47,8 @@ Error ModuleDebugStreamRef::reload() {
 
   if (auto EC = Reader.readInteger(Signature))
     return EC;
-  if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize - 4))
+  Reader.setOffset(0);
+  if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize))
     return EC;
   if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size))
     return EC;
@@ -55,8 +56,8 @@ Error ModuleDebugStreamRef::reload() {
     return EC;
 
   BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData);
-  if (auto EC =
-          SymbolReader.readArray(SymbolArray, SymbolReader.bytesRemaining()))
+  if (auto EC = SymbolReader.readArray(
+          SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t)))
     return EC;
 
   BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData);
@@ -98,9 +99,7 @@ ModuleDebugStreamRef::symbols(bool *HadError) const {
 }
 
 CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const {
-  // Offsets include the size of the 4-byte magic at the beginning, but lookup
-  // doesn't take that into account, so subtract it here.
-  auto Iter = SymbolArray.at(Offset - 4);
+  auto Iter = SymbolArray.at(Offset);
   assert(Iter != SymbolArray.end());
   return *Iter;
 }
index f325331..2f8cae4 100644 (file)
@@ -42,44 +42,45 @@ SYMS:                             Module Symbols
 SYMS-NEXT: ============================================================
 SYMS-NEXT:     Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
 SYMS-NEXT:       Symbols (
-SYMS-NEXT:         6004: 36000111 00000000 643A5C73 72635C6C 6C766D5C 74657374 5C446562 7567496E  |6.......d:\src\llvm\test\DebugIn|
-SYMS-NEXT:         6024: 666F5C50 44425C49 6E707574 735C656D 7074792E 6F626A00 3A003C11 01200000  |fo\PDB\Inputs\empty.obj.:.<.. ..|
-SYMS-NEXT:         6044: 07001200 00007D79 00001200 00007D79 00004D69 63726F73 6F667420 28522920  |......}y......}y..Microsoft (R) |
-SYMS-NEXT:         6064: 4F707469 6D697A69 6E672043 6F6D7069 6C657200 2A001011 00000000 C4000000  |Optimizing Compiler.*...........|
-SYMS-NEXT:         6084: 00000000 0A000000 03000000 08000000 01100000 10000000 0100016D 61696E00  |...........................main.|
-SYMS-NEXT:         60A4: 1E001210 00000000 00000000 00000000 00000000 00000000 00000082 12000000  |................................|
-SYMS-NEXT:         60C4: 02000600 06004C11 0E100000                                               |......L.....|
+SYMS-NEXT:         6000: 04000000 36000111 00000000 643A5C73 72635C6C 6C766D5C 74657374 5C446562  |....6.......d:\src\llvm\test\Deb|
+SYMS-NEXT:         6020: 7567496E 666F5C50 44425C49 6E707574 735C656D 7074792E 6F626A00 3A003C11  |ugInfo\PDB\Inputs\empty.obj.:.<.|
+SYMS-NEXT:         6040: 01200000 07001200 00007D79 00001200 00007D79 00004D69 63726F73 6F667420  |. ........}y......}y..Microsoft |
+SYMS-NEXT:         6060: 28522920 4F707469 6D697A69 6E672043 6F6D7069 6C657200 2A001011 00000000  |(R) Optimizing Compiler.*.......|
+SYMS-NEXT:         6080: C4000000 00000000 0A000000 03000000 08000000 01100000 10000000 0100016D  |...............................m|
+SYMS-NEXT:         60A0: 61696E00 1E001210 00000000 00000000 00000000 00000000 00000000 00000082  |ain.............................|
+SYMS-NEXT:         60C0: 12000000 02000600 06004C11 0E100000                                      |..........L.....|
 SYMS-NEXT:       )
 SYMS-NEXT:     Mod 0001 | `* Linker *`:
 SYMS-NEXT:       Symbols (
-SYMS-NEXT:         7004: 12000111 00000000 2A204C69 6E6B6572 202A0000 2E003C11 07000000 03000000  |........* Linker *....<.........|
-SYMS-NEXT:         7024: 00000000 00000C00 00007D79 00004D69 63726F73 6F667420 28522920 4C494E4B  |..........}y..Microsoft (R) LINK|
-SYMS-NEXT:         7044: 00000000 AA003D11 00637764 00643A5C 7372635C 6C6C766D 5C746573 745C4465  |......=..cwd.d:\src\llvm\test\De|
-SYMS-NEXT:         7064: 62756749 6E666F5C 5044425C 496E7075 74730065 78650043 3A5C5072 6F677261  |bugInfo\PDB\Inputs.exe.C:\Progra|
-SYMS-NEXT:         7084: 6D204669 6C657320 28783836 295C4D69 63726F73 6F667420 56697375 616C2053  |m Files (x86)\Microsoft Visual S|
-SYMS-NEXT:         70A4: 74756469 6F203132 2E305C56 435C4249 4E5C6C69 6E6B2E65 78650070 64620064  |tudio 12.0\VC\BIN\link.exe.pdb.d|
-SYMS-NEXT:         70C4: 3A5C7372 635C6C6C 766D5C74 6573745C 44656275 67496E66 6F5C5044 425C496E  |:\src\llvm\test\DebugInfo\PDB\In|
-SYMS-NEXT:         70E4: 70757473 5C656D70 74792E70 64620000 12002C11 00000500 05000000 10000000  |puts\empty.pdb....,.............|
-SYMS-NEXT:         7104: 01000100 1A003611 01000C00 00100000 1A100000 20000060 2E746578 74000000  |......6............. ..`.text...|
-SYMS-NEXT:         7124: 1A003711 1A100000 20000060 00000000 01002E74 65787424 6D6E0000 1A003611  |..7..... ..`.......text$mn....6.|
-SYMS-NEXT:         7144: 02000C00 00300000 B2020000 40000040 2E726461 74610000 1A003711 43010000  |.....0......@..@.rdata....7.C...|
-SYMS-NEXT:         7164: 40000040 00000000 02002E72 64617461 00000000 1A003711 00000000 40000040  |@..@.......rdata......7.....@..@|
-SYMS-NEXT:         7184: 43010000 02002E65 64617461 00000000 1E003711 6E010000 40000040 44010000  |C......edata......7.n...@..@D...|
-SYMS-NEXT:         71A4: 02002E72 64617461 24646562 75670000 1A003611 03000C00 00400000 04000000  |...rdata$debug....6......@......|
-SYMS-NEXT:         71C4: 400000C0 2E646174 61000000 16003711 04000000 800000C0 00000000 03002E62  |@....data.....7................b|
-SYMS-NEXT:         71E4: 73730000 1A003611 04000C00 00500000 08000000 40000042 2E72656C 6F630000  |ss....6......P......@..B.reloc..|
+SYMS-NEXT:         7000: 04000000 12000111 00000000 2A204C69 6E6B6572 202A0000 2E003C11 07000000  |............* Linker *....<.....|
+SYMS-NEXT:         7020: 03000000 00000000 00000C00 00007D79 00004D69 63726F73 6F667420 28522920  |..............}y..Microsoft (R) |
+SYMS-NEXT:         7040: 4C494E4B 00000000 AA003D11 00637764 00643A5C 7372635C 6C6C766D 5C746573  |LINK......=..cwd.d:\src\llvm\tes|
+SYMS-NEXT:         7060: 745C4465 62756749 6E666F5C 5044425C 496E7075 74730065 78650043 3A5C5072  |t\DebugInfo\PDB\Inputs.exe.C:\Pr|
+SYMS-NEXT:         7080: 6F677261 6D204669 6C657320 28783836 295C4D69 63726F73 6F667420 56697375  |ogram Files (x86)\Microsoft Visu|
+SYMS-NEXT:         70A0: 616C2053 74756469 6F203132 2E305C56 435C4249 4E5C6C69 6E6B2E65 78650070  |al Studio 12.0\VC\BIN\link.exe.p|
+SYMS-NEXT:         70C0: 64620064 3A5C7372 635C6C6C 766D5C74 6573745C 44656275 67496E66 6F5C5044  |db.d:\src\llvm\test\DebugInfo\PD|
+SYMS-NEXT:         70E0: 425C496E 70757473 5C656D70 74792E70 64620000 12002C11 00000500 05000000  |B\Inputs\empty.pdb....,.........|
+SYMS-NEXT:         7100: 10000000 01000100 1A003611 01000C00 00100000 1A100000 20000060 2E746578  |..........6............. ..`.tex|
+SYMS-NEXT:         7120: 74000000 1A003711 1A100000 20000060 00000000 01002E74 65787424 6D6E0000  |t.....7..... ..`.......text$mn..|
+SYMS-NEXT:         7140: 1A003611 02000C00 00300000 B2020000 40000040 2E726461 74610000 1A003711  |..6......0......@..@.rdata....7.|
+SYMS-NEXT:         7160: 43010000 40000040 00000000 02002E72 64617461 00000000 1A003711 00000000  |C...@..@.......rdata......7.....|
+SYMS-NEXT:         7180: 40000040 43010000 02002E65 64617461 00000000 1E003711 6E010000 40000040  |@..@C......edata......7.n...@..@|
+SYMS-NEXT:         71A0: 44010000 02002E72 64617461 24646562 75670000 1A003611 03000C00 00400000  |D......rdata$debug....6......@..|
+SYMS-NEXT:         71C0: 04000000 400000C0 2E646174 61000000 16003711 04000000 800000C0 00000000  |....@....data.....7.............|
+SYMS-NEXT:         71E0: 03002E62 73730000 1A003611 04000C00 00500000 08000000 40000042 2E72656C  |...bss....6......P......@..B.rel|
+SYMS-NEXT:         7200: 6F630000                                                                 |oc..|
 SYMS-NEXT:       )
 
 FILTERED-SYMS:                             Module Symbols
 FILTERED-SYMS-NEXT: ============================================================
 FILTERED-SYMS-NEXT:     Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
 FILTERED-SYMS-NEXT:       Symbols (
-FILTERED-SYMS-NEXT:         6004: 36000111 00000000 643A5C73 72635C6C 6C766D5C 74657374 5C446562 7567496E  |6.......d:\src\llvm\test\DebugIn|
-FILTERED-SYMS-NEXT:         6024: 666F5C50 44425C49 6E707574 735C656D 7074792E 6F626A00 3A003C11 01200000  |fo\PDB\Inputs\empty.obj.:.<.. ..|
-FILTERED-SYMS-NEXT:         6044: 07001200 00007D79 00001200 00007D79 00004D69 63726F73 6F667420 28522920  |......}y......}y..Microsoft (R) |
-FILTERED-SYMS-NEXT:         6064: 4F707469 6D697A69 6E672043 6F6D7069 6C657200 2A001011 00000000 C4000000  |Optimizing Compiler.*...........|
-FILTERED-SYMS-NEXT:         6084: 00000000 0A000000 03000000 08000000 01100000 10000000 0100016D 61696E00  |...........................main.|
-FILTERED-SYMS-NEXT:         60A4: 1E001210 00000000 00000000 00000000 00000000 00000000 00000082 12000000  |................................|
-FILTERED-SYMS-NEXT:         60C4: 02000600 06004C11 0E100000                                               |......L.....|
+FILTERED-SYMS-NEXT:         6000: 04000000 36000111 00000000 643A5C73 72635C6C 6C766D5C 74657374 5C446562  |....6.......d:\src\llvm\test\Deb|
+FILTERED-SYMS-NEXT:         6020: 7567496E 666F5C50 44425C49 6E707574 735C656D 7074792E 6F626A00 3A003C11  |ugInfo\PDB\Inputs\empty.obj.:.<.|
+FILTERED-SYMS-NEXT:         6040: 01200000 07001200 00007D79 00001200 00007D79 00004D69 63726F73 6F667420  |. ........}y......}y..Microsoft |
+FILTERED-SYMS-NEXT:         6060: 28522920 4F707469 6D697A69 6E672043 6F6D7069 6C657200 2A001011 00000000  |(R) Optimizing Compiler.*.......|
+FILTERED-SYMS-NEXT:         6080: C4000000 00000000 0A000000 03000000 08000000 01100000 10000000 0100016D  |...............................m|
+FILTERED-SYMS-NEXT:         60A0: 61696E00 1E001210 00000000 00000000 00000000 00000000 00000000 00000082  |ain.............................|
+FILTERED-SYMS-NEXT:         60C0: 12000000 02000600 06004C11 0E100000                                      |..........L.....|
 FILTERED-SYMS-NEXT:       )
 FILTERED-SYMS-NOT:      Mod 0001