[llvm-bugs] [Bug 40221] New: lld-link /debug:ghash produces bad type stream with some masm object files

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Jan 3 13:34:19 PST 2019


            Bug ID: 40221
           Summary: lld-link /debug:ghash produces bad type stream with
                    some masm object files
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: DebugInfo
          Assignee: unassignedbugs at nondot.org
          Reporter: rnk at google.com
                CC: alexandre.ganea at ubisoft.com, jdevlieghere at apple.com,
                    keith.walker at arm.com, llvm-bugs at lists.llvm.org,
                    paul_robinson at playstation.sony.com, zturner at google.com

At a high-level, when enabling /debug:ghash in official chrome builds,
chrome.dll.pdb ends up containing a cycle in the TPI stream of the final PDB.
This causes various dumpers like cvdump and `llvm-pdbutil dump -types` to crash
while dumping the type stream.

The type stream merger has extra logic to deal with the case where type records
are not topologically sorted, as is the case in .debug$T sections in
masm-produced objects. The basic idea is that, if a type record contains
forward references, we don't insert it on the first pass. Then, we re-insert
all the records in subsequent passes until all the records are successfully
inserted. This relies on the idea that type record insertion is idempotent,
i.e. we can just insert all the records again, and if they were inserted on the
first pass, nothing happens. This is inefficient, but masm type streams are
small, i.e. < 10 elements.

However, it seems that we compute the wrong ghash when the type stream contains
forward references. Here's the ghash code in question:

    for (TypeIndex TI : Indices) {
      ArrayRef<uint8_t> BytesToHash;
      if (TI.isSimple() || TI.isNoneType() || TI.toArrayIndex() >= Prev.size())
        const uint8_t *IndexBytes = reinterpret_cast<const uint8_t *>(&TI);
        BytesToHash = makeArrayRef(IndexBytes, sizeof(TypeIndex));
      } else {
        BytesToHash = Prev[TI.toArrayIndex()].Hash;

In the case of forward references, i.e. `TI.toArrayIndex() >= Prev.size()`, we
just hash the type index as a plain type index, as if it were simple. This is
wrong, it will produce different hashes in different TUs.

I don't yet see how this leads to the off-by-one error and type graph cycle in
the result, but I think that's the cause of the bug.

We've been thinking about computing ghashes in parallel up front at the start
of the link, and I think that would be a great time to detect non-topo sorted
object files and sort them at that time. They are ultimately separable tasks,
and each obj can be handled in parallel, just like ghash computation.

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190103/731f38c7/attachment-0001.html>

More information about the llvm-bugs mailing list