1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>The PDB Info Stream (aka the PDB Stream) — LLVM 13 documentation</title>
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/llvm-theme.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="The PDB TPI and IPI Streams" href="TpiStream.html" />
<link rel="prev" title="The MSF File Format" href="MsfFile.html" />
<style type="text/css">
table.right { float: right; margin-left: 20px; }
table.right td { border: 1px solid #ccc; }
</style>
</head><body>
<div class="logo">
<a href="../index.html">
<img src="../_static/logo.png"
alt="LLVM Logo" width="250" height="88"/></a>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="TpiStream.html" title="The PDB TPI and IPI Streams"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="MsfFile.html" title="The MSF File Format"
accesskey="P">previous</a> |</li>
<li><a href="https://llvm.org/">LLVM Home</a> | </li>
<li><a href="../index.html">Documentation</a>»</li>
<li class="nav-item nav-item-1"><a href="../Reference.html" >Reference</a> »</li>
<li class="nav-item nav-item-2"><a href="index.html" accesskey="U">The PDB File Format</a> »</li>
<li class="nav-item nav-item-this"><a href="">The PDB Info Stream (aka the PDB Stream)</a></li>
</ul>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3>Documentation</h3>
<ul class="want-points">
<li><a href="https://llvm.org/docs/GettingStartedTutorials.html">Getting Started/Tutorials</a></li>
<li><a href="https://llvm.org/docs/UserGuides.html">User Guides</a></li>
<li><a href="https://llvm.org/docs/Reference.html">Reference</a></li>
</ul>
<h3>Getting Involved</h3>
<ul class="want-points">
<li><a href="https://llvm.org/docs/Contributing.html">Contributing to LLVM</a></li>
<li><a href="https://llvm.org/docs/HowToSubmitABug.html">Submitting Bug Reports</a></li>
<li><a href="https://llvm.org/docs/GettingInvolved.html#mailing-lists">Mailing Lists</a></li>
<li><a href="https://llvm.org/docs/GettingInvolved.html#irc">IRC</a></li>
<li><a href="https://llvm.org/docs/GettingInvolved.html#meetups-and-social-events">Meetups and Social Events</a></li>
</ul>
<h3>Additional Links</h3>
<ul class="want-points">
<li><a href="https://llvm.org/docs/FAQ.html">FAQ</a></li>
<li><a href="https://llvm.org/docs/Lexicon.html">Glossary</a></li>
<li><a href="https://llvm.org/pubs">Publications</a></li>
<li><a href="https://github.com/llvm/llvm-project//">Github Repository</a></li>
</ul>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/PDB/PdbStream.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="the-pdb-info-stream-aka-the-pdb-stream">
<h1>The PDB Info Stream (aka the PDB Stream)<a class="headerlink" href="#the-pdb-info-stream-aka-the-pdb-stream" title="Permalink to this headline">¶</a></h1>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><p><a class="reference internal" href="#stream-header" id="id1">Stream Header</a></p></li>
<li><p><a class="reference internal" href="#named-stream-map" id="id2">Named Stream Map</a></p></li>
<li><p><a class="reference internal" href="#pdb-feature-codes" id="id3">PDB Feature Codes</a></p></li>
<li><p><a class="reference internal" href="#matching-a-pdb-to-its-executable" id="id4">Matching a PDB to its executable</a></p></li>
</ul>
</div>
<div class="section" id="stream-header">
<span id="pdb-stream-header"></span><h2><a class="toc-backref" href="#id1">Stream Header</a><a class="headerlink" href="#stream-header" title="Permalink to this headline">¶</a></h2>
<p>At offset 0 of the PDB Stream is a header with the following layout:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="nc">PdbStreamHeader</span> <span class="p">{</span>
<span class="n">ulittle32_t</span> <span class="n">Version</span><span class="p">;</span>
<span class="n">ulittle32_t</span> <span class="n">Signature</span><span class="p">;</span>
<span class="n">ulittle32_t</span> <span class="n">Age</span><span class="p">;</span>
<span class="n">Guid</span> <span class="n">UniqueId</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<ul class="simple">
<li><p><strong>Version</strong> - A Value from the following enum:</p></li>
</ul>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">enum</span> <span class="k">class</span> <span class="nc">PdbStreamVersion</span> <span class="o">:</span> <span class="kt">uint32_t</span> <span class="p">{</span>
<span class="n">VC2</span> <span class="o">=</span> <span class="mi">19941610</span><span class="p">,</span>
<span class="n">VC4</span> <span class="o">=</span> <span class="mi">19950623</span><span class="p">,</span>
<span class="n">VC41</span> <span class="o">=</span> <span class="mi">19950814</span><span class="p">,</span>
<span class="n">VC50</span> <span class="o">=</span> <span class="mi">19960307</span><span class="p">,</span>
<span class="n">VC98</span> <span class="o">=</span> <span class="mi">19970604</span><span class="p">,</span>
<span class="n">VC70Dep</span> <span class="o">=</span> <span class="mi">19990604</span><span class="p">,</span>
<span class="n">VC70</span> <span class="o">=</span> <span class="mi">20000404</span><span class="p">,</span>
<span class="n">VC80</span> <span class="o">=</span> <span class="mi">20030901</span><span class="p">,</span>
<span class="n">VC110</span> <span class="o">=</span> <span class="mi">20091201</span><span class="p">,</span>
<span class="n">VC140</span> <span class="o">=</span> <span class="mi">20140508</span><span class="p">,</span>
<span class="p">};</span>
</pre></div>
</div>
<p>While the meaning of this field appears to be obvious, in practice we have
never observed a value other than <code class="docutils literal notranslate"><span class="pre">VC70</span></code>, even with modern versions of
the toolchain, and it is unclear why the other values exist. It is assumed
that certain aspects of the PDB stream’s layout, and perhaps even that of
the other streams, will change if the value is something other than <code class="docutils literal notranslate"><span class="pre">VC70</span></code>.</p>
<ul class="simple">
<li><p><strong>Signature</strong> - A 32-bit time-stamp generated with a call to <code class="docutils literal notranslate"><span class="pre">time()</span></code> at
the time the PDB file is written. Note that due to the inherent uniqueness
problems of using a timestamp with 1-second granularity, this field does not
really serve its intended purpose, and as such is typically ignored in favor
of the <code class="docutils literal notranslate"><span class="pre">Guid</span></code> field, described below.</p></li>
<li><p><strong>Age</strong> - The number of times the PDB file has been written. This can be used
along with <code class="docutils literal notranslate"><span class="pre">Guid</span></code> to match the PDB to its corresponding executable.</p></li>
<li><p><strong>Guid</strong> - A 128-bit identifier guaranteed to be unique across space and time.
In general, this can be thought of as the result of calling the Win32 API
<a class="reference external" href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa379205(v=vs.85).aspx">UuidCreate</a>,
although LLVM cannot rely on that, as it must work on non-Windows platforms.</p></li>
</ul>
</div>
<div class="section" id="named-stream-map">
<span id="pdb-named-stream-map"></span><h2><a class="toc-backref" href="#id2">Named Stream Map</a><a class="headerlink" href="#named-stream-map" title="Permalink to this headline">¶</a></h2>
<p>Following the header is a serialized hash table whose key type is a string, and
whose value type is an integer. The existence of a mapping <code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">-></span> <span class="pre">Y</span></code> means
that the stream with the name <code class="docutils literal notranslate"><span class="pre">X</span></code> has stream index <code class="docutils literal notranslate"><span class="pre">Y</span></code> in the underlying MSF
file. Note that not all streams are named (for example, the
<a class="reference internal" href="TpiStream.html"><span class="doc">TPI Stream</span></a> has a fixed index and as such there is no need to
look up its index by name). In practice, there are usually only a small number
of named streams and these are enumerated in the table of streams in <a class="reference internal" href="index.html"><span class="doc">The PDB File Format</span></a>.
A corollary of this is if a stream does have a name (and as such is in the named
stream map) then consulting the Named Stream Map is likely to be the only way to
discover the stream’s MSF stream index. Several important streams (such as the
global string table, which is called <code class="docutils literal notranslate"><span class="pre">/names</span></code>) can only be located this way, and
so it is important to both produce and consume this correctly as tools will not
function correctly without it.</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>Some streams are located by fixed indices (e.g TPI Stream has index 2), but
other streams are located by fixed names (e.g. the string table is called
<code class="docutils literal notranslate"><span class="pre">/names</span></code>) and can only be located by consulting the Named Stream Map.</p>
</div>
<p>The on-disk layout of the Named Stream Map consists of 2 components. The first is
a buffer of string data prefixed by a 32-bit length. The second is a serialized
hash table whose key and value types are both <code class="docutils literal notranslate"><span class="pre">uint32_t</span></code>. The key is the offset
of a null-terminated string in the string data buffer specifying the name of the
stream, and the value is the MSF stream index of the stream with said name.
Note that although the key is an integer, the hash function used to find the right
bucket hashes the string at the corresponding offset in the string data buffer.</p>
<p>The on-disk layout of the serialized hash table is described at <a class="reference internal" href="HashTable.html"><span class="doc">The PDB Serialized Hash Table Format</span></a>.</p>
<p>Note that the entire Named Stream Map is not length-prefixed, so the only way to
get to the data following it is to de-serialize it in its entirety.</p>
</div>
<div class="section" id="pdb-feature-codes">
<span id="pdb-stream-features"></span><h2><a class="toc-backref" href="#id3">PDB Feature Codes</a><a class="headerlink" href="#pdb-feature-codes" title="Permalink to this headline">¶</a></h2>
<p>Following the Named Stream Map, and consuming all remaining bytes of the PDB
Stream is a list of values from the following enumeration:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">enum</span> <span class="k">class</span> <span class="nc">PdbRaw_FeatureSig</span> <span class="o">:</span> <span class="kt">uint32_t</span> <span class="p">{</span>
<span class="n">VC110</span> <span class="o">=</span> <span class="mi">20091201</span><span class="p">,</span>
<span class="n">VC140</span> <span class="o">=</span> <span class="mi">20140508</span><span class="p">,</span>
<span class="n">NoTypeMerge</span> <span class="o">=</span> <span class="mh">0x4D544F4E</span><span class="p">,</span>
<span class="n">MinimalDebugInfo</span> <span class="o">=</span> <span class="mh">0x494E494D</span><span class="p">,</span>
<span class="p">};</span>
</pre></div>
</div>
<p>The meaning of these values is summarized by the following table:</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 27%" />
<col style="width: 73%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Flag</p></th>
<th class="head"><p>Meaning</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>VC110</p></td>
<td><ul class="simple">
<li><p>No other features flags are present</p></li>
<li><p>PDB contains an <a class="reference internal" href="TpiStream.html"><span class="doc">IPI Stream</span></a></p></li>
</ul>
</td>
</tr>
<tr class="row-odd"><td><p>VC140</p></td>
<td><ul class="simple">
<li><p>Other feature flags may be present</p></li>
<li><p>PDB contains an <a class="reference internal" href="TpiStream.html"><span class="doc">IPI Stream</span></a></p></li>
</ul>
</td>
</tr>
<tr class="row-even"><td><p>NoTypeMerge</p></td>
<td><ul class="simple">
<li><p>Presumably duplicate types can appear in the
TPI Stream, although it’s unclear why this
might happen.</p></li>
</ul>
</td>
</tr>
<tr class="row-odd"><td><p>MinimalDebugInfo</p></td>
<td><ul class="simple">
<li><p>Program was linked with /DEBUG:FASTLINK</p></li>
<li><p>There is no TPI / IPI stream, all type info
is contained in the original object files.</p></li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="matching-a-pdb-to-its-executable">
<h2><a class="toc-backref" href="#id4">Matching a PDB to its executable</a><a class="headerlink" href="#matching-a-pdb-to-its-executable" title="Permalink to this headline">¶</a></h2>
<p>The linker is responsible for writing both the PDB and the final executable, and
as a result is the only entity capable of writing the information necessary to
match the PDB to the executable.</p>
<p>In order to accomplish this, the linker generates a guid for the PDB (or
re-uses the existing guid if it is linking incrementally) and increments the Age
field.</p>
<p>The executable is a PE/COFF file, and part of a PE/COFF file is the presence of
number of “directories”. For our purposes here, we are interested in the “debug
directory”. The exact format of a debug directory is described by the
<a class="reference external" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms680307(v=vs.85).aspx">IMAGE_DEBUG_DIRECTORY structure</a>.
For this particular case, the linker emits a debug directory of type
<code class="docutils literal notranslate"><span class="pre">IMAGE_DEBUG_TYPE_CODEVIEW</span></code>. The format of this record is defined in
<code class="docutils literal notranslate"><span class="pre">llvm/DebugInfo/CodeView/CVDebugRecord.h</span></code>, but it suffices to say here only
that it includes the same <code class="docutils literal notranslate"><span class="pre">Guid</span></code> and <code class="docutils literal notranslate"><span class="pre">Age</span></code> fields. At runtime, a
debugger or tool can scan the COFF executable image for the presence of
a debug directory of the correct type and verify that the Guid and Age match.</p>
</div>
</div>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="TpiStream.html" title="The PDB TPI and IPI Streams"
>next</a> |</li>
<li class="right" >
<a href="MsfFile.html" title="The MSF File Format"
>previous</a> |</li>
<li><a href="https://llvm.org/">LLVM Home</a> | </li>
<li><a href="../index.html">Documentation</a>»</li>
<li class="nav-item nav-item-1"><a href="../Reference.html" >Reference</a> »</li>
<li class="nav-item nav-item-2"><a href="index.html" >The PDB File Format</a> »</li>
<li class="nav-item nav-item-this"><a href="">The PDB Info Stream (aka the PDB Stream)</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
© Copyright 2003-2021, LLVM Project.
Last updated on 2021-09-18.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.5.4.
</div>
</body>
</html>
|