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
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Debugging JIT-ed Code — 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="A guide to Dockerfiles for building LLVM" href="Docker.html" />
<link rel="prev" title="LLVM Code Coverage Mapping Format" href="CoverageMappingFormat.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="Docker.html" title="A guide to Dockerfiles for building LLVM"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="CoverageMappingFormat.html" title="LLVM Code Coverage Mapping 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="UserGuides.html" accesskey="U">User Guides</a> »</li>
<li class="nav-item nav-item-this"><a href="">Debugging JIT-ed Code</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/DebuggingJITedCode.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="debugging-jit-ed-code">
<h1>Debugging JIT-ed Code<a class="headerlink" href="#debugging-jit-ed-code" title="Permalink to this headline">¶</a></h1>
<div class="section" id="background">
<h2>Background<a class="headerlink" href="#background" title="Permalink to this headline">¶</a></h2>
<p>Without special runtime support, debugging dynamically generated code can be
quite painful. Debuggers generally read debug information from object files on
disk, but for JITed code there is no such file to look for.</p>
<p>In order to hand over the necessary debug info, <a class="reference external" href="https://sourceware.org/gdb/current/onlinedocs/gdb/JIT-Interface.html">GDB established an
interface</a>
for registering JITed code with debuggers. LLDB implements it in the
JITLoaderGDB plugin. On the JIT side, LLVM MCJIT does implement the interface
for ELF object files.</p>
<p>At a high level, whenever MCJIT generates new machine code, it does so in an
in-memory object file that contains the debug information in DWARF format.
MCJIT then adds this in-memory object file to a global list of dynamically
generated object files and calls a special function
<code class="docutils literal notranslate"><span class="pre">__jit_debug_register_code</span></code> that the debugger knows about. When the debugger
attaches to a process, it puts a breakpoint in this function and associates a
special handler with it. Once MCJIT calls the registration function, the
debugger catches the breakpoint signal, loads the new object file from the
inferior’s memory and resumes execution. This way it can obtain debug
information for pure in-memory object files.</p>
</div>
<div class="section" id="gdb-version">
<h2>GDB Version<a class="headerlink" href="#gdb-version" title="Permalink to this headline">¶</a></h2>
<p>In order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is
available on most modern distributions of Linux. The version of GDB that
Apple ships with Xcode has been frozen at 6.3 for a while.</p>
</div>
<div class="section" id="lldb-version">
<h2>LLDB Version<a class="headerlink" href="#lldb-version" title="Permalink to this headline">¶</a></h2>
<p>Due to a regression in release 6.0, LLDB didn’t support JITed code debugging for
a while. The bug was fixed in mainline recently, so that debugging JITed ELF
objects should be possible again from the upcoming release 12.0 on. On macOS the
feature must be enabled explicitly using the <code class="docutils literal notranslate"><span class="pre">plugin.jit-loader.gdb.enable</span></code>
setting.</p>
</div>
<div class="section" id="debugging-mcjit-ed-code">
<h2>Debugging MCJIT-ed code<a class="headerlink" href="#debugging-mcjit-ed-code" title="Permalink to this headline">¶</a></h2>
<p>The emerging MCJIT component of LLVM allows full debugging of JIT-ed code with
GDB. This is due to MCJIT’s ability to use the MC emitter to provide full
DWARF debugging information to GDB.</p>
<p>Note that lli has to be passed the <code class="docutils literal notranslate"><span class="pre">--jit-kind=mcjit</span></code> flag to JIT the code
with MCJIT instead of the newer ORC JIT.</p>
<div class="section" id="example">
<h3>Example<a class="headerlink" href="#example" title="Permalink to this headline">¶</a></h3>
<p>Consider the following C code (with line numbers added to make the example
easier to follow):</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="mi">1</span> <span class="kt">int</span> <span class="n">compute_factorial</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span>
<span class="mi">2</span> <span class="p">{</span>
<span class="mi">3</span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">)</span>
<span class="mi">4</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">5</span>
<span class="mi">6</span> <span class="kt">int</span> <span class="n">f</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span>
<span class="mi">7</span> <span class="k">while</span> <span class="p">(</span><span class="o">--</span><span class="n">n</span> <span class="o">></span> <span class="mi">1</span><span class="p">)</span>
<span class="mi">8</span> <span class="n">f</span> <span class="o">*=</span> <span class="n">n</span><span class="p">;</span>
<span class="mi">9</span> <span class="k">return</span> <span class="n">f</span><span class="p">;</span>
<span class="mi">10</span> <span class="p">}</span>
<span class="mi">11</span>
<span class="mi">12</span>
<span class="mi">13</span> <span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">**</span> <span class="n">argv</span><span class="p">)</span>
<span class="mi">14</span> <span class="p">{</span>
<span class="mi">15</span> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o"><</span> <span class="mi">2</span><span class="p">)</span>
<span class="mi">16</span> <span class="k">return</span> <span class="mi">-1</span><span class="p">;</span>
<span class="mi">17</span> <span class="kt">char</span> <span class="n">firstletter</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
<span class="mi">18</span> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">compute_factorial</span><span class="p">(</span><span class="n">firstletter</span> <span class="o">-</span> <span class="sc">'0'</span><span class="p">);</span>
<span class="mi">19</span>
<span class="mi">20</span> <span class="c1">// Returned result is clipped at 255...</span>
<span class="mi">21</span> <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="mi">22</span> <span class="p">}</span>
</pre></div>
</div>
<p>Here is a sample command line session that shows how to build and run this
code via <code class="docutils literal notranslate"><span class="pre">lli</span></code> inside LLDB:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>> <span class="nb">export</span> <span class="nv">BINPATH</span><span class="o">=</span>/workspaces/llvm-project/build/bin
> <span class="nv">$BINPATH</span>/clang -g -S -emit-llvm --target<span class="o">=</span>x86_64-unknown-unknown-elf showdebug.c
> lldb <span class="nv">$BINPATH</span>/lli
<span class="o">(</span>lldb<span class="o">)</span> target create <span class="s2">"/workspaces/llvm-project/build/bin/lli"</span>
Current executable <span class="nb">set</span> to <span class="s1">'/workspaces/llvm-project/build/bin/lli'</span> <span class="o">(</span>x86_64<span class="o">)</span>.
<span class="o">(</span>lldb<span class="o">)</span> settings <span class="nb">set</span> plugin.jit-loader.gdb.enable on
<span class="o">(</span>lldb<span class="o">)</span> b compute_factorial
Breakpoint <span class="m">1</span>: no locations <span class="o">(</span>pending<span class="o">)</span>.
WARNING: Unable to resolve breakpoint to any actual locations.
<span class="o">(</span>lldb<span class="o">)</span> run --jit-kind<span class="o">=</span>mcjit showdebug.ll <span class="m">5</span>
<span class="m">1</span> location added to breakpoint <span class="m">1</span>
Process <span class="m">21340</span> stopped
* thread <span class="c1">#1, name = 'lli', stop reason = breakpoint 1.1</span>
frame <span class="c1">#0: 0x00007ffff7fd0007 JIT(0x45c2cb0)`compute_factorial(n=5) at showdebug.c:3:11</span>
<span class="m">1</span> int compute_factorial<span class="o">(</span>int n<span class="o">)</span>
<span class="m">2</span> <span class="o">{</span>
-> <span class="m">3</span> <span class="k">if</span> <span class="o">(</span>n <<span class="o">=</span> <span class="m">1</span><span class="o">)</span>
<span class="m">4</span> <span class="k">return</span> <span class="m">1</span><span class="p">;</span>
<span class="m">5</span> int <span class="nv">f</span> <span class="o">=</span> n<span class="p">;</span>
<span class="m">6</span> <span class="k">while</span> <span class="o">(</span>--n > <span class="m">1</span><span class="o">)</span>
<span class="m">7</span> f *<span class="o">=</span> n<span class="p">;</span>
<span class="o">(</span>lldb<span class="o">)</span> p n
<span class="o">(</span>int<span class="o">)</span> <span class="nv">$0</span> <span class="o">=</span> <span class="m">5</span>
<span class="o">(</span>lldb<span class="o">)</span> b showdebug.c:9
Breakpoint <span class="m">2</span>: <span class="nv">where</span> <span class="o">=</span> JIT<span class="o">(</span>0x45c2cb0<span class="o">)</span><span class="sb">`</span>compute_factorial + <span class="m">60</span> at showdebug.c:9:1, <span class="nv">address</span> <span class="o">=</span> 0x00007ffff7fd003c
<span class="o">(</span>lldb<span class="o">)</span> c
Process <span class="m">21340</span> resuming
Process <span class="m">21340</span> stopped
* thread <span class="c1">#1, name = 'lli', stop reason = breakpoint 2.1</span>
frame <span class="c1">#0: 0x00007ffff7fd003c JIT(0x45c2cb0)`compute_factorial(n=1) at showdebug.c:9:1</span>
<span class="m">6</span> <span class="k">while</span> <span class="o">(</span>--n > <span class="m">1</span><span class="o">)</span>
<span class="m">7</span> f *<span class="o">=</span> n<span class="p">;</span>
<span class="m">8</span> <span class="k">return</span> f<span class="p">;</span>
-> <span class="m">9</span> <span class="o">}</span>
<span class="m">10</span>
<span class="m">11</span> int main<span class="o">(</span>int argc, char** argv<span class="o">)</span>
<span class="m">12</span> <span class="o">{</span>
<span class="o">(</span>lldb<span class="o">)</span> p f
<span class="o">(</span>int<span class="o">)</span> <span class="nv">$1</span> <span class="o">=</span> <span class="m">120</span>
<span class="o">(</span>lldb<span class="o">)</span> bt
* thread <span class="c1">#1, name = 'lli', stop reason = breakpoint 2.1</span>
* frame <span class="c1">#0: 0x00007ffff7fd003c JIT(0x45c2cb0)`compute_factorial(n=1) at showdebug.c:9:1</span>
frame <span class="c1">#1: 0x00007ffff7fd0095 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:16:18</span>
frame <span class="c1">#2: 0x0000000002a8306e lli`llvm::MCJIT::runFunction(this=0x000000000458ed10, F=0x0000000004589ff8, ArgValues=ArrayRef<llvm::GenericValue> @ 0x00007fffffffc798) at MCJIT.cpp:554:31</span>
frame <span class="c1">#3: 0x00000000029bdb45 lli`llvm::ExecutionEngine::runFunctionAsMain(this=0x000000000458ed10, Fn=0x0000000004589ff8, argv=size=0, envp=0x00007fffffffe140) at ExecutionEngine.cpp:467:10</span>
frame <span class="c1">#4: 0x0000000001f2fc2f lli`main(argc=4, argv=0x00007fffffffe118, envp=0x00007fffffffe140) at lli.cpp:643:18</span>
frame <span class="c1">#5: 0x00007ffff788c09b libc.so.6`__libc_start_main(main=(lli`main at lli.cpp:387), argc=4, argv=0x00007fffffffe118, init=<unavailable>, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffe108) at libc-start.c:308:16</span>
frame <span class="c1">#6: 0x0000000001f2dc7a lli`_start + 42</span>
<span class="o">(</span>lldb<span class="o">)</span> finish
Process <span class="m">21340</span> stopped
* thread <span class="c1">#1, name = 'lli', stop reason = step out</span>
Return value: <span class="o">(</span>int<span class="o">)</span> <span class="nv">$2</span> <span class="o">=</span> <span class="m">120</span>
frame <span class="c1">#0: 0x00007ffff7fd0095 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:16:9</span>
<span class="m">13</span> <span class="k">if</span> <span class="o">(</span>argc < <span class="m">2</span><span class="o">)</span>
<span class="m">14</span> <span class="k">return</span> -1<span class="p">;</span>
<span class="m">15</span> char <span class="nv">firstletter</span> <span class="o">=</span> argv<span class="o">[</span><span class="m">1</span><span class="o">][</span><span class="m">0</span><span class="o">]</span><span class="p">;</span>
-> <span class="m">16</span> int <span class="nv">result</span> <span class="o">=</span> compute_factorial<span class="o">(</span>firstletter - <span class="s1">'0'</span><span class="o">)</span><span class="p">;</span>
<span class="m">17</span>
<span class="m">18</span> // Returned result is clipped at <span class="m">255</span>...
<span class="m">19</span> <span class="k">return</span> result<span class="p">;</span>
<span class="o">(</span>lldb<span class="o">)</span> p result
<span class="o">(</span>int<span class="o">)</span> <span class="nv">$3</span> <span class="o">=</span> <span class="m">73670648</span>
<span class="o">(</span>lldb<span class="o">)</span> n
Process <span class="m">21340</span> stopped
* thread <span class="c1">#1, name = 'lli', stop reason = step over</span>
frame <span class="c1">#0: 0x00007ffff7fd0098 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:19:12</span>
<span class="m">16</span> int <span class="nv">result</span> <span class="o">=</span> compute_factorial<span class="o">(</span>firstletter - <span class="s1">'0'</span><span class="o">)</span><span class="p">;</span>
<span class="m">17</span>
<span class="m">18</span> // Returned result is clipped at <span class="m">255</span>...
-> <span class="m">19</span> <span class="k">return</span> result<span class="p">;</span>
<span class="m">20</span> <span class="o">}</span>
<span class="o">(</span>lldb<span class="o">)</span> p result
<span class="o">(</span>int<span class="o">)</span> <span class="nv">$4</span> <span class="o">=</span> <span class="m">120</span>
<span class="o">(</span>lldb<span class="o">)</span> expr <span class="nv">result</span><span class="o">=</span><span class="m">42</span>
<span class="o">(</span>int<span class="o">)</span> <span class="nv">$5</span> <span class="o">=</span> <span class="m">42</span>
<span class="o">(</span>lldb<span class="o">)</span> p result
<span class="o">(</span>int<span class="o">)</span> <span class="nv">$6</span> <span class="o">=</span> <span class="m">42</span>
<span class="o">(</span>lldb<span class="o">)</span> c
Process <span class="m">21340</span> resuming
Process <span class="m">21340</span> exited with <span class="nv">status</span> <span class="o">=</span> <span class="m">42</span> <span class="o">(</span>0x0000002a<span class="o">)</span>
<span class="o">(</span>lldb<span class="o">)</span> <span class="nb">exit</span>
</pre></div>
</div>
</div>
</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="Docker.html" title="A guide to Dockerfiles for building LLVM"
>next</a> |</li>
<li class="right" >
<a href="CoverageMappingFormat.html" title="LLVM Code Coverage Mapping 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="UserGuides.html" >User Guides</a> »</li>
<li class="nav-item nav-item-this"><a href="">Debugging JIT-ed Code</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>
|