blob: ec79a54b21a2b497713c8a7c2c9eb33e0d9c83b2 [file] [log] [blame] [edit]
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Debugging Support in the Rust Compiler - Guide to Rustc Development</title>
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="A guide to developing rustc">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item affix "><a href="about-this-guide.html">About this guide</a></li><li class="chapter-item affix "><a href="getting-started.html">Getting Started</a></li><li class="spacer"></li><li class="chapter-item affix "><li class="part-title">Building and debugging rustc</li><li class="chapter-item "><a href="building/how-to-build-and-run.html"><strong aria-hidden="true">1.</strong> How to Build and Run the Compiler</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="building/prerequisites.html"><strong aria-hidden="true">1.1.</strong> Prerequisites</a></li><li class="chapter-item "><a href="building/suggested.html"><strong aria-hidden="true">1.2.</strong> Suggested Workflows</a></li><li class="chapter-item "><a href="building/build-install-distribution-artifacts.html"><strong aria-hidden="true">1.3.</strong> Distribution artifacts</a></li><li class="chapter-item "><a href="building/compiler-documenting.html"><strong aria-hidden="true">1.4.</strong> Documenting Compiler</a></li><li class="chapter-item "><a href="rustdoc.html"><strong aria-hidden="true">1.5.</strong> Rustdoc overview</a></li><li class="chapter-item "><a href="building/new-target.html"><strong aria-hidden="true">1.6.</strong> Adding a new target</a></li></ol></li><li class="chapter-item "><a href="tests/intro.html"><strong aria-hidden="true">2.</strong> The compiler testing framework</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="tests/running.html"><strong aria-hidden="true">2.1.</strong> Running tests</a></li><li class="chapter-item "><a href="tests/adding.html"><strong aria-hidden="true">2.2.</strong> Adding new tests</a></li><li class="chapter-item "><a href="compiletest.html"><strong aria-hidden="true">2.3.</strong> Using compiletest commands to control test execution</a></li></ol></li><li class="chapter-item "><a href="compiler-debugging.html"><strong aria-hidden="true">3.</strong> Debugging the Compiler</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="tracing.html"><strong aria-hidden="true">3.1.</strong> Using the tracing/logging instrumentation</a></li></ol></li><li class="chapter-item "><a href="profiling.html"><strong aria-hidden="true">4.</strong> Profiling the compiler</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="profiling/with_perf.html"><strong aria-hidden="true">4.1.</strong> with the linux perf tool</a></li><li class="chapter-item "><a href="profiling/wpa_profiling.html"><strong aria-hidden="true">4.2.</strong> with Windows Performance Analyzer</a></li></ol></li><li class="chapter-item "><a href="crates-io.html"><strong aria-hidden="true">5.</strong> crates.io Dependencies</a></li><li class="chapter-item affix "><li class="part-title">Contributing to Rust</li><li class="chapter-item "><a href="contributing.html"><strong aria-hidden="true">6.</strong> Introduction</a></li><li class="chapter-item "><a href="compiler-team.html"><strong aria-hidden="true">7.</strong> About the compiler team</a></li><li class="chapter-item "><a href="git.html"><strong aria-hidden="true">8.</strong> Using Git</a></li><li class="chapter-item "><a href="rustbot.html"><strong aria-hidden="true">9.</strong> Mastering @rustbot</a></li><li class="chapter-item "><a href="walkthrough.html"><strong aria-hidden="true">10.</strong> Walkthrough: a typical contribution</a></li><li class="chapter-item "><a href="bug-fix-procedure.html"><strong aria-hidden="true">11.</strong> Bug Fix Procedure</a></li><li class="chapter-item "><a href="implementing_new_features.html"><strong aria-hidden="true">12.</strong> Implementing new features</a></li><li class="chapter-item "><a href="stability.html"><strong aria-hidden="true">13.</strong> Stability attributes</a></li><li class="chapter-item "><a href="stabilization_guide.html"><strong aria-hidden="true">14.</strong> Stabilizing Features</a></li><li class="chapter-item "><a href="feature-gates.html"><strong aria-hidden="true">15.</strong> Feature Gates</a></li><li class="chapter-item "><a href="conventions.html"><strong aria-hidden="true">16.</strong> Coding conventions</a></li><li class="chapter-item "><a href="notification-groups/about.html"><strong aria-hidden="true">17.</strong> Notification groups</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="notification-groups/arm.html"><strong aria-hidden="true">17.1.</strong> ARM</a></li><li class="chapter-item "><a href="notification-groups/cleanup-crew.html"><strong aria-hidden="true">17.2.</strong> Cleanup Crew</a></li><li class="chapter-item "><a href="notification-groups/llvm.html"><strong aria-hidden="true">17.3.</strong> LLVM</a></li><li class="chapter-item "><a href="notification-groups/risc-v.html"><strong aria-hidden="true">17.4.</strong> RISC-V</a></li><li class="chapter-item "><a href="notification-groups/windows.html"><strong aria-hidden="true">17.5.</strong> Windows</a></li></ol></li><li class="chapter-item "><a href="licenses.html"><strong aria-hidden="true">18.</strong> Licenses</a></li><li class="chapter-item affix "><li class="part-title">High-level Compiler Architecture</li><li class="chapter-item "><a href="part-2-intro.html"><strong aria-hidden="true">19.</strong> Prologue</a></li><li class="chapter-item "><a href="overview.html"><strong aria-hidden="true">20.</strong> Overview of the Compiler</a></li><li class="chapter-item "><a href="compiler-src.html"><strong aria-hidden="true">21.</strong> The compiler source code</a></li><li class="chapter-item "><a href="building/bootstrapping.html"><strong aria-hidden="true">22.</strong> Bootstrapping</a></li><li class="chapter-item "><a href="query.html"><strong aria-hidden="true">23.</strong> Queries: demand-driven compilation</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="queries/query-evaluation-model-in-detail.html"><strong aria-hidden="true">23.1.</strong> The Query Evaluation Model in Detail</a></li><li class="chapter-item "><a href="queries/incremental-compilation.html"><strong aria-hidden="true">23.2.</strong> Incremental compilation</a></li><li class="chapter-item "><a href="queries/incremental-compilation-in-detail.html"><strong aria-hidden="true">23.3.</strong> Incremental compilation In Detail</a></li><li class="chapter-item "><a href="incrcomp-debugging.html"><strong aria-hidden="true">23.4.</strong> Debugging and Testing</a></li><li class="chapter-item "><a href="salsa.html"><strong aria-hidden="true">23.5.</strong> Salsa</a></li></ol></li><li class="chapter-item "><a href="memory.html"><strong aria-hidden="true">24.</strong> Memory Management in Rustc</a></li><li class="chapter-item "><a href="serialization.html"><strong aria-hidden="true">25.</strong> Serialization in Rustc</a></li><li class="chapter-item "><a href="parallel-rustc.html"><strong aria-hidden="true">26.</strong> Parallel Compilation</a></li><li class="chapter-item "><a href="rustdoc-internals.html"><strong aria-hidden="true">27.</strong> Rustdoc internals</a></li><li class="chapter-item affix "><li class="part-title">Source Code Representation</li><li class="chapter-item "><a href="part-3-intro.html"><strong aria-hidden="true">28.</strong> Prologue</a></li><li class="chapter-item "><a href="cli.html"><strong aria-hidden="true">29.</strong> Command-line arguments</a></li><li class="chapter-item "><a href="rustc-driver.html"><strong aria-hidden="true">30.</strong> The Rustc Driver and Interface</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="rustc-driver-interacting-with-the-ast.html"><strong aria-hidden="true">30.1.</strong> Ex: Type checking through rustc_interface</a></li><li class="chapter-item "><a href="rustc-driver-getting-diagnostics.html"><strong aria-hidden="true">30.2.</strong> Ex: Getting diagnostics through rustc_interface</a></li></ol></li><li class="chapter-item "><a href="syntax-intro.html"><strong aria-hidden="true">31.</strong> Syntax and the AST</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="the-parser.html"><strong aria-hidden="true">31.1.</strong> Lexing and Parsing</a></li><li class="chapter-item "><a href="macro-expansion.html"><strong aria-hidden="true">31.2.</strong> Macro expansion</a></li><li class="chapter-item "><a href="name-resolution.html"><strong aria-hidden="true">31.3.</strong> Name resolution</a></li><li class="chapter-item "><a href="test-implementation.html"><strong aria-hidden="true">31.4.</strong> #[test] Implementation</a></li><li class="chapter-item "><a href="panic-implementation.html"><strong aria-hidden="true">31.5.</strong> Panic Implementation</a></li><li class="chapter-item "><a href="ast-validation.html"><strong aria-hidden="true">31.6.</strong> AST Validation</a></li><li class="chapter-item "><a href="feature-gate-ck.html"><strong aria-hidden="true">31.7.</strong> Feature Gate Checking</a></li><li class="chapter-item "><a href="lang-items.html"><strong aria-hidden="true">31.8.</strong> Lang Items</a></li></ol></li><li class="chapter-item "><a href="hir.html"><strong aria-hidden="true">32.</strong> The HIR (High-level IR)</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="lowering.html"><strong aria-hidden="true">32.1.</strong> Lowering AST to HIR</a></li><li class="chapter-item "><a href="hir-debugging.html"><strong aria-hidden="true">32.2.</strong> Debugging</a></li></ol></li><li class="chapter-item "><a href="thir.html"><strong aria-hidden="true">33.</strong> The THIR (Typed High-level IR)</a></li><li class="chapter-item "><a href="mir/index.html"><strong aria-hidden="true">34.</strong> The MIR (Mid-level IR)</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="mir/construction.html"><strong aria-hidden="true">34.1.</strong> MIR construction</a></li><li class="chapter-item "><a href="mir/visitor.html"><strong aria-hidden="true">34.2.</strong> MIR visitor and traversal</a></li><li class="chapter-item "><a href="mir/passes.html"><strong aria-hidden="true">34.3.</strong> MIR passes: getting the MIR for a function</a></li></ol></li><li class="chapter-item "><a href="identifiers.html"><strong aria-hidden="true">35.</strong> Identifiers in the Compiler</a></li><li class="chapter-item "><a href="closure.html"><strong aria-hidden="true">36.</strong> Closure expansion</a></li><li class="chapter-item affix "><li class="part-title">Analysis</li><li class="chapter-item "><a href="part-4-intro.html"><strong aria-hidden="true">37.</strong> Prologue</a></li><li class="chapter-item "><a href="ty.html"><strong aria-hidden="true">38.</strong> The ty module: representing types</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="generics.html"><strong aria-hidden="true">38.1.</strong> Generics and substitutions</a></li><li class="chapter-item "><a href="ty-fold.html"><strong aria-hidden="true">38.2.</strong> TypeFolder and TypeFoldable</a></li><li class="chapter-item "><a href="generic_arguments.html"><strong aria-hidden="true">38.3.</strong> Generic arguments</a></li><li class="chapter-item "><a href="constants.html"><strong aria-hidden="true">38.4.</strong> Constants in the type system</a></li></ol></li><li class="chapter-item "><a href="type-inference.html"><strong aria-hidden="true">39.</strong> Type inference</a></li><li class="chapter-item "><a href="traits/resolution.html"><strong aria-hidden="true">40.</strong> Trait solving</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="early-late-bound.html"><strong aria-hidden="true">40.1.</strong> Early and Late Bound Parameters</a></li><li class="chapter-item "><a href="traits/hrtb.html"><strong aria-hidden="true">40.2.</strong> Higher-ranked trait bounds</a></li><li class="chapter-item "><a href="traits/caching.html"><strong aria-hidden="true">40.3.</strong> Caching subtleties</a></li><li class="chapter-item "><a href="traits/specialization.html"><strong aria-hidden="true">40.4.</strong> Specialization</a></li><li class="chapter-item "><a href="traits/chalk.html"><strong aria-hidden="true">40.5.</strong> Chalk-based trait solving</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="traits/lowering-to-logic.html"><strong aria-hidden="true">40.5.1.</strong> Lowering to logic</a></li><li class="chapter-item "><a href="traits/goals-and-clauses.html"><strong aria-hidden="true">40.5.2.</strong> Goals and clauses</a></li><li class="chapter-item "><a href="traits/canonical-queries.html"><strong aria-hidden="true">40.5.3.</strong> Canonical queries</a></li></ol></li></ol></li><li class="chapter-item "><a href="type-checking.html"><strong aria-hidden="true">41.</strong> Type checking</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="method-lookup.html"><strong aria-hidden="true">41.1.</strong> Method Lookup</a></li><li class="chapter-item "><a href="variance.html"><strong aria-hidden="true">41.2.</strong> Variance</a></li><li class="chapter-item "><a href="opaque-types-type-alias-impl-trait.html"><strong aria-hidden="true">41.3.</strong> Opaque Types</a></li></ol></li><li class="chapter-item "><a href="pat-exhaustive-checking.html"><strong aria-hidden="true">42.</strong> Pattern and Exhaustiveness Checking</a></li><li class="chapter-item "><a href="mir/dataflow.html"><strong aria-hidden="true">43.</strong> MIR dataflow</a></li><li class="chapter-item "><a href="borrow_check.html"><strong aria-hidden="true">44.</strong> The borrow checker</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="borrow_check/moves_and_initialization.html"><strong aria-hidden="true">44.1.</strong> Tracking moves and initialization</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="borrow_check/moves_and_initialization/move_paths.html"><strong aria-hidden="true">44.1.1.</strong> Move paths</a></li></ol></li><li class="chapter-item "><a href="borrow_check/type_check.html"><strong aria-hidden="true">44.2.</strong> MIR type checker</a></li><li class="chapter-item "><a href="borrow_check/region_inference.html"><strong aria-hidden="true">44.3.</strong> Region inference</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="borrow_check/region_inference/constraint_propagation.html"><strong aria-hidden="true">44.3.1.</strong> Constraint propagation</a></li><li class="chapter-item "><a href="borrow_check/region_inference/lifetime_parameters.html"><strong aria-hidden="true">44.3.2.</strong> Lifetime parameters</a></li><li class="chapter-item "><a href="borrow_check/region_inference/member_constraints.html"><strong aria-hidden="true">44.3.3.</strong> Member constraints</a></li><li class="chapter-item "><a href="borrow_check/region_inference/placeholders_and_universes.html"><strong aria-hidden="true">44.3.4.</strong> Placeholders and universes</a></li><li class="chapter-item "><a href="borrow_check/region_inference/closure_constraints.html"><strong aria-hidden="true">44.3.5.</strong> Closure constraints</a></li><li class="chapter-item "><a href="borrow_check/region_inference/error_reporting.html"><strong aria-hidden="true">44.3.6.</strong> Error reporting</a></li></ol></li><li class="chapter-item "><a href="borrow_check/two_phase_borrows.html"><strong aria-hidden="true">44.4.</strong> Two-phase-borrows</a></li></ol></li><li class="chapter-item "><a href="param_env.html"><strong aria-hidden="true">45.</strong> Parameter Environments</a></li><li class="chapter-item "><a href="diagnostics.html"><strong aria-hidden="true">46.</strong> Errors and Lints</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="diagnostics/sessiondiagnostic.html"><strong aria-hidden="true">46.1.</strong> Creating Errors With SessionDiagnostic</a></li><li class="chapter-item "><a href="diagnostics/lintstore.html"><strong aria-hidden="true">46.2.</strong> LintStore</a></li><li class="chapter-item "><a href="diagnostics/diagnostic-codes.html"><strong aria-hidden="true">46.3.</strong> Diagnostic Codes</a></li><li class="chapter-item "><a href="diagnostics/diagnostic-items.html"><strong aria-hidden="true">46.4.</strong> Diagnostic Items</a></li></ol></li><li class="chapter-item "><li class="part-title">MIR to Binaries</li><li class="chapter-item "><a href="part-5-intro.html"><strong aria-hidden="true">47.</strong> Prologue</a></li><li class="chapter-item "><a href="mir/optimizations.html"><strong aria-hidden="true">48.</strong> MIR optimizations</a></li><li class="chapter-item "><a href="mir/debugging.html"><strong aria-hidden="true">49.</strong> Debugging</a></li><li class="chapter-item "><a href="const-eval.html"><strong aria-hidden="true">50.</strong> Constant evaluation</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="miri.html"><strong aria-hidden="true">50.1.</strong> miri const evaluator</a></li></ol></li><li class="chapter-item "><a href="backend/monomorph.html"><strong aria-hidden="true">51.</strong> Monomorphization</a></li><li class="chapter-item "><a href="backend/lowering-mir.html"><strong aria-hidden="true">52.</strong> Lowering MIR</a></li><li class="chapter-item "><a href="backend/codegen.html"><strong aria-hidden="true">53.</strong> Code Generation</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="backend/updating-llvm.html"><strong aria-hidden="true">53.1.</strong> Updating LLVM</a></li><li class="chapter-item "><a href="backend/debugging.html"><strong aria-hidden="true">53.2.</strong> Debugging LLVM</a></li><li class="chapter-item "><a href="backend/backend-agnostic.html"><strong aria-hidden="true">53.3.</strong> Backend Agnostic Codegen</a></li><li class="chapter-item "><a href="backend/implicit-caller-location.html"><strong aria-hidden="true">53.4.</strong> Implicit Caller Location</a></li></ol></li><li class="chapter-item "><a href="backend/libs-and-metadata.html"><strong aria-hidden="true">54.</strong> Libraries and Metadata</a></li><li class="chapter-item "><a href="profile-guided-optimization.html"><strong aria-hidden="true">55.</strong> Profile-guided Optimization</a></li><li class="chapter-item "><a href="llvm-coverage-instrumentation.html"><strong aria-hidden="true">56.</strong> LLVM Source-Based Code Coverage</a></li><li class="chapter-item "><a href="sanitizers.html"><strong aria-hidden="true">57.</strong> Sanitizers Support</a></li><li class="chapter-item expanded "><a href="debugging-support-in-rustc.html" class="active"><strong aria-hidden="true">58.</strong> Debugging Support in the Rust Compiler</a></li><li class="spacer"></li><li class="chapter-item affix "><a href="appendix/background.html">Appendix A: Background topics</a></li><li class="chapter-item affix "><a href="appendix/glossary.html">Appendix B: Glossary</a></li><li class="chapter-item affix "><a href="appendix/code-index.html">Appendix C: Code Index</a></li><li class="chapter-item affix "><a href="appendix/compiler-lecture.html">Appendix D: Compiler Lecture Series</a></li><li class="chapter-item affix "><a href="appendix/bibliography.html">Appendix E: Bibliography</a></li><li class="chapter-item affix "><a href="appendix/humorust.html">Appendix Z: HumorRust</a></li><li class="spacer"></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Guide to Rustc Development</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/rust-lang/rustc-dev-guide" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/rust-lang/rustc-dev-guide/tree/master/src/debugging-support-in-rustc.md?mode&#x3D;edit" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="debugging-support-in-the-rust-compiler"><a class="header" href="#debugging-support-in-the-rust-compiler">Debugging support in the Rust compiler</a></h1>
<ul>
<li><a href="#preliminaries">Preliminaries</a>
<ul>
<li><a href="#debuggers">Debuggers</a></li>
<li><a href="#dwarf">DWARF</a></li>
</ul>
</li>
<li><a href="#supported-debuggers">Supported debuggers</a>
<ul>
<li><a href="#gdb">GDB</a>
<ul>
<li><a href="#rust-expression-parser">Rust expression parser</a></li>
<li><a href="#parser-extensions">Parser extensions</a></li>
<li><a href="#developer-notes">Developer notes</a></li>
</ul>
</li>
<li><a href="#lldb">LLDB</a>
<ul>
<li><a href="#rust-expression-parser-1">Rust expression parser</a></li>
<li><a href="#parser-extensions-1">Parser extensions</a></li>
<li><a href="#developer-notes-1">Developer notes</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#dwarf-and-rustc">DWARF and Rustc</a>
<ul>
<li><a href="#current-limitations-of-dwarf">Current limitations of DWARF</a></li>
</ul>
</li>
<li><a href="#developer-notes-2">Developer notes</a></li>
<li><a href="#what-is-missing">What is missing</a>
<ul>
<li><a href="#shipping-gdb-in-rustup">Shipping GDB in Rustup</a></li>
<li><a href="#code-signing-for-lldb-debug-server-on-macos">Code signing for LLDB debug server on macOS</a></li>
<li><a href="#dwarf-and-traits">DWARF and Traits</a></li>
</ul>
</li>
<li><a href="#typical-process-for-a-debug-info-change-llvm">Typical process for a Debug Info change (LLVM)</a>
<ul>
<li><a href="#procedural-macro-stepping">Procedural macro stepping</a></li>
</ul>
</li>
<li><a href="#source-file-checksums-in-debug-info">Source file checksums in debug info</a>
<ul>
<li><a href="#dwarf-5">DWARF 5</a></li>
<li><a href="#llvm">LLVM</a></li>
<li><a href="#microsoft-visual-c-compiler-zh-option">Microsoft Visual C++ Compiler /ZH option</a></li>
<li><a href="#clang">Clang</a></li>
</ul>
</li>
<li><a href="#future-work">Future work</a>
<ul>
<li><a href="#name-mangling-changes">Name mangling changes</a></li>
<li><a href="#reuse-rust-compiler-for-expressions">Reuse Rust compiler for expressions</a></li>
</ul>
</li>
</ul>
<p>This document explains the state of debugging tools support in the Rust compiler (rustc).
The document gives an overview of debugging tools like GDB, LLDB etc. and infrastructure
around Rust compiler to debug Rust code. If you want to learn how to debug the Rust compiler
itself, then you must see <a href="compiler-debugging.html">Debugging the Compiler</a> page.</p>
<p>The material is gathered from YouTube video <a href="https://www.youtube.com/watch?v=elBxMRSNYr4">Tom Tromey discusses debugging support in rustc</a>.</p>
<h2 id="preliminaries"><a class="header" href="#preliminaries">Preliminaries</a></h2>
<h3 id="debuggers"><a class="header" href="#debuggers">Debuggers</a></h3>
<p>According to Wikipedia</p>
<blockquote>
<p>A <a href="https://en.wikipedia.org/wiki/Debugger">debugger or debugging tool</a> is a computer program that is used to test and debug
other programs (the &quot;target&quot; program).</p>
</blockquote>
<p>Writing a debugger from scratch for a language requires a lot of work, especially if
debuggers have to be supported on various platforms. GDB and LLDB, however, can be
extended to support debugging a language. This is the path that Rust has chosen.
This document's main goal is to document the said debuggers support in Rust compiler.</p>
<h3 id="dwarf"><a class="header" href="#dwarf">DWARF</a></h3>
<p>According to the <a href="http://dwarfstd.org">DWARF</a> standard website</p>
<blockquote>
<p>DWARF is a debugging file format used by many compilers and debuggers to support source level
debugging. It addresses the requirements of a number of procedural languages,
such as C, C++, and Fortran, and is designed to be extensible to other languages.
DWARF is architecture independent and applicable to any processor or operating system.
It is widely used on Unix, Linux and other operating systems,
as well as in stand-alone environments.</p>
</blockquote>
<p>DWARF reader is a program that consumes the DWARF format and creates debugger compatible output.
This program may live in the compiler itself. DWARF uses a data structure called
Debugging Information Entry (DIE) which stores the information as &quot;tags&quot; to denote functions,
variables etc., e.g., <code>DW_TAG_variable</code>, <code>DW_TAG_pointer_type</code>, <code>DW_TAG_subprogram</code> etc.
You can also invent your own tags and attributes.</p>
<h2 id="supported-debuggers"><a class="header" href="#supported-debuggers">Supported debuggers</a></h2>
<h3 id="gdb"><a class="header" href="#gdb">GDB</a></h3>
<p>We have our own fork of GDB - <a href="https://github.com/rust-dev-tools/gdb">https://github.com/rust-dev-tools/gdb</a></p>
<h4 id="rust-expression-parser"><a class="header" href="#rust-expression-parser">Rust expression parser</a></h4>
<p>To be able to show debug output we need an expression parser.
This (GDB) expression parser is written in <a href="https://www.gnu.org/software/bison/">Bison</a> and is only a subset of Rust expressions.
This means that this parser can parse only a subset of Rust expressions.
GDB parser was written from scratch and has no relation to any other parser.
For example, this parser is not related to Rustc's parser.</p>
<p>GDB has Rust like value and type output. It can print values and types in a way
that look like Rust syntax in the output. Or when you print a type as <a href="https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_109.html">ptype</a> in GDB,
it also looks like Rust source code. Checkout the documentation in the <a href="https://sourceware.org/gdb/onlinedocs/gdb/Rust.html">manual for GDB/Rust</a>.</p>
<h4 id="parser-extensions"><a class="header" href="#parser-extensions">Parser extensions</a></h4>
<p>Expression parser has a couple of extensions in it to facilitate features that you cannot do
with Rust. Some limitations are listed in the <a href="https://sourceware.org/gdb/onlinedocs/gdb/Rust.html">manual for GDB/Rust</a>. There is some special
code in the DWARF reader in GDB to support the extensions.</p>
<p>A couple of examples of DWARF reader support needed are as follows -</p>
<ol>
<li>
<p>Enum: Needed for support for enum types. The Rustc writes the information about enum into
DWARF and GDB reads the DWARF to understand where is the tag field or is there a tag
field or is the tag slot shared with non-zero optimization etc.</p>
</li>
<li>
<p>Dissect trait objects: DWARF extension where the trait object's description in the DWARF
also points to a stub description of the corresponding vtable which in turn points to the
concrete type for which this trait object exists. This means that you can do a <code>print *object</code>
for that trait object, and GDB will understand how to find the correct type of the payload in
the trait object.</p>
</li>
</ol>
<p><strong>TODO</strong>: Figure out if the following should be mentioned in the GDB-Rust document rather than
this guide page so there is no duplication. This is regarding the following comments:</p>
<p><a href="https://github.com/rust-lang/rustc-dev-guide/pull/316#discussion_r284027340">This comment by Tom</a></p>
<blockquote>
<p>gdb's Rust extensions and limitations are documented in the gdb manual:
https://sourceware.org/gdb/onlinedocs/gdb/Rust.html -- however, this neglects to mention that
gdb convenience variables and registers follow the gdb $ convention, and that the Rust parser
implements the gdb @ extension.</p>
</blockquote>
<p><a href="https://github.com/rust-lang/rustc-dev-guide/pull/316#discussion_r285401353">This question by Aman</a></p>
<blockquote>
<p>@tromey do you think we should mention this part in the GDB-Rust document rather than this
document so there is no duplication etc.?</p>
</blockquote>
<h4 id="developer-notes"><a class="header" href="#developer-notes">Developer notes</a></h4>
<ul>
<li>This work is now upstream. Bugs can be reported in <a href="https://sourceware.org/bugzilla/">GDB Bugzilla</a>.</li>
</ul>
<h3 id="lldb"><a class="header" href="#lldb">LLDB</a></h3>
<p>Fork of LLVM project - <a href="https://github.com/rust-lang/llvm-project">https://github.com/rust-lang/llvm-project</a></p>
<p>LLDB currently only works on macOS because of a dependency issue. This issue was easier to
solve for macOS as compared to Linux. However, Tom has a possible solution which can enable
us to ship LLDB everywhere.</p>
<h4 id="rust-expression-parser-1"><a class="header" href="#rust-expression-parser-1">Rust expression parser</a></h4>
<p>This expression parser is written in C++. It is a type of <a href="https://en.wikipedia.org/wiki/Recursive_descent_parser">Recursive Descent parser</a>.
Implements slightly less of the Rust language than GDB. LLDB has Rust like value and type output.</p>
<h4 id="parser-extensions-1"><a class="header" href="#parser-extensions-1">Parser extensions</a></h4>
<p>There is some special code in the DWARF reader in LLDB to support the extensions.
A couple of examples of DWARF reader support needed are as follows -</p>
<ol>
<li>Enum: Needed for support for enum types. The Rustc writes the information about
enum into DWARF and LLDB reads the DWARF to understand where is the tag field or
is there a tag field or is the tag slot shared with non-zero optimization etc.
In other words, it has enum support as well.</li>
</ol>
<h4 id="developer-notes-1"><a class="header" href="#developer-notes-1">Developer notes</a></h4>
<ul>
<li>None of the LLDB work is upstream. This <a href="https://github.com/rust-lang/lldb/wiki">rust-lang/lldb wiki page</a> explains a few details.</li>
<li>The reason for forking LLDB is that LLDB recently removed all the other language plugins
due to lack of maintenance.</li>
<li>LLDB has a plugin architecture but that does not work for language support.</li>
<li>LLDB is available via Rust build (<code>rustup</code>).</li>
<li>GDB generally works better on Linux.</li>
</ul>
<h2 id="dwarf-and-rustc"><a class="header" href="#dwarf-and-rustc">DWARF and Rustc</a></h2>
<p><a href="http://dwarfstd.org">DWARF</a> is the standard way compilers generate debugging information that debuggers read.
It is <em>the</em> debugging format on macOS and Linux. It is a multi-language, extensible format
and is mostly good enough for Rust's purposes. Hence, the current implementation reuses DWARF's
concepts. This is true even if some of the concepts in DWARF do not align with Rust
semantically because generally there can be some kind of mapping between the two.</p>
<p>We have some DWARF extensions that the Rust compiler emits and the debuggers understand that
are <em>not</em> in the DWARF standard.</p>
<ul>
<li>
<p>Rust compiler will emit DWARF for a virtual table, and this <code>vtable</code> object will have a
<code>DW_AT_containing_type</code> that points to the real type. This lets debuggers dissect a trait object
pointer to correctly find the payload. E.g., here's such a DIE, from a test case in the gdb
repository:</p>
<pre><code class="language-asm">&lt;1&gt;&lt;1a9&gt;: Abbrev Number: 3 (DW_TAG_structure_type)
&lt;1aa&gt; DW_AT_containing_type: &lt;0x1b4&gt;
&lt;1ae&gt; DW_AT_name : (indirect string, offset: 0x23d): vtable
&lt;1b2&gt; DW_AT_byte_size : 0
&lt;1b3&gt; DW_AT_alignment : 8
</code></pre>
</li>
<li>
<p>The other extension is that the Rust compiler can emit a tagless discriminated union.
See <a href="http://dwarfstd.org/ShowIssue.php?issue=180517.2">DWARF feature request</a> for this item.</p>
</li>
</ul>
<h3 id="current-limitations-of-dwarf"><a class="header" href="#current-limitations-of-dwarf">Current limitations of DWARF</a></h3>
<ul>
<li>Traits - require a bigger change than normal to DWARF, on how to represent Traits in DWARF.</li>
<li>DWARF provides no way to differentiate between Structs and Tuples. Rust compiler emits
fields with <code>__0</code> and debuggers look for a sequence of such names to overcome this limitation.
For example, in this case the debugger would look at a field via <code>x.__0</code> instead of <code>x.0</code>.
This is resolved via the Rust parser in the debugger so now you can do <code>x.0</code>.</li>
</ul>
<p>DWARF relies on debuggers to know some information about platform ABI.
Rust does not do that all the time.</p>
<h2 id="developer-notes-2"><a class="header" href="#developer-notes-2">Developer notes</a></h2>
<p>This section is from the talk about certain aspects of development.</p>
<h2 id="what-is-missing"><a class="header" href="#what-is-missing">What is missing</a></h2>
<h3 id="shipping-gdb-in-rustup"><a class="header" href="#shipping-gdb-in-rustup">Shipping GDB in Rustup</a></h3>
<p>Tracking issue: <a href="https://github.com/rust-lang/rust/issues/34457">https://github.com/rust-lang/rust/issues/34457</a></p>
<p>Shipping GDB requires change to Rustup delivery system. To manage Rustup build size and
times we need to build GDB separately, on its own and somehow provide the artifacts produced
to be included in the final build. However, if we can ship GDB with rustup, it will simplify
the development process by having compiler emit new debug info which can be readily consumed.</p>
<p>Main issue in achieving this is setting up dependencies. One such dependency is Python. That
is why we have our own fork of GDB because one of the drivers is patched on Rust's side to
check the correct version of Python (Python 2.7 in this case. <em>Note: Python3 is not chosen
for this purpose because Python's stable ABI is limited and is not sufficient for GDB's needs.
See <a href="https://docs.python.org/3/c-api/stable.html">https://docs.python.org/3/c-api/stable.html</a></em>).</p>
<p>This is to keep updates to debugger as fast as possible as we make changes to the debugging symbols.
In essence, to ship the debugger as soon as new debugging info is added. GDB only releases
every six months or so. However, the changes that are
not related to Rust itself should ideally be first merged to upstream eventually.</p>
<h3 id="code-signing-for-lldb-debug-server-on-macos"><a class="header" href="#code-signing-for-lldb-debug-server-on-macos">Code signing for LLDB debug server on macOS</a></h3>
<p>According to Wikipedia, <a href="https://en.wikipedia.org/wiki/System_Integrity_Protection">System Integrity Protection</a> is</p>
<blockquote>
<p>System Integrity Protection (SIP, sometimes referred to as rootless) is a security feature
of Apple's macOS operating system introduced in OS X El Capitan. It comprises a number of
mechanisms that are enforced by the kernel. A centerpiece is the protection of system-owned
files and directories against modifications by processes without a specific &quot;entitlement&quot;,
even when executed by the root user or a user with root privileges (sudo).</p>
</blockquote>
<p>It prevents processes using <code>ptrace</code> syscall. If a process wants to use <code>ptrace</code> it has to be
code signed. The certificate that signs it has to be trusted on your machine.</p>
<p>See <a href="https://developer.apple.com/library/archive/releasenotes/MacOSX/WhatsNewInOSX/Articles/MacOSX10_11.html#//apple_ref/doc/uid/TP40016227-SW11">Apple developer documentation for System Integrity Protection</a>.</p>
<p>We may need to sign up with Apple and get the keys to do this signing. Tom has looked into if
Mozilla cannot do this because it is at the maximum number of
keys it is allowed to sign. Tom does not know if Mozilla could get more keys.</p>
<p>Alternatively, Tom suggests that maybe a Rust legal entity is needed to get the keys via Apple.
This problem is not technical in nature. If we had such a key we could sign GDB as well and
ship that.</p>
<h3 id="dwarf-and-traits"><a class="header" href="#dwarf-and-traits">DWARF and Traits</a></h3>
<p>Rust traits are not emitted into DWARF at all. The impact of this is calling a method <code>x.method()</code>
does not work as is. The reason being that method is implemented by a trait, as opposed
to a type. That information is not present so finding trait methods is missing.</p>
<p>DWARF has a notion of interface types (possibly added for Java). Tom's idea was to use this
interface type as traits.</p>
<p>DWARF only deals with concrete names, not the reference types. So, a given implementation of a
trait for a type would be one of these interfaces (<code>DW_tag_interface</code> type). Also, the type for
which it is implemented would describe all the interfaces this type implements. This requires a
DWARF extension.</p>
<p>Issue on Github: <a href="https://github.com/rust-lang/rust/issues/33014">https://github.com/rust-lang/rust/issues/33014</a></p>
<h2 id="typical-process-for-a-debug-info-change-llvm"><a class="header" href="#typical-process-for-a-debug-info-change-llvm">Typical process for a Debug Info change (LLVM)</a></h2>
<p>LLVM has Debug Info (DI) builders. This is the primary thing that Rust calls into.
This is why we need to change LLVM first because that is emitted first and not DWARF directly.
This is a kind of metadata that you construct and hand-off to LLVM. For the Rustc/LLVM hand-off
some LLVM DI builder methods are called to construct representation of a type.</p>
<p>The steps of this process are as follows -</p>
<ol>
<li>
<p>LLVM needs changing.</p>
<p>LLVM does not emit Interface types at all, so this needs to be implemented in the LLVM first.</p>
<p>Get sign off on LLVM maintainers that this is a good idea.</p>
</li>
<li>
<p>Change the DWARF extension.</p>
</li>
<li>
<p>Update the debuggers.</p>
<p>Update DWARF readers, expression evaluators.</p>
</li>
<li>
<p>Update Rust compiler.</p>
<p>Change it to emit this new information.</p>
</li>
</ol>
<h3 id="procedural-macro-stepping"><a class="header" href="#procedural-macro-stepping">Procedural macro stepping</a></h3>
<p>A deeply profound question is that how do you actually debug a procedural macro?
What is the location you emit for a macro expansion? Consider some of the following cases -</p>
<ul>
<li>You can emit location of the invocation of the macro.</li>
<li>You can emit the location of the definition of the macro.</li>
<li>You can emit locations of the content of the macro.</li>
</ul>
<p>RFC: <a href="https://github.com/rust-lang/rfcs/pull/2117">https://github.com/rust-lang/rfcs/pull/2117</a></p>
<p>Focus is to let macros decide what to do. This can be achieved by having some kind of attribute
that lets the macro tell the compiler where the line marker should be. This affects where you
set the breakpoints and what happens when you step it.</p>
<h2 id="source-file-checksums-in-debug-info"><a class="header" href="#source-file-checksums-in-debug-info">Source file checksums in debug info</a></h2>
<p>Both DWARF and CodeView (PDB) support embedding a cryptographic hash of each source file that
contributed to the associated binary.</p>
<p>The cryptographic hash can be used by a debugger to verify that the source file matches the
executable. If the source file does not match, the debugger can provide a warning to the user.</p>
<p>The hash can also be used to prove that a given source file has not been modified since it was
used to compile an executable. Because MD5 and SHA1 both have demonstrated vulnerabilities,
using SHA256 is recommended for this application.</p>
<p>The Rust compiler stores the hash for each source file in the corresponding <code>SourceFile</code> in
the <code>SourceMap</code>. The hashes of input files to external crates are stored in <code>rlib</code> metadata.</p>
<p>A default hashing algorithm is set in the target specification. This allows the target to
specify the best hash available, since not all targets support all hash algorithms.</p>
<p>The hashing algorithm for a target can also be overridden with the <code>-Z source-file-checksum=</code>
command-line option.</p>
<h4 id="dwarf-5"><a class="header" href="#dwarf-5">DWARF 5</a></h4>
<p>DWARF version 5 supports embedding an MD5 hash to validate the source file version in use.
DWARF 5 - Section 6.2.4.1 opcode DW_LNCT_MD5</p>
<h4 id="llvm"><a class="header" href="#llvm">LLVM</a></h4>
<p>LLVM IR supports MD5 and SHA1 (and SHA256 in LLVM 11+) source file checksums in the DIFile node.</p>
<p><a href="https://llvm.org/docs/LangRef.html#difile">LLVM DIFile documentation</a></p>
<h4 id="microsoft-visual-c-compiler-zh-option"><a class="header" href="#microsoft-visual-c-compiler-zh-option">Microsoft Visual C++ Compiler /ZH option</a></h4>
<p>The MSVC compiler supports embedding MD5, SHA1, or SHA256 hashes in the PDB using the <code>/ZH</code>
compiler option.</p>
<p><a href="https://docs.microsoft.com/en-us/cpp/build/reference/zh">MSVC /ZH documentation</a></p>
<h4 id="clang"><a class="header" href="#clang">Clang</a></h4>
<p>Clang always embeds an MD5 checksum, though this does not appear in documentation.</p>
<h2 id="future-work"><a class="header" href="#future-work">Future work</a></h2>
<h4 id="name-mangling-changes"><a class="header" href="#name-mangling-changes">Name mangling changes</a></h4>
<ul>
<li>New demangler in <code>libiberty</code> (gcc source tree).</li>
<li>New demangler in LLVM or LLDB.</li>
</ul>
<p><strong>TODO</strong>: Check the location of the demangler source. <a href="https://github.com/rust-lang/rustc-dev-guide/issues/1157">#1157</a></p>
<h4 id="reuse-rust-compiler-for-expressions"><a class="header" href="#reuse-rust-compiler-for-expressions">Reuse Rust compiler for expressions</a></h4>
<p>This is an important idea because debuggers by and large do not try to implement type
inference. You need to be much more explicit when you type into the debugger than your
actual source code. So, you cannot just copy and paste an expression from your source
code to debugger and expect the same answer but this would be nice. This can be helped
by using compiler.</p>
<p>It is certainly doable but it is a large project. You certainly need a bridge to the
debugger because the debugger alone has access to the memory. Both GDB (gcc) and LLDB (clang)
have this feature. LLDB uses Clang to compile code to JIT and GDB can do the same with GCC.</p>
<p>Both debuggers expression evaluation implement both a superset and a subset of Rust.
They implement just the expression language but they also add some extensions like GDB has
convenience variables. Therefore, if you are taking this route then you not only need
to do this bridge but may have to add some mode to let the compiler understand some extensions.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="sanitizers.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="appendix/background.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="sanitizers.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="appendix/background.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>