~nabijaczleweli/febug

d2d1324b9dd521c1ef278835b60a9907307ab1c1 — nab 6 months ago cd1da37
Initial upload from the Macintosh
A MacOS/attn_febug_message.5 => MacOS/attn_febug_message.5 +1 -0
@@ 0,0 1,1 @@
febug-abi.5
\ No newline at end of file

A MacOS/febug-abi.5 => MacOS/febug-abi.5 +168 -0
@@ 0,0 1,168 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "FEBUG-ABI" "5" "January 31, 2021" "Darwin 19.6.0" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
\fBstruct febug_message\fR,
\fBstruct stop_febug_message\fR,
\fBstruct attn_febug_message\fR
\- User-space debugfs ABI
.SH "SYNOPSIS"
\fB#include <febug-abi.h>\fR
.PP
\fBstruct febug_message;\fR
.PP
\fBstruct stop_febug_message;\fR
.PP
\fBstruct attn_febug_message;\fR
.SH "DESCRIPTION"
The febug ABI consists of two messages sent from the program wishing to be debugged to
febug(8),
and one sent from
febug(8)
to the program.
.PP
To be debugged, the program must create a socket with
\fRsocket(AF_UNIX, SOCK_STREAM, 0)\fR
and
connect(2)
to the appropriate end-point
(\fI/var/run/febug.sock\fR,
conventionally).
The filesystem will then immediately acquire effective credentials from the client.
After
febug(8)
receives credentials, a directory corresponding to the debugged process' PID will be created in the filesystem.
.PP
\fIAll\fR
messages must be sent in a single
send(2)
or
sendmsg(2)
call, specifying the exact size of the message, as that's what's used to differentiate between different messages.
febug(8)
will ignore messages (whose sizes) it does not recognise.
.PP
Afterward, for each variable of interest, the process should send a 4096-byte
\fBfebug_message\fR,
defined as follows:
.nf
.sp
.RS 6n
struct [[packed]] febug_message {
    uint64_t variable_id;
    uint64_t variable_type;
    uint8_t signal;
    char name[/* Enough to bring the overall size to 4096. */];
};
.RE
.fi
.PP
Wherein:
.TP 8n
\fIvariable_id\fR
is the locally unique identifier of the variable (e.g. a pointer to that variable).
.TP 8n
\fIvariable_type\fR
is the moral equivalent of
\fIvoid *\fR
\fIuserdata\fR
\[u2014] it is simply passed back to the program, unchanged (e.g. a function pointer to a formatter).
.TP 8n
\fIsignal\fR
is the signal to send to the program when a variable is to be read (see below).
\fIname\fR
is the globally unique name of this variable \[u2014]
a NUL terminator is respected, if it occurs before the end of the array, but is not required if the name truly spans to the final byte.
If the name is the same as one of an already-present variable, it will be overridden.
.PP
When
febug(8)
receives
\fBfebug_message\fR,
it creates a file under the process' directory.
When that file is opened,
febug(8)
will:
.TP 8n
1.\&
send the process an
\fBattn_febug_message\fR
with a single file descriptor via
\fRSCM_RIGHTS\fR
auxilliary data (confer
cmsg(3))
representing the write end of a pipe \[u2014] subsequent reads are serviced directly by the opposing end.
.TP 8n
2.\&
kill(2)
the process with the signal from the
\fIsignal\fR
field if it wasn't
\fRSIGKILL\fR.
.PP
Note, that the sent file descriptor
\fImust\fR
be closed by the program when it's done serialising the variable, and therefore, if the process opts not to receive a signal, it
\fImust\fR
handle the message through some other mechanism.
.PP
\fBattn_febug_message\fR
is 16 bytes, and defined as follows:
.nf
.sp
.RS 6n
struct [[packed]] attn_febug_message {
    uint64_t variable_id;
    uint64_t variable_type;
};
.RE
.fi
.PP
Both fields correspond to the ones sent in the
\fBfebug_message\fR
that installed the variable.
.PP
The process may receive any amount of
\fBattn_febug_message\fR
until it sends an 8-byte
\fBstop_febug_message\fR,
defined as follows:
.nf
.sp
.RS 6n
struct [[packed]] stop_febug_message {
    uint64_t variable_id;
};
.RE
.fi
.PP
Upon receipt, the corresponding variable, if any, is removed from the filesystem.
.PP
When the process' end of the socket is closed, all extant variables are freed, and the process' directory is removed.
.SH "SEE ALSO"
libfebug(3)
and
libfebug++(3)
\[u2014] libraries that wrap this ABI.
.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 MacOS/febug-abi.5.html => MacOS/febug-abi.5.html +460 -0
@@ 0,0 1,460 @@
<!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>FEBUG-ABI(5)</title>
</head>
<body>
<table class="head">
  <tr>
    <td class="head-ltitle">FEBUG-ABI(5)</td>
    <td class="head-vol">File Formats Manual</td>
    <td class="head-rtitle">FEBUG-ABI(5)</td>
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">struct febug_message</code>, <code class="Nm">struct
  stop_febug_message</code>, <code class="Nm">struct attn_febug_message</code>
  &#x2014;
<div class="Nd">User-space debugfs ABI</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<code class="In">#include
  &lt;<a class="In" href="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/febug-abi.h">febug-abi.h</a>&gt;</code>
<p class="Pp"><b class="Sy">struct febug_message;</b></p>
<p class="Pp"><b class="Sy">struct stop_febug_message;</b></p>
<p class="Pp"><b class="Sy">struct attn_febug_message;</b></p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
The febug ABI consists of two messages sent from the program wishing to be
  debugged to <a class="Xr" href="febug.8.html">febug(8)</a>, and one sent from
  <a class="Xr" href="febug.8.html">febug(8)</a> to the program.
<p class="Pp">To be debugged, the program must create a socket with
    <code class="Li">socket(AF_UNIX, SOCK_STREAM, 0)</code> and
    <a class="Xr">connect(2)</a> to the appropriate end-point
    (<span class="Pa">/var/run/febug.sock</span>, conventionally). The
    filesystem will then immediately acquire effective credentials from the
    client. After <a class="Xr" href="febug.8.html">febug(8)</a> receives credentials, a directory
    corresponding to the debugged process' PID will be created in the
    filesystem.</p>
