<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
" SPDX-License-Identifier: MIT
-->
<head>
<meta charset="utf-8"/>
<style>
/* $OpenBSD: mandoc.css,v 1.33 2019/06/02 16:50:46 schwarze Exp $ */
/*
* Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
*
* Written by Ingo Schwarze <schwarze@openbsd.org>.
* I place this file into the public domain.
* Permission to use, copy, modify, and distribute it for any purpose
* with or without fee is hereby granted, without any conditions.
*/
/* Tooltips removed. */
/* Global defaults. */
html { max-width: 65em;
--bg: #FFFFFF;
--fg: #000000; }
body { background: var(--bg);
color: var(--fg);
font-family: Helvetica,Arial,sans-serif; }
h1 { font-size: 110%; }
table { margin-top: 0em;
margin-bottom: 0em;
border-collapse: collapse; }
/* Some browsers set border-color in a browser style for tbody,
* but not for table, resulting in inconsistent border styling. */
tbody { border-color: inherit; }
tr { border-color: inherit; }
td { vertical-align: top;
padding-left: 0.2em;
padding-right: 0.2em;
border-color: inherit; }
ul, ol, dl { margin-top: 0em;
margin-bottom: 0em; }
li, dt { margin-top: 1em; }
.permalink { border-bottom: thin dotted;
color: inherit;
font: inherit;
text-decoration: inherit; }
* { clear: both }
/* Search form and search results. */
fieldset { border: thin solid silver;
border-radius: 1em;
text-align: center; }
input[name=expr] {
width: 25%; }
table.results { margin-top: 1em;
margin-left: 2em;
font-size: smaller; }
/* Header and footer lines. */
table.head { width: 100%;
border-bottom: 1px dotted #808080;
margin-bottom: 1em;
font-size: smaller; }
td.head-vol { text-align: center; }
td.head-rtitle {
text-align: right; }
table.foot { width: 100%;
border-top: 1px dotted #808080;
margin-top: 1em;
font-size: smaller; }
td.foot-os { text-align: right; }
/* Sections and paragraphs. */
.manual-text {
margin-left: 3.8em; }
.Nd { }
section.Sh { }
h1.Sh { margin-top: 1.2em;
margin-bottom: 0.6em;
margin-left: -3.2em; }
section.Ss { }
h2.Ss { margin-top: 1.2em;
margin-bottom: 0.6em;
margin-left: -1.2em;
font-size: 105%; }
.Pp { margin: 0.6em 0em; }
.Sx { }
.Xr { }
/* Displays and lists. */
.Bd { }
.Bd-indent { margin-left: 3.8em; }
.Bl-bullet { list-style-type: disc;
padding-left: 1em; }
.Bl-bullet > li { }
.Bl-dash { list-style-type: none;
padding-left: 0em; }
.Bl-dash > li:before {
content: "\2014 "; }
.Bl-item { list-style-type: none;
padding-left: 0em; }
.Bl-item > li { }
.Bl-compact > li {
margin-top: 0em; }
.Bl-enum { padding-left: 2em; }
.Bl-enum > li { }
.Bl-compact > li {
margin-top: 0em; }
.Bl-diag { }
.Bl-diag > dt {
font-style: normal;
font-weight: bold; }
.Bl-diag > dd {
margin-left: 0em; }
.Bl-hang { }
.Bl-hang > dt { }
.Bl-hang > dd {
margin-left: 5.5em; }
.Bl-inset { }
.Bl-inset > dt { }
.Bl-inset > dd {
margin-left: 0em; }
.Bl-ohang { }
.Bl-ohang > dt { }
.Bl-ohang > dd {
margin-left: 0em; }
.Bl-tag { margin-top: 0.6em;
margin-left: 5.5em; }
.Bl-tag > dt {
float: left;
margin-top: 0em;
margin-left: -5.5em;
padding-right: 0.5em;
vertical-align: top; }
.Bl-tag > dd {
clear: right;
column-count: 1; /* Force block formatting context. */
width: 100%;
margin-top: 0em;
margin-left: 0em;
margin-bottom: 0.6em;
vertical-align: top; }
.Bl-compact { margin-top: 0em; }
.Bl-compact > dd {
margin-bottom: 0em; }
.Bl-compact > dt {
margin-top: 0em; }
.Bl-column { }
.Bl-column > tbody > tr { }
.Bl-column > tbody > tr > td {
margin-top: 1em; }
.Bl-compact > tbody > tr > td {
margin-top: 0em; }
.Rs { font-style: normal;
font-weight: normal; }
.RsA { }
.RsB { font-style: italic;
font-weight: normal; }
.RsC { }
.RsD { }
.RsI { font-style: italic;
font-weight: normal; }
.RsJ { font-style: italic;
font-weight: normal; }
.RsN { }
.RsO { }
.RsP { }
.RsQ { }
.RsR { }
.RsT { text-decoration: underline; }
.RsU { }
.RsV { }
.eqn { }
.tbl td { vertical-align: middle; }
.HP { margin-left: 3.8em;
text-indent: -3.8em; }
/* Semantic markup for command line utilities. */
table.Nm { }
code.Nm { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Fl { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Cm { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ar { font-style: italic;
font-weight: normal; }
.Op { display: inline; }
.Ic { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ev { font-style: normal;
font-weight: normal;
font-family: monospace; }
.Pa { font-style: italic;
font-weight: normal; }
/* Semantic markup for function libraries. */
.Lb { }
code.In { font-style: normal;
font-weight: bold;
font-family: inherit; }
a.In { }
.Fd { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ft { font-style: italic;
font-weight: normal; }
.Fn { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Fa { font-style: italic;
font-weight: normal; }
.Vt { font-style: italic;
font-weight: normal; }
.Va { font-style: italic;
font-weight: normal; }
.Dv { font-style: normal;
font-weight: normal;
font-family: monospace; }
.Er { font-style: normal;
font-weight: normal;
font-family: monospace; }
/* Various semantic markup. */
.An { }
.Lk { }
.Mt { }
.Cd { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ad { font-style: italic;
font-weight: normal; }
.Ms { font-style: normal;
font-weight: bold; }
.St { }
.Ux { }
/* Physical markup. */
.Bf { display: inline; }
.No { font-style: normal;
font-weight: normal; }
.Em { font-style: italic;
font-weight: normal; }
.Sy { font-style: normal;
font-weight: bold; }
.Li { font-style: normal;
font-weight: normal;
font-family: monospace; }
/* Tooltip support. */
h1.Sh, h2.Ss { position: relative; }
.An, .Ar, .Cd, .Cm, .Dv, .Em, .Er, .Ev, .Fa, .Fd, .Fl, .Fn, .Ft,
.Ic, code.In, .Lb, .Lk, .Ms, .Mt, .Nd, code.Nm, .Pa, .Rs,
.St, .Sx, .Sy, .Va, .Vt, .Xr {
display: inline-block;
position: relative; }
/* Overrides to avoid excessive margins on small devices. */
@media (max-width: 37.5em) {
.manual-text {
margin-left: 0.5em; }
h1.Sh, h2.Ss { margin-left: 0em; }
.Bd-indent { margin-left: 2em; }
.Bl-hang > dd {
margin-left: 2em; }
.Bl-tag { margin-left: 2em; }
.Bl-tag > dt {
margin-left: -2em; }
.HP { margin-left: 2em;
text-indent: -2em; }
}
/* Overrides for a dark color scheme for accessibility. */
@media (prefers-color-scheme: dark) {
html { --bg: #1E1F21;
--fg: #EEEFF1; }
:link { color: #BAD7FF; }
:visited { color: #F6BAFF; }
}
</style>
<title>LIBFEBUG.RS(3)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">LIBFEBUG.RS(3)</td>
<td class="head-vol">Library Functions Manual</td>
<td class="head-rtitle">LIBFEBUG.RS(3)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><b class="Sy">febug::start</b>, <b class="Sy">febug::Wrapper</b>,
<b class="Sy">febug::Wrappable</b>,
<b class="Sy">febug::StaticWrappable</b>,
<var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var>,
<var class="Vt">febug::FORMATTERS</var> — <span class="Nd">User-space
debugfs ABI wrapper library for Rust</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<div class="Bd">
<pre>
[dependencies]
febug = "0.1.1-4-g79d47b6"
</pre>
</div>
<p class="Pp">
<br/>
<code class="Fd">env!("FEBUG_DONT")?</code>
<br/>
<code class="Fd">env!("FEBUG_SOCKET") =
"/var/run/febug.sock"</code>
<br/>
<code class="Fd">env!("FEBUG_SIGNUM") = SIGUSR2</code></p>
<p class="Pp">
<br/>
<code class="Fd">env::var("FEBUG_DONT")</code>
<br/>
<code class="Fd">env::var("FEBUG_SOCKET")</code></p>
<p class="Pp">
<br/>
<var class="Vt">static GLOBAL_CONTROLLED_SOCKET: AtomicI32</var> = -1;</p>
<p class="Pp">
<br/>
<var class="Ft">fn</var> <code class="Fn">febug::start</code>();</p>
<p class="Pp"><var class="Ft">fn</var>
<code class="Fn">febug::start_raw</code>(<var class="Fa" style="white-space: nowrap;">path:
&[u8]</var>);</p>
<p class="Pp"><var class="Ft">extern 'C' fn</var>
<code class="Fn">debug_handler</code>(<var class="Fa" style="white-space: nowrap;">_:
c_int</var>);</p>
<p class="Pp"><var class="Ft">bool fn</var>
<code class="Fn">febug::install_handler</code>();</p>
<p class="Pp"><var class="Ft">bool fn</var>
<code class="Fn">febug::install_handler_signal</code>(<var class="Fa" style="white-space: nowrap;">signal:
u8</var>);</p>
<p class="Pp"><var class="Ft">fn</var> <code class="Fn">febug::end</code>();</p>
<p class="Pp"><var class="Vt">static febug::FORMATTERS:
Lazy<Mutex<BTreeMap<TypeId, fn(&mut File,
usize)>>></var></p>
<p class="Pp"><b class="Sy">trait febug::StaticWrappable: 'static;</b>
<br/>
<var class="Ft">Wrapper<Self> fn</var>
<code class="Fn">febug::StaticWrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&self</var>,
<var class="Fa" style="white-space: nowrap;">name:
Arguments<'_></var>);</p>
<p class="Pp"><var class="Ft">Wrapper<Self> fn</var>
<code class="Fn">febug::StaticWrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&self</var>,
<var class="Fa" style="white-space: nowrap;">signal: u8</var>,
<var class="Fa" style="white-space: nowrap;">name:
Arguments<'_></var>);</p>
<p class="Pp"><b class="Sy">trait febug::Wrappable;</b>
<br/>
<var class="Ft">Wrapper<Self> fn</var>
<code class="Fn">febug::Wrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&self</var>,
<var class="Fa" style="white-space: nowrap;">tp: u64</var>,
<var class="Fa" style="white-space: nowrap;">name:
Arguments<'_></var>);</p>
<p class="Pp"><var class="Ft">Wrapper<Self> fn</var>
<code class="Fn">febug::Wrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&self</var>,
<var class="Fa" style="white-space: nowrap;">tp: u64</var>,
<var class="Fa" style="white-space: nowrap;">signal: u8</var>,
<var class="Fa" style="white-space: nowrap;">name:
Arguments<'_></var>);</p>
<p class="Pp"><b class="Sy">struct febug::Wrapper<T></b> { /* … */
};
<br/>
<var class="Ft">Wrapper<T> fn</var>
<code class="Fn">febug::Wrapper::new</code>(<var class="Fa" style="white-space: nowrap;">&self</var>,
<var class="Fa" style="white-space: nowrap;">tp: u64</var>,
<var class="Fa" style="white-space: nowrap;">data:argument</var>,
<var class="Fa" style="white-space: nowrap;">name: fmt::Arguments</var>,
<var class="Fa" style="white-space: nowrap;">name:
Arguments<'_></var>);</p>
<p class="Pp"><var class="Ft">Wrapper<T> fn</var>
<code class="Fn">febug::Wrapper::new_signal</code>(<var class="Fa" style="white-space: nowrap;">&self</var>,
<var class="Fa" style="white-space: nowrap;">tp: u64</var>,
<var class="Fa" style="white-space: nowrap;">data:argument</var>,
<var class="Fa" style="white-space: nowrap;">signal: u8</var>,
<var class="Fa" style="white-space: nowrap;">name: fmt::Arguments</var>,
<var class="Fa" style="white-space: nowrap;">name:
Arguments<'_></var>);</p>
<p class="Pp"><b class="Sy">struct febug::abi::FebugMessage;</b>
<b class="Sy">struct febug::abi::StopFebugMessage;</b> <b class="Sy">struct
febug::abi::AttnFebugMessage;</b></p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp"><a class="permalink" href="#libfebug.rs"><b class="Sy" id="libfebug.rs">libfebug.rs</b></a>
allows a programmer to simplify writing Rust programs debuggable with
<a class="Xr" href="febug.8.html">febug(8)</a> by presenting a high-level interface to
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a>.</p>
<p class="Pp">There are three compile-time environment variables that allow a
programmer to customise its behaviour:</p>
<dl class="Bl-tag">
<dt></dt>
<dd><code class="Fd">FEBUG_DONT</code> If set, all functions turn into no-ops;
this is intended as a way to easily disable <a class="Xr" href="febug.8.html">febug(8)</a>
integration completely on release builds.</dd>
<dt id="febug_wrap"></dt>
<dd><code class="Fd">FEBUG_SIGNUM</code> The signal to request from
<a class="Xr" href="febug.8.html">febug(8)</a> when using
<a class="permalink" href="#febug_wrap"><code class="Fn">febug_wrap</code></a>().
Defaults to <code class="Li">SIGUSR2</code>.</dd>
<dt></dt>
<dd><code class="Fd">FEBUG_SOCKET</code> The path to connect to
<a class="Xr" href="febug.8.html">febug(8)</a> on. Defaults to
<span class="Pa">/var/run/febug.sock</span>.</dd>
</dl>
<p class="Pp">There are two environment variables that allow a user to customise
its behaviour:</p>
<dl class="Bl-tag">
<dt id="FEBUG_DONT"><a class="permalink" href="#FEBUG_DONT"><i class="Em">FEBUG_DONT</i></a></dt>
<dd>If set, don't try to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, so all library
functions become no-ops.</dd>
<dt id="FEBUG_SOCKET"><a class="permalink" href="#FEBUG_SOCKET"><i class="Em">FEBUG_SOCKET</i></a></dt>
<dd>If set, use its value instead of <b class="Sy">FEBUG_SOCKET</b> to connect
to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
</dl>
<p class="Pp" id="febug::start_raw">To be debugged, a program needs to, first,
call
<a class="permalink" href="#febug::start_raw"><code class="Fn">febug::start_raw</code></a>()
(likely via
<a class="permalink" href="#febug::start"><code class="Fn" id="febug::start">febug::start</code></a>(),
which simply passes <span class="Pa">b"/var/run/febug.sock"</span>
thereto) to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, which, if successful,
will set <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> to the
connection's file descriptor.</p>
<p class="Pp" id="febug::debug_handler">The program needs to install
<a class="permalink" href="#febug::debug_handler"><code class="Fn">febug::debug_handler</code></a>()
(or a wrapper around it) as the signal handler for
<a class="permalink" href="#FEBUG_SIGNUM"><b class="Sy" id="FEBUG_SIGNUM">FEBUG_SIGNUM</b></a>
(and any other signals, if different ones are explicitly requested; if
<code class="Dv">SIGKILL</code>, some event loop that answers on
<var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> must be in place).
It's a no-op if <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.
This finishes set-up. A convenience
<a class="permalink" href="#febug::install_handler"><code class="Fn" id="febug::install_handler">febug::install_handler</code></a>()
function is provided, doing just that, and returning
<a class="permalink" href="#true"><b class="Sy" id="true">true</b></a> if
the handler was installed.</p>
<p class="Pp" id="febug::debug_handler~2">The program should register handlers
for types of variables it wishes to handle by adding entries to
<var class="Vt">febug::FORMATTERS</var>. If no handler was registered for a
type, or the lock was poisoned,
<a class="permalink" href="#febug::debug_handler~2"><code class="Fn">febug::debug_handler</code></a>()
will write a generic "not found" message. The key is
<a class="permalink" href="#std::any::TypeId"><b class="Sy" id="std::any::TypeId">std::any::TypeId</b></a>
corresponding to the debugged type; if your type is not not
<a class="permalink" href="#'static"><b class="Sy" id="'static">'static</b></a>,
lie here. The handler takes the write end of the pipe as the first argument,
and the variable ID as the second. It's a no-op if
<var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.</p>
<p class="Pp" id="febug_message">At any time, when the program wishes to expose
a variable, it can construct <b class="Sy">febug::Wrapper</b> (likely via
one of the convenience <b class="Sy">febug::StaticWrappable</b> or
<b class="Sy">febug::Wrappable</b> traits), which will send a
<a class="permalink" href="#febug_message"><b class="Sy">febug_message</b></a>
with the specified type and signal numbers (defaulting to
<code class="Li">SIGUSR2 ),</code> ID equal to the address of the data
argument, and name formatted. It's a no-op if
<var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.</p>
<p class="Pp" id="stop_febug_message">When dropped,
<b class="Sy">febug::Wrapper</b> will send a
<a class="permalink" href="#stop_febug_message"><b class="Sy">stop_febug_message</b></a>.
It's a no-op if <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is
-1.</p>
<p class="Pp" id="febug::end">When it wishes to stop being debugged, the program
may call
<a class="permalink" href="#febug::end"><code class="Fn">febug::end</code></a>()
which will shutter and reset
<var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var>, The program may omit
this if it'd be the last thing it did before exiting, since the kernel will
close all FDs and free all mappings anyway.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
<p class="Pp">The following program spawns 10 threads, each successive one
sorting a longer subsection of a String, but waits a quarter-second between
each comparison; the String for each thread and the amount of comparisons
can be inspected via a <a class="Xr" href="febug.8.html">febug(8)</a> mount:</p>
<div class="Bd Pp Bd-indent">
<pre>
// SPDX-License-Identifier: MIT
extern crate febug;
use febug::StaticWrappable;
use std::time::Duration;
use std::any::TypeId;
use std::io::Write;
use std::thread;
fn main() {
febug::start();
if febug::install_handler() {
febug::FORMATTERS.lock().unwrap().insert(TypeId::of::<String>(), |of, vid| {
let data = unsafe { &*(vid as *const String) };
let _ = of.write_all(data.as_bytes());
let _ = of.write_all(b"\n");
});
}
let threads = (0..10)
.map(|i| {
thread::spawn(move || {
let mut sorteing = "The quick red fox jumps over the lazy brown dog... tHE QUICK RED FOX JUMPS OVER THE LAZY BROWN DOG!!"[0..(i + 1) * 10]
.to_string();
let _sorteing_w = sorteing.wrap(format_args!("cool_data_{}", i));
unsafe { sorteing.as_bytes_mut() }.sort_unstable_by(|a, b| {
thread::sleep(Duration::from_millis(250));
a.cmp(b)
});
thread::sleep(Duration::from_secs(2));
})
})
.collect::<Vec<_>>();
for t in threads {
let _ = t.join();
}
}
</pre>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<p class="Pp"><a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> — the ABI wrapped by this
library.</p>
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> — an equivalent C
library.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> — an equivalent C++
library.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
<p class="Pp">Written by <span class="An">наб</span>
<<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
THANKS</a></h1>
<p class="Pp">To all who support further development, in particular:</p>
<ul class="Bl-bullet Bl-compact">
<li>ThePhD</li>
<li>Embark Studios</li>
</ul>
</section>
<section class="Sh">
<h1 class="Sh" id="REPORTING_BUGS"><a class="permalink" href="#REPORTING_BUGS">REPORTING
BUGS</a></h1>
<p class="Pp"><a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug
tracker</a></p>
<p class="Pp">febug mailing list:
<<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>>
archived at
<a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">January 30, 2021</td>
<td class="foot-os">OpenBSD 6.8</td>
</tr>
</table>
</body>
</html>