PageSourceSearch

https://0xc0ffee.netlify.app/assets/20-position-independent-code.html-deBWIlCT.js

js 0xc0ffee.netlify.app collected 2026-10-03 10:23:46 UTC 105,493 bytes, 484 lines download raw bytes

1import{_ as n,c as a,e,o as t}from"./app-CjUkjRdW.js";const i={};function l(p,s){return t(),a("div",null,s[0]||(s[0]=[e(`<h1 id="position-independent-code" tabindex="-1"><a class="header-anchor" href="#position-independent-code"><span>Position Independent Code</span></a></h1><p>Fusion is a single address space OS, which means that all tasks share the same address space. This requires the ability to load task images at arbitrary addresses (depending on the available virtual memory). Currently, when we compile and link a task, the linker will generate a binary that is not position independent; it has to be loaded at a pre-determined address. We need to change this and use position independent code (PIC) object files and position independent executables (PIE) instead.</p><h2 id="what-is-pic-and-pie" tabindex="-1"><a class="header-anchor" href="#what-is-pic-and-pie"><span>What is PIC and PIE?</span></a></h2><p>A PIE is a binary that can be loaded at any address in memory. This is achieved by using relative addressing instead of absolute addressing. For example, instead of using the absolute address of a function, the compiler uses the offset from the current instruction pointer. This is called position independent code (PIC), and is typically used for shared libraries, since they can be loaded at any address in the process address space. To generate PIC object files, we need to use the <code>-fPIC</code> compiler flag. A PIE can be generated using the <code>--pie</code> linker flag, assuming that all object files are PIC.</p><p>In some cases, however, the linker cannot use relative addressing for some symbols. In particular, global variables that contain pointers to other global variables or functions cannot be resolved at link time. This is because the linker does not know the address of the target symbol at link time, and therefore cannot compute the offset. In this case, the linker will generate a relocation entry, which is a record that tells the loader to patch the binary at runtime. The loader will then resolve the relocation entries and patch the binary before starting the task.</p><p>This process is typical in loading shared libraries, but it is also used for PIEs. There are two types of PIEs: dynamic and static.</p><ul><li>A <strong>dynamic PIE</strong> relies on the same dynamic linker as shared libraries, and therefore needs to be loaded by the dynamic linker (typically <code>ld.so</code>).</li><li>A <strong>static PIE</strong>, on the other hand, does not need a dynamic linker. Instead, it relies on C runtime startup code that is linked into the binary (typically <code>Scrt1.o</code>). The startup code applies the relocation entries by patching the loaded binary in memory.</li></ul><p>What we want is a static PIE, but since we do not have a C runtime, we need to implement the relocation patching ourselves.</p><h2 id="generating-a-static-pie" tabindex="-1"><a class="header-anchor" href="#generating-a-static-pie"><span>Generating a static PIE</span></a></h2><p>Let&#39;s modify the user task <code>nim.cfg</code> file to generate a static PIE.</p><div class="language-properties line-numbers-mode" data-highlighter="prismjs" data-ext="properties" data-title="properties"><pre><code><span class="line"><span class="token comment"># src/user/nim.cfg</span></span>
2<span class="line">...</span>
3<span class="line"><span class="token key attr-name">--passc</span><span class="token punctuation">:</span><span class="token value attr-value">&quot;-fPIC&quot;</span></span>
4<span class="line">...</span>
5<span class="line"><span class="token key attr-name">--passl</span><span class="token punctuation">:</span><span class="token value attr-value">&quot;--pie&quot;</span></span>
6<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let&#39;s also remove the fixed address from the linker script, since the whole point of a PIE is to be able to load it at any address.</p><div class="language-ld line-numbers-mode" data-highlighter="prismjs" data-ext="ld" data-title="ld"><pre><code><span class="line"><span class="token comment">/* src/user/utask.ld */</span></span>
7<span class="line"></span>
8<span class="line">SECTIONS</span>
9<span class="line"><span class="token punctuation">{</span></span>
10<span class="line">  <span class="token location-counter important">.</span> <span class="token operator">=</span> <span class="token number">0x0000000040000000</span><span class="token punctuation">;</span> <span class="token comment">/* 1 GiB */</span>    <span class="token operator">&lt;</span><span class="token operator">--</span> remove this line</span>
11<span class="line">  <span class="token location-counter important">.</span><span class="token location-counter important">.</span><span class="token location-counter important">.</span></span>
12<span class="line"><span class="token punctuation">}</span></span>
13<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Now, let&#39;s compile and link the task and take a look at the generated binary.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">just user</span></span></span>
14<span class="line"><span class="token output">...</span>
15<span class="line"></span>
16<span class="line"></span><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash"><span class="token function">file</span> build/user/utask.bin</span></span></span>
17<span class="line"><span class="token output">build/user/utask.bin: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, not stripped</span>
18<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Good, we have a static PIE. Before we try it out, let&#39;s take a look at the generated sections in the binary. To do this, we need to temporarily comment out the use of the linker script and the binary output format to generate a vanilla ELF binary that we can inspect.</p><div class="language-properties line-numbers-mode" data-highlighter="prismjs" data-ext="properties" data-title="properties"><pre><code><span class="line"><span class="token comment"># src/user/nim.cfg</span></span>
19<span class="line">...</span>
20<span class="line"><span class="token comment">#--passl:&quot;-T src/user/utask.ld&quot;</span></span>
21<span class="line"><span class="token comment">#--passl:&quot;--oformat=binary&quot;</span></span>
22<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let&#39;s use <code>llvm-readelf</code> to inspect the sections in the binary.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">llvm-readelf <span class="token parameter variable">-S</span> build/user/utask.bin</span></span></span>
23<span class="line"><span class="token output">There are 18 section headers, starting at offset 0xd300:</span>
24<span class="line"></span>
25<span class="line">Section Headers:</span>
26<span class="line">  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al</span>
27<span class="line">  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0</span>
28<span class="line">  [ 1] .dynsym           DYNSYM          0000000000000200 000200 000018 18   A  4   1  8</span>
29<span class="line">  [ 2] .gnu.hash         GNU_HASH        0000000000000218 000218 00001c 00   A  1   0  8</span>
30<span class="line">  [ 3] .hash             HASH            0000000000000234 000234 000010 04   A  1   0  4</span>
31<span class="line">  [ 4] .dynstr           STRTAB          0000000000000244 000244 000001 00   A  0   0  1</span>
32<span class="line">  [ 5] .rela.dyn         RELA            0000000000000248 000248 000300 18   A  1   0  8</span>
33<span class="line">  [ 6] .rodata           PROGBITS        0000000000000550 000550 000bb0 00 AMS  0   0 16</span>
34<span class="line">  [ 7] .text             PROGBITS        0000000000002100 001100 008c3a 00  AX  0   0 16</span>
35<span class="line">  [ 8] .data.rel.ro      PROGBITS        000000000000bd40 009d40 000180 00  WA  0   0 16</span>
36<span class="line">  [ 9] .dynamic          DYNAMIC         000000000000bec0 009ec0 0000d0 10  WA  4   0  8</span>
37<span class="line">  [10] .got              PROGBITS        000000000000bf90 009f90 000000 00  WA  0   0  8</span>
38<span class="line">  [11] .relro_padding    NOBITS          000000000000bf90 009f90 000070 00  WA  0   0  1</span>
39<span class="line">  [12] .data             PROGBITS        000000000000cf90 009f90 0000e0 00  WA  0   0  8</span>
40<span class="line">  [13] .bss              NOBITS          000000000000d070 00a070 2004a8 00  WA  0   0 16</span>
41<span class="line">  [14] .comment          PROGBITS        0000000000000000 00a070 00007d 01  MS  0   0  1</span>
42<span class="line">  [15] .symtab           SYMTAB          0000000000000000 00a0f0 001848 18     17 258  8</span>
43<span class="line">  [16] .shstrtab         STRTAB          0000000000000000 00b938 000091 00      0   0  1</span>
44<span class="line">  [17] .strtab           STRTAB          0000000000000000 00b9c9 001930 00      0   0  1</span>
45<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>There&#39;s a lot of sections here, but we&#39;ll focus on code (text) and data sections. In addition to the usual ones (<code>.text</code>, <code>.rodata</code>, <code>.data</code>, and <code>.bss</code>), a new data section shows up: <code>.data.rel.ro</code>. This is a read-only data section (similar to <code>.rodata</code>) that contains data that needs to be relocated. We&#39;ll look at relocations later, but for now let&#39;s just include this section in the linker script.</p><div class="language-ld line-numbers-mode" data-highlighter="prismjs" data-ext="ld" data-title="ld"><pre><code><span class="line">SECTIONS</span>
46<span class="line"><span class="token punctuation">{</span></span>
47<span class="line">  <span class="token section keyword">.text</span> <span class="token operator">:</span> <span class="token punctuation">{</span></span>
48<span class="line">    <span class="token operator">*</span>utask<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.UserMain<span class="token punctuation">)</span></span>
49<span class="line">    <span class="token operator">*</span>utask<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.<span class="token operator">*</span><span class="token punctuation">)</span></span>
50<span class="line">    <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text<span class="token operator">*</span><span class="token punctuation">)</span></span>
51<span class="line">  <span class="token punctuation">}</span></span>
52<span class="line">  <span class="token section keyword">.rodata</span>
52      <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>rodata<span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
53<span class="line highlighted">  <span class="token section keyword">.data</span><span class="token section keyword">.rel</span><span class="token section keyword">.ro</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.data</span><span class="token section keyword">.rel</span><span class="token section keyword">.ro</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
54<span class="line">  <span class="token section keyword">.data</span>        <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>data<span class="token operator">*</span><span class="token punctuation">)</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>bss<span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
55<span class="line"></span>
56<span class="line">  <span class="token section keyword">.shstrtab</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.shstrtab</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">/* cannot be discarded */</span></span>
57<span class="line">  <span class="token operator">/</span>DISCARD<span class="token operator">/</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
58<span class="line"><span class="token punctuation">}</span></span>
59<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="trying-it-out" tabindex="-1"><a class="header-anchor" href="#trying-it-out"><span>Trying it out</span></a></h2><p>Let&#39;s uncomment the lines we commented out earlier in the <code>nim.cfg</code> file (for the linker script and output format) and see what happens when we try to run it.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">just run</span></span></span>
60<span class="line"><span class="token output">...</span>
61<span class="line"></span>
62<span class="line">kernel: Initializing Syscalls [success]</span>
63<span class="line">kernel: Creating user task</span>
64<span class="line">kernel: Switching to user mode</span>
65<span class="line">syscall: num=2</span>
66<span class="line">syscall: print</span>
67<span class="line"></span>
68<span class="line">syscall: num=1</span>
69<span class="line">syscall: exit: code=0</span>
70<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>It works, but there&#39;
70s no message printed from the user task (that we pass to the <code>print</code> syscall). Let&#39;s print the <code>arg1</code> argument value passed to the <code>print</code> syscall to see what address is being passed.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/user/syscalls.nim</span></span>
71<span class="line"><span class="token operator">...</span></span>
72<span class="line"></span>
73<span class="line"><span class="token keyword">proc</span> <span class="token function">print<span class="token operator">*</span></span><span class="token punctuation">(</span>args<span class="token operator">:</span> <span class="token keyword">ptr</span> SyscallArgs<span class="token punctuation">)</span><span class="token operator">:</span> uint64 <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
74<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;syscall: print (arg1={args.arg1:#x})&quot;</span></span>
75<span class="line">  <span class="token operator">...</span></span>
76<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token output">kernel: Switching to user mode</span>
77<span class="line">syscall: num=2</span>
78<span class="line">syscall: print (arg1=0x40209ee8)</span>
79<span class="line"></span>
80<span class="line">syscall: num=1</span>
81<span class="line">syscall: exit: code=0</span>
82<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The <code>arg1</code> looks like a valid address, but for some reason nothing is printed. If we look at the linker map file at that address we can see that it&#39;s the address of the <code>msg</code> string:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">    VMA              LMA        Size Align Out     In      Symbol</span>
83<span class="line">    ...</span>
84<span class="line">    209ee0           209ee0       18     8         build/user/@mutask.nim.c.o:(.bss)</span>
85<span class="line">    209ee0           209ee0        8     1                 pmsg__utask_u5</span>
86<span class="line highlighted">    209ee8           209ee8       10     1                 msg__utask_u4</span>
87<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This was very confusing to me before I learned about the need for relocation even in static PIEs. To understand what&#39;s going on, we need to look at how Nim defines its <code>string</code> type. The relevant definition is in the <code>system/strs_v2.nim</code> file in the Nim standard library.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token keyword">type</span></span>
88<span class="line">  <span class="token operator">...</span></span>
89<span class="line"></span>
90<span class="line">  NimStrPayload <span class="token punctuation">{.</span>core<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
91<span class="line">    cap<span class="token operator">:</span> int</span>
92<span class="line">    data<span class="token operator">:</span> UncheckedArray<span class="token punctuation">[</span>char<span class="token punctuation">]</span></span>
93<span class="line"></span>
94<span class="line">  NimStringV2 <span class="token punctuation">{.</span>
94core<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
95<span class="line">    len<span class="token operator">:</span> int</span>
96<span class="line">    p<span class="token operator">:</span> <span class="token keyword">ptr</span> NimStrPayload <span class="token comment">## can be nil if len == 0.</span></span>
97<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The <code>NimStrPayload</code> object contains the capacity of the string and the actual bytes making up the string. The <code>NimStringV2</code> object contains the length of the string and a <strong>pointer</strong> to a payload object (this is the <code>string</code> type normally used in Nim code). OK, so now we know that the <code>msg</code> variable is not the string itself, but a pair of length and pointer to the string. This is evident from the <code>Size</code> value in the linker map file: the <code>msg</code> variable takes up <code>0x10</code> (16) bytes: 8 bytes for the <code>len</code> field and 8 bytes for the <code>p</code> field.</p><p>So, let&#39;s find out what&#39;s stored in the fields of the <code>msg</code> string variable.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/user/syscalls.nim</span></span>
98<span class="line"><span class="token operator">...</span></span>
99<span class="line"></span>
100<span class="line"><span class="token keyword">proc</span> <span class="token function">print<span class="token operator">*</span></span><span class="token punctuation">(</span>args<span class="token operator">:</span> <span class="token keyword">ptr</span> SyscallArgs<span class="token punctuation">)</span><span class="token operator">:</span> uint64 <span class="token punctuation">{.</span>cdecl<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
101<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;syscall: print (arg1={args.arg1:#x})&quot;</span></span>
102<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;syscall: print: arg1.len = {cast[ptr uint64](args.arg1)[]}&quot;</span></span>
103<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;syscall: print: arg1.p   = {cast[ptr uint64](args.arg1 + 8)[]:#x}&quot;</span></span>
104<span class="line">  <span class="token operator">...</span></span>
105<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Creating user task</span>
106<span class="line">kernel: Switching to user mode</span>
107<span class="line">syscall: num=2</span>
108<span class="line">syscall: print (arg1=0x40209ee8)</span>
109<span class="line">syscall: print: arg1.len = 21</span>
110<span class="line">syscall: print: arg1.p   = 0x0</span>
111<span class="line"></span>
112<span class="line">syscall: num=1</span>
113<span class="line">syscall: exit: code=0</span>
114<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Well, the <code>len</code> field is correct, but the <code>p</code> field is <code>0x0</code>. This is the situation I talked about above: we have a global pointer (the <code>p</code> field of <code>NimStringV2</code>) that points to another global variable (the <code>NimStrPayload</code>
114 object). The linker cannot resolve this at link time for a PIE, so it sets it to 0, and generates a relocation entry for the loader to use for patching that location at load time (once the actual location of the binary is known). That&#39;s what we need to do to make this work.</p><h2 id="understanding-relocations" tabindex="-1"><a class="header-anchor" href="#understanding-relocations"><span>Understanding relocations</span></a></h2><p>Let&#39;s take a look at the sections in the binary again.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">llvm-readelf <span class="token parameter variable">-S</span> build/user/utask.bin</span></span></span>
115<span class="line"><span class="token output">There are 18 section headers, starting at offset 0xd300:</span>
116<span class="line"></span>
117<span class="line">Section Headers:</span>
118<span class="line">  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al</span>
119<span class="line">  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0</span>
120<span class="line">  [ 1] .dynsym           DYNSYM          0000000000000200 000200 000018 18   A  4   1  8</span>
121<span class="line">  [ 2] .gnu.hash         GNU_HASH        0000000000000218 000218 00001c 00   A  1   0  8</span>
122<span class="line">  [ 3] .hash             HASH            0000000000000234 000234 000010 04   A  1   0  4</span>
123<span class="line">  [ 4] .dynstr           STRTAB          0000000000000244 000244 000001 00   A  0   0  1</span>
124<span class="line highlighted">  [ 5] .rela.dyn         RELA            0000000000000248 000248 000300 18   A  1   0  8</span>
125<span class="line">  [ 6] .rodata           PROGBITS        0000000000000550 000550 000bb0 00 AMS  0   0 16</span>
126<span class="line">  [ 7] .text             PROGBITS        0000000000002100 001100 008c3a 00  AX  0   0 16</span>
127<span class="line">  [ 8] .data.rel.ro      PROGBITS        000000000000bd40 009d40 000180 00  WA  0   0 16</span>
128<span class="line">  [ 9] .dynamic          DYNAMIC         000000000000bec0 009ec0 0000d0 10  WA  4   0  8</span>
129<span class="line">  [10] .got              PROGBITS        000000000000bf90 009f90 000000 00  WA  0   0  8</span>
130<span class="line">  [11] .relro_padding    NOBITS          000000000000bf90 009f90 000070 00  WA  0   0  1</span>
131<span class="line">  [12] .data             PROGBITS        000000000000cf90 009f90 0000e0 00  WA  0   0  8</span>
132<span class="line">  [13] .bss              NOBITS          000000000000d070 00a070 2004a8 00  WA  0   0 16</span>
133<span class="line">  [14] .comment          PROGBITS        0000000000000000 00a070 00007d 01  MS  0   0  1</span>
134<span class="line">  [15] .symtab           SYMTAB          0000000000000000 00a0f0 001848 18     17 258  8</span>
135<span class="line">  [16] .shstrtab         STRTAB          0000000000000000 00b938 000091 00      0   0  1</span>
136<span class="line">  [17] .strtab           STRTAB          0000000000000000 00b9c9 001930 00      0   0  1</span>
137<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This time we&#39;ll focus on the section containing the relocation entries: <code>.rela.dyn</code> (notice that its type is <code>RELA</code>, which is short for RELocations with Addend). Let&#39;s take a look at the relocation entries (I&#39;ll use <code>llvm-objdump -R</code> here instead of <code>llvm-readelf -r</code> since interpreting its output is more straightforward).</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">llvm-objdump <span class="token parameter variable">-R</span> build/user/utask.bin</span></span></span>
138<span class="line"></span>
139<span class="line"><span class="token output">build/user/utask.bin:   file format elf64-x86-64</span>
140<span class="line"></span>
141<span class="line">DYNAMIC RELOCATION RECORDS</span>
142<span class="line">OFFSET           TYPE                     VALUE</span>
143<span class="line">000000000000bd48 R_X86_64_RELATIVE        *ABS*+0xd38</span>
144<span class="line">000000000000bd58 R_X86_64_RELATIVE        *ABS*+0xd58</span>
145<span class="line">000000000000bd68 R_X86_64_RELATIVE        *ABS*+0xd90</span>
146<span class="line">000000000000bd78 R_X86_64_RELATIVE        *ABS*+0xda0</span>
147<span class="line">000000000000bd88 R_X86_64_RELATIVE        *ABS*+0xdb8</span>
148<span class="line">000000000000bd98 R_X86_64_RELATIVE        *ABS*+0xdd8</span>
149<span class="line">000000000000bda8 R_X86_64_RELATIVE        *ABS*+0xde8</span>
150<span class="line">000000000000bdb8 R_X86_64_RELATIVE        *ABS*+0xdf8</span>
151<span class="line">
151000000000000bdc8 R_X86_64_RELATIVE        *ABS*+0xe08</span>
152<span class="line">000000000000bdd8 R_X86_64_RELATIVE        *ABS*+0xdf8</span>
153<span class="line">000000000000bde8 R_X86_64_RELATIVE        *ABS*+0xe28</span>
154<span class="line">000000000000bdf8 R_X86_64_RELATIVE        *ABS*+0xe38</span>
155<span class="line">000000000000be08 R_X86_64_RELATIVE        *ABS*+0xe48</span>
156<span class="line">000000000000be18 R_X86_64_RELATIVE        *ABS*+0xe70</span>
157<span class="line">000000000000be28 R_X86_64_RELATIVE        *ABS*+0xea0</span>
158<span class="line">000000000000be38 R_X86_64_RELATIVE        *ABS*+0xeb0</span>
159<span class="line">000000000000be48 R_X86_64_RELATIVE        *ABS*+0xef0</span>
160<span class="line">000000000000be58 R_X86_64_RELATIVE        *ABS*+0xf70</span>
161<span class="line">000000000000be68 R_X86_64_RELATIVE        *ABS*+0xf90</span>
162<span class="line">000000000000be78 R_X86_64_RELATIVE        *ABS*+0x1000</span>
163<span class="line">000000000000be88 R_X86_64_RELATIVE        *ABS*+0x1010</span>
164<span class="line">000000000000be98 R_X86_64_RELATIVE        *ABS*+0x10b8</span>
165<span class="line">000000000000bea8 R_X86_64_RELATIVE        *ABS*+0x10c8</span>
166<span class="line">000000000000beb8 R_X86_64_RELATIVE        *ABS*+0x10e0</span>
167<span class="line">000000000000cf90 R_X86_64_RELATIVE        *ABS*+0x2100</span>
168<span class="line">000000000000cfa8 R_X86_64_RELATIVE        *ABS*+0x550</span>
169<span class="line">000000000000cfc8 R_X86_64_RELATIVE        *ABS*+0x2140</span>
170<span class="line">000000000000cfe0 R_X86_64_RELATIVE        *ABS*+0x560</span>
171<span class="line">000000000000d000 R_X86_64_RELATIVE        *ABS*+0x2180</span>
172<span class="line">000000000000d018 R_X86_64_RELATIVE        *ABS*+0x570</span>
173<span class="line">000000000000d038 R_X86_64_RELATIVE        *ABS*+0x21c0</span>
174<span class="line">000000000000d050 R_X86_64_RELATIVE        *ABS*+0x590</span>
175<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>There are a lot of relocation entries here, but they all have the same type: <code>R_X86_64_RELATIVE</code>. Basically, this tells the loader to patch the binary at the given <code>OFFSET</code> by adding the addend <code>VALUE</code> to the base address where the binary is loaded (<code>*ABS*</code>). For example, the first entry tells the loader to patch the binary at offset <code>0xbd48</code> by adding the addend <code>0xd38</code> to the image base address.</p><p>If we look at those offsets, we can see that the first 24 entries are in the <code>.data.rel.ro</code> section, and the last 8 entries are in the <code>.data</code> section.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al</span>
176<span class="line">  ...</span>
177<span class="line">  [ 8] .data.rel.ro      PROGBITS        000000000000bd40 009d40 000180 00  WA  0   0 16</span>
178<span class="line">  ...</span>
179<span class="line">  [12] .data             PROGBITS        000000000000cf90 009f90 0000e0 00  WA  0   0  8</span>
180<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The <code>.data.rel.ro</code> section contains read-only data that needs to be relocated (often called RELRO). But how can it be read-only if it needs to be patched? The idea is to make the section read-only <em>after</em> the relocation entries have been applied. The <code>.data</code> section contains read-write data, some of which also needs to be relocated.</p><p>Let&#39;s take a look at linker map file to see what is in these sections.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">    VMA              LMA     Size Align Out     In      Symbol</span>
181<span class="line">    ...</span>
182<span class="line">
182    bd40             bd40      180    16 .data.rel.ro</span>
183<span class="line">    bd40             bd40      120     8         build/user/@m..@s..@s..@s..@s..@[email protected]@[email protected]@[email protected]:(.data.rel.ro)</span>
184<span class="line">    bd40             bd40       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_54</span>
185<span class="line">    bd50             bd50       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_56</span>
186<span class="line">    bd60             bd60       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_58</span>
187<span class="line">    bd70             bd70       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_60</span>
188<span class="line">    bd80             bd80       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_45</span>
189<span class="line">    bd90             bd90       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_65</span>
190<span class="line">    bda0             bda0       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_67</span>
191<span class="line">    bdb0             bdb0       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_72</span>
192<span class="line">    bdc0             bdc0       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_74</span>
193<span class="line">    bdd0             bdd0       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_77</span>
194<span class="line">    bde0             bde0       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_81</span>
195<span class="line">    bdf0             bdf0       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_83</span>
196<span class="line">    be00             be00       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_9</span>
197<span class="line">    be10             be10       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_70</span>
198<span class="line">    be20             be20       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_7</span>
199<span class="line">    be30             be30       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_85</span>
200<span class="line">    be40             be40       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_87</span>
201<span class="line">    be50             be50       10     1                 TM__Q5wkpxktOdTGvlSRo9bzt9aw_90</span>
202<span class="line">    be60             be60       10     8         build/user/@m..@[email protected]:(.data.rel.ro)</span>
203<span class="line">    be60             be60       10     1                 TM__pmebpDrnfB5mBIQZTCopKw_3</span>
204<span class="line">    be70             be70       10     8         build/user/@m..@[email protected]:(.data.rel.ro)</span>
205<span class="line">    be70             be70       10     1                 TM__yBWtCXgKzcQMoAZ89cNTLsQ_9</span>
206<span class="line">    be80             be80       20    16         build/user/@m..@[email protected]:(.data.rel.ro)</span>
207<span class="line">    be80             be80       10     1                 TM__1g8zrI6ncbiETa2P7NNF9bg_4</span>
208<span class="line">    be90             be90       10     1                 TM__1g8zrI6ncbiETa2P7NNF9bg_6</span>
209<span class="line">    bea0             bea0       10    16         build/user/@m..@[email protected]:(.data.rel.ro)</span>
210<span class="line">    bea0             bea0       10     1                 TM__DFVzADEzeiwVkSytAkgKSQ_4</span>
211<span class="line">    beb0             beb0       10     8         build/user/@mutask.nim.c.o:(.data.rel.ro)</span>
212<span class="line">    beb0             beb0       10     1                 TM__ZYeLyBLx1ZJA3JEc71VOcA_3</span>
213<span class="line">    ...</span>
214<span class="line">    cf90             cf90       e0     8 .data</span>
215<span class="line">    cf90             cf90       e0     8         build/user/@m..@s..@s..@s..@s..@[email protected]@[email protected]@slib@[email protected]:(.data)</span>
216<span class="line">    cf90             cf90       38     1                 NTIv2__KZk2hR9c7XDat5d89bT8RgRA_</span>
217<span class="line">    cfc8             cfc8       38     1                 NTIv2__sUSFsM69cxbQEmaJuFxUD8w_</span>
218<span class="line">    d000             d000       38     1                 NTIv2__nv8HG9cQ7K8ZPnb0AFnX9cYQ_</span>
219<span class="line">    d038             d038       38     1                 NTIv2__CrB9bTWm1Xdf09bhlG9cbbyPA_</span>
220<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The mangled symbols in the linker map file are Nim-generated C symbols, so it&#39;s hard to tell what they are. But let&#39;s take the one symbol defined in the <code>build/user/@mutask.nim.c.o</code> object file. If we look at the corresponding generated C code, we find that it&#39;s a pointer to a string struct (I included both the string struct and the pointer).</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre><code><span class="line"><span class="token keyword">static</span> <span class="token keyword">const</span> <span class="token keyword">
220struct</span> <span class="token punctuation">{</span></span>
221<span class="line">  NI cap<span class="token punctuation">;</span> NIM_CHAR data<span class="token punctuation">[</span><span class="token number">21</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
222<span class="line"><span class="token punctuation">}</span> TM__ZYeLyBLx1ZJA3JEc71VOcA_2 <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">21</span> <span class="token operator">|</span> NIM_STRLIT_FLAG<span class="token punctuation">,</span> <span class="token string">&quot;Hello from user mode!&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span></span>
223<span class="line"></span>
224<span class="line"><span class="token keyword">static</span> <span class="token keyword">const</span> NimStringV2 TM__ZYeLyBLx1ZJA3JEc71VOcA_3 <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">21</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>NimStrPayload<span class="token operator">*</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>TM__ZYeLyBLx1ZJA3JEc71VOcA_2<span class="token punctuation">}</span><span class="token punctuation">;</span></span>
225<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>These are the two types we saw above: <code>NimStrPayload</code> and <code>NimStringV2</code>: <code>TM__ZYeLyBLx1ZJA3JEc71VOcA_2</code> is an instance of the <code>NimStrPayload</code> type (which contains the actual char array), and <code>TM__ZYeLyBLx1ZJA3JEc71VOcA_3</code> is an instance of the <code>NimStringV2</code> type (which contains the length and a pointer to the payload object).</p><p>Given that the address offset of the <code>NimStringV2</code> object is <code>0xbeb0</code> (as shown in the linker map file), and that the <code>p</code> field is at offset <code>8</code> in the struct (the <code>len</code> field takes 8 bytes), then the location to be patched is <code>0xbeb0 + 8 = 0xbeb8</code>. If we look at the relocation entries we saw above, indeed we can see an entry for this offset:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">000000000000beb8 R_X86_64_RELATIVE        *ABS*+0x10e0</span>
226<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><p>So the loader is asked to patch that location by adding the addend <code>0x10e0</code> to the image base address. Let&#39;s see what&#39;s at that address in the linker map.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">    VMA              LMA     Size Align Out     In      Symbol</span>
227<span class="line">    ...</span>
228<span class="line">    10e0             10e0       20     8         build/user/@mutask.nim.c.o:(.rodata)</span>
229<span class="line">    10e0             10e0       20     1                 TM__ZYeLyBLx1ZJA3JEc71VOcA_2</span>
230<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Lo and behold, it&#39;s the <code>NimStrPayload</code> object we saw above. So the loader will patch the <code>p</code> pointer at offset <code>0xbeb8</code> by adding <code>0x10e0</code> to the image base address, which will make it point to the <code>NimStrPayload</code> object. Voilà!</p><h2 id="raw-binary-with-relocations" tabindex="-1"><a class="header-anchor" href="#raw-binary-with-relocations"><span>Raw binary with relocations</span></a></h2><p>We don&#39;t have ELF support in our kernel (at least not yet), and I don&#39;t want to distract myself by implementing it now. So, we&#39;ll keep it simple and update the linker script to include the <code>.rela.dyn</code> section in the binary, and use it to patch the binary at load time. There&#39;s one problem though: the loader needs to know where the relocation entries are in the binary, and how many there are. We can add our own metadata section, but there&#39;s already one available as part of the ELF format: the <code>.dynamic</code> section. This section contains a list of tags and values that are typically used by the dynamic linker, but we can also use it to locate the relocation entries. Let&#39;s take a quick look at that section using <code>llvm-readelf -d</code>.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">llvm-readelf <span class="token parameter variable">-d</span> build/user/utask.bin</span></span></span>
231<span class="line"><span class="token output">Dynamic section at offset 0x9ec0 contains 13 entries:</span>
232<span class="line">  Tag                Type        Name/Value</span>
233<span class="line">  0x000000006ffffffb (FLAGS_1)   PIE </span>
234<span class="line">  0x0000000000000015 (DEBUG)     0x0</span>
235<span class="line highlighted">  0x0000000000000007 (RELA)      0x248</span>
236<span class="line highlighted">  0x0000000000000008 (RELASZ)    768 (bytes)</span>
237<span class="line highlighted">  0x0000000000000009 (RELAENT)   24 (bytes)</span>
238<span class="line highlighted">  0x000000006ffffff9 (RELACOUNT) 32</span>
239<span class="line">  0x0000000000000006 (SYMTAB)    0x200</span>
240<span class="line">  0x000000000000000b (SYMENT)    24 (bytes)</span>
241<span class="line">  0x0000000000000005 (STRTAB)    0x244</span>
242<span class="line">  0x000000000000000a (STRSZ)     1 (bytes)</span>
243<span class="line">  0x000000006ffffef5 (GNU_HASH)  0x218</span>
244<span class="line">  0x0000000000000004 (HASH)      0x234</span>
245<span class="line">  0x0000000000000000 (NULL)      0x0</span>
246<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>I highlighted the relevant entries. The <code>RELA</code> entry tells us where the relocation entries section (<code>.rela.dyn</code>) is located in the binary, the <code>RELASZ</code> entry tells us the size of that section, the <code>RELAENT</code> entry tells us the size of each relocation entry, and the <code>RELACOUNT</code> entry tells us how many relocation entries there are. It&#39;s exactly what we want. Also, notice that the last entry is always a NULL entry, so we can use that to locate the end of the section.</p><p>But where do we put the <code>.dynamic</code> section in the output image? If we put it in the middle (or end) of the image, we won&#39;t be able to locate it, so we&#39;ll need something else to locate it. Instead, we can just put it in the beginning of the image, followed by the relocation entries, followed by the text and data sections. We just have to adjust our assumption that the entry point is not at the beginning of the image, but rather comes after the <code>.rela.dyn</code> section. Let&#39;s update the linker script to do so.</p><div class="language-ld line-numbers-mode" data-highlighter="prismjs" data-ext="ld" data-title="ld"><pre><code><span class="line">SECTIONS</span>
247<span class="line"><span class="token punctuation">{</span></span>
248<span class="line highlighted">  <span class="token section keyword">.dynamic</span>  <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.dynamic</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
249<span class="line highlighted">  <span class="token section keyword">.rela</span><span class="token section keyword">.dyn</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.rela</span><span class="token section keyword">.dyn</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
250<span class="line"></span>
251<span class="line">  <span class="token section keyword">.text</span> <span class="token operator">:</span> <span class="token punctuation">{</span></span>
252<span class="line">    <span class="token operator">*</span>utask<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.UserMain<span class="token punctuation">)</span></span>
253<span class="line">    <span class="token operator">*</span>utask<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.<span class="token operator">*</span><span class="token punctuation">)</span></span>
254<span class="line">    <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text<span class="token operator">*</span><span class="token punctuation">)</span></span>
255<span class="line">  <span class="token punctuation">}</span></span>
256<span class="line">  <span class="token section keyword">.rodata</span>
256      <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>rodata<span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
257<span class="line">  <span class="token section keyword">.data</span><span class="token section keyword">.rel</span><span class="token section keyword">.ro</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.data</span><span class="token section keyword">.rel</span><span class="token section keyword">.ro</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
258<span class="line">  <span class="token section keyword">.data</span>        <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>data<span class="token operator">*</span><span class="token punctuation">)</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>bss<span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
259<span class="line"></span>
260<span class="line">  <span class="token section keyword">.shstrtab</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.shstrtab</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">/* cannot be discarded */</span></span>
261<span class="line">  <span class="token operator">/</span>DISCARD<span class="token operator">/</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
262<span class="line"><span class="token punctuation">}</span></span>
263<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If we compile and link the task, we get the following error:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">ld.lld: error: section: .data.rel.ro is not contiguous with other relro sections</span>
264<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><p>Apparently, some loaders support loading only a single RELRO segment (a segment in ELF maps to one or more contiguous sections). Both the <code>.dynamic</code> and <code>.data.rel.ro</code> sections are RELRO sections, so we need to make sure they are contiguous. We can fix it by putting the <code>.data.rel.ro</code> right after the <code>.dynamic</code> section.</p><div class="language-ld line-numbers-mode" data-highlighter="prismjs" data-ext="ld" data-title="ld"><pre><code><span class="line">SECTIONS</span>
265<span class="line"><span class="token punctuation">{</span></span>
266<span class="line">  <span class="token section keyword">.dynamic</span>     <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.dynamic</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
267<span class="line highlighted">  <span class="token section keyword">.data</span><span class="token section keyword">.rel</span><span class="token section keyword">.ro</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.data</span><span class="token section keyword">.rel</span><span class="token section keyword">.ro</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
268<span class="line">  <span class="token section keyword">.rela</span><span class="token section keyword">.dyn</span>    <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.rela</span><span class="token section keyword">.dyn</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
269<span class="line"></span>
270<span class="line">  <span class="token section keyword">.text</span> <span class="token operator">:</span> <span class="token punctuation">{</span></span>
271<span class="line">    <span class="token operator">*</span>utask<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.UserMain<span class="token punctuation">)</span></span>
272<span class="line">    <span class="token operator">*</span>utask<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.<span class="token operator">*</span><span class="token punctuation">)</span></span>
273<span class="line">    <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text<span class="token operator">*</span><span class="token punctuation">)</span></span>
274<span class="line">  <span class="token punctuation">}</span></span>
275<span class="line">  <span class="token section keyword">.rodata</span>
275      <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>rodata<span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
276<span class="line">  <span class="token section keyword">.data</span>        <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>data<span class="token operator">*</span><span class="token punctuation">)</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>bss<span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
277<span class="line"></span>
278<span class="line">  <span class="token section keyword">.shstrtab</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.shstrtab</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">/* cannot be discarded */</span></span>
279<span class="line">  <span class="token operator">/</span>DISCARD<span class="token operator">/</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
280<span class="line"><span class="token punctuation">}</span></span>
281<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The user task should now compile and link successfully. If we look at the resulting sections, we should see the <code>.dynamic</code> section followed by the <code>.data.rel.ro</code> section followed by the <code>.rela.dyn</code> section.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">llvm-readelf <span class="token parameter variable">-S</span> build/user/utask.bin</span></span></span>
282<span class="line"><span class="token output">There are 8 section headers, starting at offset 0x20b2e8:</span>
283<span class="line"></span>
284<span class="line">Section Headers:</span>
285<span class="line">  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al</span>
286<span class="line">  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0</span>
287<span class="line highlighted">  [ 1] .dynamic          DYNAMIC         0000000000000000 001000 0000b0 10  WA  0   0  8</span>
288<span class="line highlighted">  [ 2] .data.rel.ro      PROGBITS        00000000000000b0 0010b0 000180 00  WA  0   0 16</span>
289<span class="line highlighted">  [ 3] .rela.dyn         RELA            0000000000000230 001230 000300 18   A  0   0  8</span>
290<span class="line">  [ 4] .text             PROGBITS        0000000000000530 001530 008c34 00  AX  0   0 16</span>
291<span class="line">  [ 5] .rodata           PROGBITS        0000000000009170 00a170 000bb0 00 AMS  0   0 16</span>
292<span class="line">  [ 6] .data             PROGBITS        0000000000009d20 00ad20 200588 00  WA  0   0 16</span>
293<span class="line">  [ 7] .shstrtab         STRTAB          0000000000000000 20b2a8 00003f 00      0   0  1</span>
294<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="applying-the-relocations" tabindex="-1"><a class="header-anchor" href="#applying-the-relocations"><span>Applying the relocations</span></a></h2><p>We now have a binary with relocation entries, so let&#39;s start by parsing the <code>.dynamic</code> section at the beginning of the image. Let&#39;s create a <code>loader.nim</code> module and define a <code>DynamicEntry</code> type to represent each entry, and a <code>DynamicEntryType</code>
294 enum to represent the different types of entries. We&#39;ll also define an <code>applyRelocations</code> proc to parse the dynamic section.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/loader.nim</span></span>
295<span class="line"></span>
296<span class="line"><span class="token keyword">type</span></span>
297<span class="line">  DynamicEntry <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
298<span class="line">    tag<span class="token operator">:</span> uint64</span>
299<span class="line">    value<span class="token operator">:</span> uint64</span>
300<span class="line"></span>
301<span class="line">  DynamicEntryType <span class="token operator">=</span> <span class="token keyword">enum</span></span>
302<span class="line">    Rela <span class="token operator">=</span> <span class="token number">7</span></span>
303<span class="line">    RelaSize <span class="token operator">=</span> <span class="token number">8</span></span>
304<span class="line">    RelaEntSize <span class="token operator">=</span> <span class="token number">9</span></span>
305<span class="line">    RelaCount <span class="token operator">=</span> <span class="token number">0x6ffffff9</span></span>
306<span class="line"></span>
307<span class="line"><span class="token keyword">proc</span> <span class="token function">applyRelocations<span class="token operator">*</span></span><span class="token punctuation">(</span>image<span class="token operator">:</span> <span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>byte<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">:</span> uint64 <span class="token operator">=</span></span>
308<span class="line">  <span class="token comment">## Apply relocations to the image. Return the entry point address.</span></span>
309<span class="line">  <span class="token keyword">var</span></span>
310<span class="line">    dyn <span class="token operator">=</span> <span class="token keyword">cast</span><span class="token punctuation">[</span><span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>DynamicEntry<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>image<span class="token punctuation">)</span></span>
311<span class="line">    reloffset <span class="token operator">=</span> <span class="token number">0&#39;u64</span></span>
312<span class="line">    relsize <span class="token operator">=</span> <span class="token number">0&#39;u64</span></span>
313<span class="line">    relentsize <span class="token operator">=</span> <span class="token number">0&#39;u64</span></span>
314<span class="line">    relcount <span class="token operator">=</span> <span class="token number">0&#39;u64</span></span>
315<span class="line"></span>
316<span class="line">  <span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span></span>
317<span class="line">  <span class="token keyword">while</span> dyn<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>tag <span class="token operator">!=</span> <span class="token number">0</span><span class="token operator">:</span></span>
318<span class="line">    <span class="token keyword">case</span> dyn<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>tag</span>
319<span class="line">    <span class="token operator">of</span> DynamicEntryType<span class="token operator">.</span>Rela<span class="token operator">.</span>uint64<span class="token operator">:</span></span>
320<span class="line">      reloffset <span class="token operator">=</span> dyn<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>value</span>
321<span class="line">    <span class="token operator">of</span> DynamicEntryType<span class="token operator">.</span>RelaSize<span class="token operator">.</span>
321uint64<span class="token operator">:</span></span>
322<span class="line">      relsize <span class="token operator">=</span> dyn<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>value</span>
323<span class="line">    <span class="token operator">of</span> DynamicEntryType<span class="token operator">.</span>RelaEntSize<span class="token operator">.</span>uint64<span class="token operator">:</span></span>
324<span class="line">      relentsize <span class="token operator">=</span> dyn<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>value</span>
325<span class="line">    <span class="token operator">of</span> DynamicEntryType<span class="token operator">.</span>RelaCount<span class="token operator">.</span>uint64<span class="token operator">:</span></span>
326<span class="line">      relcount <span class="token operator">=</span> dyn<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>value</span>
327<span class="line">    <span class="token keyword">else</span><span class="token operator">:</span></span>
328<span class="line">      <span class="token keyword">discard</span></span>
329<span class="line"></span>
330<span class="line">    inc i</span>
331<span class="line"></span>
332<span class="line">  <span class="token keyword">if</span> reloffset <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">or</span> relsize <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">or</span> relentsize <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">or</span> relcount <span class="token operator">==</span> <span class="token number">0</span><span class="token operator">:</span></span>
333<span class="line">    <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span>Exception<span class="token punctuation">,</span> <span class="token string">&quot;Invalid dynamic section. Missing .dynamic information.&quot;</span><span class="token punctuation">)</span></span>
334<span class="line"></span>
335<span class="line">  <span class="token keyword">if</span> relsize <span class="token operator">!=</span> relentsize <span class="token operator">*</span> relcount<span class="token operator">:</span></span>
336<span class="line">    <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span>Exception<span class="token punctuation">,</span> <span class="token string">&quot;Invalid dynamic section. .rela.dyn size mismatch.&quot;</span><span class="token punctuation">)</span></span>
337<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The proc iterates over the dynamic entries until it finds the entries we&#39;re interested in (the ones describing the <code>.rela.dyn</code> section). It then checks that the values are valid.</p><p>
337Now that we know where the relocation entries are, let&#39;s parse them. We&#39;ll define a <code>RelaEntry</code> type to represent each entry, and a <code>RelType</code> enum to represent the different types of entries. We&#39;ll use these types to parse the <code>.rela.dyn</code> section.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/loader.nim</span></span>
338<span class="line"></span>
339<span class="line"><span class="token keyword">type</span></span>
340<span class="line">  <span class="token operator">...</span></span>
341<span class="line"></span>
342<span class="line">  RelaEntry <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
343<span class="line">    offset<span class="token operator">:</span> uint64</span>
344<span class="line">    info<span class="token operator">:</span> RelaEntryInfo</span>
345<span class="line">    addend<span class="token operator">:</span> int64</span>
346<span class="line"></span>
347<span class="line">  RelaEntryInfo <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
348<span class="line">    <span class="token identifier"><span class="token punctuation">\`</span>type<span class="token punctuation">\`</span></span><span class="token operator">:</span> uint8</span>
349<span class="line">    sym<span class="token operator">:</span> uint8</span>
350<span class="line">    unused1<span class="token operator">:</span> uint16</span>
351<span class="line">    unused2<span class="token operator">:</span> uint32</span>
352<span class="line"></span>
353<span class="line">  RelType <span class="token operator">=</span> <span class="token keyword">enum</span></span>
354<span class="line">    Relative <span class="token operator">=</span> <span class="token number">8</span>  <span class="token comment"># R_X86_64_RELATIVE</span></span>
355<span class="line"></span>
356<span class="line"><span class="token keyword">proc</span> <span class="token function">applyRelocations<span class="token operator">*</span></span><span class="token punctuation">(</span>image<span class="token operator">:</span> <span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>byte<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">:</span> uint64 <span class="token operator">=</span></span>
357<span class="line">  <span class="token operator">...</span></span>
358<span class="line"></span>
359<span class="line">  <span class="token comment"># rela points to the first relocation entry</span></span>
360<span class="line">  <span class="token keyword">let</span> rela <span class="token operator">=</span> <span class="token keyword">cast</span><span class="token punctuation">[</span><span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>RelaEntry<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token function">cast[uint64]</span><span class="token punctuation">(</span>image<span class="token punctuation">)</span> <span class="token operator">+</span> reloffset<span class="token operator">.</span>uint64<span class="token punctuation">)</span></span>
361<span class="line"></span>
362<span class="line">  <span class="token keyword">for</span> i <span class="token operator">in</span> <span class="token number">0</span> <span class="token operator">..&lt;</span> relcount<span class="token operator">:</span></span>
363<span class="line">    <span class="token keyword">let</span> relent <span class="token operator">=</span> rela<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
364<span class="line">    <span class="token keyword">if</span> relent<span class="token operator">.</span>info<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">!=</span> RelType<span class="token operator">.</span>Relative<span class="token operator">.</span>uint8<span class="token operator">:</span></span>
365<span class="line">
365      <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span></span>
366<span class="line">        Exception<span class="token punctuation">,</span></span>
367<span class="line">        <span class="token operator">&amp;</span><span class="token string">&quot;Unsupported relocation type {relent.info.type:#x}. Only R_X86_64_RELATIVE is supported.&quot;</span></span>
368<span class="line">      <span class="token punctuation">)</span></span>
369<span class="line">    <span class="token comment"># apply relocation</span></span>
370<span class="line">    <span class="token keyword">let</span> target <span class="token operator">=</span> <span class="token function">cast[ptr uint64]</span><span class="token punctuation">(</span><span class="token function">cast[uint64]</span><span class="token punctuation">(</span>image<span class="token punctuation">)</span> <span class="token operator">+</span> relent<span class="token operator">.</span>offset<span class="token punctuation">)</span></span>
371<span class="line">    <span class="token keyword">let</span> value <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span><span class="token function">cast[int64]</span><span class="token punctuation">(</span>image<span class="token punctuation">)</span> <span class="token operator">+</span> relent<span class="token operator">.</span>addend<span class="token punctuation">)</span></span>
372<span class="line">    target<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> value</span>
373<span class="line"></span>
374<span class="line">  <span class="token comment"># entry point comes after .rela.dyn</span></span>
375<span class="line">  <span class="token keyword">return</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>image<span class="token punctuation">)</span> <span class="token operator">+</span> reloffset <span class="token operator">+</span> relsize</span>
376<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The proc iterates over the relocation entries and applies each one. The only type of relocation we support for now is relative relocation. For each relocation entry, we add the addend to the image base address and store the result at the offset specified by the relocation entry.</p><p>Finally, we return the entry point address, which comes right after the <code>.rela.dyn</code> section. This is the address we&#39;ll use to jump to user mode, instead of the fixed address we had before.</p><p>Let&#39;s modify the <code>createTask</code> proc in <code>tasks.nim</code> to use the new <code>applyRelocations</code> proc. We&#39;ll remove the <code>entryPoint</code> argument (passed in <code>main.nim</code>), and use the return value of <code>applyRelocations</code> as the entry point address.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/tasks.nim</span></span>
377<span class="line"><span class="token operator">...</span></span>
378<span class="line"></span>
379<span class="line"><span class="token keyword">proc</span> <span class="token function">createTask<span class="token operator">*</span></span><span class="token punctuation">(</span></span>
380<span class="line">  imageVirtAddr<span class="token operator">:</span> VirtAddr<span class="token punctuation">,</span></span>
381<span class="line">  imagePhysAddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span></span>
382<span class="line">  imagePageCount<span class="token operator">:</span>
382 uint64<span class="token punctuation">,</span></span>
383<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> Task <span class="token operator">=</span></span>
384<span class="line">  <span class="token operator">...</span></span>
385<span class="line"></span>
386<span class="line">  <span class="token comment"># map user image</span></span>
387<span class="line">  <span class="token operator">...</span></span>
388<span class="line"></span>
389<span class="line">  <span class="token comment"># (temporarily) map the user image in kernel space</span></span>
390<span class="line">  <span class="token function">mapRegion</span><span class="token punctuation">(</span></span>
391<span class="line">    pml4 <span class="token operator">=</span> kspace<span class="token operator">.</span>pml4<span class="token punctuation">,</span></span>
392<span class="line">    virtAddr <span class="token operator">=</span> imageVirtAddr<span class="token punctuation">,</span></span>
393<span class="line">    physAddr <span class="token operator">=</span> imagePhysAddr<span class="token punctuation">,</span></span>
394<span class="line">    pageCount <span class="token operator">=</span> imagePageCount<span class="token punctuation">,</span></span>
395<span class="line">    pageAccess <span class="token operator">=</span> paReadWrite<span class="token punctuation">,</span></span>
396<span class="line">    pageMode <span class="token operator">=</span> pmSupervisor<span class="token punctuation">,</span></span>
397<span class="line">  <span class="token punctuation">)</span></span>
398<span class="line">  <span class="token comment"># apply relocations to user image</span></span>
399<span class="line">  debugln <span class="token string">&quot;kernel: Applying relocations to user image&quot;</span></span>
400<span class="line">  <span class="token keyword">let</span> entryPoint <span class="token operator">=</span> <span class="token function">applyRelocations</span><span class="token punctuation">(</span><span class="token keyword">cast</span><span class="token punctuation">[</span><span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>byte<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>imageVirtAddr<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
401<span class="line"></span>
402<span class="line">  <span class="token comment"># map kernel space</span></span>
403<span class="line">  <span class="token operator">...</span></span>
404<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Finally, we&#39;ll remove the <code>entryPoint</code> argument from call in <code>main.nim</code>.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span>
405<span class="line"><span class="token operator">...</span></span>
406<span class="line"></span>
407<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMain</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
408<span class="line">  <span class="token operator">...</span></span>
409<span class="line"></span>
410<span class="line">  debugln <span class="token string">&quot;kernel: Creating user task&quot;</span></span>
411<span class="line">  <span class="token keyword">var</span> task <span class="token operator">=</span> <span class="token function">createTask</span><span class="token punctuation">(</span></span>
412<span class="line">
412    imageVirtAddr <span class="token operator">=</span> UserImageVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span></span>
413<span class="line">    imagePhysAddr <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePhysicalBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span></span>
414<span class="line">    imagePageCount <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePages<span class="token punctuation">,</span></span>
415<span class="line">  <span class="token punctuation">)</span></span>
416<span class="line"></span>
417<span class="line">  <span class="token operator">...</span></span>
418<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>That should do it. Let&#39;s compile and run the kernel.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token output">kernel: Creating user task</span>
419<span class="line">kernel: Applying relocations to user image</span>
420<span class="line">kernel: Switching to user mode</span>
421<span class="line">syscall: num=2</span>
422<span class="line">syscall: print (arg1=0x4020a298)</span>
423<span class="line">syscall: print: arg1.len = 21</span>
424<span class="line">syscall: print: arg1.p   = 0x40009d00</span>
425<span class="line">Hello from user mode!</span>
426<span class="line">syscall: num=1</span>
427<span class="line">syscall: exit: code=0</span>
428<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>It works! The message from the user task is printed correctly. We can see that the <code>arg1.p</code> value is now <code>0x40009d00</code> instead of <code>0</code>, which means that the relocation was applied correctly. To verify that we can load the task at any address, let&#39;s change the <code>UserImageVirtualBase</code> to something other than <code>0x40000000</code> and see if it still works.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span>
429<span class="line"></span>
430<span class="line"><span class="token keyword">const</span></span>
431<span class="line">  UserImageVirtualBase <span class="token operator">=</span> <span class="token number">0x80000000</span></span>
432<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token output">kernel: Creating user task</span>
433<span class="line">kernel: Applying relocations to user image</span>
434<span class="line">kernel: Switching to user mode</span>
435<span class="line">syscall: num=2</span>
436<span class="line">syscall: print (arg1=0x8020a298)</span>
437<span class="line">syscall: print: arg1.len = 21</span>
438<span class="line">syscall: print: arg1.p   = 0x80009d00</span>
439<span class="line">Hello from user mode!</span>
440<span class="line">syscall: num=1</span>
441<span class="line">syscall: exit: code=0</span>
442<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>It still works! Notice that the <code>arg1.p</code> value is now <code>0x80009d00</code> instead of <code>0x40009d00</code>, which proves that we can now load the user task at any address.</p><h2 id="dynamic-virtual-memory-allocation" tabindex="-1"><a class="header-anchor" href="#dynamic-virtual-memory-allocation"><span>Dynamic virtual memory allocation</span></a></h2><p>So far we&#39;ve been telling the kernel where to load the user task, but we want to be able to load tasks at any available address. The VMM keeps track of the available virtual memory, so we can leverage that to dynamically allocate virtual memory for the user task. Let&#39;s remove the <code>imageVirtAddr</code> argument from the <code>createTask</code> proc, and use the VMM to allocate the virtual memory for the user task.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/tasks.nim</span></span>
443<span class="line"><span class="token operator">...</span></span>
444<span class="line"></span>
445<span class="line"><span class="token keyword">proc</span> <span class="token function">createTask<span class="token operator">*</span></span><span class="token punctuation">(</span></span>
446<span class="line">  imagePhysAddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span></span>
447<span class="line">  imagePageCount<span class="token operator">:</span>
447 uint64<span class="token punctuation">,</span></span>
448<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> Task <span class="token operator">=</span></span>
449<span class="line">  <span class="token operator">...</span></span>
450<span class="line"></span>
451<span class="line">  <span class="token comment"># allocate user image vm region</span></span>
452<span class="line">  <span class="token keyword">let</span> imageVirtAddrOpt <span class="token operator">=</span> <span class="token function">vmalloc</span><span class="token punctuation">(</span>uspace<span class="token punctuation">,</span> imagePageCount<span class="token punctuation">,</span> paReadWrite<span class="token punctuation">,</span> pmUser<span class="token punctuation">)</span></span>
453<span class="line">  <span class="token keyword">if</span> imageVirtAddrOpt<span class="token operator">.</span>isNone<span class="token operator">:</span></span>
454<span class="line">    <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span>Exception<span class="token punctuation">,</span> <span class="token string">&quot;tasks: Failed to allocate VM region for user image&quot;</span><span class="token punctuation">)</span></span>
455<span class="line">  <span class="token keyword">let</span> imageVirtAddr <span class="token operator">=</span> imageVirtAddrOpt<span class="token operator">.</span>get</span>
456<span class="line"></span>
457<span class="line">  <span class="token comment"># map user image</span></span>
458<span class="line">  <span class="token operator">...</span></span>
459<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Now, let&#39;s modify the <code>KernelMain</code> proc to use the new <code>createTask</code> proc.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span>
460<span class="line"></span>
461<span class="line"><span class="token comment"># const</span></span>
462<span class="line"><span class="token comment">#   UserImageVirtualBase = 0x80000000  &lt;-- remove this</span></span>
463<span class="line"></span>
464<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMain</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
465<span class="line">  <span class="token operator">...</span></span>
466<span class="line"></span>
467<span class="line">  debugln <span class="token string">&quot;kernel: Creating user task&quot;</span></span>
468<span class="line">  <span class="token keyword">var</span> task <span class="token operator">=</span> <span class="token function">createTask</span><span class="token punctuation">(</span></span>
469<span class="line">    imagePhysAddr <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePhysicalBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span></span>
470<span class="line">    imagePageCount <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePages<span class="token punctuation">,</span></span>
471<span class="line">  <span class="token punctuation">)</span></span>
472<span class="line"></span>
473<span class="line">  <span class="token operator">...</span></span>
474<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If we compile and run the kernel, we should see the same output as before, with the user task being loaded at a different address.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token output">kernel: Creating user task</span>
475<span class="line">kernel: Applying relocations to user image</span>
476<span class="line">kernel: Switching to user mode</span>
477<span class="line">syscall: num=2</span>
478<span class="line">syscall: print (arg1=0x415678)</span>
479<span class="line">syscall: print: arg1.len = 21</span>
480<span class="line">syscall: print: arg1.p   = 0x2150e0</span>
481<span class="line">Hello from user mode!</span>
482<span class="line">syscall: num=1</span>
483<span class="line">syscall: exit: code=0</span>
484<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>It works! The user task is now loaded at a different address that was dynamically allocated, and the message is printed correctly.</p><p>This is another milestone; this means we can now load PIE tasks at any address, depending on the available virtual memory, and they all share the same address space. Keep in mind that we still need to have protection between tasks, so each task will still have its own page table mappings, but we won&#39;t have to rely on pre-arranging shared memory pages for inter-task communication. We&#39;ll get to that in a later section once we start tackling capabilities.</p><p>In the next section, we&#39;
484ll try to get two copies of the user task running at the same time, and try to switch between them using cooperative multitasking (we&#39;ll get to preemptive multitasking later).</p>`,95)]))}const c=n(i,[["render",l],["__file","20-position-independent-code.html.vue"]]),r=JSON.parse('{"path":"/osdev/20-position-independent-code.html","title":"Position Independent Code","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"What is PIC and PIE?","slug":"what-is-pic-and-pie","link":"#what-is-pic-and-pie","children":[]},{"level":2,"title":"Generating a static PIE","slug":"generating-a-static-pie","link":"#generating-a-static-pie","children":[]},{"level":2,"title":"Trying it out","slug":"trying-it-out","link":"#trying-it-out","children":[]},{"level":2,"title":"Understanding relocations","slug":"understanding-relocations","link":"#understanding-relocations","children":[]},{"level":2,"title":"Raw binary with relocations","slug":"raw-binary-with-relocations","link":"#raw-binary-with-relocations","children":[]},{"level":2,"title":"Applying the relocations","slug":"applying-the-relocations","link":"#applying-the-relocations","children":[]},{"level":2,"title":"Dynamic virtual memory allocation","slug":"dynamic-virtual-memory-allocation","link":"#dynamic-virtual-memory-allocation","children":[]}],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/20-position-independent-code.md","excerpt":"\\n<p>Fusion is a single address space OS, which means that all tasks share the same address\\nspace. This requires the ability to load task images at arbitrary addresses (depending on\\nthe available virtual memory). Currently, when we compile and link a task, the linker will\\ngenerate a binary that is not position independent; it has to be loaded at a\\npre-determined address. We need to change this and use position independent code (PIC)\\nobject files and position independent executables (PIE) instead.</p>"}');export{c as comp,r as data};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.