aboutsummaryrefslogtreecommitdiffhomepage
path: root/print.html
diff options
context:
space:
mode:
Diffstat (limited to 'print.html')
-rw-r--r--print.html619
1 files changed, 591 insertions, 28 deletions
diff --git a/print.html b/print.html
index 28df4d6..2d17d9e 100644
--- a/print.html
+++ b/print.html
@@ -32,10 +32,11 @@
<!-- Custom theme stylesheets -->
- <!-- Provide site root to javascript -->
+ <!-- Provide site root and default themes to javascript -->
<script>
- var path_to_root = "";
- var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
+ const path_to_root = "";
+ const default_light_theme = "light";
+ const default_dark_theme = "navy";
</script>
<!-- Start loading toc.js asap -->
<script src="toc.js"></script>
@@ -45,8 +46,8 @@
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
- var theme = localStorage.getItem('mdbook-theme');
- var sidebar = localStorage.getItem('mdbook-sidebar');
+ let theme = localStorage.getItem('mdbook-theme');
+ let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
@@ -60,7 +61,8 @@
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
- var theme;
+ const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
+ let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
@@ -73,8 +75,8 @@
<!-- Hide / unhide sidebar before it is displayed -->
<script>
- var sidebar = null;
- var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
+ let sidebar = null;
+ const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
@@ -110,6 +112,7 @@
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
+ <li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
@@ -1426,7 +1429,7 @@ eval strace -f (find /dev -name 'std*' | xargs -I {} echo -P {}) ls
# eval strace -f -P /dev/stdin -P /dev/stdout -P /dev/stderr ls
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="grep1"><a class="header" href="#grep1">grep(1)</a></h1>
-<pre><code>sort [opts] [pattern] [files]
+<pre><code>grep [opts] [pattern] [files]
-e &lt;pattern&gt; pattern to search for (can be supplied multiple times)
-i ignore case in patterns
-v invert match
@@ -2829,6 +2832,7 @@ renice -n 5 -p PID
<li><a href="trace_profile/./callgrind.html">callgrind</a></li>
<li><a href="trace_profile/./valgrind.html">valgrind</a></li>
<li><a href="trace_profile/./vtune.html">vtune</a></li>
+<li><a href="trace_profile/./tracy.html">tracy</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="usrbintime1"><a class="header" href="#usrbintime1">/usr/bin/time(1)</a></h1>
<pre><code class="language-markdown"># statistics of process run
@@ -3276,6 +3280,231 @@ main: main.c
vtune: main
$(VTUNE)/bin64/vtune -collect hotspots -start-paused -- ./main
</code></pre>
+<div style="break-before: page; page-break-before: always;"></div><h1 id="tracy1"><a class="header" href="#tracy1">tracy(1)</a></h1>
+<p><a href="https://github.com/wolfpld/tracy">Tracy</a> is a frame profiler, supporting manual code instrumentation
+and providing a sampling profiler.</p>
+<p>One can either record and visualize the profiling data live using
+<code>tracy-profiler</code> or record the profiling data to a file using <code>tracy-capture</code>.</p>
+<pre><code>tracy-profiler [file] [-p port]
+
+tracy-capture -o file [-f] [-p port]
+ -f overwrite &lt;file&gt; if it exists
+</code></pre>
+<h2 id="example-7"><a class="header" href="#example-7">Example</a></h2>
+<p>The example showcases different cases:</p>
+<ol>
+<li>Use tracy from a single binary. In that case the <code>TracyClient.cpp</code> can be
+directly linked / included in the instrumented binary.</li>
+<li>Use tracy from different binaries (eg main executable + shared library). In
+this case the <code>TracyClient.cpp</code> should be compiled into its own shared
+library, such that there is a single tracy client.</li>
+<li>Use tracy from different binaries on windows. In this case the
+<code>TracyClient.cpp</code> must be compiled again into a separate shared library,
+while defining <code>TRACY_EXPORTS</code>. The code being instrumented must be compiled
+with <code>TRACY_IMPORTS</code> defined.</li>
+</ol>
+<p>An instrumented <code>c++</code> example:</p>
+<pre><code class="language-cpp">#include &lt;chrono&gt;
+#include &lt;thread&gt;
+
+#include &lt;tracy/Tracy.hpp&gt;
+
+#ifdef USE_FOO
+extern "C" void foo_comp_hook(int64_t);
+#endif
+
+void init() {
+ // Create a named zone (active for the current scope).
+ // Name will be used when rendering the zone in the thread timeline.
+ ZoneScopedN("init()");
+ // Set explicit color for the rendered zone.
+ ZoneColor(0xff0000);
+
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+}
+
+void comp(const char* name) {
+ // Track call count.
+ static int64_t ccnt = 0;
+ ccnt += 1;
+
+ // Create an unnamed zone for the current scope.
+ ZoneScoped;
+ // Name the zone by formatting the name dynamically.
+ // This name is shown for the zone in the thread timeline, however
+ // in the zone statistics they are all accounted under one common
+ // zone "comp".
+ ZoneNameF("comp(%s)", name);
+ // Additional text to attach to the zone.
+ ZoneTextF("text(%s)", name);
+ // Additional value to attach to the zone measurement.
+ ZoneValue(ccnt);
+
+ // Statistics for dynamic names, text and values can be looked at in the zone
+ // statistics.There measurements can be grouped by different categories.
+
+ // Add a simple plot.
+ TracyPlot("comp-plot", ccnt % 4);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+#ifdef USE_FOO
+ foo_comp_hook(ccnt);
+#endif
+}
+
+void post_comp() {
+ // Create an unnamed zone for the current scope and capture callstack (max
+ // depth 10). Capturing callstack requires platform with TRACY_HAS_CALLSTACK
+ // support.
+ ZoneScopedS(10);
+ // Name the zone, w/o formatting.
+ const char name[] = "post_comp()";
+ ZoneName(name, sizeof(name));
+
+ // Add trace messages to the timeline.
+ TracyMessageL("start sleep in post_comp()");
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ TracyMessageL("end sleep in post_comp()");
+}
+
+void fini() {
+ // Create a named zone with an explicit color.
+ ZoneScopedNC("fini()", 0x00ff00);
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+}
+
+int main() {
+ // Create a named zone.
+ ZoneScopedN("main()");
+
+ init();
+
+ int step = 0;
+ while (step++ &lt; 10) {
+ // Create a frame message, this start a new frame with the name
+ // "step" and end the previous frame with the name "step".
+ FrameMarkNamed("step");
+ // Create a named scope.
+ ZoneScopedN("step()");
+ comp("a");
+ comp("b");
+ comp("c");
+ post_comp();
+ }
+
+ fini();
+}
+</code></pre>
+<p>An instrumented <code>c</code> example:</p>
+<pre><code class="language-c">#include &lt;stdint.h&gt;
+#include &lt;inttypes.h&gt;
+#include &lt;stdio.h&gt;
+
+#include &lt;tracy/TracyC.h&gt;
+
+static void comp_helper(int64_t i) {
+ char buf[64];
+ int cnt = snprintf(buf, sizeof(buf), "helper(%" PRId64 ")", i);
+
+ // Create an active unnamed zone.
+ TracyCZone(ctx, 1);
+
+ // Name the zone.
+ TracyCZoneName(ctx, buf, cnt);
+ // Add custom text to the zone measurement.
+ TracyCZoneText(ctx, buf, cnt);
+ // Add custom value to the zone measurement.
+ TracyCZoneValue(ctx, i);
+
+ for (int ii = 0; ii &lt; i * 100000; ++ii) {
+ /* fake work */
+ }
+
+ // End the zone measurement.
+ TracyCZoneEnd(ctx);
+}
+
+void foo_comp_hook(int64_t cnt) {
+ // Create an active named zone.
+ TracyCZoneN(ctx, "foo", 1);
+
+ for (int i = 0; i &lt; cnt; ++i) {
+ // Plot value.
+ TracyCPlot("foo_comp_hook", cnt + i);
+
+ comp_helper(i);
+ }
+
+ // Configure plot "foo", probably best done once during initialization..
+ TracyCPlotConfig("foo", TracyPlotFormatNumber, 1 /* step */, 1 /* fill */,
+ 0xff0000);
+ // Plot value.
+ TracyCPlot("foo", cnt);
+
+ // End the zone measurement.
+ TracyCZoneEnd(ctx);
+}
+</code></pre>
+<p>Raw build commands to demonstrate compiling tracy w/o <code>cmake</code>, in case we need
+to integrate it into a different build system.</p>
+<pre><code class="language-makefile">B := BUILD
+
+main: $(B)/main-static $(B)/main-dynamic $(B)/main-dynamic-win
+tracy: $(B)/tracy
+.PHONY: main tracy
+
+# -- TRACY STATIC ---------------------------------------------------------------
+
+$(B)/main-static: main.cpp | $(B)
+ clang++ -DTRACY_ENABLE -I$(B)/tracy/public -o $@ $^ $(B)/tracy/public/TracyClient.cpp
+
+# -- TRACY DYNAMIC --------------------------------------------------------------
+
+$(B)/main-dynamic: main.cpp $(B)/foo.so $(B)/TracyClient.so | $(B)
+ clang++ -DTRACY_ENABLE -I$(B)/tracy/public -DUSE_FOO -o $@ $^
+
+$(B)/foo.so: foo.c $(B)/TracyClient.so
+ clang -DTRACY_ENABLE -I$(B)/tracy/public -fPIC -shared -o $@ $^
+
+$(B)/TracyClient.so: $(B)/tracy/public/TracyClient.cpp
+ clang++ -DTRACY_ENABLE -I$(B)/tracy/public -fPIC -shared -o $@ $^
+
+# -- TRACY DYNAMIC WINDOWS ------------------------------------------------------
+
+$(B)/main-dynamic-win: main.cpp $(B)/foo.dll $(B)/TracyClient.dll
+ @# eg run with wine
+ zig c++ -target x86_64-windows -DTRACY_ENABLE -DTRACY_IMPORTS -DUSE_FOO -o $@ $^ -I $(B)/tracy/public
+
+$(B)/foo.dll: foo.c $(B)/TracyClient.dll
+ zig c++ -target x86_64-windows -DTRACY_ENABLE -DTRACY_IMPORTS -fPIC -shared -o $@ $^ -I $(B)/tracy/public
+
+$(B)/TracyClient.dll: $(B)/tracy/public/TracyClient.cpp
+ @# win libs from 'pragma comment(lib, ..)'
+ zig c++ -target x86_64-windows -DTRACY_ENABLE -DTRACY_EXPORTS -fPIC -shared -o $@ $^ -lws2_32 -ldbghelp -ladvapi32 -luser32
+
+# -- TRACY ----------------------------------------------------------------------
+
+# Get latest tracy and build profiler.
+$(B)/tracy: $(B)
+ cd $(B); bash $(CURDIR)/get-tracy.sh
+.PHONY: $(B)/tracy
+
+$B:
+ mkdir -p $(B)
+.PHONY: $(B)
+
+# -- CLEAN ----------------------------------------------------------------------
+
+clean:
+ $(RM) $(B)/*.so $(B)/*.dll $(B)/*.pdb $(B)/*.lib $(B)/main*
+
+distclean:
+ rm -rf $(B)
+</code></pre>
+<blockquote>
+<p>Find <code>get-tracy.sh</code> <a href="https://github.com/johannst/notes/blob/master/src/trace_profile/tracy/get-tracy.sh">here</a>.</p>
+</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h1 id="debug-1"><a class="header" href="#debug-1">Debug</a></h1>
<ul>
<li><a href="debug/./gdb.html">gdb</a></li>
@@ -3774,7 +4003,7 @@ $MOOSE=moose
host:port
tty
</code></pre>
-<h2 id="example-7"><a class="header" href="#example-7">Example</a></h2>
+<h2 id="example-8"><a class="header" href="#example-8">Example</a></h2>
<pre><code class="language-markdown"># Start gdbserver.
gdbserver localhost:1234 /bin/ls
@@ -3941,6 +4170,8 @@ objdump -C --disassemble=foo::bar &lt;bin&gt;
<li><a href="development/./c++.html">c++</a></li>
<li><a href="development/./glibc.html">glibc</a></li>
<li><a href="development/./gcc.html">gcc</a></li>
+<li><a href="development/./gas.html">gas</a></li>
+<li><a href="development/./ld.html">ld</a></li>
<li><a href="development/./git.html">git</a></li>
<li><a href="development/./cmake.html">cmake</a></li>
<li><a href="development/./make.html">make</a></li>
@@ -5015,6 +5246,287 @@ run1:
<li>C ABI (x86_64) - <a href="https://gitlab.com/x86-psABIs/x86-64-ABI">SystemV ABI</a></li>
<li>C++ ABI - <a href="https://itanium-cxx-abi.github.io/cxx-abi">C++ Itanium ABI</a></li>
</ul>
+<div style="break-before: page; page-break-before: always;"></div><h1 id="gas"><a class="header" href="#gas">gas</a></h1>
+<h2 id="frequently-used-directives"><a class="header" href="#frequently-used-directives">Frequently used directives</a></h2>
+<ul>
+<li><code>.section</code> to define a section (elf files)
+<pre><code class="language-x86asm">.section .text.foo, "ax", @progbits
+; defines section named .text.foo with alloc+exec perms
+
+.section .data.foo, "aw", @progbits
+; defines section named .data.foo with alloc+write perms
+
+.section .rodata.foo, "a", @progbits
+; defines section named .rodata.foo with alloc perms
+</code></pre>
+</li>
+<li><code>.byte</code>, <code>.2byte</code>, <code>.4byte</code>, <code>.8byte</code> to define a N byte value
+<pre><code class="language-x86asm">.byte 0xaa
+.2byte 0xaabb
+.2byte 0xaa, 0xbb
+.4byte 0xaabbccdd
+.8byte 0xaabbccdd11223344
+</code></pre>
+</li>
+<li><code>.ascii</code> to define an ascii string
+<pre><code class="language-x86asm">.ascii "foo" ; allocates 3 bytes
+</code></pre>
+</li>
+<li><code>.asciz</code> to define an ascii string with <code>'\0'</code> terminator
+<pre><code class="language-x86asm">.asciz "foo" ; allocates 4 bytes (str + \0)
+</code></pre>
+</li>
+<li><code>.macro</code> to define assembler macros. Arguments are accessed with the
+<code>\arg</code> syntax.
+<pre><code class="language-x86asm">.macro defstr name str
+\name:
+ .ascii "\str"
+\name\()_len:
+ .8byte . - \name
+.endm
+
+; use as
+defstr foo, "foobar"
+</code></pre>
+<blockquote>
+<p>Use <code>\()</code> to concatenate macro argument and literal.</p>
+</blockquote>
+</li>
+<li><code>.rept</code> to repeat a sequence of lines between <code>.rept</code> and <code>.endr</code>.
+<pre><code class="language-x86asm">.rept 4
+.4byte 123
+.endr
+</code></pre>
+</li>
+<li><code>.fill cnt, elem_size, val</code> write <code>cnt</code> times <code>val</code> with element size <code>elem_size</code>. For example one can use it to create a mbr boot record (magic number 0xaa55 at byte 511, 512).
+<pre><code class="language-x86asm">.section .boot, "ax", @progbits
+; some code ..
+.4byte 0xff
+
+.fill 510 - (. - .boot), 1, 0x00
+.2byte 0xaa55
+
+; as foo.s &amp;&amp; objdump -j .boot -s
+; Contents of section .boot:
+; 0000 ff000000 00000000 00000000 00000000
+; ..
+; 01f0 00000000 00000000 00000000 000055aa
+</code></pre>
+<blockquote>
+<p>Here <code>.</code> stands for the current location counter.</p>
+</blockquote>
+</li>
+</ul>
+<h2 id="references-4"><a class="header" href="#references-4">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>
+<li><a href="https://sourceware.org/binutils/docs/as/i386_002dDependent.html">GNU Assembler <code>x86_64</code> dependent features</a></li>
+</ul>
+<div style="break-before: page; page-break-before: always;"></div><h1 id="ld1"><a class="header" href="#ld1">ld(1)</a></h1>
+<pre><code>ld [opts] files...
+ -T &lt;script&gt; use &lt;script&gt; as linker script
+ --trace report each file the linker touches
+ --start-group archives --end-group
+ search archives repearepeatedly until no new
+ undefined references are created
+ (eg helpfull with list of static libraries)
+</code></pre>
+<h2 id="linker-script"><a class="header" href="#linker-script">Linker Script</a></h2>
+<p><code>output</code> sections are defined as follows (full description at <a href="https://sourceware.org/binutils/docs/ld/Output-Section-Attributes.html">output
+section</a> and <a href="https://sourceware.org/binutils/docs/ld/Input-Section.html">input section</a>).</p>
+<pre><code>section_name [vaddr] : [AT(paddr)] {
+ file_pattern (section_pattern)
+}
+</code></pre>
+<p>The following gives an example of an <code>output</code> section with two <code>input</code> section rules.</p>
+<pre><code>.foo : {
+ abc.o (.foo)
+ *.o (.foo.*)
+}
+</code></pre>
+<h3 id="example-virtual-vs-physical-load-address"><a class="header" href="#example-virtual-vs-physical-load-address">Example: virtual vs physical (load) address</a></h3>
+<p>Sometimes code is initially located at a different location as when being run.
+For example in embedded cases, where code may initially resides in a <em>rom</em> and
+startup code will copy a section with writable <em>data</em> into <em>ram</em>. Code accessing
+the writable data accesses the data in the <em>ram</em>.</p>
+<p>In this case we need different addresses for the same data.</p>
+<ul>
+<li>The <code>virtual</code> or <em>runtime</em> address, this is the address used when the linker
+resolves accesses to the data. Hence, this is the address the data will have
+when the code is running.</li>
+<li>The <code>physical</code> or <em>load</em> address, this is the address the data is stored at
+initially. Startup code typically copies the initial values from the
+<code>physical</code> to the <code>virtual</code> address.</li>
+</ul>
+<p>The following shows an example linker script which uses <em>virtual</em> and <em>physical</em>
+addresses. The full source files can be found <a href="https://github.com/johannst/notes/tree/master/src/development/ld">here</a>.</p>
+<pre><code>OUTPUT_FORMAT(elf64-x86-64)
+ENTRY(_entry)
+
+SECTIONS {
+ /* Set the initial location counter (vaddr) */
+ . = 0x00800000;
+
+ /* Create .text output section at current vaddr */
+ .text : {
+ *(.text*)
+ }
+
+ ASSERT(. == 0x00800000 + SIZEOF(.text), "inc loc counter automatically")
+
+ /* Create .data section at location counter aligned to the next 0x100 (vaddr) */
+ /* Set the load address to 0x00100000 (paddr) */
+ .data ALIGN(0x100) : AT(0x00100000) {
+ HIDDEN(_data_vaddr = .);
+ HIDDEN(_data_paddr = LOADADDR(.data));
+ *(.data*)
+ }
+
+ /* Create .rodata with explicit vaddr */
+ /* Re-adjust the paddr location counter */
+ .rodata 0x00804000 : AT(ADDR(.rodata)) {
+ *(.rodata*)
+ }
+
+ ASSERT(. == 0x00804000 + SIZEOF(.rodata), "inc loc counter automatically")
+
+ .stack ALIGN (0x1000) : {
+ . += 0x1000;
+ HIDDEN(_stack_top = .);
+ }
+
+ /DISCARD/ : {
+ *(.*)
+ }
+}
+
+/* Some example assertions */
+ASSERT(ADDR(.data) != LOADADDR(.data), "DATA vaddr and paddr must be different")
+ASSERT(SIZEOF(.stack) == 0x1000, "STACK section must be 0x1000")
+</code></pre>
+<p>We can use the following assembly snippet to explore the linker script.</p>
+<pre><code class="language-x86asm">.section .text, "ax", @progbits
+.global _entry
+_entry:
+ mov $_stack_top, %rsp
+ mov $asm_array, %rax
+ mov (asm_len), %eax
+
+ hlt
+ jmp _entry
+
+.section .data.asm, "aw", @progbits
+asm_array:
+ .4byte 0xa
+ .4byte 0xb
+ .4byte 0xc
+ .4byte 0xd
+.rept 4
+ .4byte 0xff
+.endr
+
+.section .rodata.asm, "a", @progbits
+asm_len:
+ .4byte 8
+</code></pre>
+<blockquote>
+<p><code>gcc -c data.S &amp;&amp; ld -o link-nomem -T link-nomem.ld data.o</code></p>
+</blockquote>
+<p>The elf load segments show the difference in <em>physical</em> and <em>virtual</em> address
+for the segment containing the <code>.data</code> section.</p>
+<pre><code class="language-sh">&gt; readelf -W -l link-nomem
+# There are 4 program headers, starting at offset 64
+#
+# Program Headers:
+# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+# LOAD 0x001100 0x0000000000800100 0x0000000000100000 0x000020 0x000020 RW 0x1000
+# LOAD 0x002000 0x0000000000800000 0x0000000000800000 0x000018 0x000018 R E 0x1000
+# LOAD 0x003000 0x0000000000804000 0x0000000000804000 0x000004 0x000004 R 0x1000
+# LOAD 0x000000 0x0000000000805000 0x0000000000805000 0x000000 0x001000 RW 0x1000
+#
+# Section to Segment mapping:
+# Segment Sections...
+# 00 .data
+# 01 .text
+# 02 .rodata
+# 03 .stack
+</code></pre>
+<p>Startup code could copy data from <code>_data_paddr</code> to <code>_data_vaddr</code>.</p>
+<pre><code class="language-sh">&gt; nm link-nomem
+# 0000000000800100 d asm_array
+# 0000000000804000 r asm_len
+# 0000000000100000 a _data_paddr
+# 0000000000800100 d _data_vaddr
+# 0000000000800000 T _entry
+# 0000000000806000 b _stack_top
+</code></pre>
+<p>The linker resolves symbols to their <em>virtual</em> address, this can be seen by the
+access to the <code>asm_array</code> variable.</p>
+<pre><code class="language-sh">&gt; objdump -d link-nomem
+# Disassembly of section .text:
+#
+# 0000000000800000 &lt;_entry&gt;:
+# 800000: 48 c7 c4 00 60 80 00 mov $0x806000,%rsp
+# 800007: 48 c7 c0 00 01 80 00 mov $0x800100,%rax ;; mov $asm_array, %rax
+# 80000e: 8b 04 25 00 40 80 00 mov 0x804000,%eax
+# 800015: f4 hlt
+# 800016: eb e8 jmp 800000 &lt;_entry&gt;
+</code></pre>
+<p>The following linker script shows an example with the <code>MEMORY</code> command.</p>
+<pre><code>OUTPUT_FORMAT(elf64-x86-64)
+ENTRY(_entry)
+
+MEMORY {
+ ROM : ORIGIN = 0x00100000, LENGTH = 0x4000
+ RAM : ORIGIN = 0x00800000, LENGTH = 0x4000
+}
+
+SECTIONS {
+ /* Create .text output section at ROM (vaddr) */
+ .text : {
+ *(.text*)
+ } &gt; ROM
+
+ ASSERT(. == ORIGIN(ROM) + SIZEOF(.text), "inc loc counter automatically")
+
+ /* Create .data output section at RAM (vaddr) */
+ /* Set load addr to ROM, right after .text (paddr) */
+ .data : {
+ HIDDEN(_data_vaddr = .);
+ HIDDEN(_data_paddr = LOADADDR(.data));
+ *(.data*)
+ } &gt; RAM AT &gt; ROM
+
+ /* Append .rodata output section at ROM (vaddr) */
+ .rodata : {
+ *(.rodata*)
+ } &gt; ROM
+
+ /* Append .stack output section at RAM (vaddr) aligned up to next 0x1000 */
+ .stack : ALIGN (0x1000) {
+ . += 0x1000;
+ HIDDEN(_stack_top = .);
+ } &gt; RAM
+
+ /DISCARD/ : {
+ *(.*)
+ }
+}
+
+/* Some example assertions */
+ASSERT(ADDR(.data) != LOADADDR(.data), "DATA vaddr and paddr must be different")
+ASSERT(ADDR(.rodata) == LOADADDR(.rodata), "RODATA vaddr and paddr must be euqal")
+ASSERT(ADDR(.stack) == ORIGIN(RAM) + 0x1000, "STACK section must aligned to 0x1000")
+ASSERT(SIZEOF(.stack) == 0x1000, "STACK section must be 0x1000")
+</code></pre>
+<h2 id="references-5"><a class="header" href="#references-5">References</a></h2>
+<ul>
+<li><a href="https://sourceware.org/binutils/docs/ld/">ld manual</a></li>
+<li><a href="https://sourceware.org/binutils/docs/ld/Input-Section.html">ld script: input sections</a></li>
+<li><a href="https://sourceware.org/binutils/docs/ld/Output-Section-Attributes.html">ld script: output sections</a></li>
+<li><a href="https://github.com/johannst/notes/tree/master/src/development/ld">notes/ld example files</a></li>
+</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="git1"><a class="header" href="#git1">git(1)</a></h1>
<h2 id="working-areas"><a class="header" href="#working-areas">Working areas</a></h2>
<pre><code class="language-text">+-------------------+ --- stash -----&gt; +-------+
@@ -5968,7 +6480,7 @@ func_v0
func_v1
func_v2
</code></pre>
-<h2 id="references-4"><a class="header" href="#references-4">References</a></h2>
+<h2 id="references-6"><a class="header" href="#references-6">References</a></h2>
<ul>
<li><a href="https://akkadia.org/drepper/symbol-versioning">ELF Symbol Versioning</a></li>
<li><a href="https://sourceware.org/binutils/docs/ld/VERSION.html">Binutils ld: Symbol Versioning</a></li>
@@ -6091,7 +6603,7 @@ link time <code>-lgcov</code>.</p>
generated for a single file for example such as</p>
<pre><code class="language-shell">gcov &lt;SRC FILE | OBJ FILE&gt;
</code></pre>
-<h2 id="example-8"><a class="header" href="#example-8">Example</a></h2>
+<h2 id="example-9"><a class="header" href="#example-9">Example</a></h2>
<pre><code class="language-cpp">#include &lt;cstdio&gt;
void tell_me(int desc) {
@@ -6372,7 +6884,7 @@ journalctl --user -u test -n 5
--disk-usage Show current disk usage
--vacuum-size=&lt;size&gt; Reduce journal log to &lt;size&gt; (K/M/G)
</code></pre>
-<h2 id="references-5"><a class="header" href="#references-5">References</a></h2>
+<h2 id="references-7"><a class="header" href="#references-7">References</a></h2>
<ul>
<li><a href="https://www.man7.org/linux/man-pages/man5/systemd.unit.5.html">man systemd.unit(5)</a></li>
<li><a href="https://www.man7.org/linux/man-pages/man5/systemd.service.5.html">man systemd.service(5)</a></li>
@@ -6755,7 +7267,7 @@ group::r-x
mask::r-x
other::rwx
</code></pre>
-<h2 id="references-6"><a class="header" href="#references-6">References</a></h2>
+<h2 id="references-8"><a class="header" href="#references-8">References</a></h2>
<ul>
<li><a href="https://www.man7.org/linux/man-pages/man5/acl.5.html">acl(5)</a></li>
<li><a href="https://www.man7.org/linux/man-pages/man1/getfacl.1.html">getfacl(1)</a></li>
@@ -6997,7 +7509,7 @@ cpupower -c all frequency-info -g
# Change frequency governor to POWERSAVE (eg).
cpupower -c all frequency-set -g powersave
</code></pre>
-<h2 id="example-9"><a class="header" href="#example-9">Example</a></h2>
+<h2 id="example-10"><a class="header" href="#example-10">Example</a></h2>
<p>Watch cpu frequency.</p>
<pre><code class="language-sh">watch -n1 "cpupower -c all frequency-info -f -m | xargs -n2 -d'\n'"
</code></pre>
@@ -7052,6 +7564,9 @@ lp -d PRINTER FILE
-o sides=one-sided print front-page only
-o sides=two-sided-long-edge print duplex
+# Show job queue
+lpq -P PRINTER
+
# Remove pending print job.
lprm JOOBID
</code></pre>
@@ -7112,7 +7627,7 @@ locally and <code>-R</code> means that requests are issued remotely.</p>
drop into shell)</li>
<li><code>-f</code> run <code>ssh</code> command in the background</li>
</ul>
-<h3 id="example-10"><a class="header" href="#example-10">Example</a></h3>
+<h3 id="example-11"><a class="header" href="#example-11">Example</a></h3>
<pre><code class="language-sh"># Forward requests on localhost:8080 to moose:1234 and keep ssh in forground
# but dont drop into a shell.
ssh -N -L 8080:1234 moose
@@ -7290,7 +7805,7 @@ firewall-cmd --remove-port 8000/tcp
# Remove rich rule.
firewall-cmd --remove-rich-rule 'rule family="ipv4" forward-port port="80" protocol="tcp" to-port="8080"'
</code></pre>
-<h2 id="references-7"><a class="header" href="#references-7">References</a></h2>
+<h2 id="references-9"><a class="header" href="#references-9">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>
@@ -8307,6 +8822,41 @@ wrmsr // Write MSR register, effectively does MSR[ECX] &lt;- EDX:EAX
<blockquote>
<p>See <a href="https://github.com/johannst/mini-kvm-rs/blob/main/guest/guest64-msr.S">guest64-msr.S</a> as an example.</p>
</blockquote>
+<h4 id="some-interesting-msrs"><a class="header" href="#some-interesting-msrs">Some interesting MSRs</a></h4>
+<ul>
+<li><code>C000_0082: IA32_LSTAR</code> target address for <a href="https://www.felixcloutier.com/x86/syscall"><code>syscall</code></a> instruction
+in <strong>IA-32e</strong> (64 bit) mode.</li>
+<li><code>C000_0100: IA32_FS_BASE</code> storage for <strong>%fs</strong> segment base address.</li>
+<li><code>C000_0101: IA32_GS_BASE</code> storage for <strong>%gs</strong> segment base address.</li>
+<li><code>C000_0102: IA32_KERNEL_GS_BASE</code> additional register, <a href="https://www.felixcloutier.com/x86/swapgs"><code>swapgs</code></a>
+swaps <strong>GS_BASE</strong> and <strong>KERNEL_GS_BASE</strong>, without altering any register state.
+Can be used to swap in a pointer to a kernel data structure on syscall entry,
+as for example in <a href="https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/entry_64.S?h=v6.13#n87"><code>entry_SYSCALL_64</code></a>.</li>
+</ul>
+<h2 id="current-privilege-level"><a class="header" href="#current-privilege-level">Current privilege level</a></h2>
+<p>The current privilege level can be found at any time in the last two bits of the
+code segment selector <code>cs</code>. The following shows an example debugging an entry
+and exit of a syscall in x86_64-linux.</p>
+<pre><code>Breakpoint 1, entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:90
+90 swapgs
+(gdb) info r rax rcx cs
+rax 0x0 0 ; syscall nr
+rcx 0x7feb16399e56 140647666916950 ; ret addr
+cs 0x10 16 ; cs &amp; 0x3 -&gt; 0 (ring0,kernel)
+
+(gdb) c
+Breakpoint 2, entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:217
+217 sysretq
+(gdb) info r rcx cs
+rcx 0x7feb16399e56 140647666916950 ; ret addr
+cs 0x10 16 ; cs &amp; 0x3 -&gt; 0 (ring0,kernel)
+
+(gdb) b *$rcx
+(gdb) s
+Breakpoint 3, 0x00007feb16399e56 in ?? ()
+(gdb) info r cs
+cs 0x33 51 ; cs &amp; 0x3 -&gt; 3 (ring3,user)
+</code></pre>
<h2 id="size-directives"><a class="header" href="#size-directives">Size directives</a></h2>
<p>Explicitly specify size of the operation.</p>
<pre><code class="language-x86asm">mov byte ptr [rax], 0xff // save 1 byte(s) at [rax]
@@ -8373,6 +8923,18 @@ mov al, 0xaa
mov cx, 0x10
rep stosb
</code></pre>
+<h2 id="att-syntax-for-intel-syntax-users"><a class="header" href="#att-syntax-for-intel-syntax-users">AT&amp;T syntax for intel syntax users</a></h2>
+<pre><code class="language-x86asm">mov %rax, %rbx // mov rbx, rax
+mov $12, %rax // mov rax, 12
+
+mov (%rsp), %rax // mov rax, [rsp]
+mov 8(%rsp), %rax // mov rax, [rsp + 8]
+mov (%rsp,%rcx,4), %rax // mov rax, [rsp + 8 * rcx]
+mov 0x100, %rax // mov rax, [0x100]
+mov (0x100), %rax // mov rax, [0x100]
+
+mov %gs:8, %rax // mov rax, gs:8
+</code></pre>
<h2 id="time-stamp-counter---rdtsc"><a class="header" href="#time-stamp-counter---rdtsc">Time stamp counter - <code>rdtsc</code></a></h2>
<pre><code class="language-c">static inline uint64_t rdtsc() {
uint32_t eax, edx;
@@ -8566,34 +9128,35 @@ must must save these registers in case they are used.</p>
<li>gnu assembler <a href="https://sourceware.org/binutils/docs/as"><code>gas</code></a></li>
<li>intel syntax</li>
</ul>
-<pre><code class="language-x86asm"># file: greet.s
+<pre><code class="language-x86asm">// file: greet.S
+#include &lt;asm/unistd.h&gt;
.intel_syntax noprefix
.section .text, "ax", @progbits
.global _start
_start:
- mov rdi, 1 # fd
+ mov rdi, 1 # fd (stdout)
lea rsi, [rip + greeting] # buf
mov rdx, [rip + greeting_len] # count
- mov rax, 1 # write(2) syscall nr
+ mov rax, __NR_write # write(2) syscall nr
syscall
- mov rdi, 0 # exit code
+ mov rdi, __NR_exit # exit code
mov rax, 60 # exit(2) syscall nr
syscall
.section .rdonly, "a", @progbits
greeting:
- .asciz "Hi ASM-World!\n"
+ .ascii "Hi ASM-World!\n"
greeting_len:
.int .-greeting
</code></pre>
<blockquote>
-<p>Syscall numbers are defined in <code>/usr/include/asm/unistd.h</code>.</p>
+<p>Files with <code>.S</code> suffix are pre-processed, while files with <code>.s</code> suffix are not.</p>
</blockquote>
<p>To compile and run:</p>
-<pre><code class="language-bash">&gt; gcc -o greet greet.s -nostartfiles -nostdlib &amp;&amp; ./greet
+<pre><code class="language-bash">&gt; gcc -o greet greet.S -nostartfiles -nostdlib &amp;&amp; ./greet
Hi ASM-World!
</code></pre>
<h2 id="mbr-boot-sectors-example"><a class="header" href="#mbr-boot-sectors-example">MBR boot sectors example</a></h2>
@@ -8785,7 +9348,7 @@ address translation.</p>
<p>The example in <a href="arch/x86/seg/seg.c">seg.c</a> shows how to set the <code>gs</code> base
address and to relative accesses.</p>
</blockquote>
-<h2 id="references-8"><a class="header" href="#references-8">References</a></h2>
+<h2 id="references-10"><a class="header" href="#references-10">References</a></h2>
<ul>
<li><a href="https://gitlab.com/x86-psABIs/x86-64-ABI">SystemV AMD64 ABI</a></li>
<li><a href="https://www.amd.com/system/files/TechDocs/24592.pdf">AMD64 Vol1: Application Programming</a></li>
@@ -9058,7 +9621,7 @@ Hi ASM-World!
distributions. Explicitly specifying the dynamic linker should not be
required when compiling natively on arm64.</p>
</blockquote>
-<h2 id="references-9"><a class="header" href="#references-9">References</a></h2>
+<h2 id="references-11"><a class="header" href="#references-11">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>
@@ -9303,7 +9866,7 @@ Hi ASM-World!
distributions. Explicitly specifying the dynamic linker should not be
required when compiling natively on arm.</p>
</blockquote>
-<h2 id="references-10"><a class="header" href="#references-10">References</a></h2>
+<h2 id="references-12"><a class="header" href="#references-12">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>
@@ -9384,7 +9947,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-11"><a class="header" href="#references-11">References</a></h2>
+<h2 id="references-13"><a class="header" href="#references-13">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>