~nabijaczleweli/febug

dbc39ab71e91cce64d3c895ce2666553876102b5 — наб autouploader 7 months ago d27da6d
FreeBSD manpage update by job 401869
M FreeBSD/febug-abi.5 => FreeBSD/febug-abi.5 +1 -1
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "FEBUG-ABI" "3" "January 20, 2021" "FreeBSD 12.1-RELEASE-p7" "FreeBSD Library Functions Manual"
.TH "FEBUG-ABI" "3" "January 20, 2021" "FreeBSD 12.1-RELEASE-p10" "FreeBSD Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"

M FreeBSD/febug-abi.5.html => FreeBSD/febug-abi.5.html +1 -1
@@ 454,7 454,7 @@ To all who support further development, in particular:
<table class="foot">
  <tr>
    <td class="foot-date">January 20, 2021</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p7</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p10</td>
  </tr>
</table>
</body>

M FreeBSD/febug.8 => FreeBSD/febug.8 +1 -1
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "FEBUG" "8" "FEBUG" "FreeBSD 12.1-RELEASE-p7" "FreeBSD System Manager's Manual"
.TH "FEBUG" "8" "FEBUG" "FreeBSD 12.1-RELEASE-p10" "FreeBSD System Manager's Manual"
.nh
.if n .ad l
.SH "NAME"

M FreeBSD/febug.8.html => FreeBSD/febug.8.html +1 -1
@@ 430,7 430,7 @@ To all who support further development, in particular:
<table class="foot">
  <tr>
    <td class="foot-date">FEBUG</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p7</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p10</td>
  </tr>
</table>
</body>

M FreeBSD/index.0 => FreeBSD/index.0 +5 -2
@@ 1,11 1,11 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "index" "0" "January 20, 2021" "FreeBSD 12.1-RELEASE-p7" "0"
.TH "index" "0" "January 20, 2021" "FreeBSD 12.1-RELEASE-p10" "0"
.nh
.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 FreeBSD/index.0.html => FreeBSD/index.0.html +4 -2
@@ 317,7 317,7 @@ html {		--bg: #1E1F21;
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">index</code> &#x2014;
<div class="Nd">febug manpages</div>
<div class="Nd">febug version 0.0.0 manpages</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE


@@ 328,6 328,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>


@@ 356,7 358,7 @@ To all who support further development, in particular:
<table class="foot">
  <tr>
    <td class="foot-date">January 20, 2021</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p7</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p10</td>
  </tr>
</table>
</body>

M FreeBSD/libfebug++.3 => FreeBSD/libfebug++.3 +17 -12
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG++" "3" "January 20, 2021" "FreeBSD 12.1-RELEASE-p7" "FreeBSD Library Functions Manual"
.TH "LIBFEBUG++" "3" "January 20, 2021" "FreeBSD 12.1-RELEASE-p10" "FreeBSD Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"


@@ 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 FreeBSD/libfebug++.3.html => FreeBSD/libfebug++.3.html +16 -12
@@ 427,7 427,7 @@ struct febug::controlled_socket {
    typeid(std::decay_t&lt;T&gt;).hash_code(), so if this yields different
    results for two types that should have the same handler, multiple entries
    need to be registered. If no handler was registered for a type,
    <code class="Fn">febug::debug_handler</code>() will print a generic
    <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>()


@@ 480,16 480,18 @@ The following program sorts a std::vector&lt;int&gt; with


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 {};


@@ 523,6 525,8 @@ int main() {
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this library.
<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>


@@ 551,7 555,7 @@ To all who support further development, in particular:
<table class="foot">
  <tr>
    <td class="foot-date">January 20, 2021</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p7</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p10</td>
  </tr>
</table>
</body>

M FreeBSD/libfebug.3 => FreeBSD/libfebug.3 +5 -2
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG" "3" "January 20, 2021" "FreeBSD 12.1-RELEASE-p7" "FreeBSD Library Functions Manual"
.TH "LIBFEBUG" "3" "January 20, 2021" "FreeBSD 12.1-RELEASE-p10" "FreeBSD Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"


@@ 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 FreeBSD/libfebug.3.html => FreeBSD/libfebug.3.html +4 -2
@@ 430,7 430,7 @@ html {		--bg: #1E1F21;
    wishes to handle by calling <code class="Fn">febug_register_type</code>()
    &#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>()


@@ 532,6 532,8 @@ int main() {
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this library.
<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>


@@ 560,7 562,7 @@ To all who support further development, in particular:
<table class="foot">
  <tr>
    <td class="foot-date">January 20, 2021</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p7</td>
    <td class="foot-os">FreeBSD 12.1-RELEASE-p10</td>
  </tr>
</table>
</body>

A FreeBSD/libfebug.rs.3 => FreeBSD/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" "FreeBSD 12.1-RELEASE-p10" "FreeBSD 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 FreeBSD/libfebug.rs.3.html => FreeBSD/libfebug.rs.3.html +559 -0
@@ 0,0 1,559 @@
<!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">FreeBSD 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>
<b class="Sy">febug::controlled_socket</b>, <b class="Sy">febug::wrapper</b>,
  <var class="Vt">febug::formatters</var> &#x2014;
<div class="Nd">User-space debugfs ABI wrapper library for Rust</div>
</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>
<b class="Sy">libfebug.rs</b> 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 class="Pp">There are two environment variables that allow a user to customise
    its behaviour:</p>
<dl class="Bl-tag">
  <dt><i class="Em">FEBUG_DONT</i></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><i class="Em">FEBUG_SOCKET</i></dt>
  <dd>If set, use its value instead of the argument to
      <code class="Fn">febug::start_raw</code>() to connect to
      <a class="Xr" href="febug.8.html">febug(8)</a></dd>
</dl>
<p class="Pp">To be debugged, a program needs to, first, call
    <code class="Fn">febug::start_raw</code>() (likely via
    <code class="Fn">febug::start</code>(), 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">The program needs to install
    <code class="Fn">febug::debug_handler</code>() (or a wrapper around it) as
    the signal handler for <b class="Sy">FEBUG_SIGNUM</b> (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
    <code class="Fn">febug::install_handler</code>() function is provided, doing
    just that, and returning <b class="Sy">true</b> if the handler was
    installed.</p>
<p class="Pp">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,
    <code class="Fn">febug::debug_handler</code>() will write a generic
    &quot;not found&quot; message. The key is <b class="Sy">std::any::TypeId</b>
    corresponding to the debugged type; if your type is not not
    <b class="Sy">'static</b>, 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">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
    <b class="Sy">febug_message</b> 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">When dropped, <b class="Sy">febug::Wrapper</b> will send a
    <b class="Sy">stop_febug_message</b>. It's a no-op if
    <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.</p>
<p class="Pp">When it wishes to stop being debugged, the program may call
    <code class="Fn">febug::end</code>() 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>
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:
<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>
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this library.
<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>
Written by <span class="An">&#x043D;&#x0430;&#x0431;</span>
  &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
  THANKS</a></h1>
To all who support further development, in particular:
<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>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug tracker</a>
<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">FreeBSD 12.1-RELEASE-p10</td>
  </tr>
</table>
</body>
</html>