<!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="Fn">febug_start</code>(), <code class="Fn">febug_end</code>(),
<code class="Fn">febug_register_type</code>(),
<code class="Fn">febug_wrap</code>(), <code class="Fn">febug_unwrap</code>()
—
<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
<<a class="In" href="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/libfebug.h">libfebug.h</a>></code>
<p class="Pp"><span class="Lb">library “libfebug”</span></p>
<p class="Pp">
<br/>
<code class="Fd">#define FEBUG_DONT 0</code>
<br/>
<code class="Fd">#define FEBUG_SOCKET "/var/run/febug.sock"</code>
<br/>
<code class="Fd">#define FEBUG_SIGNUM SIGUSR2</code></p>
<p class="Pp">
<br/>
<code class="Fd">getenv("FEBUG_DONT")</code>
<br/>
<code class="Fd">getenv("FEBUG_SOCKET")</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>
<code class="Nm"></code>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 the 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>()
— those type numbers should be consistent across the program, lest
the wrong handler is called. If no handler was registered for a type,
<code class="Fn">febug_debug_handler</code>() will print a generic "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 <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->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 <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();
}
</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> — the ABI wrapped by this library.
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> — an equivalent C++
library.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
Written by <span class="An">наб</span>
<<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>>
</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">
<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 bug
tracker</a>
<p class="Pp">febug mailing list:
<<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>>
archived at
<a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">January 19, 2021</td>
<td class="foot-os">NetBSD 9.1</td>
</tr>
</table>
</body>
</html>