<p class="Pp"><i class="Em">All</i> messages must be sent in a single
    <a class="Xr">send(2)</a> or <a class="Xr">sendmsg(2)</a> call, specifying
    the exact size of the message, as that's what's used to differentiate
    between different messages. <a class="Xr" href="febug.8.html">febug(8)</a> will ignore messages
    (whose sizes) it does not recognise.</p>
<p class="Pp">Afterward, for each variable of interest, the process should send
    a 4096-byte <b class="Sy">febug_message</b>, defined as follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct [[packed]] febug_message {
    uint64_t variable_id;
    uint64_t variable_type;
    uint8_t signal;
    char name[/* Enough to bring the overall size to 4096. */];
};
</pre>
</div>
<p class="Pp">Wherein:</p>
<dl class="Bl-tag">
  <dt></dt>
  <dd><i class="Em">variable_id</i> is the locally unique identifier of the
      variable (e.g. a pointer to that variable).</dd>
  <dt></dt>
  <dd><i class="Em">variable_type</i> is the moral equivalent of
      <var class="Vt">void *</var> <var class="Va">userdata</var> &#x2014; it is
      simply passed back to the program, unchanged (e.g. a function pointer to a
      formatter).</dd>
  <dt></dt>
  <dd><i class="Em">signal</i> is the signal to send to the program when a
      variable is to be read (see below). <i class="Em">name</i> is the globally
      unique name of this variable &#x2014; a NUL terminator is respected, if it
      occurs before the end of the array, but is not required if the name truly
      spans to the final byte. If the name is the same as one of an
      already-present variable, it will be overridden.</dd>
</dl>
<p class="Pp">When <a class="Xr" href="febug.8.html">febug(8)</a> receives
    <b class="Sy">febug_message</b>, it creates a file under the process'
    directory. When that file is opened, <a class="Xr" href="febug.8.html">febug(8)</a> will:</p>
<ol class="Bl-enum">
  <li>send the process an <b class="Sy">attn_febug_message</b> with a single
      file descriptor via <code class="Dv">SCM_RIGHTS</code> auxilliary data
      (confer <a class="Xr">cmsg(3)</a>) representing the write end of a pipe
      &#x2014; subsequent reads are serviced directly by the opposing end.</li>
  <li><a class="Xr">kill(2)</a> the process with the signal from the
      <var class="Va">signal</var> field if it wasn't
      <code class="Dv">SIGKILL</code>.</li>
</ol>
<p class="Pp">Note, that the sent file descriptor <i class="Em">must</i> be
    closed by the program when it's done serialising the variable, and
    therefore, if the process opts not to receive a signal, it
    <i class="Em">must</i> handle the message through some other mechanism.</p>
<p class="Pp"><b class="Sy">attn_febug_message</b> is 16 bytes, and defined as
    follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct [[packed]] attn_febug_message {
    uint64_t variable_id;
    uint64_t variable_type;
};
</pre>
</div>
<p class="Pp">Both fields correspond to the ones sent in the
    <b class="Sy">febug_message</b> that installed the variable.</p>
<p class="Pp">The process may receive any amount of
    <b class="Sy">attn_febug_message</b> until it sends an 8-byte
    <b class="Sy">stop_febug_message</b>, defined as follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct [[packed]] stop_febug_message {
    uint64_t variable_id;
};
</pre>
</div>
<p class="Pp">Upon receipt, the corresponding variable, if any, is removed from
    the filesystem.</p>
<p class="Pp">When the process' end of the socket is closed, all extant
    variables are freed, and the process' directory is removed.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> and <a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014;
  libraries that wrap this ABI.
</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 31, 2021</td>
    <td class="foot-os">Darwin 19.6.0</td>
  </tr>
</table>
</body>
</html>

