aboutsummaryrefslogtreecommitdiffhomepage
path: root/print.html
diff options
context:
space:
mode:
authorjohannst <johannst@users.noreply.github.com>2022-11-13 14:13:35 +0000
committerjohannst <johannst@users.noreply.github.com>2022-11-13 14:13:35 +0000
commit2dfbc312e6ccb88f838170d8e777d48aacde2ff5 (patch)
treea4a83435e10a7ad38f454a30cbd7b30640cd1a7d /print.html
parentccbbcafbc7337c8d7a785b9034716618dce36e4d (diff)
downloadnotes-2dfbc312e6ccb88f838170d8e777d48aacde2ff5.tar.gz
notes-2dfbc312e6ccb88f838170d8e777d48aacde2ff5.zip
deploy: 026d679006e5d470bacdc74bb3082072edf31e36
Diffstat (limited to 'print.html')
-rw-r--r--print.html475
1 files changed, 470 insertions, 5 deletions
diff --git a/print.html b/print.html
index 5f6b2fa..abeecd8 100644
--- a/print.html
+++ b/print.html
@@ -76,7 +76,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
- <ol class="chapter"><li class="chapter-item expanded affix "><a href="intro.html">Introduction</a></li><li class="chapter-item expanded "><a href="tools/index.html"><strong aria-hidden="true">1.</strong> Tools</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="tools/zsh.html"><strong aria-hidden="true">1.1.</strong> zsh</a></li><li class="chapter-item expanded "><a href="tools/bash.html"><strong aria-hidden="true">1.2.</strong> bash</a></li><li class="chapter-item expanded "><a href="tools/fish.html"><strong aria-hidden="true">1.3.</strong> fish</a></li><li class="chapter-item expanded "><a href="tools/tmux.html"><strong aria-hidden="true">1.4.</strong> tmux</a></li><li class="chapter-item expanded "><a href="tools/git.html"><strong aria-hidden="true">1.5.</strong> git</a></li><li class="chapter-item expanded "><a href="tools/awk.html"><strong aria-hidden="true">1.6.</strong> awk</a></li><li class="chapter-item expanded "><a href="tools/emacs.html"><strong aria-hidden="true">1.7.</strong> emacs</a></li><li class="chapter-item expanded "><a href="tools/gpg.html"><strong aria-hidden="true">1.8.</strong> gpg</a></li><li class="chapter-item expanded "><a href="tools/gdb.html"><strong aria-hidden="true">1.9.</strong> gdb</a></li><li class="chapter-item expanded "><a href="tools/gdbserver.html"><strong aria-hidden="true">1.10.</strong> gdbserver</a></li><li class="chapter-item expanded "><a href="tools/radare2.html"><strong aria-hidden="true">1.11.</strong> radare2</a></li><li class="chapter-item expanded "><a href="tools/qemu.html"><strong aria-hidden="true">1.12.</strong> qemu</a></li><li class="chapter-item expanded "><a href="tools/pacman.html"><strong aria-hidden="true">1.13.</strong> pacman</a></li><li class="chapter-item expanded "><a href="tools/dot.html"><strong aria-hidden="true">1.14.</strong> dot</a></li></ol></li><li class="chapter-item expanded "><a href="monitor/index.html"><strong aria-hidden="true">2.</strong> Resource analysis & monitor</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="monitor/lsof.html"><strong aria-hidden="true">2.1.</strong> lsof</a></li><li class="chapter-item expanded "><a href="monitor/ss.html"><strong aria-hidden="true">2.2.</strong> ss</a></li><li class="chapter-item expanded "><a href="monitor/pidstat.html"><strong aria-hidden="true">2.3.</strong> pidstat</a></li><li class="chapter-item expanded "><a href="monitor/pgrep.html"><strong aria-hidden="true">2.4.</strong> pgrep</a></li><li class="chapter-item expanded "><a href="monitor/pmap.html"><strong aria-hidden="true">2.5.</strong> pmap</a></li><li class="chapter-item expanded "><a href="monitor/pstack.html"><strong aria-hidden="true">2.6.</strong> pstack</a></li></ol></li><li class="chapter-item expanded "><a href="trace_profile/index.html"><strong aria-hidden="true">3.</strong> Trace and Profile</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="trace_profile/strace.html"><strong aria-hidden="true">3.1.</strong> strace</a></li><li class="chapter-item expanded "><a href="trace_profile/ltrace.html"><strong aria-hidden="true">3.2.</strong> ltrace</a></li><li class="chapter-item expanded "><a href="trace_profile/perf.html"><strong aria-hidden="true">3.3.</strong> perf</a></li><li class="chapter-item expanded "><a href="trace_profile/oprofile.html"><strong aria-hidden="true">3.4.</strong> OProfile</a></li><li class="chapter-item expanded "><a href="trace_profile/time.html"><strong aria-hidden="true">3.5.</strong> time</a></li></ol></li><li class="chapter-item expanded "><a href="binary/index.html"><strong aria-hidden="true">4.</strong> Binary</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="binary/od.html"><strong aria-hidden="true">4.1.</strong> od</a></li><li class="chapter-item expanded "><a href="binary/xxd.html"><strong aria-hidden="true">4.2.</strong> xxd</a></li><li class="chapter-item expanded "><a href="binary/readelf.html"><strong aria-hidden="true">4.3.</strong> readelf</a></li><li class="chapter-item expanded "><a href="binary/objdump.html"><strong aria-hidden="true">4.4.</strong> objdump</a></li><li class="chapter-item expanded "><a href="binary/nm.html"><strong aria-hidden="true">4.5.</strong> nm</a></li></ol></li><li class="chapter-item expanded "><a href="development/index.html"><strong aria-hidden="true">5.</strong> Development</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="development/c++filt.html"><strong aria-hidden="true">5.1.</strong> c++filt</a></li><li class="chapter-item expanded "><a href="development/c++.html"><strong aria-hidden="true">5.2.</strong> c++</a></li><li class="chapter-item expanded "><a href="development/glibc.html"><strong aria-hidden="true">5.3.</strong> glibc</a></li><li class="chapter-item expanded "><a href="development/gcc.html"><strong aria-hidden="true">5.4.</strong> gcc</a></li><li class="chapter-item expanded "><a href="development/make.html"><strong aria-hidden="true">5.5.</strong> make</a></li><li class="chapter-item expanded "><a href="development/ld.so.html"><strong aria-hidden="true">5.6.</strong> ld.so</a></li><li class="chapter-item expanded "><a href="development/symbolver.html"><strong aria-hidden="true">5.7.</strong> symbol versioning</a></li><li class="chapter-item expanded "><a href="development/python.html"><strong aria-hidden="true">5.8.</strong> python</a></li></ol></li><li class="chapter-item expanded "><a href="linux/index.html"><strong aria-hidden="true">6.</strong> Linux</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="linux/systemd.html"><strong aria-hidden="true">6.1.</strong> systemd</a></li><li class="chapter-item expanded "><a href="linux/coredump.html"><strong aria-hidden="true">6.2.</strong> coredump</a></li><li class="chapter-item expanded "><a href="linux/ptrace_scope.html"><strong aria-hidden="true">6.3.</strong> ptrace_scope</a></li><li class="chapter-item expanded "><a href="linux/cryptsetup.html"><strong aria-hidden="true">6.4.</strong> cryptsetup</a></li><li class="chapter-item expanded "><a href="linux/swap.html"><strong aria-hidden="true">6.5.</strong> swap</a></li></ol></li><li class="chapter-item expanded "><a href="network/index.html"><strong aria-hidden="true">7.</strong> Network</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="network/tcpdump.html"><strong aria-hidden="true">7.1.</strong> tcpdump</a></li></ol></li><li class="chapter-item expanded "><a href="web/index.html"><strong aria-hidden="true">8.</strong> Web</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="web/html.html"><strong aria-hidden="true">8.1.</strong> html</a></li></ol></li><li class="chapter-item expanded "><a href="arch/index.html"><strong aria-hidden="true">9.</strong> Arch</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="arch/x86_64.html"><strong aria-hidden="true">9.1.</strong> x86_64</a></li><li class="chapter-item expanded "><a href="arch/arm64.html"><strong aria-hidden="true">9.2.</strong> arm64</a></li><li class="chapter-item expanded "><a href="arch/armv7.html"><strong aria-hidden="true">9.3.</strong> armv7</a></li><li class="chapter-item expanded "><a href="arch/riscv.html"><strong aria-hidden="true">9.4.</strong> riscv</a></li></ol></li></ol>
+ <ol class="chapter"><li class="chapter-item expanded affix "><a href="intro.html">Introduction</a></li><li class="chapter-item expanded "><a href="tools/index.html"><strong aria-hidden="true">1.</strong> Tools</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="tools/zsh.html"><strong aria-hidden="true">1.1.</strong> zsh</a></li><li class="chapter-item expanded "><a href="tools/bash.html"><strong aria-hidden="true">1.2.</strong> bash</a></li><li class="chapter-item expanded "><a href="tools/fish.html"><strong aria-hidden="true">1.3.</strong> fish</a></li><li class="chapter-item expanded "><a href="tools/tmux.html"><strong aria-hidden="true">1.4.</strong> tmux</a></li><li class="chapter-item expanded "><a href="tools/git.html"><strong aria-hidden="true">1.5.</strong> git</a></li><li class="chapter-item expanded "><a href="tools/awk.html"><strong aria-hidden="true">1.6.</strong> awk</a></li><li class="chapter-item expanded "><a href="tools/emacs.html"><strong aria-hidden="true">1.7.</strong> emacs</a></li><li class="chapter-item expanded "><a href="tools/gpg.html"><strong aria-hidden="true">1.8.</strong> gpg</a></li><li class="chapter-item expanded "><a href="tools/gdb.html"><strong aria-hidden="true">1.9.</strong> gdb</a></li><li class="chapter-item expanded "><a href="tools/gdbserver.html"><strong aria-hidden="true">1.10.</strong> gdbserver</a></li><li class="chapter-item expanded "><a href="tools/radare2.html"><strong aria-hidden="true">1.11.</strong> radare2</a></li><li class="chapter-item expanded "><a href="tools/qemu.html"><strong aria-hidden="true">1.12.</strong> qemu</a></li><li class="chapter-item expanded "><a href="tools/pacman.html"><strong aria-hidden="true">1.13.</strong> pacman</a></li><li class="chapter-item expanded "><a href="tools/dot.html"><strong aria-hidden="true">1.14.</strong> dot</a></li></ol></li><li class="chapter-item expanded "><a href="monitor/index.html"><strong aria-hidden="true">2.</strong> Resource analysis & monitor</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="monitor/lsof.html"><strong aria-hidden="true">2.1.</strong> lsof</a></li><li class="chapter-item expanded "><a href="monitor/ss.html"><strong aria-hidden="true">2.2.</strong> ss</a></li><li class="chapter-item expanded "><a href="monitor/pidstat.html"><strong aria-hidden="true">2.3.</strong> pidstat</a></li><li class="chapter-item expanded "><a href="monitor/pgrep.html"><strong aria-hidden="true">2.4.</strong> pgrep</a></li><li class="chapter-item expanded "><a href="monitor/pmap.html"><strong aria-hidden="true">2.5.</strong> pmap</a></li><li class="chapter-item expanded "><a href="monitor/pstack.html"><strong aria-hidden="true">2.6.</strong> pstack</a></li></ol></li><li class="chapter-item expanded "><a href="trace_profile/index.html"><strong aria-hidden="true">3.</strong> Trace and Profile</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="trace_profile/strace.html"><strong aria-hidden="true">3.1.</strong> strace</a></li><li class="chapter-item expanded "><a href="trace_profile/ltrace.html"><strong aria-hidden="true">3.2.</strong> ltrace</a></li><li class="chapter-item expanded "><a href="trace_profile/perf.html"><strong aria-hidden="true">3.3.</strong> perf</a></li><li class="chapter-item expanded "><a href="trace_profile/oprofile.html"><strong aria-hidden="true">3.4.</strong> OProfile</a></li><li class="chapter-item expanded "><a href="trace_profile/time.html"><strong aria-hidden="true">3.5.</strong> time</a></li></ol></li><li class="chapter-item expanded "><a href="binary/index.html"><strong aria-hidden="true">4.</strong> Binary</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="binary/od.html"><strong aria-hidden="true">4.1.</strong> od</a></li><li class="chapter-item expanded "><a href="binary/xxd.html"><strong aria-hidden="true">4.2.</strong> xxd</a></li><li class="chapter-item expanded "><a href="binary/readelf.html"><strong aria-hidden="true">4.3.</strong> readelf</a></li><li class="chapter-item expanded "><a href="binary/objdump.html"><strong aria-hidden="true">4.4.</strong> objdump</a></li><li class="chapter-item expanded "><a href="binary/nm.html"><strong aria-hidden="true">4.5.</strong> nm</a></li></ol></li><li class="chapter-item expanded "><a href="development/index.html"><strong aria-hidden="true">5.</strong> Development</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="development/c++filt.html"><strong aria-hidden="true">5.1.</strong> c++filt</a></li><li class="chapter-item expanded "><a href="development/c++.html"><strong aria-hidden="true">5.2.</strong> c++</a></li><li class="chapter-item expanded "><a href="development/glibc.html"><strong aria-hidden="true">5.3.</strong> glibc</a></li><li class="chapter-item expanded "><a href="development/gcc.html"><strong aria-hidden="true">5.4.</strong> gcc</a></li><li class="chapter-item expanded "><a href="development/make.html"><strong aria-hidden="true">5.5.</strong> make</a></li><li class="chapter-item expanded "><a href="development/ld.so.html"><strong aria-hidden="true">5.6.</strong> ld.so</a></li><li class="chapter-item expanded "><a href="development/symbolver.html"><strong aria-hidden="true">5.7.</strong> symbol versioning</a></li><li class="chapter-item expanded "><a href="development/python.html"><strong aria-hidden="true">5.8.</strong> python</a></li></ol></li><li class="chapter-item expanded "><a href="linux/index.html"><strong aria-hidden="true">6.</strong> Linux</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="linux/systemd.html"><strong aria-hidden="true">6.1.</strong> systemd</a></li><li class="chapter-item expanded "><a href="linux/coredump.html"><strong aria-hidden="true">6.2.</strong> coredump</a></li><li class="chapter-item expanded "><a href="linux/ptrace_scope.html"><strong aria-hidden="true">6.3.</strong> ptrace_scope</a></li><li class="chapter-item expanded "><a href="linux/cryptsetup.html"><strong aria-hidden="true">6.4.</strong> cryptsetup</a></li><li class="chapter-item expanded "><a href="linux/swap.html"><strong aria-hidden="true">6.5.</strong> swap</a></li><li class="chapter-item expanded "><a href="linux/input.html"><strong aria-hidden="true">6.6.</strong> input</a></li></ol></li><li class="chapter-item expanded "><a href="network/index.html"><strong aria-hidden="true">7.</strong> Network</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="network/tcpdump.html"><strong aria-hidden="true">7.1.</strong> tcpdump</a></li><li class="chapter-item expanded "><a href="network/firewall-cmd.html"><strong aria-hidden="true">7.2.</strong> firewall-cmd</a></li></ol></li><li class="chapter-item expanded "><a href="web/index.html"><strong aria-hidden="true">8.</strong> Web</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="web/html.html"><strong aria-hidden="true">8.1.</strong> html</a></li><li class="chapter-item expanded "><a href="web/chartjs.html"><strong aria-hidden="true">8.2.</strong> chartjs</a></li></ol></li><li class="chapter-item expanded "><a href="arch/index.html"><strong aria-hidden="true">9.</strong> Arch</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="arch/x86_64.html"><strong aria-hidden="true">9.1.</strong> x86_64</a></li><li class="chapter-item expanded "><a href="arch/arm64.html"><strong aria-hidden="true">9.2.</strong> arm64</a></li><li class="chapter-item expanded "><a href="arch/armv7.html"><strong aria-hidden="true">9.3.</strong> armv7</a></li><li class="chapter-item expanded "><a href="arch/riscv.html"><strong aria-hidden="true">9.4.</strong> riscv</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -1722,6 +1722,75 @@ define hook-quit
break-save quit
end
</code></pre>
+<h2 id="watchpoint-on-struct--class-member"><a class="header" href="#watchpoint-on-struct--class-member">Watchpoint on struct / class member</a></h2>
+<p>A symbolic watchpoint defined on a member variable for debugging is only valid
+as long as the expression is in scope. Once out of scope the watchpoint gets
+deleted.</p>
+<p>When debugging some memory corruption we want to keep the watchpoint even the
+expression goes out of scope to find the location that overrides the variable
+and introduces the corruption.</p>
+<pre><code class="language-markdown">(gdb) l
+1 struct S { int v; };
+2
+3 void set(struct S* s, int v) {
+4 s-&gt;v = v;
+5 }
+6
+7 int main() {
+8 struct S s;
+9 set(&amp;s, 1);
+10 set(&amp;s, 2);
+11 set(&amp;s, 3);
+...
+
+(gdb) s
+set (s=0x7fffffffe594, v=1) at test.c:4
+4 s-&gt;v = v;
+
+# Define a new watchpoint on the member of the struct. The expression however
+# is only valid in the current functions scope.
+
+(gdb) watch s-&gt;v
+Hardware watchpoint 2: s-&gt;v
+
+(gdb) c
+Hardware watchpoint 2: s-&gt;v
+Old value = 0
+New value = 1
+set (s=0x7fffffffe594, v=1) at test.c:5
+5 }
+
+# The watchpoint gets deleted as soon as we leave the function scope.
+
+(gdb) c
+Watchpoint 2 deleted because the program has left the block in
+which its expression is valid.
+main () at test.c:10
+10 set(&amp;s, 2);
+
+(gdb) p &amp;s-&gt;v
+$1 = (int *) 0x7fffffffe594
+
+# Define a watchpoint o the address of the member variable of the s instance.
+# This of course only makes sense as long as the s instance is not moved in memory.
+
+(gdb) watch *0x7fffffffe594
+Hardware watchpoint 3: *0x7fffffffe594
+
+(gdb) c
+Hardware watchpoint 3: *0x7fffffffe594
+Old value = 1
+New value = 2
+set (s=0x7fffffffe594, v=2) at test.c:5
+5 }
+
+(gdb) c
+Hardware watchpoint 3: *0x7fffffffe594
+Old value = 2
+New value = 3
+set (s=0x7fffffffe594, v=3) at test.c:5
+5 }
+</code></pre>
<h1 id="know-bugs"><a class="header" href="#know-bugs">Know Bugs</a></h1>
<h2 id="workaround-command--finish-bug"><a class="header" href="#workaround-command--finish-bug">Workaround <code>command + finish</code> bug</a></h2>
<p>When using <code>finish</code> inside a <code>command</code> block, commands after <code>finish</code> are not
@@ -2626,6 +2695,112 @@ int main() {
return 0;
}
</code></pre>
+<h2 id="example-minimal-templatized-test-registry"><a class="header" href="#example-minimal-templatized-test-registry">Example: Minimal templatized test registry</a></h2>
+<p>A small test function registry bringing together a few different template
+features.</p>
+<pre><code class="language-cpp">#include &lt;cstdio&gt;
+#include &lt;functional&gt;
+#include &lt;map&gt;
+#include &lt;string&gt;
+#include &lt;type_traits&gt;
+
+template&lt;typename R, typename... P&gt;
+struct registry {
+ using FUNC = R (*)(P...);
+ using SELF = registry&lt;R, P...&gt;;
+ using RET = R;
+
+ static SELF&amp; get() {
+ static SELF r;
+ return r;
+ }
+
+ bool add(std::string nm, FUNC fn) {
+ const auto r = m_fns.insert({std::move(nm), std::move(fn)});
+ return r.second;
+ }
+
+ R invoke(const std::string&amp; nm, P... p) const { return invoke_impl&lt;R&gt;(nm, p...); }
+
+ void dump() const {
+ for (const auto&amp; it : m_fns) {
+ std::puts(it.first.c_str());
+ }
+ }
+
+ private:
+ std::map&lt;std::string, FUNC&gt; m_fns;
+
+ template&lt;typename RET&gt;
+ std::enable_if_t&lt;std::is_same_v&lt;RET, void&gt;&gt; invoke_impl(const std::string&amp; nm, P... p) const {
+ const auto it = m_fns.find(nm);
+ if (it == m_fns.end()) {
+ return;
+ }
+ std::invoke(it-&gt;second, p...);
+ }
+
+ template&lt;typename RET&gt;
+ std::enable_if_t&lt;!std::is_same_v&lt;RET, void&gt;, RET&gt; invoke_impl(const std::string&amp; nm,
+ P... p) const {
+ const auto it = m_fns.find(nm);
+ if (it == m_fns.end()) {
+ static_assert(std::is_default_constructible_v&lt;RET&gt;,
+ &quot;RET must be default constructible&quot;);
+ return {};
+ }
+ return std::invoke(it-&gt;second, p...);
+ }
+};
+
+#define TEST_REGISTER(REGISTRY, NAME) \
+ static bool regfn_##REGISTRY##NAME() { \
+ const bool r = REGISTRY::get().add(#NAME, NAME); \
+ if (!r) { \
+ std::puts(&quot;Failed to register test &quot; #NAME &quot;, same name already registered!&quot;); \
+ std::abort(); \
+ } \
+ return r; \
+ } \
+ static const bool reg_##REGISTRY##NAME = regfn_##REGISTRY##NAME();
+
+#define TEST(REGISTRY, NAME, ...) \
+ REGISTRY::RET NAME(__VA_ARGS__); \
+ TEST_REGISTER(REGISTRY, NAME); \
+ REGISTRY::RET NAME(__VA_ARGS__)
+
+// -- Usage 1 simple usage.
+
+using REG1 = registry&lt;void&gt;;
+TEST(REG1, test1) {
+ std::puts(&quot;REG1::test1&quot;);
+}
+TEST(REG1, test2) {
+ std::puts(&quot;REG1::test2&quot;);
+}
+
+// -- Usage 2 with convenience macro wrapper.
+
+using REG2 = registry&lt;void, bool&gt;;
+#define TEST2(NAME, ...) TEST(REG2, NAME, ##__VA_ARGS__)
+
+TEST2(test1, bool val) {
+ printf(&quot;REG2::test1 val %d\n&quot;, val);
+}
+
+int main() {
+ const auto&amp; R1 = REG1::get();
+ R1.dump();
+ R1.invoke(&quot;test1&quot;);
+ R1.invoke(&quot;test2&quot;);
+
+ const auto&amp; R2 = REG2::get();
+ R2.dump();
+ R2.invoke(&quot;test1&quot;, true);
+
+ return 0;
+}
+</code></pre>
<h2 id="example-concepts-pre-c20"><a class="header" href="#example-concepts-pre-c20">Example: Concepts pre c++20</a></h2>
<p>Prior to c++20's concepts, <code>SFINAE</code> and <code>std::void_t</code> can be leveraged to build
something similar allowing to define an interface (aka trait) for a template
@@ -3304,6 +3479,7 @@ def sum(a: int, b: int) -&gt; int:
<li><a href="linux/./ptrace_scope.html">ptrace_scope</a></li>
<li><a href="linux/./cryptsetup.html">cryptsetup</a></li>
<li><a href="linux/./swap.html">swap</a></li>
+<li><a href="linux/./input.html">input</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="systemd"><a class="header" href="#systemd">systemd</a></h1>
<h2 id="systemctl"><a class="header" href="#systemctl">systemctl</a></h2>
@@ -3566,9 +3742,129 @@ For example as <code>systemd</code> service:</p>
<pre><code>systemctl status dphys-swapfile
</code></pre>
</blockquote>
+<div style="break-before: page; page-break-before: always;"></div><h1 id="linux-input"><a class="header" href="#linux-input">Linux input</a></h1>
+<p>Some notes on using <code>/dev/input/*</code> device driver files.</p>
+<h2 id="mousex--mice"><a class="header" href="#mousex--mice">mouseX / mice</a></h2>
+<p>These device files are created by the [mousedev] driver.</p>
+<ul>
+<li><code>/dev/input/mouseX</code> represents the input stream for a <em>SINGLE</em> mouse device.</li>
+<li><code>/dev/input/mice</code> represents the merged input stream for <em>ALL</em> mouse devices.</li>
+</ul>
+<p>The data stream consists of <code>3 bytes</code> per <code>event</code>. An event is encoded as <code>(BTN, X, Y)</code>.</p>
+<ul>
+<li><code>BTN</code> button pressed</li>
+<li><code>X</code> movement in x-direction <code>-1 -&gt; left</code> and <code>1 -&gt; right</code></li>
+<li><code>Y</code> movement in y-direction <code>-1 -&gt; down</code> and <code>1 -&gt; up</code></li>
+</ul>
+<p>The raw data stream can be inspected as follows.</p>
+<pre><code class="language-bash">sudo cat /dev/input/mice | od -tx1 -w3 -v
+</code></pre>
+<h2 id="eventx"><a class="header" href="#eventx">eventX</a></h2>
+<p>These device files are created by the [evdev] driver.</p>
+<ul>
+<li><code>/dev/input/eventX</code> represents the generic input event interface a <em>SINGLE</em> input deivece.</li>
+</ul>
+<p>Input events are encoded as given by the <code>input_event</code> struct below. Reading
+from the <code>eventX</code> device file will always yield whole number of input events.</p>
+<pre><code class="language-c">struct input_event {
+ struct timeval time;
+ unsigned short type;
+ unsigned short code;
+ unsigned int value;
+};
+</code></pre>
+<p>On most 64bit machines the raw data stream can be inspected as follows.</p>
+<pre><code class="language-bash">sudo cat /dev/input/event4 | od -tx1 -w24 -v
+</code></pre>
+<h2 id="identifyin-device-files"><a class="header" href="#identifyin-device-files">Identifyin device files.</a></h2>
+<p>To find out which device file is assigned to which input device the following
+file <code>/proc/bus/input/devices</code> in the proc filesystem can be consulted.</p>
+<p>This yields entries as follows and shows which <code>Handlers</code> are assigned to which
+<code>Name</code>.</p>
+<pre><code>I: Bus=0018 Vendor=04f3 Product=0033 Version=0000
+N: Name=&quot;Elan Touchpad&quot;
+...
+H: Handlers=event15 mouse0
+...
+</code></pre>
+<h2 id="example-toying-with-devinputeventx"><a class="header" href="#example-toying-with-devinputeventx">Example: Toying with <code>/dev/input/eventX</code></a></h2>
+<p>Once compiled, the example should be run as <code>sudo ./event /dev/input/eventX</code>.</p>
+<pre><code class="language-c">#include &lt;stdio.h&gt;
+#include &lt;fcntl.h&gt;
+#include &lt;assert.h&gt;
+#include &lt;unistd.h&gt;
+#include &lt;time.h&gt;
+
+#include &lt;sys/time.h&gt;
+#include &lt;linux/input-event-codes.h&gt;
+
+struct input_event {
+ struct timeval time;
+ unsigned short type;
+ unsigned short code;
+ unsigned int value;
+};
+
+const char* type(unsigned short t) {
+ static char buf[32];
+ const char* fmt = &quot;0x%x&quot;;
+ switch (t) {
+#define FMT(TYPE) case TYPE: fmt = #TYPE&quot;(0x%x)&quot;; break
+ FMT(EV_SYN);
+ FMT(EV_KEY);
+ FMT(EV_REL);
+ FMT(EV_ABS);
+#undef FMT
+ }
+ snprintf(buf, sizeof(buf), fmt, t);
+ return buf;
+}
+
+const char* code(unsigned short c) {
+ static char buf[32];
+ const char* fmt = &quot;0x%x&quot;;
+ switch (c) {
+#define FMT(CODE) case CODE: fmt = #CODE&quot;(0x%x)&quot;; break
+ FMT(BTN_LEFT);
+ FMT(BTN_RIGHT);
+ FMT(BTN_MIDDLE);
+ FMT(REL_X);
+ FMT(REL_Y);
+#undef FMT
+ }
+ snprintf(buf, sizeof(buf), fmt, c);
+ return buf;
+}
+
+const char* timefmt(const struct timeval* t) {
+ assert(t);
+ struct tm* lt = localtime(&amp;t-&gt;tv_sec); // Returns pointer to static tm object.
+ static char buf[64];
+ strftime(buf, sizeof(buf), &quot;%H:%M:%S&quot;, lt);
+ return buf;
+}
+
+int main(int argc, char* argv[]) {
+ assert(argc == 2);
+
+ int fd = open(argv[1], O_RDONLY);
+ assert(fd != -1);
+
+ struct input_event inp;
+ while (1) {
+ int ret = read(fd, &amp;inp, sizeof(inp));
+ assert(ret == sizeof(inp));
+ printf(&quot;time: %s type: %s code: %s value: 0x%x\n&quot;,
+ timefmt(&amp;inp.time), type(inp.type), code(inp.code), inp.value);
+ }
+}
+</code></pre>
+<p>[mousedev]: TODO /home/johannst/dev/linux/drivers/input/mousedev.c
+[evdev]: TODO /home/johannst/dev/linux/drivers/input/evdev.c</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="network-1"><a class="header" href="#network-1">Network</a></h1>
<ul>
<li><a href="network/./tcpdump.html">tcpdump</a></li>
+<li><a href="network/./firewall-cmd.html">firewall-cmd</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="tcpdump1"><a class="header" href="#tcpdump1">tcpdump(1)</a></h1>
<h1 id="cli-3"><a class="header" href="#cli-3">CLI</a></h1>
@@ -3593,9 +3889,42 @@ tcp/udp/icmp Filter for protocol.
<pre><code class="language-makrdown"># -k: Start capturing immediately.
ssh &lt;host&gt; tcpdump -i &lt;IF&gt; -w - | sudo wireshark -k -i -
</code></pre>
+<div style="break-before: page; page-break-before: always;"></div><h1 id="firewall-cmd1"><a class="header" href="#firewall-cmd1">firewall-cmd(1)</a></h1>
+<p>Command line interface to the <a href="https://firewalld.org/documentation/man-pages/firewalld.html">firewalld(1)</a> daemon.</p>
+<h2 id="list-current-status-of-the-firewall"><a class="header" href="#list-current-status-of-the-firewall">List current status of the firewall</a></h2>
+<pre><code class="language-sh"># List all services and ports for all zones.
+firewall-cmd --list-all
+# List all services.
+firewall-cmd --list-services
+# List all ports.
+firewall-cmd --list-ports
+</code></pre>
+<blockquote>
+<p>Add <code>--zone &lt;ZONE&gt;</code> to limit output to a given <code>ZONE</code>. Use <code>--get-zones</code> to
+see all available zones.</p>
+</blockquote>
+<h2 id="add-entries"><a class="header" href="#add-entries">Add entries</a></h2>
+<pre><code class="language-sh"># Add a service to the firewall, use `--get-services` to list all available
+# service names.
+firewall-cmd --add-service &lt;SERVICE&gt;
+# Add a specific port.
+firewall-cmd --add-port 8000/tcp
+</code></pre>
+<h2 id="remove-entries"><a class="header" href="#remove-entries">Remove entries</a></h2>
+<pre><code class="language-sh"># Remove service.
+firewall-cmd --remove-service &lt;SERVICE&gt;
+# Remove port.
+firewall-cmd --remove-port 8000/tcp
+</code></pre>
+<h2 id="references-4"><a class="header" href="#references-4">References</a></h2>
+<ul>
+<li>man <a href="https://firewalld.org/documentation/man-pages/firewall-cmd.html">firewall-cmd(1)</a></li>
+<li>man <a href="https://firewalld.org/documentation/man-pages/firewalld.html">firewalld(1)</a></li>
+</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="web"><a class="header" href="#web">Web</a></h1>
<ul>
<li><a href="web/./html.html">html</a></li>
+<li><a href="web/./chartjs.html">chartjs</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="html"><a class="header" href="#html">html</a></h1>
<h2 id="collapsible-element"><a class="header" href="#collapsible-element">Collapsible element</a></h2>
@@ -3694,6 +4023,142 @@ p {
&lt;/div&gt;
</code></pre>
+<h1 id="minimal-tabs"><a class="header" href="#minimal-tabs">Minimal tabs</a></h1>
+<p><a href="web/src/tabs.html">Rendered html</a></p>
+<pre><code class="language-html">&lt;script&gt;
+const showTab = (E, T) =&gt; {
+ const TABS = Array.from(document.getElementsByClassName(&quot;content&quot;));
+ TABS.forEach(T =&gt; {
+ T.style.display = &quot;none&quot;;
+ });
+
+ document.getElementById(T).style.display = &quot;block&quot;;
+};
+
+window.onload = () =&gt; {
+ document.getElementById(&quot;bTab1&quot;).onclick = (E) =&gt; {
+ showTab(E, &quot;tTab1&quot;);
+ };
+ document.getElementById(&quot;bTab2&quot;).onclick = (E) =&gt; {
+ showTab(E, &quot;tTab2&quot;);
+ };
+}
+&lt;/script&gt;
+
+&lt;button type=&quot;button&quot; id=&quot;bTab1&quot;&gt;Tab1&lt;/button&gt;
+&lt;button type=&quot;button&quot; id=&quot;bTab2&quot;&gt;Tab2&lt;/button&gt;
+
+&lt;div id=&quot;tTab1&quot; class=&quot;content&quot; style=&quot;display: block;&quot;&gt;
+ &lt;p&gt;Some content goes here ...&lt;/p&gt;
+&lt;/div&gt;
+
+&lt;div id=&quot;tTab2&quot; class=&quot;content&quot; style=&quot;display: none;&quot;&gt;
+ &lt;p&gt;... and there.&lt;/p&gt;
+&lt;/div&gt;
+</code></pre>
+<div style="break-before: page; page-break-before: always;"></div><h1 id="chartjs"><a class="header" href="#chartjs">Chart.js</a></h1>
+<h2 id="minimal-example-with-external-tooltips"><a class="header" href="#minimal-example-with-external-tooltips">Minimal example with <em>external</em> tooltips</a></h2>
+<p><a href="web/src/chartjs-ext-tooltip.html">Rendered html</a></p>
+<pre><code class="language-html">&lt;canvas id=&quot;myChart&quot; style=&quot;margin:5em;&quot;&gt;&lt;/canvas&gt;
+
+&lt;script&gt;
+const get_or_create_tooltip = (id) =&gt; {
+ if (tooltip = document.getElementById(id)) {
+ return tooltip;
+ } else {
+ // -- Create a new Tooltip element.
+ const tooltip = document.createElement('div');
+ tooltip.id = id;
+ document.body.appendChild(tooltip);
+
+ // -- Some minimal styling.
+ tooltip.style.background = 'rgba(0, 0, 0, 0.1)';
+ tooltip.style.position = 'absolute';
+ tooltip.style.transition = 'all .2s ease';
+
+ // -- Add a table element for the tooltip content.
+ const table = document.createElement('table');
+ tooltip.appendChild(table);
+
+ return tooltip
+ }
+}
+
+const render_tooltip = (context) =&gt; {
+ const {chart, tooltip} = context;
+
+ // -- Get Tooltip element.
+ const tooltip_elem = get_or_create_tooltip('myTooltip');
+
+ // -- Get data point values (only one data point).
+ const {label: x, formattedValue: y} = tooltip.dataPoints[0];
+
+ // -- Format new tooltip.
+ const link = document.createElement('a');
+ link.href = &quot;https://github.com/johannst&quot;;
+ link.innerHTML = &quot;X:&quot; + x + &quot; Y:&quot; + y;
+
+ // -- Remove previous child element and add new one.
+ const table = tooltip_elem.querySelector('table');
+ table.innerHTML = &quot;&quot;;
+ table.appendChild(link);
+
+ // -- Get absolute X/Y position of the top left corner of the canvas.
+ const {offsetLeft: canvas_x, offsetTop: canvas_y} = chart.canvas;
+
+ // -- Set position and minimal style for the tooltip.
+ tooltip_elem.style.left = canvas_x + tooltip.caretX + 'px';
+ tooltip_elem.style.top = canvas_y + tooltip.caretY + 'px';
+ tooltip_elem.style.font = tooltip.options.bodyFont.string;
+
+ // -- Place the tooltip (I) left or (II) right of the data point.
+ if (tooltip.xAlign === &quot;right&quot;) {
+ tooltip_elem.style.transform = 'translate(-100%, 0)'; // (I)
+ } else if (tooltip.xAlign === &quot;left&quot;) {
+ tooltip_elem.style.transform = 'translate(0%, 0)'; // (II)
+ }
+}
+
+// -- Render a chart with some dummy data on the canvas.
+const chart = new Chart(
+ document.getElementById('myChart'),
+ {
+ data: {
+ datasets: [{
+ // -- A single dataset.
+ label: 'Just some values',
+ type: 'scatter',
+ data: [
+ {x: 4, y: 4},
+ {x: 5, y: 1},
+ {x: 7, y: 6},
+ {x: 10, y: 8},
+ {x: 10, y: 7},
+ {x: 10, y: 3},
+ ],
+ backgroundColor: 'rgba(255, 99, 132, 0.5)',
+ borderColor: 'rgb(255, 99, 132)',
+ }],
+ },
+ options: {
+ scales: {
+ y: {
+ beginAtZero: true, // -- Start the Y-Axis at zero instead min(y) of dataset.
+ }
+ },
+ plugins: {
+ tooltip: {
+ enabled: false, // -- Disable builtin tooltips.
+ mode: 'nearest', // -- Get the item that is nearest to the mouse.
+ intersect: false, // -- 'mode' is active also when the mouse doesnt intersect with an item on the chart.
+ external: render_tooltip, // -- External tooltip handler, allows to create own HTML.
+ }
+ }
+ }
+ }
+);
+&lt;/script&gt;
+</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="arch"><a class="header" href="#arch">Arch</a></h1>
<ul>
<li><a href="arch/./x86_64.html">x86_64</a></li>
@@ -3954,7 +4419,7 @@ greeting_len:
<pre><code class="language-bash">&gt; gcc -o greet greet.s -nostartfiles -nostdlib &amp;&amp; ./greet
Hi ASM-World!
</code></pre>
-<h2 id="references-4"><a class="header" href="#references-4">References</a></h2>
+<h2 id="references-5"><a class="header" href="#references-5">References</a></h2>
<ul>
<li><a href="https://www.uclibc.org/docs/psABI-x86_64.pdf">SystemV AMD64 ABI</a></li>
<li><a href="https://www.amd.com/system/files/TechDocs/24592.pdf">AMD64 Vol1: Application Programming</a></li>
@@ -4183,7 +4648,7 @@ Hi ASM-World!
distributions. Explicitly specifying the dynamic linker should not be
required when compiling natively on arm64.</p>
</blockquote>
-<h2 id="references-5"><a class="header" href="#references-5">References</a></h2>
+<h2 id="references-6"><a class="header" href="#references-6">References</a></h2>
<ul>
<li><a href="https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst">Procedure Call Standard ARM64</a></li>
<li><a href="https://developer.arm.com/documentation/den0024/latest">ARMv8-A Programmer's Guide</a></li>
@@ -4427,7 +4892,7 @@ Hi ASM-World!
distributions. Explicitly specifying the dynamic linker should not be
required when compiling natively on arm.</p>
</blockquote>
-<h2 id="references-6"><a class="header" href="#references-6">References</a></h2>
+<h2 id="references-7"><a class="header" href="#references-7">References</a></h2>
<ul>
<li><a href="https://github.com/ARM-software/abi-aa/blob/master/aapcs32/aapcs32.rst">Procedure Call Standard ARM</a></li>
<li><a href="https://developer.arm.com/documentation/den0013/latest">ARMv7-A Programmer's Guide</a></li>
@@ -4508,7 +4973,7 @@ distributions. Explicitly specifying the dynamic linker should not be
required when compiling natively on riscv.</p>
<p>Select dynamic linker according to abi used during compile &amp; link.</p>
</blockquote>
-<h2 id="references-7"><a class="header" href="#references-7">References</a></h2>
+<h2 id="references-8"><a class="header" href="#references-8">References</a></h2>
<ul>
<li><a href="https://sourceware.org/binutils/docs/as">GNU Assembler</a></li>
<li><a href="https://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops">GNU Assembler Directives</a></li>