~nabijaczleweli/febug

d27da6d8a6a892420d7529cda1af0d8637946f00 — наб autouploader 7 months ago f34d5be
OpenBSD manpage update by job 401870
M OpenBSD/index.0 => OpenBSD/index.0 +4 -1
@@ 5,7 5,7 @@
.if n .ad l
.SH "NAME"
\fBindex\fR
\- febug manpages
\- febug version 0.0.0 manpages
.SH "SEE ALSO"
febug(8)
\[u2013] User-space debugfs filesystem driver


@@ 18,6 18,9 @@ libfebug(3)
.PP
libfebug++(3)
\[u2013] User-space debugfs ABI wrapper library for C++
.PP
libfebug.rs(3)
\[u2013] User-space debugfs ABI wrapper library for Rust
.SH "AUTHORS"
Written by
\[u043D]\[u0430]\[u0431] <\fInabijaczleweli@nabijaczleweli.xyz\fR>

M OpenBSD/index.0.html => OpenBSD/index.0.html +3 -1
@@ 317,7 317,7 @@ html {		--bg: #1E1F21;
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><code class="Nm">index</code> &#x2014; <span class="Nd">febug
    manpages</span></p>
    version 0.0.0 manpages</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE


@@ 329,6 329,8 @@ html {		--bg: #1E1F21;
    wrapper library</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2013; User-space debugfs ABI
    wrapper library for C++</p>
<p class="Pp"><a class="Xr">libfebug.rs(3)</a> &#x2013; User-space debugfs ABI
    wrapper library for Rust</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>

M OpenBSD/libfebug++.3 => OpenBSD/libfebug++.3 +16 -11
@@ 132,7 132,7 @@ The program should register handlers for types of variables it wishes to handle 
multiple entries need to be registered.
If no handler was registered for a type,
\fBfebug::debug_handler\fR()
will print a generic "not found" message.
will write a generic "not found" message.
The handler takes the write end of the pipe as the first argument, and the variable ID as the second; it shouldn't close the pipe, as that is done by
\fBfebug::debug_handler\fR()
regardless, and the program would then run the risk of closing another file with the same descriptor simultaneously opened by another thread.


@@ 196,16 196,18 @@ mount:


int main() {
	febug::formatters.emplace(typeid(std::vector<int>).hash_code(), [](int retpipe, std::size_t vid) {
		const std::vector<int> & data = *(const std::vector<int> *)vid;
		for(auto num : data)
			dprintf(retpipe, "%d ", num);
		write(retpipe, "\\n", 1);
	});
	febug::formatters.emplace(typeid(std::size_t).hash_code(), [](int retpipe, std::size_t vid) {
		const std::size_t & data = *(const std::size_t *)vid;
		dprintf(retpipe, "%zu\\n", data);
	});
	if(febug::global_controlled_socket != -1) {
		febug::formatters.emplace(typeid(std::vector<int>).hash_code(), [](int retpipe, std::size_t vid) {
			const std::vector<int> & data = *(const std::vector<int> *)vid;
			for(auto num : data)
				dprintf(retpipe, "%d ", num);
			write(retpipe, "\\n", 1);
		});
		febug::formatters.emplace(typeid(std::size_t).hash_code(), [](int retpipe, std::size_t vid) {
			const std::size_t & data = *(const std::size_t *)vid;
			dprintf(retpipe, "%zu\\n", data);
		});
	}


	struct sigaction handler {};


@@ 238,6 240,9 @@ febug-abi(5)
.PP
libfebug(3)
\[u2014] an equivalent C library.
.PP
libfebug(3)
\[u2014] an equivalent Rust library.
.SH "AUTHORS"
Written by
\[u043D]\[u0430]\[u0431] <\fInabijaczleweli@nabijaczleweli.xyz\fR>

M OpenBSD/libfebug++.3.html => OpenBSD/libfebug++.3.html +15 -11
@@ 430,7 430,7 @@ struct febug::controlled_socket {
    results for two types that should have the same handler, multiple entries
    need to be registered. If no handler was registered for a type,
    <a class="permalink" href="#febug::debug_handler~2"><code class="Fn">febug::debug_handler</code></a>()
    will print a generic &quot;not found&quot; message. The handler takes the
    will write a generic &quot;not found&quot; message. The handler takes the
    write end of the pipe as the first argument, and the variable ID as the
    second; it shouldn't close the pipe, as that is done by
    <code class="Fn">febug::debug_handler</code>() regardless, and the program


@@ 487,16 487,18 @@ struct febug::wrapper {


int main() {
	febug::formatters.emplace(typeid(std::vector&lt;int&gt;).hash_code(), [](int retpipe, std::size_t vid) {
		const std::vector&lt;int&gt; &amp; data = *(const std::vector&lt;int&gt; *)vid;
		for(auto num : data)
			dprintf(retpipe, &quot;%d &quot;, num);
		write(retpipe, &quot;\n&quot;, 1);
	});
	febug::formatters.emplace(typeid(std::size_t).hash_code(), [](int retpipe, std::size_t vid) {
		const std::size_t &amp; data = *(const std::size_t *)vid;
		dprintf(retpipe, &quot;%zu\n&quot;, data);
	});
	if(febug::global_controlled_socket != -1) {
		febug::formatters.emplace(typeid(std::vector&lt;int&gt;).hash_code(), [](int retpipe, std::size_t vid) {
			const std::vector&lt;int&gt; &amp; data = *(const std::vector&lt;int&gt; *)vid;
			for(auto num : data)
				dprintf(retpipe, &quot;%d &quot;, num);
			write(retpipe, &quot;\n&quot;, 1);
		});
		febug::formatters.emplace(typeid(std::size_t).hash_code(), [](int retpipe, std::size_t vid) {
			const std::size_t &amp; data = *(const std::size_t *)vid;
			dprintf(retpipe, &quot;%zu\n&quot;, data);
		});
	}


	struct sigaction handler {};


@@ 531,6 533,8 @@ int main() {
    library.</p>
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent C
  library.</p>
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent Rust
  library.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>

M OpenBSD/libfebug.3 => OpenBSD/libfebug.3 +4 -1
@@ 121,7 121,7 @@ The program should register handlers for types of variables it wishes to handle 
\[u2014] those type numbers should be consistent across the program, lest the wrong handler is called.
If no handler was registered for a type,
\fBfebug_debug_handler\fR()
will print a generic "not found" message.
will write a generic "not found" message.
The handler takes the write end of the pipe as the first argument, and the variable ID as the second; it shouldn't close the pipe, as that is done by
\fBfebug_debug_handler\fR()
regardless, and the program would then run the risk of closing another file with the same descriptor simultaneously opened by another thread.


@@ 236,6 236,9 @@ febug-abi(5)
.PP
libfebug++(3)
\[u2014] an equivalent C++ library.
.PP
libfebug++(3)
\[u2014] an equivalent Rust library.
.SH "AUTHORS"
Written by
\[u043D]\[u0430]\[u0431] <\fInabijaczleweli@nabijaczleweli.xyz\fR>

M OpenBSD/libfebug.3.html => OpenBSD/libfebug.3.html +3 -1
@@ 435,7 435,7 @@ html {		--bg: #1E1F21;
    <a class="permalink" href="#febug_register_type"><code class="Fn">febug_register_type</code></a>()
    &#x2014; those type numbers should be consistent across the program, lest
    the wrong handler is called. If no handler was registered for a type,
    <code class="Fn">febug_debug_handler</code>() will print a generic &quot;not
    <code class="Fn">febug_debug_handler</code>() will write a generic &quot;not
    found&quot; message. The handler takes the write end of the pipe as the
    first argument, and the variable ID as the second; it shouldn't close the
    pipe, as that is done by <code class="Fn">febug_debug_handler</code>()


@@ 545,6 545,8 @@ int main() {
    library.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent C++
    library.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent Rust
    library.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>

A OpenBSD/libfebug.rs.3 => OpenBSD/libfebug.rs.3 +246 -0
@@ 0,0 1,246 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG.RS" "3" "January 20, 2021" "OpenBSD 6.8" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
\fBfebug::controlled_socket\fR,
\fBfebug::wrapper\fR,
\fIfebug::formatters\fR
\- User-space debugfs ABI wrapper library for Rust
.SH "SYNOPSIS"
.nf
.RS 0n
[dependencies]
febug = "0.0.0"
.RE
.fi
.PP
\fBgetenv("FEBUG_DONT")\fR
.br
\fBgetenv("FEBUG_SOCKET")\fR
.PP
\fIstatic GLOBAL_CONTROLLED_SOCKET: AtomicI32\fR
= -1;
.HP 4n
\fBfn febug::start\fR();
.HP 4n
\fBfn febug::start_raw\fR(\fIpath:\ &[u8]\fR);
.HP 4n
\fBextern 'C' fn debug_handler\fR(\fI_:\ c_int\fR);
.HP 4n
\fBbool fn febug::install_handler\fR();
.HP 4n
\fBbool fn febug::install_handler_signal\fR(\fIsignal:\ u8\fR);
.HP 4n
\fBfn febug::end\fR();
.PP
\fIstatic febug::FORMATTERS: Lazy<Mutex<BTreeMap<TypeId, fn(&mut File, usize)>>>\fR
.PP
\fBtrait febug::StaticWrappable: 'static;\fR
.br
.PD 0
.HP 4n
\fBWrapper<Self> fn febug::StaticWrappable::wrap\fR(\fI&self\fR, \fIname:\ Arguments<'_>\fR);
.PD
.HP 4n
\fBWrapper<Self> fn febug::StaticWrappable::wrap_signal\fR(\fI&self\fR, \fIsignal:\ u8\fR, \fIname:\ Arguments<'_>\fR);
.PP
\fBtrait febug::Wrappable;\fR
.br
.PD 0
.HP 4n
\fBWrapper<Self> fn febug::Wrappable::wrap\fR(\fI&self\fR, \fItp:\ u64\fR, \fIname:\ Arguments<'_>\fR);
.PD
.HP 4n
\fBWrapper<Self> fn febug::Wrappable::wrap_signal\fR(\fI&self\fR, \fItp:\ u64\fR, \fIsignal:\ u8\fR, \fIname:\ Arguments<'_>\fR);
.PP
\fBstruct febug::Wrapper<T>\fR
{ /* \[u2026] */ };
.br
.PD 0
.HP 4n
\fBWrapper<T> fn febug::Wrapper::new\fR(\fI&self\fR, \fItp:\ u64\fR, \fIdata:argument\fR, \fIname:\ fmt::Arguments\fR, \fIname:\ Arguments<'_>\fR);
.PD
.HP 4n
\fBWrapper<T> fn febug::Wrapper::new_signal\fR(\fI&self\fR, \fItp:\ u64\fR, \fIdata:argument\fR, \fIsignal:\ u8\fR, \fIname:\ fmt::Arguments\fR, \fIname:\ Arguments<'_>\fR);
.PP
\fBstruct febug::abi::FebugMessage;\fR
\fBstruct febug::abi::StopFebugMessage;\fR
\fBstruct febug::abi::AttnFebugMessage;\fR
.SH "DESCRIPTION"
\fBlibfebug.rs\fR
allows a programmer to simplify writing Rust programs debuggable with
febug(8)
by presenting a high-level interface to
febug-abi(5).
.PP
There are two environment variables that allow a user to customise its behaviour:
.TP 8n
\fIFEBUG_DONT\fR
If set, don't try to connect to
febug(8),
so all library functions become no-ops.
.TP 8n
\fIFEBUG_SOCKET\fR
If set, use its value instead of
the argument to
\fBfebug::start_raw\fR()
to connect to
febug(8)
.PP
To be debugged, a program needs to, first, call
\fBfebug::start_raw\fR()
(likely via
\fBfebug::start\fR(),
which simply passes
\fIb\&"/var/run/febug.sock"\fR
thereto) to connect to
febug(8),
which, if successful, will set
\fIfebug::GLOBAL_CONTROLLED_SOCKET\fR
to the connection's file descriptor.
.PP
The program needs to install
\fBfebug::debug_handler\fR()
(or a wrapper around it) as the signal handler for
\fBFEBUG_SIGNUM\fR
(and any other signals, if different ones are explicitly requested; if
\fRSIGKILL\fR,
some event loop that answers on
\fIfebug::GLOBAL_CONTROLLED_SOCKET\fR
must be in place). It's a no-op if
\fIfebug::GLOBAL_CONTROLLED_SOCKET\fR
is -1. This finishes set-up.
A convenience
\fBfebug::install_handler\fR()
function is provided, doing just that, and returning
\fBtrue\fR
if the handler was installed.
.PP
The program should register handlers for types of variables it wishes to handle by adding entries to
\fIfebug::FORMATTERS\fR.
If no handler was registered for a type, or the lock was poisoned,
\fBfebug::debug_handler\fR()
will write a generic "not found" message.
The key is
\fBstd::any::TypeId\fR
corresponding to the debugged type; if your type is not not
\fB'static\fR,
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
\fIfebug::GLOBAL_CONTROLLED_SOCKET\fR
is -1.
.PP
At any time, when the program wishes to expose a variable, it can construct
\fBfebug::Wrapper\fR
(likely via one of the convenience
\fBfebug::StaticWrappable\fR
or
\fBfebug::Wrappable\fR
traits), which will send a
\fBfebug_message\fR
with the specified type and signal numbers (defaulting to
\fRSIGUSR2 ),\fR
ID equal to the address of the data argument, and name formatted.
It's a no-op if
\fIfebug::GLOBAL_CONTROLLED_SOCKET\fR
is -1.
.PP
When dropped,
\fBfebug::Wrapper\fR
will send a
\fBstop_febug_message\fR.
It's a no-op if
\fIfebug::GLOBAL_CONTROLLED_SOCKET\fR
is -1.
.PP
When it wishes to stop being debugged, the program may call
\fBfebug::end\fR()
which will shutter and reset
\fIfebug::GLOBAL_CONTROLLED_SOCKET\fR,
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.
.SH "EXAMPLES"
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
febug(8)
mount:
.nf
.sp
.RS 6n
// 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();
    }
}
.RE
.fi
.SH "SEE ALSO"
febug-abi(5)
\[u2014] the ABI wrapped by this library.
.PP
libfebug(3)
\[u2014] an equivalent C library.
.PP
libfebug++(3)
\[u2014] an equivalent C++ library.
.SH "AUTHORS"
Written by
\[u043D]\[u0430]\[u0431] <\fInabijaczleweli@nabijaczleweli.xyz\fR>
.SH "SPECIAL THANKS"
To all who support further development, in particular:
.PD 0
.TP 8n
\fB\(bu\fR
ThePhD
.TP 8n
\fB\(bu\fR
Embark Studios
.PD
.SH "REPORTING BUGS"
\fIfebug tracker\fR: \fBhttps://todo.sr.ht/~nabijaczleweli/febug\fR
.PP
febug mailing list:
<\fI~nabijaczleweli/febug@lists.sr.ht\fR>
archived at
\fBhttps://lists.sr.ht/~nabijaczleweli/febug\fR

A OpenBSD/libfebug.rs.3.html => OpenBSD/libfebug.rs.3.html +577 -0
@@ 0,0 1,577 @@
<!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"><a class="permalink" href="#febug::controlled_socket"><b class="Sy" id="febug::controlled_socket">febug::controlled_socket</b></a>,
    <a class="permalink" href="#febug::wrapper"><b class="Sy" id="febug::wrapper">febug::wrapper</b></a>,
    <var class="Vt">febug::formatters</var> &#x2014; <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 = &quot;0.0.0&quot;
</pre>
</div>
<p class="Pp">
  <br/>
  <code class="Fd">getenv(&quot;FEBUG_DONT&quot;)</code>
  <br/>
  <code class="Fd">getenv(&quot;FEBUG_SOCKET&quot;)</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:
    &amp;[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&lt;Mutex&lt;BTreeMap&lt;TypeId, fn(&amp;mut File,
    usize)&gt;&gt;&gt;</var></p>
<p class="Pp"><b class="Sy">trait febug::StaticWrappable: 'static;</b>
  <br/>
  <var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::StaticWrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::StaticWrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">signal: u8</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><b class="Sy">trait febug::Wrappable;</b>
  <br/>
  <var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::Wrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::Wrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;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&lt;'_&gt;</var>);</p>
<p class="Pp"><b class="Sy">struct febug::Wrapper&lt;T&gt;</b> { /* &#x2026; */
    };
  <br/>
  <var class="Ft">Wrapper&lt;T&gt; fn</var>
    <code class="Fn">febug::Wrapper::new</code>(<var class="Fa" style="white-space: nowrap;">&amp;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&lt;'_&gt;</var>);</p>
<p class="Pp"><var class="Ft">Wrapper&lt;T&gt; fn</var>
    <code class="Fn">febug::Wrapper::new_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;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&lt;'_&gt;</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 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 the argument to
      <a class="permalink" href="#febug::start_raw"><code class="Fn" id="febug::start_raw">febug::start_raw</code></a>()
      to connect to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
</dl>
<p class="Pp" id="febug::start_raw~2">To be debugged, a program needs to, first,
    call
    <a class="permalink" href="#febug::start_raw~2"><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&quot;/var/run/febug.sock&quot;</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 &quot;not found&quot; 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::StaticWrappable">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
    <a class="permalink" href="#febug::StaticWrappable"><b class="Sy">febug::StaticWrappable</b></a>
    or
    <a class="permalink" href="#febug::Wrappable"><b class="Sy" id="febug::Wrappable">febug::Wrappable</b></a>
    traits), which will send a
    <a class="permalink" href="#febug_message"><b class="Sy" id="febug_message">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::&lt;String&gt;(), |of, vid| {
            let data = unsafe { &amp;*(vid as *const String) };

            let _ = of.write_all(data.as_bytes());
            let _ = of.write_all(b&quot;\n&quot;);
        });
    }


    let threads = (0..10)
        .map(|i| {
            thread::spawn(move || {
                let mut sorteing = &quot;The quick red fox jumps over the lazy brown dog... tHE QUICK RED FOX JUMPS OVER THE LAZY BROWN DOG!!&quot;[0..(i + 1) * 10]
                    .to_string();
                let _sorteing_w = sorteing.wrap(format_args!(&quot;cool_data_{}&quot;, 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::&lt;Vec&lt;_&gt;&gt;();
    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> &#x2014; the ABI wrapped by this
    library.</p>
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent C
  library.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; 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">&#x043D;&#x0430;&#x0431;</span>
    &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;</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:
    &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
    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 20, 2021</td>
    <td class="foot-os">OpenBSD 6.8</td>
  </tr>
</table>
</body>
</html>