A MacOS/febug.8 => MacOS/febug.8 +117 -0
@@ 0,0 1,117 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "FEBUG" "8" "FEBUG" "Darwin 19.6.0" "System Manager's Manual"
.nh
.if n .ad l
.SH "NAME"
\fBfebug\fR
\- User-space debugfs filesystem driver
.SH "SYNOPSIS"
.HP 6n
\fBfebug\fR
[\fB\-hV\fR]
[\fBlibfuse options\fR]
\fImountpoint\fR
.SH "DESCRIPTION"
\fBfebug\fR
mounts a filesystem at
\fImountpoint\fR
that allows programs to register themselves and expose variables to be (relatively) non-intrusively inspected at run-time, inspired by
Linux's
\fIdebugfs\fR: \fBhttps://www.kernel.org/doc/html/latest/filesystems/debugfs.html\fR
filesystem.
.PP
See
febug-abi(8)
for implementation details. And the
\fIEXAMPLES\fR
section for an example debug session.
.SH "OPTIONS"
\fB\-h\fR \fBor\fR \fB\--help\fR
and
\fB\-V\fR \fBor\fR \fB\--version\fR
are self-explanatory.
.PP
\fB\-d\fR
enables debug output from both
\fBfebug\fR
and
\fBlibfuse\fR.
.PP
\fBfebug\fR
passes all arguments (which have to, therefore, include
\fImountpoint\fR)
to
fuse_main(3), with
\fB\-f\fR
(foreground) and
\fB\-o\fR \fBdefault_permissions\fR
appended.
If run with effective UID of 0, it also appends
\fB\-o\fR \fBallow_other\fR.
.SH "ENVIRONMENT"
\fIFEBUG_SOCKET\fR
the socket at which to listen for programs, or
\fI/var/run/febug.sock\fR
by default.
.SH "EXAMPLES"
.nf
.RS 6n
\&# launchctl start xyz.nabijaczleweli.febug
$ mount | grep febug
febug@macfuse0 on /private/var/run/febug (macfuse, synchronous)
$ ./out/examples/vector-sort &
[1] 1409
$ LD_LIBRARY_PATH=out ./out/examples/string-qsort &
[2] 1410
$ ls /var/run/febug/
1409 1410
$ ls -l /var/run/febug/
dr-xr-x--- 4 nabijaczleweli users 0 Jan 15 19:52 1409
dr-xr-x--- 3 nabijaczleweli users 0 Jan 15 19:52 1410
$ ls /var/run/febug/1409/
comparisons cool_data
$ cat /var/run/febug/1409/\&*
24
-3 -2 -3 -2 -3 -2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
$ cat /var/run/febug/1409/\&*
45
-3 -2 -3 -2 -3 -2 -3 -2 -2 -3 -3 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
$ grep . /var/run/febug/\&*/\&*
/var/run/febug/1409/comparisons:71
/var/run/febug/1409/cool_data:-3 -3 -3 -3 -3 -3 -2 -2 -2 -2 -2 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
/var/run/febug/1410/cool_data:3012987654ACEFOLJKODNIEMIGHBPPbdWwnfTpXQcreRlVvUSitZQWjRTYUazuqwertyuiopoxyhmYsgkq
$ kill %1
$ ls /var/run/febug/
1410
.RE
.fi
.SH "SEE ALSO"
febug-abi(5)
\[u2014] the ABI used to connect with this filesystem.
.PP
libfebug(3)
\[u2014] a library wrapping this ABI.
.PP
libfebug++(3)
\[u2014] a C++ library wrapping this ABI.
.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 MacOS/febug.8.html => MacOS/febug.8.html +439 -0
@@ 0,0 1,439 @@
<!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>FEBUG(8)</title>
</head>
<body>
<table class="head">
  <tr>
    <td class="head-ltitle">FEBUG(8)</td>
    <td class="head-vol">System Manager's Manual</td>
    <td class="head-rtitle">FEBUG(8)</td>
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">febug</code> &#x2014;
<div class="Nd">User-space debugfs filesystem driver</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<table class="Nm">
  <tr>
    <td><code class="Nm">febug</code></td>
    <td>[<code class="Fl">-hV</code>] [<b class="Sy">libfuse options</b>]
      <var class="Ar">mountpoint</var></td>
  </tr>
</table>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<code class="Nm">febug</code> mounts a filesystem at
  <var class="Ar">mountpoint</var> that allows programs to register themselves
  and expose variables to be (relatively) non-intrusively inspected at run-time,
  inspired by Linux's
  <a class="Lk" href="https://www.kernel.org/doc/html/latest/filesystems/debugfs.html">debugfs</a>
  filesystem.
<p class="Pp">See <a class="Xr">febug-abi(8)</a> for implementation details. And
    the <a class="Sx" href="#EXAMPLES">EXAMPLES</a> section for an example debug
    session.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="OPTIONS"><a class="permalink" href="#OPTIONS">OPTIONS</a></h1>
<code class="Fl">-h</code> <code class="Nm">or</code>
  <code class="Fl">--help</code> and <code class="Fl">-V</code>
  <code class="Nm">or</code> <code class="Fl">--version</code> are
  self-explanatory.
<p class="Pp"><code class="Fl">-d</code> enables debug output from both
    <code class="Nm">febug</code> and <code class="Nm">libfuse</code>.</p>
<p class="Pp"><code class="Nm">febug</code> passes all arguments (which have to,
    therefore, include <var class="Ar">mountpoint</var>) to
    <a class="Xr">fuse_main(3)</a>, with <code class="Fl">-f</code> (foreground)
    and <code class="Fl">-o</code> <code class="Nm">default_permissions</code>
    appended. If run with effective UID of 0, it also appends
    <code class="Fl">-o</code> <code class="Nm">allow_other</code>.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="ENVIRONMENT"><a class="permalink" href="#ENVIRONMENT">ENVIRONMENT</a></h1>
<i class="Em">FEBUG_SOCKET</i> the socket at which to listen for programs, or
  <span class="Pa">/var/run/febug.sock</span> by default.
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
<div class="Bd Bd-indent">
<pre>
# launchctl start xyz.nabijaczleweli.febug
$ mount | grep febug
febug@macfuse0 on /private/var/run/febug (macfuse, synchronous)
$ ./out/examples/vector-sort &amp;
[1] 1409
$ LD_LIBRARY_PATH=out ./out/examples/string-qsort &amp;
[2] 1410
$ ls /var/run/febug/
1409 1410
$ ls -l /var/run/febug/
dr-xr-x--- 4 nabijaczleweli users 0 Jan 15 19:52 1409
dr-xr-x--- 3 nabijaczleweli users 0 Jan 15 19:52 1410
$ ls /var/run/febug/1409/
comparisons cool_data
$ cat /var/run/febug/1409/*
24
-3 -2 -3 -2 -3 -2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
$ cat /var/run/febug/1409/*
45
-3 -2 -3 -2 -3 -2 -3 -2 -2 -3 -3 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
$ grep . /var/run/febug/*/*
/var/run/febug/1409/comparisons:71
/var/run/febug/1409/cool_data:-3 -3 -3 -3 -3 -3 -2 -2 -2 -2 -2 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
/var/run/febug/1410/cool_data:3012987654ACEFOLJKODNIEMIGHBPPbdWwnfTpXQcreRlVvUSitZQWjRTYUazuqwertyuiopoxyhmYsgkq
$ kill %1
$ ls /var/run/febug/
1410
</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 used to connect with this
  filesystem.
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; a library wrapping this
    ABI.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; a C++ library wrapping
    this ABI.</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">FEBUG</td>
    <td class="foot-os">Darwin 19.6.0</td>
  </tr>
</table>
</body>
</html>

A MacOS/febug::FORMATTERS.3 => MacOS/febug::FORMATTERS.3 +1 -0
@@ 0,0 1,1 @@
libfebug.rs.3
\ No newline at end of file

A MacOS/febug::GLOBAL_CONTROLLED_SOCKET.3 => MacOS/febug::GLOBAL_CONTROLLED_SOCKET.3 +1 -0
@@ 0,0 1,1 @@
libfebug.rs.3
\ No newline at end of file

