~nabijaczleweli/febug

ref: f2e2a7f676c04f383026174fdd55e698baf35379 febug/FreeBSD/libfebug++.3 -rw-r--r-- 7.0 KiB
f2e2a7f6 — наб autouploader FreeBSD manpage update by job 411516 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG++" "3" "January 30, 2021" "FreeBSD 12.2-RELEASE-p1" "FreeBSD Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
\fBfebug::controlled_socket\fR,
\fBfebug::wrapper\fR,
\fIfebug::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