examples: Using custom version of SQLite (LD_PRELOAD) v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Fri, 29 Nov 2019 20:03:12 +0100
branchv_0
changeset 285 a6df8cac399e
parent 284 075d3d62d913
child 286 37c50bb1f36f
examples: Using custom version of SQLite (LD_PRELOAD)
relpipe-data/examples-tr-sqlite-custom-version.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/relpipe-data/examples-tr-sqlite-custom-version.xml	Fri Nov 29 20:03:12 2019 +0100
@@ -0,0 +1,133 @@
+<stránka
+	xmlns="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana"
+	xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro">
+	
+	<nadpis>Using custom version of SQLite (LD_PRELOAD)</nadpis>
+	<perex>switch to a newer or modified version of library using a little hack</perex>
+	<m:pořadí-příkladu>03600</m:pořadí-příkladu>
+
+	<text xmlns="http://www.w3.org/1999/xhtml">
+		
+		<p>
+			One of reasons why we prefer shared libraries (<code>.so</code>) rather than static linking,
+			is that shared libraries are much more hacker-friendly and allow the user switching to a newer or modified library without recompiling the program.
+		</p>
+		
+		<p>
+			By default, <code>relpipe-tr-sql</code> links to the SQLite library available in our distribution (e.g. 3.22).
+			As we can check:
+		</p>
+		
+		<m:pre jazyk="text"><![CDATA[$ ldd $(which relpipe-tr-sql) | grep sqlite
+    libsqlite3.so.0 => /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f4c73888000)]]></m:pre>
+	
+		<p>
+			But what if we want to use some new features like <a href="https://www.sqlite.org/windowfunctions.html">window functions</a> that are available in later (3.25) library versions?
+			Or what if we want to add our own custom modifications to this library?
+			Do we have to recompile the <m:name/> tools?
+		</p>
+		
+		<p>
+			No, we can just plug the new/modified library in and use it instead of the distribution one.
+		</p>
+		
+		<h2>Download and compile SQLite library</h2>
+		
+		<p>
+			The build process of SQLite should be straightforward:
+		</p>
+		
+		<m:pre jazyk="bash"><![CDATA[
+# Switch to the user for such experiments (optional but recommended):
+su - hacker
+
+# Create directories, download and extract sources:
+mkdir -p ~/src/sqlite
+cd ~/src/sqlite
+wget https://www.sqlite.org/2019/sqlite-autoconf-3300100.tar.gz
+tar xvzf sqlite-autoconf-3300100.tar.gz
+cd sqlite-autoconf-3300100/
+			
+# Optional: do some changes to the source code
+
+# Build SQLite:
+./configure
+make
+
+# Test it:
+echo "SELECT 'hello world'" | ./sqlite3
+]]></m:pre>
+
+		<p>
+			The desired shared libraries are located in the <code>.libs</code> directory.
+		</p>
+		
+		<h2>Use this library in the <m:name/> tools</h2>
+		
+		<p>
+			We have already build/installed <code>relpipe-tr-sql</code> which is linked to the SQLite library available in our distribution.
+			Then switching to a custom version of the library is very easy – we just need to set an environment variable.
+		</p>
+		
+		<m:pre jazyk="bash"><![CDATA[export LD_PRELOAD=~/src/sqlite/sqlite-autoconf-3300100/.libs/libsqlite3.so.0]]></m:pre>
+		
+		<p>And then <code>relpipe-tr-sql</code> will use the newer library version as we can check:</p>
+		
+		<m:pre jazyk="text"><![CDATA[$ ldd $(which relpipe-tr-sql) | grep sqlite
+    /home/hacker/src/sqlite/sqlite-autoconf-3300100/.libs/libsqlite3.so.0 (0x00007f9979578000)]]></m:pre>
+		
+		<p>Now we can use new features like window functions:</p>
+		
+		<m:pre jazyk="bash"><![CDATA[relpipe-in-fstab \
+	| relpipe-tr-sql \
+		--relation "fs_types" "
+			SELECT 
+				mount_point, 
+				type, 
+				count(*) OVER (PARTITION BY type) AS same_type_count 
+			FROM fstab" \
+	| relpipe-out-tabular]]></m:pre>
+	
+		<p>And get result like this one:</p>
+		<m:pre jazyk="text"><![CDATA[fstab:
+ ╭──────────────────────┬───────────────┬──────────────────────────╮
+ │ mount_point (string) │ type (string) │ same_type_count (string) │
+ ├──────────────────────┼───────────────┼──────────────────────────┤
+ │ /home                │ btrfs         │ 1                        │
+ │ /                    │ ext4          │ 2                        │
+ │ /mnt/data            │ ext4          │ 2                        │
+ │ /media/cdrom0        │ udf,iso9660   │ 1                        │
+ │ /mnt/private         │ xfs           │ 1                        │
+ ╰──────────────────────┴───────────────┴──────────────────────────╯
+Record count: 5]]></m:pre>
+		
+		
+		<p>That would not be possible with older versions of the SQLite library – as we can check by unsetting the <code>LD_PRELOAD</code> variable:</p>
+		<m:pre jazyk="bash"><![CDATA[unset LD_PRELOAD]]></m:pre>
+		<p>Which returns us to the previous state where SQLite from our distribution was used. And the calling the same SQL query leads to an error.</p>
+		
+		<p>
+			The <code>LD_PRELOAD</code> hack can be used with any other software – it is not specific to <m:name/>.
+			Another example is the <a href="https://mouse.globalcode.info/v_0/spacenav-hack.xhtml">Spacenav Hack</a>  which bridges/translates two APIs of a library.
+		</p>
+
+				
+		<h2>ABI compatibility</h2>
+		
+		<p>
+			The prerequisite for such easy library swapping is the compatibility of the ABI (application binary interface).
+			It means that we can change the library internals (the SQL language features in this case) but we must retain the compiled representation of the C functions compatible
+			so the both parts (the library and the program) will still fit together. We can not e.g. remove a C function.
+			And we should also not do any incompatible changes on the semantic level (although it could still link together, it would lead to unwanted results).
+		</p>
+		
+		<p>
+			In case of libraries that follow the <a href="https://semver.org/">Semantic versioning</a> (as required by <a href="https://sane-software.globalcode.info/">Sane software manifesto</a>) for their ABI,
+			it is easy to say which versions are compatible and which would require recompiling the program or even changing its source code.
+			If the <em>patch</em> or <em>minor</em> version numbers were changed, the libraries could be swapped this way.
+			If the <em>major</em> version was changed, it would be probably necessary to also modify the software that uses this library.
+		</p>
+		
+	</text>
+
+</stránka>