A MacOS/febug::StaticWrappable.3 => MacOS/febug::StaticWrappable.3 +1 -0
@@ 0,0 1,1 @@
libfebug.rs.3
\ No newline at end of file

A MacOS/febug::Wrappable.3 => MacOS/febug::Wrappable.3 +1 -0
@@ 0,0 1,1 @@
libfebug.rs.3
\ No newline at end of file

A MacOS/febug::Wrapper.3 => MacOS/febug::Wrapper.3 +1 -0
@@ 0,0 1,1 @@
libfebug.rs.3
\ No newline at end of file

A MacOS/febug::controlled_socket.3 => MacOS/febug::controlled_socket.3 +1 -0
@@ 0,0 1,1 @@
libfebug++.3
\ No newline at end of file

A MacOS/febug::debug_handler.3 => MacOS/febug::debug_handler.3 +1 -0
@@ 0,0 1,1 @@
libfebug++.3
\ No newline at end of file

A MacOS/febug_end.3 => MacOS/febug_end.3 +1 -0
@@ 0,0 1,1 @@
libfebug.3
\ No newline at end of file

A MacOS/febug_message.5 => MacOS/febug_message.5 +1 -0
@@ 0,0 1,1 @@
febug-abi.5
\ No newline at end of file

A MacOS/febug_register_type.3 => MacOS/febug_register_type.3 +1 -0
@@ 0,0 1,1 @@
libfebug.3
\ No newline at end of file

A MacOS/febug_start.3 => MacOS/febug_start.3 +1 -0
@@ 0,0 1,1 @@
libfebug.3
\ No newline at end of file

A MacOS/febug_unwrap.3 => MacOS/febug_unwrap.3 +1 -0
@@ 0,0 1,1 @@
libfebug.3
\ No newline at end of file

A MacOS/febug_wrap.3 => MacOS/febug_wrap.3 +1 -0
@@ 0,0 1,1 @@
libfebug.3
\ No newline at end of file

A MacOS/index.0 => MacOS/index.0 +43 -0
@@ 0,0 1,43 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "index" "0" "January 31, 2021" "Darwin 19.6.0" "0"
.nh
.if n .ad l
.SH "NAME"
\fBindex\fR
\- febug version 0.1.2 manpages
.SH "SEE ALSO"
febug(8)
\[u2013] User-space debugfs filesystem driver
.PP
febug-abi(5)
\[u2013] User-space debugfs ABI
.PP
libfebug(3)
\[u2013] User-space debugfs ABI wrapper library
.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>
.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 MacOS/index.0.html => MacOS/index.0.html +365 -0
@@ 0,0 1,365 @@
<!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>index(0)</title>
</head>
<body>
<table class="head">
  <tr>
    <td class="head-ltitle">index(0)</td>
    <td class="head-vol">0</td>
    <td class="head-rtitle">index(0)</td>
  </tr>
</table>
<div class="manual-text">
<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 version 0.1.2 manpages</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.8.html">febug(8)</a> &#x2013; User-space debugfs filesystem driver
<p class="Pp"><a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2013; User-space debugfs ABI</p>
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2013; User-space debugfs ABI
    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" href="libfebug.rs.3.html">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>
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 31, 2021</td>
    <td class="foot-os">Darwin 19.6.0</td>
  </tr>
</table>
</body>
</html>

