Issue 159978
Summary PDB named stream map forgets to mention niMac
Labels documentation, debuginfo
Assignees
Reporter nlguillemot
    If I look at the named stream map from a real-world pdb in the debugger, I see the following data:

<!DOCTYPE html>
<HTML>
<head>
<title>Document</title></head>
<body>
<!--StartFragment-->


index | value
-- | --
[0x00000000] | 0x00000005
[0x00000001] | 0x0000000a
[0x00000002] | 0x00000001
[0x00000003] | 0x0000002f
[0x00000004] | 0x00000000
[0x00000005] | 0x0000002b
[0x00000006] | 0x0000031b
[0x00000007] | 0x0000001a
[0x00000008] | 0x00000319
[0x00000009] | 0x00000000
[0x0000000a] | 0x00000005
[0x0000000b] | 0x0000000a
[0x0000000c] | 0x00000006
[0x0000000d] | 0x00000013
[0x0000000e] | 0x00000007
[0x0000000f] | 0x00000000
[0x00000010] | 0x013351dc


<!--EndFragment-->
</body>
</HTML>

It begins with 5 which is the number of pairs in the map.

Then we see 10 for the capacity of the map (for the runtime data structure it originally came from, [not the stored data](https://github.com/llvm/llvm-project/issues/76602))

Then we see the present bit vector with 1 word, followed by that one word.

Then the deleted bit vector has 0 words, so we see the count 0, followed by no other words from it.

Then we see 5 pairs of uint32, for the map entries.

At the very end, after the named stream data, we can see the feature code 0x013351dc for PdbRaw_FeatureSig::VC140.

But in between the end of the pairs and the feature flag, there's one word that has the value 0. That is the issue for this bug.

Based on the Microsoft reference code I think this is the niMac field, used to incrementally generate indices for named streams. It happens to be zero in this case because the named stream map was created using a mode where the indices are assigned by a user-defined function.

```cpp
    // create a name table with client defined name index generation
    NMTNI(BOOL (*pfnNi_)(void*, OUT NI*), void* pfnNiArg_ = 0)
    {
        pfnNi = pfnNi_;
        pfnNiArg = pfnNiArg_;
 niMac = 0; // will not be used
        mapSzoNi.setContext(&buf);
 }
```

In the save code itself, you can see where the niMac is appended to the buffer.

```cpp
    BOOL save(Buffer* pbuf) {
 MTS_PROTECT(m_csReadWrite);

        // optimization: since mapNiSzo is just the reverse map of mapSzoNi,
        // we store only the latter
 if (!buf.save(pbuf))
            return FALSE;
        traceOnly(CB cb0 = pbuf->Size());

        if (!mapSzoNi.save(pbuf))
            return FALSE;
        traceOnly(CB cbMap = pbuf->Size() - cb0);

        if (!pbuf->Append((PB)&niMac, sizeof niMac))
            return FALSE;

 trace((trSave, "NMTNI::save() cbBuf=%d cbMap=%d\n", buf.Size(), cbMap));
        return TRUE;
    }
```

In all PDB parsers (MSFT, LLVM, and Molecular Matters' [raw_pdb](https://github.com/MolecularMatters/raw_pdb)), it seems to me like the existence of this field is ignored. The parser just looks for feature flags and ignores anything that doesn't match. It just happens that the niMac field doesn't match the pattern for a feature flag, so it doesn't cause a false positive. In theory somebody could append an incredible number of named streams so that the niMac field looks like a feature flag. It's unlikely (impossible?) to happen in practice but I believe it is in fact a documentation bug.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to