A MacOS/libfebug++.3 => MacOS/libfebug++.3 +266 -0
@@ 0,0 1,266 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG++" "3" "January 31, 2021" "Darwin 19.6.0" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
\fBfebug::controlled_socket\fR,
\fBfebug::wrapper\fR,
\fBfebug::formatters\fR,
\fBfebug::debug_handler()\fR
\- User-space debugfs ABI wrapper library for C++
.SH "SYNOPSIS"
\fB#include <libfebug.hpp>\fR
.PP
library \(lqlibfebug++\(rq
.PP
\fB#define FEBUG_DONT 0\fR
.br
\fB#define FEBUG_SOCKET \&"/var/run/febug.sock"\fR
.br
\fB#define FEBUG_SIGNUM SIGUSR2\fR
.PP
\fBgetenv("FEBUG_DONT")\fR
.br
\fBgetenv("FEBUG_SOCKET")\fR
.PP
\fBstruct febug::controlled_socket;\fR
.br
\fIconst febug::controlled_socket febug::global_controlled_socket;\fR
.PP
\fBstruct febug::wrapper;\fR
.br
.PD 0
.HP 4n
\fBfebug::wrapper::wrapper\fR(\fIconst\ T\ &\ data\fR, \fIconst\ char\ *\ name\fR, \fI...\fR);
.PD
.HP 4n
\fBfebug::wrapper::wrapper\fR(\fIconst\ T\ &\ data\fR, \fIuint8_t\ signal\fR, \fIconst\ char\ *\ name\fR, \fI...\fR);
.HP 4n
\fBfebug::wrapper::wrapper\fR(\fIconst\ T\ &\ data\fR, \fIuint8_t\ signal\fR, \fIconst\ char\ *\ name\fR, \fIva_list\ ap\fR);
.PP
\fIstd::map<size_t, void (*)(int, size_t)> febug::formatters;\fR
.HP 4n
\fBvoid febug::debug_handler\fR(\fIint\fR);
.SH "DESCRIPTION"
\fBlibfebug++\fR
allows a programmer to simplify writing C++ programs debuggable with
febug(8)
by presenting a high-level interface to
febug-abi(5).
.PP
There are three compile-time macros that allow a program to customise its behaviour:
.TP 8n
\fBFEBUG_DONT\fR
.br
If non-zero, all symbols become
\fBstatic\fR,
functions turn into no-ops, and therefore no symbols from libfebug++.a/.so are imported at link-time;
this is intended as a way to easily disable
febug(8)
integration completely on release builds.
.TP 8n
\fBFEBUG_SIGNUM\fR
.br
The signal to request from
febug(8)
when using
\fBfebug_wrap\fR().
Defaults to
\fRSIGUSR2\fR.
.TP 8n
\fBFEBUG_SOCKET\fR
.br
The path to connect to
febug(8)
on. Defaults to
\fI/var/run/febug.sock\fR.
.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
\fBFEBUG_SOCKET\fR
to connect to
febug(8)
.PP
The
\fBfebug::controlled_socket\fR
structure is defined as follows:
.nf
.sp
.RS 6n
struct febug::controlled_socket {
    int fd = -1;
    inline operator int() const noexcept { return this->fd; }
    controlled_socket(const char * path = FEBUG_SOCKET) noexcept;
    ~controlled_socket() noexcept;
};
.RE
.fi
.PP
There is a global instance at
\fIfebug::global_controlled_socket\fR
which, if
\fIpath\fR
isn't the null pointer, attempts connection to
febug(8)
and will set
\fIfd\fR,
if successful. Similarly, destroying it will hang up and reset
\fIfd\fR.
.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.
.PP
The program should register handlers for types of variables it wishes to handle by adding entries to
\fIfebug::formatters\fR
\[u2014] the key is typeid(std::decay_t<T>).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,
\fBfebug::debug_handler\fR()
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.
.PP
The
\fBfebug::wrapper\fR
structure is defined as follows:
.nf
.sp
.RS 6n
template <class T>
struct febug::wrapper {
    const T * data;
    wrapper(const T & data, const char * name, ...) noexcept;
    wrapper(const T & data, uint8_t signal, const char * name, ...) noexcept;
    wrapper(const T & data, uint8_t signal, const char * name, va_list ap) noexcept;
    ~wrapper() noexcept;
};
.RE
.fi
.PP
If the program wishes to debug a variable, it should construct a
\fBfebug::wrapper\fR
referencing it; the constructor will send a
\fBfebug_message\fR
with the type corresponding to
\fRtypeid(std::decay_t<T>).hash_code()\fR,
ID corresponding to the pointer to
\fIdata\fR,
signal being either specified or defaulting to
\fBFEBUG_SIGNUM,\fR
.br
and name formatted according to
printf(3).
The destructor will send a
\fBstop_febug_message\fR.
Both become no-ops if
\fIfebug::global_controlled_socket\fR
is -1.
.SH "EXAMPLES"
The following program sorts a std::vector<int> with
\fBstd::sort\fR()
but waits a second between each comparison; the vector and the amount of comparisons can be inspected via a
febug(8)
mount:
.nf
.sp
.RS 6n
// SPDX-License-Identifier: MIT


#include <libfebug.hpp>

#include <vector>

#include <algorithm>
#include <cstring>
#include <errno.h>

#include <unistd.h>


int main() {
	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 {};
	handler.sa_handler = febug::debug_handler;
	if(sigaction(FEBUG_SIGNUM, &handler, nullptr) == -1)
		std::fprintf(stderr, "sigaction: %s\\n", std::strerror(errno));


	{
		std::vector<int> data{-1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3,
		                      -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3};
		std::size_t comparisons_done{};
		febug::wrapper data_w{data, "cool_data"};
		febug::wrapper comparisons_done_w{comparisons_done, "comparisons"};

		std::sort(data.begin(), data.end(), [&](auto lhs, auto rhs) {
			sleep(1);
			++comparisons_done;
			return lhs < rhs;
		});
	}

	sleep(2);
}
.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 Rust 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 MacOS/libfebug++.3.html => MacOS/libfebug++.3.html +563 -0
@@ 0,0 1,563 @@
<!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++(3)</title>
</head>
<body>
<table class="head">
  <tr>
    <td class="head-ltitle">LIBFEBUG++(3)</td>
    <td class="head-vol">Library Functions Manual</td>
    <td class="head-rtitle">LIBFEBUG++(3)</td>
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">febug::controlled_socket</code>,
  <code class="Nm">febug::wrapper</code>,
  <code class="Nm">febug::formatters</code>,
  <code class="Nm">febug::debug_handler()</code> &#x2014;
<div class="Nd">User-space debugfs ABI wrapper library for C++</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<code class="In">#include
  &lt;<a class="In" href="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/libfebug.hpp">libfebug.hpp</a>&gt;</code>
<p class="Pp"><span class="Lb">library &#x201C;libfebug++&#x201D;</span></p>
<p class="Pp">
  <br/>
  <code class="Fd">#define FEBUG_DONT 0</code>
  <br/>
  <code class="Fd">#define FEBUG_SOCKET &quot;/var/run/febug.sock&quot;</code>
  <br/>
  <code class="Fd">#define FEBUG_SIGNUM SIGUSR2</code></p>
<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"><b class="Sy">struct febug::controlled_socket;</b>
  <br/>
  <var class="Vt">const febug::controlled_socket
    febug::global_controlled_socket;</var></p>
<p class="Pp"><b class="Sy">struct febug::wrapper;</b>
  <br/>
  <code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
    T &amp; data</var>, <var class="Fa" style="white-space: nowrap;">const char
    * name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
    T &amp; data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
    T &amp; data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">va_list
  ap</var>);</p>
<p class="Pp"><var class="Vt">std::map&lt;size_t, void (*)(int, size_t)&gt;
    febug::formatters;</var></p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug::debug_handler</code>(<var class="Fa" style="white-space: nowrap;">int</var>);</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<b class="Sy">libfebug++</b> allows a programmer to simplify writing C++
  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 three compile-time macros that allow a program to
    customise its behaviour:</p>
<dl class="Bl-tag">
  <dt></dt>
  <dd><code class="Fd">FEBUG_DONT</code> If non-zero, all symbols become
      <b class="Sy">static</b>, functions turn into no-ops, and therefore no
      symbols from libfebug++.a/.so are imported at link-time; 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></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
      <code class="Fn">febug_wrap</code>(). 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><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 <b class="Sy">FEBUG_SOCKET</b> to connect
      to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
</dl>
<p class="Pp">The <b class="Sy">febug::controlled_socket</b> structure is
    defined as follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct febug::controlled_socket {
    int fd = -1;
    inline operator int() const noexcept { return this-&gt;fd; }
    controlled_socket(const char * path = FEBUG_SOCKET) noexcept;
    ~controlled_socket() noexcept;
};
</pre>
</div>
<p class="Pp">There is a global instance at
    <var class="Vt">febug::global_controlled_socket</var> which, if
    <var class="Vt">path</var> isn't the null pointer, attempts connection to
    <a class="Xr" href="febug.8.html">febug(8)</a> and will set <var class="Vt">fd</var>, if
    successful. Similarly, destroying it will hang up and reset
    <var class="Vt">fd</var>.</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.</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> &#x2014; the key is
    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 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 would then run the risk of closing another file
    with the same descriptor simultaneously opened by another thread.</p>
<p class="Pp">The <b class="Sy">febug::wrapper</b> structure is defined as
    follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
template &lt;class T&gt;
struct febug::wrapper {
    const T * data;
    wrapper(const T &amp; data, const char * name, ...) noexcept;
    wrapper(const T &amp; data, uint8_t signal, const char * name, ...) noexcept;
    wrapper(const T &amp; data, uint8_t signal, const char * name, va_list ap) noexcept;
    ~wrapper() noexcept;
};
</pre>
</div>
<p class="Pp">If the program wishes to debug a variable, it should construct a
    <b class="Sy">febug::wrapper</b> referencing it; the constructor will send a
    <b class="Sy">febug_message</b> with the type corresponding to
    <code class="Dv">typeid(std::decay_t&lt;T&gt;).hash_code()</code>, ID
    corresponding to the pointer to <var class="Vt">data</var>, signal being
    either specified or defaulting to <code class="Fd">FEBUG_SIGNUM,</code> and
    name formatted according to <a class="Xr">printf(3)</a>. The destructor will
    send a <b class="Sy">stop_febug_message</b>. Both become no-ops if
    <var class="Vt">febug::global_controlled_socket</var> is -1.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
The following program sorts a std::vector&lt;int&gt; with
  <code class="Fn">std::sort</code>() but waits a second between each
  comparison; the vector 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


#include &lt;libfebug.hpp&gt;

#include &lt;vector&gt;

#include &lt;algorithm&gt;
#include &lt;cstring&gt;
#include &lt;errno.h&gt;

#include &lt;unistd.h&gt;


int main() {
	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 {};
	handler.sa_handler = febug::debug_handler;
	if(sigaction(FEBUG_SIGNUM, &amp;handler, nullptr) == -1)
		std::fprintf(stderr, &quot;sigaction: %s\n&quot;, std::strerror(errno));


	{
		std::vector&lt;int&gt; data{-1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3,
		                      -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3};
		std::size_t comparisons_done{};
		febug::wrapper data_w{data, &quot;cool_data&quot;};
		febug::wrapper comparisons_done_w{comparisons_done, &quot;comparisons&quot;};

		std::sort(data.begin(), data.end(), [&amp;](auto lhs, auto rhs) {
			sleep(1);
			++comparisons_done;
			return lhs &lt; rhs;
		});
	}

	sleep(2);
}
</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 Rust
  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 31, 2021</td>
    <td class="foot-os">Darwin 19.6.0</td>
  </tr>
</table>
</body>
</html>

A MacOS/libfebug.3 => MacOS/libfebug.3 +262 -0
@@ 0,0 1,262 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG" "3" "January 31, 2021" "Darwin 19.6.0" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
\fBfebug_start()\fR,
\fBfebug_end()\fR,
\fBfebug_register_type()\fR,
\fBfebug_wrap()\fR,
\fBfebug_unwrap()\fR
\- User-space debugfs ABI wrapper library
.SH "SYNOPSIS"
\fB#include <libfebug.h>\fR
.PP
library \(lqlibfebug\(rq
.PP
\fB#define FEBUG_DONT 0\fR
.br
\fB#define FEBUG_SOCKET \&"/var/run/febug.sock"\fR
.br
\fB#define FEBUG_SIGNUM SIGUSR2\fR
.PP
\fBgetenv("FEBUG_DONT")\fR
.br
\fBgetenv("FEBUG_SOCKET")\fR
.PP
\fIint febug_global_controlled_socket\fR
= -1;
.HP 4n
\fBvoid febug_start\fR();
.HP 4n
\fBvoid febug_start_path\fR(\fIconst\ char\ *\ path\fR);
.HP 4n
\fBvoid febug_debug_handler\fR(\fIint\fR);
.HP 4n
\fBvoid febug_register_type\fR(\fIuint64_t\ type\fR, \fIvoid\ (*formatter)(int,\ size_t)\fR);
.HP 4n
\fBvoid febug_wrap\fR(\fIuint64_t\ type\fR, \fIconst\ void\ *\ data\fR, \fIconst\ char\ *\ name\fR, \fI...\fR);
.HP 4n
\fBvoid febug_wrap_signal\fR(\fIuint64_t\ type\fR, \fIconst\ void\ *\ data\fR, \fIuint8_t\ signal\fR, \fIconst\ char\ *\ name\fR, \fI...\fR);
.HP 4n
\fBvoid febug_wrap_signalv\fR(\fIuint64_t\ type\fR, \fIconst\ void\ *\ data\fR, \fIuint8_t\ signal\fR, \fIconst\ char\ *\ name\fR, \fIva_list\ ap\fR);
.HP 4n
\fBvoid febug_unwrap\fR(\fIconst\ void\ *\ data\fR);
.HP 4n
\fBvoid febug_end\fR();
.SH "DESCRIPTION"
\fBlibfebug\fR
allows a programmer to simplify writing programs debuggable with
febug(8)
by presenting a high-level interface to
febug-abi(5).
.PP
There are three compile-time macros that allow a program to customise its behaviour:
.TP 8n
\fBFEBUG_DONT\fR
.br
If non-zero, all symbols become
\fBstatic\fR,
functions turn into no-ops, and therefore no symbols from libfebug.a/.so are imported at link-time;
this is intended as a way to easily disable
febug(8)
integration completely on release builds.
.TP 8n
\fBFEBUG_SIGNUM\fR
.br
The signal to request from
febug(8)
when using
\fBfebug_wrap\fR().
Defaults to
\fRSIGUSR2\fR.
.TP 8n
\fBFEBUG_SOCKET\fR
.br
The path to connect to
febug(8)
on. Defaults to
\fI/var/run/febug.sock\fR.
.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
\fBFEBUG_SOCKET\fR
to connect to
febug(8)
.PP
To be debugged, a program needs to, first, call
\fBfebug_start_path\fR()
(likely via
\fBfebug_start\fR(),
which simply passes
\fBFEBUG_SOCKET\fR
.br
thereto) to connect to
febug(8),
which, if successful, will set
\fIfebug_global_controlled_socket\fR
appropriately.
.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.
.PP
The program should register handlers for types of variables it wishes to handle by calling
\fBfebug_register_type\fR()
\[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 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.
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 call
\fBfebug_wrap_signalv\fR()
(likely via
\fBfebug_wrap_signal\fR()
(likely via
\fBfebug_wrap\fR(),
which passes
\fBFEBUG_SIGNUM\fR
thereto)), which will send a
\fBfebug_message\fR
with the specified type and signal numbers, ID equal to the data pointer, and name formatted according to
printf(3).
It's a no-op if
\fIfebug_global_controlled_socket\fR
is -1.
.PP
When the variable goes out of scope, the program should call
\fBfebug_unwrap\fR()
to send a
\fBstop_febug_message\fR
with the same data pointer as it did
\fBfebug_wrap\fR(),
to prevent reading random data that might no longer be mapped, or make sense.
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,
if any, and deallocate the type->handler map.
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 sorts a string with
qsort(3)
but waits half a second between each comparison; the string can be inspected via a
febug(8)
mount:
.nf
.sp
.RS 6n
// SPDX-License-Identifier: MIT


#define _POSIX_C_SOURCE 200809L

#include <libfebug.h>

#include <signal.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>


#define CSTRING_FEBUG_TP 420
static void cstring_febug_formatter(int fd, size_t data) {
	const char * str = (const char *)data;
	dprintf(fd, "%s\\n", str);
}


static int char_comp(const void * lhs, const void * rhs) {
	const struct timespec half_second = {0, 500 * 1000 * 1000};
	nanosleep(&half_second, 0);

	return *(const char *)lhs - *(const char *)rhs;
}


int main() {
	febug_start();
	febug_register_type(CSTRING_FEBUG_TP, cstring_febug_formatter);


	struct sigaction handler;
	memset(&handler, 0, sizeof(handler));
	handler.sa_handler = febug_debug_handler;
	if(sigaction(FEBUG_SIGNUM, &handler, 0) == -1) {
		fprintf(stderr, "sigaction: %s\\n", strerror(errno));
		return 1;
	}


	{
		__attribute__((__cleanup__(febug_unwrap))) char data[] = "JVLOkgsYmhCyEFxouKzDNajivGlpWqbdBwnfTAXQcreRHPIUSMtZQWERTYUIOPqwertyuiop1234567890";
		febug_wrap(CSTRING_FEBUG_TP, data, "cool_data");

		qsort(data, strlen(data), 1, char_comp);
	}

	sleep(2);

	febug_end();
}
.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 Rust 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 MacOS/libfebug.3.html => MacOS/libfebug.3.html +569 -0
@@ 0,0 1,569 @@
<!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(3)</title>
</head>
<body>
<table class="head">
  <tr>
    <td class="head-ltitle">LIBFEBUG(3)</td>
    <td class="head-vol">Library Functions Manual</td>
    <td class="head-rtitle">LIBFEBUG(3)</td>
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">febug_start()</code>, <code class="Nm">febug_end()</code>,
  <code class="Nm">febug_register_type()</code>,
  <code class="Nm">febug_wrap()</code>, <code class="Nm">febug_unwrap()</code>
  &#x2014;
<div class="Nd">User-space debugfs ABI wrapper library</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<code class="In">#include
  &lt;<a class="In" href="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/libfebug.h">libfebug.h</a>&gt;</code>
<p class="Pp"><span class="Lb">library &#x201C;libfebug&#x201D;</span></p>
<p class="Pp">
  <br/>
  <code class="Fd">#define FEBUG_DONT 0</code>
  <br/>
  <code class="Fd">#define FEBUG_SOCKET &quot;/var/run/febug.sock&quot;</code>
  <br/>
  <code class="Fd">#define FEBUG_SIGNUM SIGUSR2</code></p>
<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">int febug_global_controlled_socket</var> = -1;</p>
<p class="Pp">
  <br/>
  <var class="Ft">void</var> <code class="Fn">febug_start</code>();</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_start_path</code>(<var class="Fa" style="white-space: nowrap;">const
    char * path</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_debug_handler</code>(<var class="Fa" style="white-space: nowrap;">int</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_register_type</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">void
    (*formatter)(int, size_t)</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_wrap</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">const void *
    data</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">const void *
    data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_wrap_signalv</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">const void *
    data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">va_list
  ap</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_unwrap</code>(<var class="Fa" style="white-space: nowrap;">const
    void * data</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <code class="Fn">febug_end</code>();</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<b class="Sy">libfebug</b> allows a programmer to simplify writing 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 three compile-time macros that allow a program to
    customise its behaviour:</p>
<dl class="Bl-tag">
  <dt></dt>
  <dd><code class="Fd">FEBUG_DONT</code> If non-zero, all symbols become
      <b class="Sy">static</b>, functions turn into no-ops, and therefore no
      symbols from libfebug.a/.so are imported at link-time; 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></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
      <code class="Fn">febug_wrap</code>(). 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><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 <b class="Sy">FEBUG_SOCKET</b> 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_path</code>() (likely via
    <code class="Fn">febug_start</code>(), which simply passes
    <code class="Fd">FEBUG_SOCKET</code> 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> appropriately.</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.</p>
<p class="Pp">The program should register handlers for types of variables it
    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 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 would then run the risk of closing another file
    with the same descriptor simultaneously opened by another thread. 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
    call <code class="Fn">febug_wrap_signalv</code>() (likely via
    <code class="Fn">febug_wrap_signal</code>() (likely via
    <code class="Fn">febug_wrap</code>(), which passes
    <b class="Sy">FEBUG_SIGNUM</b> thereto)), which will send a
    <b class="Sy">febug_message</b> with the specified type and signal numbers,
    ID equal to the data pointer, and name formatted according to
    <a class="Xr">printf(3)</a>. It's a no-op if
    <var class="Vt">febug_global_controlled_socket</var> is -1.</p>
<p class="Pp">When the variable goes out of scope, the program should call
    <code class="Fn">febug_unwrap</code>() to send a
    <b class="Sy">stop_febug_message</b> with the same data pointer as it did
    <code class="Fn">febug_wrap</code>(), to prevent reading random data that
    might no longer be mapped, or make sense. 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>, if any, and deallocate
    the type-&gt;handler map. 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 sorts a string with <a class="Xr">qsort(3)</a> but waits
  half a second between each comparison; the string 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


#define _POSIX_C_SOURCE 200809L

#include &lt;libfebug.h&gt;

#include &lt;signal.h&gt;

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;time.h&gt;
#include &lt;errno.h&gt;
#include &lt;unistd.h&gt;


#define CSTRING_FEBUG_TP 420
static void cstring_febug_formatter(int fd, size_t data) {
	const char * str = (const char *)data;
	dprintf(fd, &quot;%s\n&quot;, str);
}


static int char_comp(const void * lhs, const void * rhs) {
	const struct timespec half_second = {0, 500 * 1000 * 1000};
	nanosleep(&amp;half_second, 0);

	return *(const char *)lhs - *(const char *)rhs;
}


int main() {
	febug_start();
	febug_register_type(CSTRING_FEBUG_TP, cstring_febug_formatter);


	struct sigaction handler;
	memset(&amp;handler, 0, sizeof(handler));
	handler.sa_handler = febug_debug_handler;
	if(sigaction(FEBUG_SIGNUM, &amp;handler, 0) == -1) {
		fprintf(stderr, &quot;sigaction: %s\n&quot;, strerror(errno));
		return 1;
	}


	{
		__attribute__((__cleanup__(febug_unwrap))) char data[] = &quot;JVLOkgsYmhCyEFxouKzDNajivGlpWqbdBwnfTAXQcreRHPIUSMtZQWERTYUIOPqwertyuiop1234567890&quot;;
		febug_wrap(CSTRING_FEBUG_TP, data, &quot;cool_data&quot;);

		qsort(data, strlen(data), 1, char_comp);
	}

	sleep(2);

	febug_end();
}
</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 Rust
    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 31, 2021</td>
    <td class="foot-os">Darwin 19.6.0</td>
  </tr>
</table>
</body>
</html>

A MacOS/libfebug.rs.3 => MacOS/libfebug.rs.3 +279 -0
@@ 0,0 1,279 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG.RS" "3" "January 31, 2021" "Darwin 19.6.0" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
\fBfebug::start()\fR,
\fBfebug::Wrapper\fR,
\fBfebug::Wrappable\fR,
\fBfebug::StaticWrappable\fR,
\fBfebug::GLOBAL_CONTROLLED_SOCKET\fR,
\fBfebug::FORMATTERS\fR
\- User-space debugfs ABI wrapper library for Rust
.SH "SYNOPSIS"
.nf
.RS 0n
[dependencies]
febug = "0.1.2"
.RE
.fi
.PP
\fBenv!("FEBUG_DONT")?\fR
.br
\fBenv!("FEBUG_SOCKET") = \&"/var/run/febug.sock"\fR
.br
\fBenv!("FEBUG_SIGNUM") = SIGUSR2\fR
.PP
\fBenv::var("FEBUG_DONT")\fR
.br
\fBenv::var("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 three compile-time environment variables that allow a programmer to customise its behaviour:
.TP 8n
\fBFEBUG_DONT\fR
.br
If set, all functions turn into no-ops;
this is intended as a way to easily disable
febug(8)
integration completely on release builds.
.TP 8n
\fBFEBUG_SIGNUM\fR
.br
The signal to request from
febug(8)
when using
\fBfebug_wrap\fR().
Defaults to
\fRSIGUSR2\fR.
.TP 8n
\fBFEBUG_SOCKET\fR
.br
The path to connect to
febug(8)
on. Defaults to
\fI/var/run/febug.sock\fR.
.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
\fBFEBUG_SOCKET\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 MacOS/libfebug.rs.3.html => MacOS/libfebug.rs.3.html +586 -0
@@ 0,0 1,586 @@
<!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>
<code class="Nm">febug::start()</code>, <code class="Nm">febug::Wrapper</code>,
  <code class="Nm">febug::Wrappable</code>,
  <code class="Nm">febug::StaticWrappable</code>,
  <code class="Nm">febug::GLOBAL_CONTROLLED_SOCKET</code>,
  <code class="Nm">febug::FORMATTERS</code> &#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.1.2&quot;
</pre>
</div>
<p class="Pp">
  <br/>
  <code class="Fd">env!(&quot;FEBUG_DONT&quot;)?</code>
  <br/>
  <code class="Fd">env!(&quot;FEBUG_SOCKET&quot;) =
    &quot;/var/run/febug.sock&quot;</code>
  <br/>
  <code class="Fd">env!(&quot;FEBUG_SIGNUM&quot;) = SIGUSR2</code></p>
<p class="Pp">
  <br/>
  <code class="Fd">env::var(&quot;FEBUG_DONT&quot;)</code>
  <br/>
  <code class="Fd">env::var(&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 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></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
      <code class="Fn">febug_wrap</code>(). 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><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 <b class="Sy">FEBUG_SOCKET</b> 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 31, 2021</td>
    <td class="foot-os">Darwin 19.6.0</td>
  </tr>
</table>
</body>
</html>

A MacOS/stop_febug_message.5 => MacOS/stop_febug_message.5 +1 -0
@@ 0,0 1,1 @@
febug-abi.5
\ No newline at end of file