<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
	<title>Via Insita</title>
	<link>https://viainsita.com.hr/</link>
	<description>Recent content on Via Insita</description>
	<generator>Hugo -- gohugo.io</generator>
	<language>en-us</language>
	<lastBuildDate>Sat, 03 Jan 2026 10:45:57 +0100</lastBuildDate>
    
        <atom:link href="https://viainsita.com.hr/index.xml" rel="self" type="application/rss+xml" />
	
	
	<item>
		<title>Zephyr template project for event-driven application development</title>
		<link>https://viainsita.com.hr/zephyr_template_project_for_event_driven_application_development/</link>
		<pubDate>Sat, 03 Jan 2026 10:45:57 +0100</pubDate>
		
		<guid>https://viainsita.com.hr/zephyr_template_project_for_event_driven_application_development/</guid>
		<description>&lt;p&gt;It&amp;rsquo;s been quite some time since I got a taste of working with Zephyr so I decided to revisit some old code I have written to see if I can turn it into something useful that other developers could use.&lt;/p&gt;
&lt;p&gt;After a few interations, I&amp;rsquo;ve decided to reshape this old code into an event-driven template project for developing C++ applications. You can take a look at the template on &lt;a href=&#34;https://github.com/martincvitic19/zephyr-event-driven-blueprint&#34;&gt;my Github repository&lt;/a&gt; where you will see further instructions on building and flashing your project with the template.&lt;/p&gt;
&lt;p&gt;It is basically a blinky with sane hardware support for user interaction (i.e. button and LED) so you can easily start from that point and then upscale the complexity of your project as needed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/demo.gif&#34; alt=&#34;event-driven project template demo&#34; title=&#34;demo&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you would like to support the work I do, consider donating &lt;a href=&#34;https://viainsita.com.hr/about&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Setting up Yocto for efficient embedded Linux systems development</title>
		<link>https://viainsita.com.hr/setting_up_yocto_for_efficient_embedded_linux_systems_development/</link>
		<pubDate>Sun, 27 Jul 2025 06:24:13 +0200</pubDate>
		
		<guid>https://viainsita.com.hr/setting_up_yocto_for_efficient_embedded_linux_systems_development/</guid>
		<description>&lt;p&gt;In this blog post, I will explain how I&amp;rsquo;ve set up my workstation for building custom Linux image for STM32MP157D-DK1 and demonstrate a basic build in this setup.&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#first-yocto-build&#34;&gt;First Yocto build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#build-process-and-basic-yocto-lexicon&#34;&gt;Build process and basic Yocto lexicon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#advanced-yocto-configuration&#34;&gt;Advanced Yocto configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#summary&#34;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Similarly to my previous posts, this writeup is based on Bootlin&amp;rsquo;s &lt;a href=&#34;https://bootlin.com/doc/training/yocto-stm32/yocto-stm32-labs.pdf&#34;&gt;Yocto labs&lt;/a&gt;. And as always, thanks to Bootlin for making their materials free and open source!&lt;/p&gt;
&lt;p&gt;Before starting with Yocto, make sure you check all the required boxes for working with Yocto as described in &lt;a href=&#34;https://docs.yoctoproject.org/ref-manual/system-requirements.html&#34;&gt;Yocto&amp;rsquo;s system requirements reference manual&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This especially goes out to all Arch-based distro users as it doesn&amp;rsquo;t support natively!&lt;/p&gt;
&lt;p&gt;Even though it is possible to work with Yocto on an Arch-based distribution, the build environment must be at least containerized which many users prefer and I would argue makes the builds more easily reproducible and transferable. If one opts no to use podman or docker to do do and still work with Yocto on Arch or similar non-supported distros, get ready to jump through some hoops because there will be quite few of them.&lt;/p&gt;
&lt;p&gt;Also, make sure your home directory is not encrypted with &lt;a href=&#34;https://www.ecryptfs.org/&#34;&gt;eCryptFS&lt;/a&gt; since OpenEmbedded cannot be used on top of it due to limitation in file name lengths.&lt;/p&gt;
&lt;p&gt;If you are using Ubuntu: Ubuntu 24.04 added an apparmor policy preventing usage of unprivileged user namespace restrictions to improve security. This prevents &lt;code&gt;bitbake&lt;/code&gt; from working, because it uses namespaces to forbid
untracked downloads outside of the &lt;code&gt;do_fetch&lt;/code&gt; task (we will get to terminology and technicalities later, don&amp;rsquo;t worry if you don&amp;rsquo;t understand these terms).
Ironically, &lt;code&gt;bitbake&lt;/code&gt; does this to improve security. This
results in operation not permitted error which can be disabled by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You will need to run this command time you reboot your machine or look at the &lt;a href=&#34;https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#p-99950-unprivileged-user-namespace-restrictions&#34;&gt;Ubuntu 24.04 Release Notes&lt;/a&gt; to see how to disable this restriction permanently.&lt;/p&gt;
&lt;h2 id=&#34;first-yocto-build&#34;&gt;First Yocto build&lt;/h2&gt;
&lt;p&gt;SIDE NOTE: For a quick build, you can check out &lt;a href=&#34;https://docs.yoctoproject.org/brief-yoctoprojectqs/index.html&#34;&gt;Yocto Project Quick Build&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The first prerequisite to building with a Yocto image for SMT32MP157D-DK1 is to install required packages and to download data which we will use for our board.&lt;/p&gt;
&lt;p&gt;First, install the required packages:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential \
chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils \
iputils-ping python3-git python3-jinja2 python3-subunit zstd liblz4-tool \
file locales libacl1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, obtain data we will use for working with target board in this setup:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd
$ wget https://bootlin.com/doc/training/yocto-stm32/yocto-stm32-labs.tar.xz
$ tar xvf yocto-stm32-labs.tar.xz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After that, update your distribution:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ sudo apt update
$ sudo apt dist-upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next, download Yocto (I used the &lt;code&gt;scarthgap&lt;/code&gt; version of Poky reference distribution):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git clone https://git.yoctoproject.org/git/poky
$ cd $HOME/yocto-stm32-labs/poky
$ git checkout -b scarthgap-5.0.1 scarthgap-5.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, return to project root directory and download the OpenEmbedded and STM32MP layers:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd $HOME/yocto-stm32-labs/
$ git clone -b scarthgap https://git.openembedded.org/meta-openembedded
$ git clone https://github.com/STMicroelectronics/meta-st-stm32mp
$ cd meta-st-stm32mp
$ git checkout b820cf3a1a855d2bd95969251e6465e281502759
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You now just need to set up the build environment:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd $HOME/yocto-stm32-labs
$ source poky/oe-init-build-env
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and you are now ready to use the &lt;code&gt;bitbake&lt;/code&gt; which is Yocto&amp;rsquo;s main build engine.&lt;/p&gt;
&lt;p&gt;To build specifically for SMT32MP157D-DK1, you must specify the target machine in the &lt;code&gt;conf/local.conf&lt;/code&gt; configuration file.&lt;/p&gt;
&lt;p&gt;To save disk space on your computer, you can add &lt;code&gt;INHERIT += &amp;quot;rm_work&amp;quot;&lt;/code&gt; at the end of the same file which will remove package work directory once a package is built.&lt;/p&gt;
&lt;p&gt;Also, the build configuration needs to be aware of the OpenEmbedded and STM32MP layers. This is done by editing the &lt;code&gt;$BUILDDIR/conf/bblayers.conf&lt;/code&gt; configuration file by adding full paths to layers to the &lt;code&gt;BBLAYERS&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;If not done already, make sure to configure your git username and email as some recipe builds can fail without it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git config --global user.name &amp;quot;Your Name&amp;quot;
$ git config --global user.email &amp;quot;your@email.com&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To test image build with set configuration, run the following from the sourced environment:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ bitbake core-image-minimal
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This build will initially last for quite some time. Mine was building for an hour if I recall correctly.
Anyway, the build might fail for various unexpected reasons. One might be due to RAM limitations where you can build the failing recipe individually will all the RAM available for it. Simply rerunning &lt;code&gt;bitbake core-image-minimal&lt;/code&gt; sometimes did the trick for me because &lt;code&gt;bitake&lt;/code&gt; caches various stages of the build so it doesn&amp;rsquo;t have to rebuild the same recipes over again when rebuilding the full image.&lt;/p&gt;
&lt;p&gt;In that case, make sure to search though the internet for your specific build issue if one occurs.&lt;/p&gt;
&lt;p&gt;Once the build is finished, you can observe the output image under &lt;code&gt;$BUILDDIR/tmp/deploy/images/stm32mp1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, the easiest way to transfer the newly built image onto the board is by using an SD card. Insert your SD you plan to use to store the bootloader, kernel and root filesystem files into the SD card reader of your computer.&lt;/p&gt;
&lt;p&gt;To generate the final image for the board run the following script located in &lt;code&gt;$BUILDDIR/tmp/deploy/images/stm32mp1/scripts&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./create_sdcard_from_flashlayout.sh \
../flashlayout_core-image-minimal/extensible/FlashLayout_sdcard_\
stm32mp157d-dk1-extensible.tsv
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, flash the SD card with image:&lt;/p&gt;
&lt;p&gt;WARNING: make sure you are 100% sure you know which partition are you writing to because overwriting other paritions might cause irreversible changes!&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ umount /dev/mmcblk0p*
$ sudo dd if=../FlashLayout_sdcard_stm32mp157d-dk1-extensible.raw of=/dev/mmcblk0 bs=8M \
conv=fdatasync status=progress
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To observe the booting process of our custom Linux distribution we have places onto the SD card, we first need to set up serial communication with SMT32MP157D-DK1. Plug the USB-A to micro USB-B cable on the Discovery board to micro USB port (CN11) which is actually ST-LINK.
This is a debug interface and exposes multiple debugging interfaces including a serial interface. When you plug it in your computer, a serial device should appear. The exact name of it can be observed by looking ath the output of &lt;code&gt;dmesg&lt;/code&gt; utility. Once we have identified the device, we can pass it to &lt;code&gt;picocom&lt;/code&gt; in order to start the serial communication with the board:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;picocom -b 115200 /dev/ttyACM0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can now insert the SD card into the dedicated slot on the STM32MP157D-DK1 and then power up the baord by connecting the USB-C cable to the board (CN6).
You should now see boot messages in &lt;code&gt;picocom&lt;/code&gt;. Wait until the login prompt and then enter &lt;code&gt;root&lt;/code&gt; as username and &lt;code&gt;root&lt;/code&gt; as password.&lt;/p&gt;
&lt;p&gt;Great! The board has booted and now we have access to the shell!&lt;/p&gt;
&lt;h2 id=&#34;build-process-and-basic-yocto-lexicon&#34;&gt;Build process and basic Yocto lexicon&lt;/h2&gt;
&lt;p&gt;in principle, you can think of Yocto as a build system that takes custom built and open-source components as an input and builds binary packages (i.e. distributions) as its output.&lt;/p&gt;
&lt;h2 id=&#34;yocto-lexicon&#34;&gt;Yocto lexicon&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bitbake&lt;/code&gt;: Yocto&amp;rsquo;s main build engine that functions like a task scheduler parsing text files (i.e. recipes) to what to build and how to build it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;recipe&lt;/code&gt;: a text file that describes how to fetch and build a software component - program, library or an image&lt;/li&gt;
&lt;li&gt;&lt;code&gt;task&lt;/code&gt;: a specific step of the build process / a smaller execution unit of a recipe being built
&lt;ul&gt;
&lt;li&gt;for example: &lt;code&gt;fetch&lt;/code&gt;,&lt;code&gt;configure&lt;/code&gt;, &lt;code&gt;compile&lt;/code&gt;, &lt;code&gt;package&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metadata&lt;/code&gt;: configuration files, recipes, classes and include files organized in &lt;code&gt;layers&lt;/code&gt; which act as an input to &lt;code&gt;bitbake&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layer&lt;/code&gt;: a set of configuration files, recipes, classes and include files with a common purpose
&lt;ul&gt;
&lt;li&gt;for example, &lt;a href=&#34;https://layers.openembedded.org/layerindex/branch/kirkstone/layer/meta-stm32mp15x/&#34;&gt;&lt;code&gt;meta-stm32mp15x&lt;/code&gt;&lt;/a&gt; for STM32MP157x board support package&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://layers.openembedded.org/layerindex/branch/master/layer/openembedded-core/&#34;&gt;&lt;code&gt;openembedded-core&lt;/code&gt;&lt;/a&gt; is the core layer that all other layers a built on top of&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poky&lt;/code&gt;: Yocto&amp;rsquo;s reference distribution (tools and metadata) which serves as a starting point for building custom embedded Linux system&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;advanced-yocto-configuration&#34;&gt;Advanced Yocto configuration&lt;/h2&gt;
&lt;h3 id=&#34;setting-up-ethernet-communication-and-nfs-on-the-board&#34;&gt;Setting up Ethernet communication and NFS on the board&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s very impractical to to reflash the root filesystem onto the SD card every time Yocto rebuilds an image. This is why it is very useful to set up networking between the development workstation (host) and the target machine because the target machine can then access workstation files using &lt;a href=&#34;https://en.wikipedia.org/wiki/Network_File_System&#34;&gt;NFS&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;We first need to set the kernel boot arguments U-Boot will pass to the Linux kenrel on the target at boot time. To do that, modify the &lt;code&gt;mmc0_extlinux/extlinux.conf&lt;/code&gt; configuration file and cahnge the &lt;code&gt;APPEND&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;APPEND root=/dev/nfs rw console=ttySTM0,115200 nfsroot=192.168.0.1:/nfs,vers=3,tcp ip=192.168.0.100
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;setting-up-ethernet-communication-on-the-workstation&#34;&gt;Setting up Ethernet communication on the workstation&lt;/h3&gt;
&lt;p&gt;Now with a network cable, connect the Ethernet port of the board to the computer over the USB Ethernet adapter if your computer already has a wired connection to the network. A new network interface should appear on your computer that you can check by running &lt;code&gt;ip a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The network interface name is &lt;code&gt;enxxx&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You now need to make sure you set the static IP of that port to be in a different subnet of where your computer is connected. You can do that over the command line:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;nmcli con add type ethernet ifname en... ip4 192.168.0.1/24
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Change &lt;code&gt;en...&lt;/code&gt; and &lt;code&gt;192.160.1/24&lt;/code&gt; to fit your network configuaration.&lt;/p&gt;
&lt;h3 id=&#34;setting-up-the-nfs-server-on-the-workstation&#34;&gt;Setting up the NFS server on the workstation&lt;/h3&gt;
&lt;p&gt;First install the NFS server on the workstation by running the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ sudo apt install nfs-kernel-server
$ sudo mkdir -m 777 /nfs
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then make sure this directory is used and exported by the NFS server by adding the following line to the &lt;code&gt;/etc/exports&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/nfs *(rw,sync,no_root_squash,subtree_check) # NOTE: modify the last parameter to no_subtree_check if needed!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, make the NFS server use the new configuration:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ sudo exportfs -r
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;adding-ssh-support&#34;&gt;Adding SSH support&lt;/h3&gt;
&lt;p&gt;We will now add a package called &lt;code&gt;dropbear&lt;/code&gt; to support connecting to the board over SSH by appending the &lt;code&gt;IMAGE_INSTALL&lt;/code&gt; variable &lt;code&gt;$BUILDDIR/conf/local.conf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The Dropbear SSH server is now enabled and runs as a service on the STM32MP157D-DK1 board.&lt;/p&gt;
&lt;p&gt;We first need to put the rootfs under the NFS root directory so that it is accessible by NFS clients. To do taht, uncompress the archived output image in the previously created &lt;code&gt;/nfs&lt;/code&gt; directory:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo tar xpf $BUILDDIR/tmp/deploy/images/stm32mp1/\
core-image-minimal-stm32mp1.rootfs.tar.xz -C /nfs
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now boot the board and open a separate terminal to access it using ssh:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ssh root@192.168.2.100
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;setting-up-tftp&#34;&gt;Setting up TFTP&lt;/h3&gt;
&lt;p&gt;Setting up &lt;a href=&#34;https://en.wikipedia.org/wiki/Trivial_File_Transfer_Protocol&#34;&gt;TFTP&lt;/a&gt; is extremely useful since it lets us bypass having to reflash the SD card for every test.&lt;/p&gt;
&lt;p&gt;We first need to install a TFTP server on our host machine:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ sudo apt install tftp-hpa
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We then need tp copy the Linux kernel image and the device tree to the TFTP server home directory (which is &lt;code&gt;/srv/tftp&lt;/code&gt; in my case as defined in &lt;code&gt;/etc/default/tftpd-hpa&lt;/code&gt;) so that they are reachable by the TFTP server.&lt;/p&gt;
&lt;p&gt;We then need to boot the board and interrupt the booting process to enter in the U-Boot shell and change the &lt;code&gt;bootcmd&lt;/code&gt; variable to load the kernel image and the device tree over TFTP:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;setenv ipaddr &amp;lt;your-client-ip&amp;gt;
setenv serverip &amp;lt;your-server-ip&amp;gt;
setenv bootcmd &#39;tftp 0xc2000000 zImage; tftp 0xc4000000 dtb; bootz 0xc2000000 - 0xc4000000&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And finally, set the &lt;code&gt;bootargs&lt;/code&gt; variable as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;setenv bootargs root=/dev/nfs rw console=ttySTM0,115200 nfsroot=&amp;lt;your-server-ip&amp;gt;:/nfs,vers=3,tcp ip=&amp;lt;your-client-ip&amp;gt;
saveenv
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For more information on how to set up TFTP, make sure you check out section on this &lt;a href=&#34;https://bootlin.com/doc/training/yocto-stm32/yocto-stm32-labs.pdf&#34;&gt;link&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s it. You now have a well configured and hassle-free setup for developing with Yocto!&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Using Yocto to create a Linux-based gaming console</title>
		<link>https://viainsita.com.hr/using_yocto_to_create_a_linux-based_gaming_console/</link>
		<pubDate>Mon, 21 Jul 2025 16:01:39 +0200</pubDate>
		
		<guid>https://viainsita.com.hr/using_yocto_to_create_a_linux-based_gaming_console/</guid>
		<description>&lt;p&gt;In this blog post, I will explain how I built the world&amp;rsquo;s worst gaming console (at least by today&amp;rsquo;s standards but it makes it one of the best anti-gaming consoles today in my opinion):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/worst_console.jpeg&#34; alt=&#34;worst_console.jpeg&#34;&gt;&lt;/p&gt;
&lt;p&gt;As you can see from the picture above, the user experience is terrible and this console is extremely poorly portable because of cabling and jumper wires used to connect the Wii Nunchuck and the &lt;a href=&#34;https://www.st.com/en/evaluation-tools/stm32mp157d-dk1.html&#34;&gt;STM32MP157D-DK1&lt;/a&gt; board. Other than that there is only one game you can play and it&amp;rsquo;s &lt;a href=&#34;https://ninvaders.sourceforge.net/&#34;&gt;nInvaders&lt;/a&gt; - a ncurses &lt;a href=&#34;https://en.wikipedia.org/wiki/Space_Invaders&#34;&gt;Space Invaders&lt;/a&gt; clone.&lt;/p&gt;
&lt;p&gt;This is exactly why it&amp;rsquo;s one of the best anti-gaming consoles.&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#writing-a-recipe-to-support-ninvaders-and-integrating-it-to-an-existing-layer&#34;&gt;Writing a recipe to support nInvaders and integrating it to an existing layer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#applying-patches-to-an-existing-recipe-by-adding-joystick-support&#34;&gt;Applying patches to an existing recipe by adding joystick support&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;in this blog post, I will be using the setup I describred in my &lt;a href=&#34;https://viainsita.com.hr/setting_up_yocto_for_efficient_embedded_linux_systems_development&#34;&gt;Setting up workspace for developing and building custom Linux-based distributions with Yocto&lt;/a&gt; blog post.&lt;/p&gt;
&lt;p&gt;Similary to my previous posts, this writeup is based on Bootlin&amp;rsquo;s &lt;a href=&#34;https://bootlin.com/doc/training/yocto-stm32/yocto-stm32-labs.pdf&#34;&gt;Yocto labs&lt;/a&gt;. And as always, thanks to Bootlin for making their materials free and open source!&lt;/p&gt;
&lt;p&gt;Before we continue, I would like to give a quick refresher of some basic terms used when working with Yocto as described in my previous post with regards the &lt;a href=&#34;setting_up_yocto_for_efficient_embedded_linux_systems_development&#34;&gt;Setting up Yocto for efficient embedded Linux system development&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bitbake&lt;/code&gt;: Yocto&amp;rsquo;s main build engine that functions like a task scheduler parsing text files (i.e. recipes) to what to build and how to build it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;recipe&lt;/code&gt;: a text file that describes how to fetch and build a software component - program, library or an image&lt;/li&gt;
&lt;li&gt;&lt;code&gt;task&lt;/code&gt;: a specific step of the build process / a smaller execution unit of a recipe being built
&lt;ul&gt;
&lt;li&gt;for example: &lt;code&gt;fetch&lt;/code&gt;,&lt;code&gt;configure&lt;/code&gt;, &lt;code&gt;compile&lt;/code&gt;, &lt;code&gt;package&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metadata&lt;/code&gt;: configuration files, recipes, classes and include files organized in &lt;code&gt;layers&lt;/code&gt; which act as an input to &lt;code&gt;bitbake&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layer&lt;/code&gt;: a set of configuration files, recipes, classes and include files with a common purpose
&lt;ul&gt;
&lt;li&gt;for example, &lt;a href=&#34;https://layers.openembedded.org/layerindex/branch/kirkstone/layer/meta-stm32mp15x/&#34;&gt;&lt;code&gt;meta-stm32mp15x&lt;/code&gt;&lt;/a&gt; for STM32MP157x board support package&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://layers.openembedded.org/layerindex/branch/master/layer/openembedded-core/&#34;&gt;&lt;code&gt;openembedded-core&lt;/code&gt;&lt;/a&gt; is the core layer that all other layers a built on top of&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poky&lt;/code&gt;: Yocto&amp;rsquo;s reference distribution (tools and metadata) which serves as a starting point for building custom embedded Linux system&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want more details, either check out the previous blog post or better yet, check out the &lt;a href=&#34;https://docs.yoctoproject.org/ref-manual/terms.html&#34;&gt;official Yocto Project terms&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;writing-a-recipe-to-support-ninvaders-and-integrating-it-to-an-existing-layer&#34;&gt;Writing a recipe to support nInvaders and integrating it to an existing layer&lt;/h2&gt;
&lt;p&gt;Before downloading nInvaders, make sure you run the follwing command in poky&amp;rsquo;s root directory:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;source oe-init-build-env
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This now lets you use &lt;code&gt;bitbake&lt;/code&gt; for your builds.&lt;/p&gt;
&lt;p&gt;Next, locate the &lt;code&gt;recipes-extended&lt;/code&gt; directory and create a directory for &lt;code&gt;nInvaders&lt;/code&gt; where you will download the &lt;a href=&#34;https://ninvaders.sourceforge.net/&#34;&gt;source code&lt;/a&gt; of the game. In my case, this was:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/yocto-stm32-labs/meta-openembedded/meta-oe/recipes-extended/ninvaders
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next, inside the same directory, create a recipe which will tell &lt;code&gt;bitbake&lt;/code&gt; how to handle building &lt;code&gt;nInvders&lt;/code&gt;. The recipe name should follow the Yocto nomenclature - {recipe_name}_{recipe_version}.bb. More info on Yocto naming conventions can be found &lt;a href=&#34;https://docs.yoctoproject.org/ref-manual/variables.html&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The link to my recipe can be found on my corresponding &lt;a href=&#34;https://github.com/martincvitic19/bootlin-yocto-stm32-labs-solutions&#34;&gt;GitHub page&lt;/a&gt;.
Here is a preview of how I&amp;rsquo;ve written the recipe:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/ninvaders_src.png&#34; alt=&#34;nInvaders_src&#34;&gt;&lt;/p&gt;
&lt;p&gt;You can now build the recipe by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bitbake ninvaders
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Output of the build process should look something like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/bitbake_ninvaders.png&#34; alt=&#34;bitbake_ninvaders&#34;&gt;&lt;/p&gt;
&lt;p&gt;Build files of the recipe we have now built is in &lt;code&gt;tmp/work/...&lt;/code&gt; folder:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/ninvaders_dir_in_build_work_dir.png&#34; alt=&#34;ninvaders_dir_in_build_work_dir&#34;&gt;&lt;/p&gt;
&lt;p&gt;A good practice before generating a new image which will end up on the target board is to verify in which layer is the recipe which contains our application present as well as is the application built for proper architecture which is &lt;code&gt;arm&lt;/code&gt; in our case.&lt;/p&gt;
&lt;p&gt;Running &lt;code&gt;bibake-layers show-layer ninvaders&lt;/code&gt; from the &lt;code&gt;build&lt;/code&gt; folder will show where is our recipe present:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/check_ninvaders_recipe.png&#34; alt=&#34;check_ninvaders_recipe&#34;&gt;&lt;/p&gt;
&lt;p&gt;Great, our recipe is included in the &lt;code&gt;meta-oe&lt;/code&gt; layer. Even though this is not the best practice (and we will fix that in quite soon), we can be sure that it is included in the build since &lt;code&gt;meta-oe&lt;/code&gt; is definately included in the build:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/bitbake_layers.png&#34; alt=&#34;bitbake_layers&#34;&gt;&lt;/p&gt;
&lt;p&gt;Finally, let&amp;rsquo;s verify that the ninvaders recipe has been built for proper architecture by running &lt;code&gt;bitbake -e ninvaders | ^TARGET_ARCH=&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/bitbake_Xcompiling_check.png&#34; alt=&#34;bitbake_Xcompiling_check&#34;&gt;&lt;/p&gt;
&lt;p&gt;Once nInvaders recipe has been successfully built, generate a new rootfs image which will contain nInvaders by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bitbake core-image-minimal
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The image with our ninvaders application is now in &lt;code&gt;/tmp/deploy/images...&lt;/code&gt; and we can now extract the image to our NFS root directory on the host machine (&lt;code&gt;/nfs&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/extract_ninvaders_to_nfs.png&#34; alt=&#34;extract_ninvaders_to_nfs&#34;&gt;&lt;/p&gt;
&lt;p&gt;where we see our ninvaders app in the third column in the lower mid section. Great!&lt;/p&gt;
&lt;p&gt;We can now just connect over ssh to board, and run &lt;code&gt;nInvaders&lt;/code&gt; from &lt;code&gt;/usr/bin&lt;/code&gt; by running &lt;code&gt;/usr/bin/ninvaders&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/play_ninvaders.png&#34; alt=&#34;play_ninvaders&#34;&gt;
&lt;img src=&#34;https://viainsita.com.hr/play_ninvaders_pt2.png&#34; alt=&#34;play_ninvaders_pt2&#34;&gt;&lt;/p&gt;
&lt;p&gt;We can now use the keyboard to play &lt;code&gt;nInvaders&lt;/code&gt; on STM32MP157D-DK1!&lt;/p&gt;
&lt;h2 id=&#34;creating-and-integrating-a-custom-yocto-layer-into-the-build&#34;&gt;Creating and integrating a custom Yocto layer into the build&lt;/h2&gt;
&lt;p&gt;It is a good practice to leave your custom software fully decoupled from basic Yocto project files. This goes for both adding new recipes or customizing the existing ones. This is why I will go through explaining how to create a new layer with our application which we will integrate into the build.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s add a new layer into the build. This can be done by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bitbake-layers reate-layer meta-bootlinlabs --priority 7

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can now verify that the layer has been added either by running &lt;code&gt;bitbake-layers show-layers&lt;/code&gt;:
&lt;img src=&#34;https://viainsita.com.hr/ninvaders_part_of_different_layer_now.png&#34; alt=&#34;ninvaders_part_of_different_layer_now&#34;&gt;&lt;/p&gt;
&lt;p&gt;To integrate this newly created layer into the build, add it to the &lt;code&gt;conf/bblayers.conf&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/add_meta_bootlinlabs.png&#34; alt=&#34;add_meta_bootlinlabs&#34;&gt;&lt;/p&gt;
&lt;p&gt;We can now move the ninvaders recipe into our custom &lt;code&gt;meta-bootlinlabs&lt;/code&gt; layer by simply copying all of the contents from &lt;code&gt;/yocto-stm32-labs/meta-openembedded/meta-oe/recipes-extended/ninvaders&lt;/code&gt; to &lt;code&gt;yocto-stm32-labs/meta-bootlinlabs&lt;/code&gt;. To can now either delete old files from the &lt;code&gt;recipes-extended&lt;/code&gt; directory or leave them as they are. &lt;code&gt;bitbake&lt;/code&gt; will build the ninvaders recipe with the higher priority first anyway. You can now check that ninvaders recipe is part of our new &lt;code&gt;meta-bootlinlabs&lt;/code&gt; layer by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bitbake-layers show-recipes ninvaders
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/ninvaders_part_of_different_layer_now.png&#34; alt=&#34;ninvaders_part_of_different_layer_now&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;applying-patches-to-an-existing-recipe-by-adding-joystick-support&#34;&gt;Applying patches to an existing recipe by adding joystick support&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;bitbake&lt;/code&gt; allows users to extend recipes by the means of .bbappend files. In this chapter we will go thorugh extending the &lt;code&gt;linux-stm32mp&lt;/code&gt; recipe by applying a patch and including it into the build. This patch which will enable us to play nInvaders with &lt;a href=&#34;https://www.olimex.com/Products/Modules/Sensors/MOD-WII/MOD-Wii-UEXT-NUNCHUCK/&#34;&gt;Wii&amp;rsquo;s Nunchuck joystick&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, we will create a &lt;code&gt;linux-stm32mp_6.1.bbappend&lt;/code&gt; file in the &lt;code&gt;/yocto-stm32-labs/meta-bootlinlabs/recipes-kernel/linux&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;You can now run &lt;code&gt;bitbake-layers show-appends&lt;/code&gt; to see all the available &lt;code&gt;bbappend&lt;/code&gt; files and the recipe they apply to. There you can see the &lt;code&gt;.bbappend&lt;/code&gt; file we have created for our kernel recipe:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/append_present.png&#34; alt=&#34;append_present&#34;&gt;&lt;/p&gt;
&lt;p&gt;The content of the &lt;code&gt;.bbappend&lt;/code&gt; file can be seen &lt;a href=&#34;https://github.com/martincvitic19/bootlin-yocto-stm32-labs-solutions/blob/solutions/linux-stm32mp_6.1.bbappend&#34;&gt;here&lt;/a&gt;, and here is the preview for illustrative purposes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/append_content.png&#34; alt=&#34;append_content&#34;&gt;&lt;/p&gt;
&lt;p&gt;Notice how the &lt;code&gt;.bbappend&lt;/code&gt; file matches the exact recipe name of a file we want to extend. The needed patch for using the Nunchuck joystick as input to our console was provided by Bootlin and is present &lt;a href=&#34;https://github.com/bootlin/training-materials/tree/master/lab-data/yocto-stm32/bootlin-lab-data&#34;&gt;on this link&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As you can see, &lt;code&gt;defconfig&lt;/code&gt; and patches are present in the source file list. Last two lines are used as an inidication to the &lt;code&gt;linux-stm32mp&lt;/code&gt; recipe to use kernel configuration as defined by &lt;code&gt;defconfig&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Treeview of the directory responsible for handling the nunchuck at the kernel level is now:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/patch_file_organization.png&#34; alt=&#34;patch_file_organization&#34;&gt;&lt;/p&gt;
&lt;p&gt;You can now rebuild the kernel to verify that the patches have been included into the build by running &lt;code&gt;cat ...&lt;/code&gt; after rebuilding the kernel with &lt;code&gt;bitbake virtual/kernel&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/patch_is_present_virtual.png&#34; alt=&#34;patch_is_present_virtual&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.bbappend&lt;/code&gt; file responsible for handling the nunchuck at the application level is &lt;a href=&#34;https://github.com/martincvitic19/bootlin-yocto-stm32-labs-solutions/blob/solutions/ninvaders_0.1.1.bbappend&#34;&gt;here&lt;/a&gt; and looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/joystick_ninvaders_support_patch.png&#34; alt=&#34;joystick_ninvaders_support_patch&#34;&gt;&lt;/p&gt;
&lt;p&gt;Treeview of the directory responsible for using the nunchuck in the game is now:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/patch_file_organization_ninvaders.png&#34; alt=&#34;patch_file_organization_ninvaders&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;transferring-kernel-image-and-device-tree-blob-to-tftp&#34;&gt;Transferring kernel image and device tree blob to TFTP&lt;/h3&gt;
&lt;p&gt;We can now rebuild the whole &lt;code&gt;core-image-minimal&lt;/code&gt; and copy the newly generated kernel and device tree images to the TFTP server home directory (&lt;code&gt;/srv/tftp&lt;/code&gt; in my case). Files you are looking for and that you want to transfer to the directory are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;zImage&lt;/li&gt;
&lt;li&gt;stm32mp157d-dk1.dtb&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/zImage_and_dtb_local.png&#34; alt=&#34;zImage_and_dtb_local&#34;&gt;&lt;/p&gt;
&lt;p&gt;Whith these files now present, the board&amp;rsquo;s bootloade can now load the proper image with proper hardware support.&lt;/p&gt;
&lt;p&gt;We can now reset the board and observe the boot logs until we have access to the command line. Near the end of the boot, we should now observe the following.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/serial_boot_nunchuck_partTwo.png&#34; alt=&#34;serial_boot_nunchuck_partTwo&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;testing-the-nunchuck&#34;&gt;Testing the Nunchuck&lt;/h3&gt;
&lt;p&gt;Connection diagram for the Nunchuck can be seen on following images provided by Bootlin:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/connection_diagram.png&#34; alt=&#34;connection_diagram&#34;&gt;
&lt;img src=&#34;https://viainsita.com.hr/connection_diagram_board.png&#34; alt=&#34;connection_diagram_board&#34;&gt;&lt;/p&gt;
&lt;p&gt;You can now check that the Nunchuck is present and working by checking the presence of the &lt;code&gt;js0&lt;/code&gt; device file by running:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat /dev/input/js0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/nunchuck_present.png&#34; alt=&#34;nunchuck_present&#34;&gt;&lt;/p&gt;
&lt;p&gt;Notice the random characters that appear while both playing with the Nunchuck&amp;rsquo;s joystick or by even moving the controller since the driver we integrated also handles acclerometer events.&lt;/p&gt;
&lt;p&gt;And now finnaly, simply run &lt;code&gt;/usr/bin/ninvaders&lt;/code&gt; and use the &lt;code&gt;C&lt;/code&gt; button on the joystik to confirm and fire and &lt;code&gt;Z&lt;/code&gt; to pause the game:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/playing_real_deal_zoomed_in.png&#34; alt=&#34;playing_real_deal_zoomed_in&#34;&gt;&lt;/p&gt;
&lt;p&gt;Amd that&amp;rsquo;s it.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Using valgrind with vgdb and address sanitizer to analyze memory errors</title>
		<link>https://viainsita.com.hr/using_valgrind_with_vgdb_and_address_sanitizer_to_analyze_memory_errors/</link>
		<pubDate>Tue, 20 May 2025 16:57:17 +0200</pubDate>
		
		<guid>https://viainsita.com.hr/using_valgrind_with_vgdb_and_address_sanitizer_to_analyze_memory_errors/</guid>
		<description>&lt;p&gt;In this blog post, I will explain how I used &lt;code&gt;valgrind&lt;/code&gt; with &lt;code&gt;vgdb&lt;/code&gt; to detect memory errors leaks and misbehaviors: &lt;img src=&#34;https://viainsita.com.hr/valgrind_vgdb_setup.jpeg&#34; alt=&#34;valgrind_vgdb_setup.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;as well as &lt;code&gt;address sanitizer&lt;/code&gt; to do the same, but quicker: &lt;img src=&#34;https://viainsita.com.hr/asan_setup.jpeg&#34; alt=&#34;asan_jpeg.jpeg&#34;&gt;&lt;/p&gt;
&lt;p&gt;In this post, I will not be focusing on giving a detailed tutorial on how to solve Bootlin&amp;rsquo;s debugging &lt;a href=&#34;https://bootlin.com/doc/training/debugging/debugging-labs.pdf&#34;&gt;lab&lt;/a&gt; but rather present how I approached solving memory leaks of a running application and how I detected and fixed the root cause of it.&lt;/p&gt;
&lt;p&gt;As usual, I would like to give a shout out to Bootlin for making their materials free and open source, including materials I used to demonstrate detecting and fixing memory leaks described in this blog post.&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-valgrind&#34;&gt;Using valgrind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#valgrind-and-vgdb&#34;&gt;valgrind and vgdb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#address-sanitizer&#34;&gt;Address sanitizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this blog post, I will be using the same setup as described in the &lt;a href=&#34;https://viainsita.com.hr/setting_up_gdb_for_debugging_embedded_devices&#34;&gt;GDB setup for debugging embedded applications&lt;/a&gt; blog post. As always, special thanks to Bootlin for providing the &lt;a href=&#34;https://github.com/bootlin/training-materials/tree/master/lab-data/debugging/nfsroot/root&#34;&gt;source code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On your development host, change directory to &lt;code&gt;valgrind&lt;/code&gt; folder, cross-compile &lt;code&gt;valgrind.c&lt;/code&gt; and then run it on the target:
&lt;img src=&#34;https://viainsita.com.hr/mem_leak_no_detect.jpeg&#34; alt=&#34;mem_leak_no_detect.jpeg&#34;&gt;&lt;/p&gt;
&lt;p&gt;Even though there is no segfault, an application might leak memory or perform out-of-bounds access or just simply contain uninitialized memory blocks. One useful tool to detect these &amp;ldquo;invisible&amp;rdquo; memory issues is &lt;a href=&#34;https://valgrind.org/&#34;&gt;valgrind&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;using-valgrind&#34;&gt;Using valgrind&lt;/h2&gt;
&lt;p&gt;When we run the application again with valgrind we get the following result:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ valgrind --leak-check=full ./faulty_mem_app 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/valgrind0.jpeg&#34; alt=&#34;valgrind0.jpeg&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/valgrind.jpeg&#34; alt=&#34;valgrind.jpeg&#34;&gt;&lt;/p&gt;
&lt;p&gt;The output indicates following occurences in &lt;code&gt;faulty_mem_app&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;invalid memory write&lt;/li&gt;
&lt;li&gt;uninitialized memory&lt;/li&gt;
&lt;li&gt;memory leak (memory was allocated but never freed)
&lt;a href=&#34;slika.png&#34;&gt;!slika.png&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The call stack indicates the following origin and error propagation:
&lt;code&gt;main()&lt;/code&gt; -&amp;gt; &lt;code&gt;do_something()&lt;/code&gt; -&amp;gt; &lt;code&gt;clear_array()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To fix this issue, we have to check if array access is out of bounds and that &lt;code&gt;malloc()&lt;/code&gt; is allocating enough space. Also, this memory has to initialized before use and freed in the end.&lt;/p&gt;
&lt;p&gt;Backtracing the call stack to pinpoint where the issue occurs will, in majority of cases, most likely be enough to solve the memory issue.&lt;/p&gt;
&lt;p&gt;However, in order to pinpoint each error exactly dynamically and be able to debug with &lt;code&gt;gdb&lt;/code&gt;, &lt;a href=&#34;https://man7.org/linux/man-pages/man1/vgdb.1.html&#34;&gt;&lt;code&gt;vgdb&lt;/code&gt;&lt;/a&gt; can be used. &lt;code&gt;vgdb&lt;/code&gt; is a bridge that allows &lt;code&gt;gdb&lt;/code&gt; to attach to and control a running &lt;code&gt;valgrind&lt;/code&gt; process.&lt;/p&gt;
&lt;h2 id=&#34;valgrind-and-vgdb&#34;&gt;valgrind and vgdb&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;valgrind&lt;/code&gt; with &lt;code&gt;vgdb&lt;/code&gt; gives us dynamic interactive control by letting us stop execution at memory errors, inspect variables, set breakpoints, and trace exact causes, whereas using plain &lt;code&gt;valgrind&lt;/code&gt; only gives a post-mortem report.
We will do that remotely on the host using &lt;code&gt;gdb-multiarch&lt;/code&gt;. First, run the following on the target:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ valgrind --vgdb=yes --vgdb-error=0 --leak-check=full ./faulty_mem_app
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In order to do remote debugging using &lt;code&gt;vgdb&lt;/code&gt;, it has to be in listen mode. Start another terminal in SSH on the target and run:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# vgdb --port=1234
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On the host side, run:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ gdb-multiarch ./faulty_mem_app
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and connect to &lt;code&gt;vgdb&lt;/code&gt; using the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) target remote 192.168.0.100:1234
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can now debug each error using gdb with valgrind&amp;rsquo;s supervision which will interrupt the program each time it detects an error. The setup should now look something like this (same picture as the first one):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/valgrind_vgdb_setup.jpeg&#34; alt=&#34;valgrind_vgdb_setup.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;One more thing to note is that backtrace for leaks is not shown on the target because all libraries are stripped and thus do not have any debugging symbols anymore. This leads to the impossibility to use the &lt;a href=&#34;https://dwarfstd.org/&#34;&gt;DWARF&lt;/a&gt; information for backtracing.&lt;/p&gt;
&lt;p&gt;First thing I always like to do is to set a breakpoint to &lt;code&gt;main()&lt;/code&gt; and start the program to reach the application&amp;rsquo;s entry point. Then, we can set breakpoints to both functions mentioned in the backtrace above: &lt;code&gt;clear_array()&lt;/code&gt; and &lt;code&gt;do_something()&lt;/code&gt;. If we were to execute &lt;code&gt;continue&lt;/code&gt; command, eventually, &lt;code&gt;gdb&lt;/code&gt; would stop execution when &lt;code&gt;valgrind&lt;/code&gt; detects an error as shown in the upper-right corner:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/continue_stop.jpeg&#34; alt=&#34;continue_stop.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;until we reach the end of execution:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/end.jpeg&#34; alt=&#34;end.jpeg&#34;&gt;&lt;/p&gt;
&lt;p&gt;Solution to memory issues is quite straightforward and consists of changing&lt;code&gt;&amp;lt;=&lt;/code&gt; to &lt;code&gt;&amp;lt;&lt;/code&gt; in the &lt;code&gt;clear_array()&lt;/code&gt; function. You can see the fixed source code &lt;a href=&#34;https://github.com/martincvitic19/bootlin-debugging-labs-solutions/blob/solutions/valgrind/faulty_mem_app.c&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;recompiling and running &lt;code&gt;valgrind&lt;/code&gt; on the recompiled app will now give the following result:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/no_mem_leak.jpeg&#34; alt=&#34;no_mem_leak.jpeg&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;address-sanitizer&#34;&gt;Address Sanitizer&lt;/h2&gt;
&lt;p&gt;An even simpler way to detect memory errors is to use &lt;a href=&#34;https://github.com/google/sanitizers/wiki/addresssanitizer&#34;&gt;address sanitizer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, make sure you obtain &lt;code&gt;address sanitizer&lt;/code&gt;. I downloaded it via &lt;code&gt;apt&lt;/code&gt; on my Ubuntu machine:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ sudo apt install libasan* # replace &amp;quot;*&amp;quot; with corresponding version of gcc you are using
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once this was done, I opened the &lt;code&gt;Makefile&lt;/code&gt; and simply added the following compiler and linker flags as shown below and just ran the app as I would when testing it&amp;rsquo;s behavior on the target:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/asan0.jpeg&#34; alt=&#34;asan0.png&#34;&gt;
&lt;img src=&#34;https://viainsita.com.hr/asan.jpeg&#34; alt=&#34;asan.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Address sanitizer gave us a clear backtrace to the &lt;code&gt;clear_array()&lt;/code&gt; function as the source of heap buffer overflow and more or less same information that &lt;code&gt;valgrind&lt;/code&gt; provided. This is something I would first recommend someone to run their code through since it doesn&amp;rsquo;t require much effort to set up and yet gives quite a readable insight into where memory leaks lurk. If you want to go a step further and have observe leaky code dynamically, use &lt;code&gt;valgrind&lt;/code&gt; with &lt;code&gt;vgdb&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you would like to support the work I do, consider donating &lt;a href=&#34;https://viainsita.com.hr/about&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Using strace to analyze application&#39;s system calls</title>
		<link>https://viainsita.com.hr/using_strace_to_analyze_system_calls_an_application_makes/</link>
		<pubDate>Wed, 26 Mar 2025 06:49:05 +0100</pubDate>
		
		<guid>https://viainsita.com.hr/using_strace_to_analyze_system_calls_an_application_makes/</guid>
		<description>&lt;p&gt;In this blog post, I will explain how I used &lt;code&gt;strace&lt;/code&gt; to analyze an application for which I didn&amp;rsquo;t have the access to the source code:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/stracepretty.jpeg&#34; alt=&#34;strace pretty&#34; title=&#34;strace pretty&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#what-is-a-syscall&#34;&gt;What is a syscall?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#making-sense-of-the-output&#34;&gt;Making sense of the output&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#applications-strace-output-analysis&#34;&gt;Application&amp;rsquo;s &lt;code&gt;strace&lt;/code&gt; output analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#summary&#34;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this blog post, I will be using the same setup as described in the &lt;a href=&#34;https://viainsita.com.hr/setting_up_gdb_for_debugging_embedded_devices&#34;&gt;GDB setup for debugging embedded applications&lt;/a&gt; blog post. As always, special thanks to Bootlin for providing the &lt;a href=&#34;https://github.com/bootlin/training-materials/tree/master/lab-data/debugging/nfsroot/root&#34;&gt;source code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In order to see which system calls &lt;code&gt;strace_me&lt;/code&gt; application invokes, run the following in the &lt;code&gt;nfsroot/root/strace&lt;/code&gt; directory and observe the output as shown in the figure below:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ strace ./strace_me&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/straceoutput.jpeg&#34; alt=&#34;strace output&#34; title=&#34;strace output&#34;&gt;&lt;/p&gt;
&lt;p&gt;Before making sense of the output, let&amp;rsquo;s see what syscalls actually are.&lt;/p&gt;
&lt;h2 id=&#34;what-is-a-syscall&#34;&gt;What is a syscall?&lt;/h2&gt;
&lt;p&gt;A system call (or just simply, &amp;ldquo;syscall&amp;rdquo;) is a special type of a call that an application makes to the operating system&amp;rsquo;s kernel in order to communicate with it. This is depicted in the following figure I found on &lt;a href=&#34;https://www.redhat.com/en/blog/architecting-containers-part-1-why-understanding-user-space-vs-kernel-space-matters&#34;&gt;Red Hat&amp;rsquo;s blog&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/syscall.png&#34; alt=&#34;syscall&#34; title=&#34;syscall&#34;&gt;&lt;/p&gt;
&lt;p&gt;Applications live in the so called &amp;ldquo;userspace&amp;rdquo; and the kernel lives in the &amp;ldquo;kernelspace&amp;rdquo; which means that they reside in different protection rings due to the nature and consequences of operations in the respective spaces as depicted in this figure I found on &lt;a href=&#34;https://stackoverflow.com/questions/5957570/what-is-the-difference-between-the-kernel-space-and-the-user-space&#34;&gt;stack overflow&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/pring.png&#34; alt=&#34;protection rings&#34; title=&#34;protection rings&#34;&gt;&lt;/p&gt;
&lt;p&gt;For example, a program can do a wide variety of things in the userspace like calculating complex math or manipulating data structures, but if it wants do anything with the network or the filesystem for example, it has to talk to the kernel and in order for the application to communicate with the kernel, As noted earlier, syscalls can be traced with a tool called strace which was used to trace syscalls that &lt;code&gt;strace_me&lt;/code&gt; application has made.&lt;/p&gt;
&lt;p&gt;NOTE: There is also an &amp;ldquo;inverse&amp;rdquo; of this communication userspace-&amp;gt;kernelspace communication so to speak called signals which the kernel uses to send information to userspace applications. Signals are asynchronous software interrupts that notify a process about some events. A process is a running instance of an application in this case. It is created when you run &lt;code&gt;strace_me&lt;/code&gt; application which in turn enables the kernel to send signals to &lt;code&gt;strace_me&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;making-sense-of-the-output&#34;&gt;Making sense of the output&lt;/h2&gt;
&lt;p&gt;Generally, everything up until &lt;code&gt;openat()&lt;/code&gt; command is generally just application initialization. The real work of the application begins with the openat() which passes the path to the file which we want to open along with some other options.
Make sure to check the file descriptor after the equals sign. The following are taken by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 -&amp;gt; stdin&lt;/li&gt;
&lt;li&gt;1 -&amp;gt; stdout&lt;/li&gt;
&lt;li&gt;2 -&amp;gt; stderr&lt;/li&gt;
&lt;li&gt;3 -&amp;gt; anything else&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before diving deeper, focus on two calls as they are usually most telling of what the application effectively does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;openat()&lt;/li&gt;
&lt;li&gt;read()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To see this in action, use &lt;code&gt;grep&lt;/code&gt; to see which files did the &lt;code&gt;strace_me&lt;/code&gt; application open:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/straceopenat.jpeg&#34; alt=&#34;openat()&#34; title=&#34;openat()&#34;&gt;&lt;/p&gt;
&lt;p&gt;I also used &lt;code&gt;grep&lt;/code&gt; to see what was being &lt;code&gt;read()&lt;/code&gt; and how may times was it called:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/straceread.jpeg&#34; alt=&#34;read()&#34; title=&#34;read()&#34;&gt;&lt;/p&gt;
&lt;p&gt;NOTE: The &lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt; part of the &lt;code&gt;strace&lt;/code&gt; command is used to redirect standard error &lt;code&gt;stderr(2)&lt;/code&gt; to standard output &lt;code&gt;stdout(1)&lt;/code&gt; because &lt;code&gt;strace&lt;/code&gt; outputs syscalls to the &lt;code&gt;stderr&lt;/code&gt;, not to &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt; searches lines only in &lt;code&gt;stdout&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;applications-strace-output-analysis&#34;&gt;Application&amp;rsquo;s &lt;code&gt;strace&lt;/code&gt; output analysis&lt;/h2&gt;
&lt;h3 id=&#34;process-execution&#34;&gt;Process execution&lt;/h3&gt;
&lt;p&gt;The first line that can be seen from the output is the system call that starts the strace_me binary. The return value of &lt;code&gt;0&lt;/code&gt; indicates successful execution:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;execve(&amp;quot;./strace_me&amp;quot;, [&amp;quot;./strace_me&amp;quot;], 0xbfef60d8 /* 14 vars */) = 0&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;memory-management&#34;&gt;Memory management&lt;/h3&gt;
&lt;p&gt;Next three lines are used for memory allocation:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;brk(NULL) = 0x491000
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6eed000
mprotect(0xb6ebf000, 8192, PROT_READ) = 0

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;brk(NULL)&lt;/code&gt; checks the program break (heap start), while &lt;code&gt;mmap2(...)&lt;/code&gt;, the application allocates 8KB of anonymous private memory, most likely for stack or heap. Finally, &lt;code&gt;mprotect(...)&lt;/code&gt; sets memory permissions by making a region read-only.&lt;/p&gt;
&lt;h3 id=&#34;filesystem-access&#34;&gt;Filesystem access&lt;/h3&gt;
&lt;p&gt;Next two lines:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;access(&amp;quot;/etc/ld.so.preload&amp;quot;, R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, &amp;quot;/etc/ld.so.cache&amp;quot;, O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;indicate that there is no custom shared library preloading and that no pre-cached library paths were found, meaning &lt;code&gt;ld.so&lt;/code&gt; has to search directories manually.&lt;/p&gt;
&lt;p&gt;The following line:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;openat(AT_FDCWD, &amp;quot;/etc/fstab&amp;quot;, O_RDONLY|O_LARGEFILE) = 3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;indicates that &lt;code&gt;strace_me&lt;/code&gt; successfully opened the &lt;code&gt;/etc/fstab&lt;/code&gt; file which contains filesystem mount information.&lt;/p&gt;
&lt;p&gt;This line:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;openat(AT_FDCWD, &amp;quot;/tmp/tmp.GchbQ27l&amp;quot;, O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;indicates that the application tries to open a temporary file called &lt;code&gt;tmp.GchbQ27l&lt;/code&gt; but fails.&lt;/p&gt;
&lt;p&gt;The following lines:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;rt_sigaction(SIGALRM, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0xb6de2510}, 8) = 0
kill(0, SIGALRM) = 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;are used by &lt;code&gt;strace_me&lt;/code&gt; to set a signal handler for &lt;code&gt;SIGALRM&lt;/code&gt; and keep it at default behavior with &lt;code&gt;SIG_DFL&lt;/code&gt; flag. It then sends &lt;code&gt;SIGALRM&lt;/code&gt; to itself (&lt;code&gt;kill(0, SIGALRM)&lt;/code&gt;) which leads to process termination. &lt;code&gt;SIGALRM&lt;/code&gt; is a signal that the kernel sends to the userspace program when working with timers which in turn means that &lt;code&gt;strace_me&lt;/code&gt; is dependent upon some kind of a timer in some way.&lt;/p&gt;
&lt;p&gt;In the end, &lt;code&gt;strace_me&lt;/code&gt; terminates normally.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;We now have enough information about &lt;code&gt;strace_me&lt;/code&gt; to make following conlusions and assumptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;manages memory via &lt;code&gt;mmap2()&lt;/code&gt; and &lt;code&gt;mprotect()&lt;/code&gt;, likely enforcing stack security&lt;/li&gt;
&lt;li&gt;dynamically linked, looks for shared libraries but doesn&amp;rsquo;t preload anything&lt;/li&gt;
&lt;li&gt;checks system files (&lt;code&gt;/etc/fstab&lt;/code&gt;) - might be inspecting mounts&lt;/li&gt;
&lt;li&gt;tries to open temp files in &lt;code&gt;/tmp/&lt;/code&gt; but fails - possible optional config check&lt;/li&gt;
&lt;li&gt;sets &lt;code&gt;SIGALRM&lt;/code&gt; to default behavior - program will exit when it receives an alarm signal indicating some kind of a timeout&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;what-strace_me-is-most-likely-doing&#34;&gt;What strace_me is most likely doing&lt;/h3&gt;
&lt;p&gt;Based on the strace output, the &lt;code&gt;strace_me&lt;/code&gt; is a test application that interacts with system files and memory. It and exits cleanly upon receiving a &lt;code&gt;SIGALRM&lt;/code&gt; signal without doing much.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;strace&lt;/code&gt; lets you trace system calls that an application makes which provides more information about how does the application interact with the system it runs on. Useful calls that provide useful information that you should have an eye on are &lt;code&gt;openat()&lt;/code&gt; and &lt;code&gt;read()&lt;/code&gt;. Generally, everything up until &lt;code&gt;openat()&lt;/code&gt; syscall is basically just application initialization. Every syscall afterwards gives us more meaningful information about the application.&lt;/p&gt;
&lt;p&gt;If you would like to support the work I do, consider donating &lt;a href=&#34;https://viainsita.com.hr/about&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Using ltrace and software shims to bypass a credential-checking algorithm</title>
		<link>https://viainsita.com.hr/using_ltrace_and_software_shims_to_bypass_a_credentials_checking_algorithm/</link>
		<pubDate>Sun, 23 Feb 2025 08:57:50 +0100</pubDate>
		
		<guid>https://viainsita.com.hr/using_ltrace_and_software_shims_to_bypass_a_credentials_checking_algorithm/</guid>
		<description>&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;In this blog post, I will explain how I have used &lt;code&gt;ltrace&lt;/code&gt; to analyze dynamic library calls from an application requesting user credentials and managed to hack a credential-checking algorithm:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/credshacking.jpeg&#34; alt=&#34;hacking a credential-checking algorithm&#34; title=&#34;hacking a credential-checking algorithm&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#running-an-authentication-constrained-application&#34;&gt;Running an authentication-constrained application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#bypassing-credential-checking-algorithm&#34;&gt;Bypassing credential-checking algorithm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The setup for demonstrating &lt;code&gt;ltrace&lt;/code&gt; and software shims is described in &lt;a href=&#34;https://viainsita.com.hr/setting_up_gdb_for_debugging_embedded_devices&#34;&gt;GDB setup for debugging embedded applications&lt;/a&gt; blog post. As always, special thanks to Bootlin for providing the &lt;a href=&#34;https://github.com/bootlin/training-materials/tree/master/lab-data/debugging/nfsroot/root&#34;&gt;source code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ltrace&lt;/code&gt; is a tool to trace shared library calls used by a program and all the signals it receives. This is especially useful when we don&amp;rsquo;t have access to the source files of the binaries we are analyzing.
A software shim is a piece of code (a library to be more precise) that lives in between a program and some other library that the program uses. A shim intercepts calls from the program to the library allowing us to monitor and &lt;em&gt;change the behavior&lt;/em&gt; of those calls.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These tools are extremely useful to analyze and change the behavior of an existing program for which we don&amp;rsquo;t have source code and that we cannot recompile.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My mind is unironically blown.&lt;/p&gt;
&lt;h2 id=&#34;running-an-authentication-constrained-application&#34;&gt;Running an authentication-constrained application&lt;/h2&gt;
&lt;p&gt;Since our application uses a local dynamic shared library which is not in the default paths expected by the linker, we provided that path using &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; by running the following on the target:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# export LD_LIBRARY_PATH=$PWD&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And when we now run the application:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# ./authent&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;we can see that our application is failing to correctly authenticate the user:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/credscheckingfailblur.jpeg&#34; alt=&#34;attempting to run an authentication-constrained application&#34; title=&#34;attempting to run an authentication-constrained application&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;bypassing-credential-checking-algorithm&#34;&gt;Bypassing credential-checking algorithm&lt;/h2&gt;
&lt;p&gt;By using &lt;code&gt;ltrace&lt;/code&gt; on the target, we can trace the application on the target in order to understand what is going on and based on that trace which function fails:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# ltrace ./authent&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/ltrace.jpeg&#34; alt=&#34;ltrace overview&#34; title=&#34;ltrace overview&#34;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the function that fails is &lt;code&gt;al_authent_user()&lt;/code&gt; and this is the function which we will override in a new file, &lt;code&gt;overload.c&lt;/code&gt; which will print the user, password and simply return 0:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/overload.jpeg&#34; alt=&#34;overload.c source file overview&#34; title=&#34;overload.c source file overview&#34;&gt;&lt;/p&gt;
&lt;p&gt;In this case, I looked at the &lt;code&gt;authent_library.h&lt;/code&gt; inside the &lt;code&gt;ltrace\&lt;/code&gt; directory to conclude what the function prototype should be.&lt;/p&gt;
&lt;p&gt;Now, to use the overload we just created, compile your source file on the development host with the following command:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ ${CROSS_COMPILE}gcc -fPIC -shared overload.c -o overload.so&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This command generates a position-independent shared library &lt;code&gt;overload.so&lt;/code&gt; which can be loaded at any valid memory address without requiring modification.&lt;/p&gt;
&lt;p&gt;Finally, run the application and preload the new library using the following command on the target:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# LD_PRELOAD=./overload.so ./authent&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This command sets the &lt;code&gt;LD_PRELOAD&lt;/code&gt; environment variable which tells the loader to first check our newly compiled &lt;code&gt;overload.so&lt;/code&gt; library when running the &lt;code&gt;authent&lt;/code&gt; binary. When &lt;code&gt;al_authent_user&lt;/code&gt; function is called in the &lt;code&gt;authent&lt;/code&gt; binary, our function with the same name will be called and credentials will be printed on the console:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/credshacking.jpeg&#34; alt=&#34;authentication algorithm bypassed&#34; title=&#34;authentication algorithm bypassed&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you would like to support the work I do, consider donating &lt;a href=&#34;https://viainsita.com.hr/about&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Using a coredump with GDB for post mortem crash analysis</title>
		<link>https://viainsita.com.hr/using_a_coredump_with_gdb_for_postmortem_crash_analysis/</link>
		<pubDate>Sat, 01 Feb 2025 21:37:19 +0100</pubDate>
		
		<guid>https://viainsita.com.hr/using_a_coredump_with_gdb_for_postmortem_crash_analysis/</guid>
		<description>&lt;p&gt;I configured the Linux kernel core to dump a core file that I analyzed in order to find the root cause of a segmentation fault:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/coredumpsetup.jpeg&#34; alt=&#34;coredump setup overview&#34; title=&#34;coredump setup overview&#34;&gt;&lt;/p&gt;
&lt;p&gt;In this blog post, I will set up the working environment exactly the same as I described in previous &lt;a href=&#34;https://viainsita.com.hr/detecting_and_fixing_the_cause_of_a_segementation_fault_on_an_embedded_linux_system&#34;&gt;post&lt;/a&gt;. A coredump is a file that that holds the recorded state of the program&amp;rsquo;s memory at moment of crash. This kind of static analysis is useful when code crashes occur in end-of-line testing, or worse yet, out in the field when it has been shipped to the customer. Wherever they occur, coredump files are sent to developers for a debugging session.&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#running-core-dump-through-gdb&#34;&gt;Running core dump through GDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#additional-considerations&#34;&gt;Additional considerations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;One thing that has to be taken into account in software development is the difference between debug build and release build binaries. Debug builds have a larger memory footprint due to additional debug symbols that compiler uses for debugging purposes, whereas build binaries are often stripped off of this additional information. As suggested by Jacob Sorber in his &lt;a href=&#34;https://www.youtube.com/watch?v=OLH_k6IhTyM&amp;amp;t=242s&#34;&gt;Can I Debug Release Code?&lt;/a&gt; video, the best of both worlds approach would be to compile your release binaries with debug symbols, but then strip them afterward before shipping them to the customer which will decrease binary size but still leave you with an option to debug a program using a coredump. I highly recommend you check out this video if you I piqued your interest on this topic. As always, special thanks to Bootlin for providing the &lt;a href=&#34;https://github.com/bootlin/training-materials/tree/master/lab-data/debugging/nfsroot/root&#34;&gt;source code&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;running-coredump-through-gdb&#34;&gt;Running coredump through GDB&lt;/h2&gt;
&lt;p&gt;In order to configure the Linux kernel to generate such a file, run the following on the target machine:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# ulimit -c unlimited&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;which removes the size limit of coredumps that are going to be saved. By default, they are set to zero on most machines (i.e. they don&amp;rsquo;t get generated).&lt;/p&gt;
&lt;p&gt;Them, run &lt;code&gt;./linked_list&lt;/code&gt; again and observe that a core file has been generated:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/coregenerated.jpeg&#34; alt=&#34;core file generated&#34; title=&#34;core file generated&#34;&gt;&lt;/p&gt;
&lt;p&gt;On your host machine, change the permissions by running:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo chown $USER:$USER core&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;and run the failed program with the coredump in GDB which will point you to the exact moment your program crashed:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$gdb-multiarch ./linked_list ./core&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/corefilerun.jpeg&#34; alt=&#34;core dump in GDB&#34; title=&#34;core dump in GDB&#34;&gt;&lt;/p&gt;
&lt;p&gt;Coredump analysis is less dynamic than the usual way of debugging binaries we execute live on GDB. It nevertheless still allows you to pinpoint the exact moment when the crash occured by manipulating the coredump file. Since it is only a memory snapshot and the program is not running anymore, we cannot step through the code by using GDB commands such as &lt;code&gt;continue&lt;/code&gt; or &lt;code&gt;step&lt;/code&gt; but we can print variables that are in scope.&lt;/p&gt;
&lt;p&gt;I have already demonstrated one way of finding and resolving the root cause of the segmentation fault in this &lt;a href=&#34;https://viainsita.com.hr/Detecting_and_fixing_the_cause_of_a_segementation_fault_on_an_embedded_Linux_system.md&#34;&gt;post&lt;/a&gt; in this particular case and we know what the causes it. That is why I will take a different approach this time for demonstration purposes.&lt;/p&gt;
&lt;p&gt;I will define custom commands in order to ease printing elements of the &lt;a href=&#34;https://man7.org/linux/man-pages/man3/slist.3.html&#34;&gt;singly linked list&lt;/a&gt; we are working here with. Let&amp;rsquo;s backtrace the program execution a bit and define the command that will print out elements of our list:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/gdbcustomcommand.jpeg&#34; alt=&#34;GDB custom print command&#34; title=&#34;GDB custom print command&#34;&gt;&lt;/p&gt;
&lt;p&gt;where &lt;code&gt;slh_first&lt;/code&gt; and &lt;code&gt;sle_next&lt;/code&gt; allude to the following macros as described in &lt;code&gt;sys/queue.h&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SLIST_ENTRY(name) next&lt;/code&gt; - this macro creates a structure containing a pointer called &lt;code&gt;sle_next&lt;/code&gt; (&amp;ldquo;singly linked entry next&amp;rdquo;) pointing to the next node&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SLIST_HEAD(name_list, name) name_list&lt;/code&gt; - this macro creates the list head that contains a pointer called &lt;code&gt;slh_first&lt;/code&gt; (&amp;ldquo;singly linked head first&amp;rdquo;) which points to the first element of the list&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though this is quite telling and enough to make conclusions if you were to look under the hood of the &lt;code&gt;word_list&lt;/code&gt; and &lt;code&gt;linked_list.c&lt;/code&gt;, I will lay out additional considerations that might be useful in pinpointing the exact root cause of the segmentation fault.&lt;/p&gt;
&lt;h2 id=&#34;additional-considerations&#34;&gt;Additional considerations&lt;/h2&gt;
&lt;p&gt;Even though running the coredump GDB points you to the exact function in the source code where the crash occured, the assembly view of the memory, as well as examining the state of the CPU registers can provide additional useful information that can help us in backtracing the root cause of the segmentation fault.&lt;/p&gt;
&lt;p&gt;To print the state of the registers at the moment of crash, run &lt;code&gt;info registers&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/inforeg.jpeg&#34; alt=&#34;info registers&#34; title=&#34;info registers&#34;&gt;&lt;/p&gt;
&lt;p&gt;Based on the pc (program counter) register value, we can conclude where the execution has stopped - 36 bytes into the &lt;code&gt;display_linked_list()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Based on the lr (link register) register value, which holds the reutrn address, we can conclude that &lt;code&gt;display_linked_list()&lt;/code&gt; was still executing when the appliction crashed.&lt;/p&gt;
&lt;p&gt;Based on the r2 register value, which in this case stores function arguments, we can see that it equals to ASCII &lt;em&gt;&amp;rsquo;m&#39;&lt;/em&gt; indicating that overflowing occurs at the &amp;rsquo;m&#39; character of the word &lt;em&gt;&amp;ldquo;fermentum&amp;rdquo;&lt;/em&gt; as concluded in the &lt;a href=&#34;https://viainsita.com.hr/Detecting_and_fixing_the_cause_of_a_segementation_fault_on_an_embedded_Linux_system.md&#34;&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To access the assembly view of the function where the crash occured (i.e. &lt;code&gt;display_linked_list()&lt;/code&gt;), run &lt;code&gt;dissasemble display_linked_list&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/assmeblyexamine.jpeg&#34; alt=&#34;assembly view and register examination&#34; title=&#34;assembly view and register examination&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0x4c8a04 &amp;lt;display_linked_list+36&amp;gt;: ldr r1, [r3]&lt;/code&gt; indicates that the CPU  is trying to dereference the memory address stored in &amp;lsquo;r3&amp;rsquo; register.&lt;/p&gt;
&lt;p&gt;When we examine the value stored in register r3, we get familiar feedback: &lt;code&gt;Cannot access memory at address 0x6c&lt;/code&gt; which is a suspiciously low memory address where no user-defined variables should reside indicating that an invalid pointer dereferencing might have occurred. And it did.&lt;/p&gt;
&lt;p&gt;If you would like to support the work I do, consider donating &lt;a href=&#34;https://viainsita.com.hr/about&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Detecting and fixing the cause of a segmentation fault on an embedded Linux system</title>
		<link>https://viainsita.com.hr/detecting_and_fixing_the_cause_of_a_segementation_fault_on_an_embedded_linux_system/</link>
		<pubDate>Mon, 30 Dec 2024 23:03:48 +0100</pubDate>
		
		<guid>https://viainsita.com.hr/detecting_and_fixing_the_cause_of_a_segementation_fault_on_an_embedded_linux_system/</guid>
		<description>&lt;p&gt;I used GDB on my host machine to detect root cause of a segmentation fault on the &lt;a href=&#34;https://www.st.com/en/evaluation-tools/stm32mp157d-dk1.html&#34;&gt;STM32MP157D-DK1&lt;/a&gt; (I am using &lt;a href=&#34;https://github.com/cyrus-and/gdb-dashboard&#34;&gt;gdb-dashboard&lt;/a&gt; here btw):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/gdbdashboardoverview.jpeg&#34; alt=&#34;gdb-dashboard overview&#34; title=&#34;gdb-dashboard overview&#34;&gt;&lt;/p&gt;
&lt;p&gt;In this post, I will not be focusing on giving a detailed tutorial on how to solve Bootlin&amp;rsquo;s debugging &lt;a href=&#34;https://bootlin.com/doc/training/debugging/debugging-labs.pdf&#34;&gt;lab&lt;/a&gt; but rather present how I approached solving a crash caused by a segmentation fault and how I detected and fixed the source code snippet that caused the segmentation fault.&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#setting-up-the-debug-environment&#34;&gt;Setting up the debug environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#application-debugging&#34;&gt;Application debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#summary&#34;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;To demonstrate how to solve an application crash caused by a segmentation fault, I will be using &lt;a href=&#34;https://github.com/bootlin/training-materials/tree/master/lab-data/debugging/nfsroot/root/gdb&#34;&gt;source code&lt;/a&gt; that Bootlin provided for their &lt;a href=&#34;https://bootlin.com/training/debugging/&#34;&gt;Linux debugging, profiling, tracing and performance analysis training&lt;/a&gt; which I highly recommend you check out.
Before continuing, I would like to express my gratitude towards everyone responsible for making Bootlin happen. I really appreciate their desire to contribute to the world of embedded Linux and that they keep their materials free and open source. Kudos!&lt;/p&gt;
&lt;p&gt;Also, here is a picture of the STM32MP157D-DK1 I was working with:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/STM32MP157D.jpeg&#34; alt=&#34;STM32MP157D-DK1&#34; title=&#34;STM32MP157D-DK1&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;reproducing-the-segmentation-fault&#34;&gt;Reproducing the segmentation fault&lt;/h2&gt;
&lt;p&gt;If you haven&amp;rsquo;t read &lt;a href=&#34;https://viainsita.com.hr/setting_up_gdb_for_debugging_embedded_devices&#34;&gt;GDB setup for debugging embedded applications&lt;/a&gt;, I advise you to read it so you get a better understanding of what will be laid out in the rest of this blog post.&lt;/p&gt;
&lt;p&gt;On your host machine, make sure you prepare the current shell for cross-compiling by running:
&lt;code&gt;$ export CROSS_COMPILE=/home/$USER/debugging-labs/buildroot/output/host/bin/arm-linux-&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then, run &lt;code&gt;make&lt;/code&gt; in the &lt;code&gt;nfsroot/root/gdb&lt;/code&gt; directory to build the &lt;code&gt;linked_list&lt;/code&gt; binary. Now, if you run &lt;code&gt;linked_list&lt;/code&gt; on your target, you will get a segmentation fault:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/segfaultdemo.jpeg&#34; alt=&#34;segfault demo&#34; title=&#34;segmentation fault&#34;&gt;&lt;/p&gt;
&lt;p&gt;Generally, a segmentation fault indicates that a program attempted to access a memory location that it was not allowed to access. That means that one of the following scenarios is the root cause of the application crash we trying to resolve:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;access violation
&lt;ul&gt;
&lt;li&gt;reading or writing to an invalid memory address such as a null pointer, an uninitialized pointer, a pointer  to a memory address that has been freed or is out of scope, an out-of-bounds array index&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;improper memory usage
&lt;ul&gt;
&lt;li&gt;recursive function calls can exhaust the stack memory causing it to overflow&lt;/li&gt;
&lt;li&gt;improper use of dynamic memory allocation or deallocation like using &lt;code&gt;free&lt;/code&gt; multiple times on the same memory block or writing beyond the allocated memory causes heap corruption&lt;/li&gt;
&lt;li&gt;attempting to access data at an address not aligned to the data type&amp;rsquo;s requirements like reading a 4-byte integer from a 3-byte aligned address&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;logic error occurence in the source code
&lt;ul&gt;
&lt;li&gt;dereferencing a pointer before it has been properly initialized (i.e. dereferencing a null pointer)&lt;/li&gt;
&lt;li&gt;passing invalid pointers to functions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;setting-up-the-debug-environment&#34;&gt;Setting up the debug environment&lt;/h2&gt;
&lt;p&gt;As hinted at in the beginning of this blog post, we will be using a remote GDB setup since our target does not embed a fully featured GDB, but only a &lt;code&gt;gdbserver&lt;/code&gt; that allows connecting with a remote fully featured version of GDB that we have running on our host machine.
Let&amp;rsquo;s start our program on the target by using &lt;code&gt;gdbserver&lt;/code&gt; in multi mode:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# gdbserver --multi :2000 ./linked_list&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;On the host side use &lt;code&gt;gdb-multiarch&lt;/code&gt; to attach to the process on the target:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ gdb-multiarch ./linked_list&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/gdbsetup.jpeg&#34; alt=&#34;gdb setup&#34; title=&#34;gdb setup&#34;&gt;&lt;/p&gt;
&lt;p&gt;when in gdb, enter the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) target extended-remote 192.168.0.100:2000
(gdb) set sysroot /home/&amp;lt;user&amp;gt;/debugging-labs/buildroot/output/staging/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can now enter the TUI either by &lt;code&gt;ctrl + x + a&lt;/code&gt; or by typing &lt;code&gt;lay next&lt;/code&gt; and hitting enter a couple of times until you see the source code, assembly view and the GDB console:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/TUI.jpeg&#34; alt=&#34;TUI&#34; title=&#34;TUI&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NOTE: Besides GDB TUI, there are several other user interfaces with debugging options such as &lt;a href=&#34;https://www.gdbgui.com/&#34;&gt;gdbgui&lt;/a&gt; and &lt;a href=&#34;https://github.com/cyrus-and/gdb-dashboard&#34;&gt;gdb-dashboard&lt;/a&gt; which I will be using the most from the next blog post onwards.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;application-debugging&#34;&gt;Application debugging&lt;/h2&gt;
&lt;p&gt;The first thing I recommend doing is setting a breakpoint in the main function so you can see where exactly the segfault occurs when you backtrace it after the program has crashed:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break main
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, run the program to reach the breakpoint at the main function and continue execution until the crash occurs:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) run
(gdb) continue
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the program segfaults, show the backtrace to pinpoint the function that causes the segfault:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) backtrace
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/backtrace.jpeg&#34; alt=&#34;backtrace&#34; title=&#34;backtrace&#34;&gt;
As you can see, the line causing the crash in the main program is located in the linked_list.c at 81. Add the breakpoint to that line:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break linked_list.c:81
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Restart the program in GDB by running &lt;code&gt;start&lt;/code&gt; or &lt;code&gt;run&lt;/code&gt;. You will reach the main function again since this is the first breakpoint we set and then run continue until you reach the function causing the problem which is &lt;code&gt;display_linked_list()&lt;/code&gt;. Enter &lt;code&gt;step&lt;/code&gt; to enter this function.&lt;/p&gt;
&lt;p&gt;A very useful GDB command in this case is &lt;code&gt;print&lt;/code&gt; which is used to print variables inthe current scope:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/manualstepping.jpeg&#34; alt=&#34;manual stepping&#34; title=&#34;manual stepping&#34;&gt;&lt;/p&gt;
&lt;p&gt;You can see strings being printed line after line in the target machine&amp;rsquo;s console. Stepping and printing will give you a glimpse of how the function is being executed sequentially. For education and demonstration purposes, feel free to step through every entry of the word list until you reach the segfault. Generally, if typing the same command becomes way too repetitive way too quickly, consider using conditional breakpoints.&lt;/p&gt;
&lt;p&gt;When you reach the last entry being printed, notice the difference between what is being shown in the GDB console and on the target machine&amp;rsquo;s console. One says &lt;em&gt;&amp;ldquo;fermentu&amp;rdquo;&lt;/em&gt; and the other &lt;em&gt;&amp;ldquo;fermentum&amp;rdquo;&lt;/em&gt;. This should raise an eyebrow&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/mismatch.jpeg&#34; alt=&#34;character mismatch&#34; title=&#34;character mismatch&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you now &lt;code&gt;step&lt;/code&gt; and try printing the next entry in the linked list, you will see that you are pointing to an address you cannot access which is causing the segmentation fault:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/segfaulteclipse.jpeg&#34; alt=&#34;segfault eclipse&#34; title=&#34;segfault eclipse&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now, if you take a look at the name struct in &lt;code&gt;linked_list.c&lt;/code&gt; you will see that it has a member name which is an array of 8 characters:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/changetobemade.jpeg&#34; alt=&#34;change to be made&#34; title=&#34;change to be made&#34;&gt;&lt;/p&gt;
&lt;p&gt;And &amp;ldquo;fermentum&amp;rdquo; has 9 characters&amp;hellip;eureka! The program is trying to display a word of 9 characters when it only has 8 character slots for a given entry from the word list. That is the reason why the program segfaults.&lt;/p&gt;
&lt;p&gt;There are more intelligent ways of solving this problem but I will propose the simplest and quickest one. I looked at the world list being printed and none of the words contain more than 20 characters. Let&amp;rsquo;s change &lt;code&gt;char name[8]&lt;/code&gt; to &lt;code&gt;char name [20]&lt;/code&gt; and recompile the program. Now, we run the program we can see it execute correctly. Awesome!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/linkedlistsuccess.jpeg&#34; alt=&#34;linked list success&#34; title=&#34;program runs successfully!&#34;&gt;&lt;/p&gt;
&lt;p&gt;As stated earlier, conditional breakpoints may provide a more elegant way of solving segmentation faults, especially when some parts of code are iterative in nature. In order to set a breakpoint when the pointer to the next element of the linked list is nonexistent, do the following:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/condbreakpointsetup.jpeg&#34; alt=&#34;conditional breakpoint setup&#34; title=&#34;conditional breakpoint setup&#34;&gt;&lt;/p&gt;
&lt;p&gt;Restarting the application in GDB will now result in:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/condbreakpointresult.jpeg&#34; alt=&#34;conditional breakpoint result&#34; title=&#34;conditional breakpoint result&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;There are many ways to go about solving an application crash on an embedded device, and this is one of them. In general, you want to consider the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;compile you application with debug symbols (g3, ggdb if necessary)&lt;/li&gt;
&lt;li&gt;establish connection between the development host and the target machine (via SSH or serial communication)&lt;/li&gt;
&lt;li&gt;create a breakpoint in the main function and let it run to provoke the segmentation fault and use backtracing to pinpoint the function causing where the fault occurs&lt;/li&gt;
&lt;li&gt;add new breakpoint to that function&lt;/li&gt;
&lt;li&gt;run the program again and continue execution until you reach the newly added breakpoint and step into the function where the fault occurs&lt;/li&gt;
&lt;li&gt;modify the source code, recompile it and run your faultfree application!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you would like to support the work I do, consider donating &lt;a href=&#34;https://viainsita.com.hr/about&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>Setting up GDB for debugging embedded devices</title>
		<link>https://viainsita.com.hr/setting_up_gdb_for_debugging_embedded_devices/</link>
		<pubDate>Mon, 30 Dec 2024 23:03:48 +0100</pubDate>
		
		<guid>https://viainsita.com.hr/setting_up_gdb_for_debugging_embedded_devices/</guid>
		<description>&lt;p&gt;In this blog post, I will explain how I have set up GDB on my host machine for debugging an application on STM32MP157D-DK1:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/gdbsetup.jpeg&#34; alt=&#34;remote debugging setup overview&#34; title=&#34;remote debugging setup overview&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#development-workstation-setup&#34;&gt;Development Workstation Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#gdb-setup-for-embedded-systems&#34;&gt;GDB setup for embedded systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#automating-repetitive-tasks&#34;&gt;Automating repetitive tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#useful-resources&#34;&gt;Useful resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;development-workstation-setup&#34;&gt;Development workstation setup&lt;/h2&gt;
&lt;p&gt;I have set up an NFS server on my development machine as well as configured U-Boot on STM32MP157-DK1 so that any built binaries of interest on the host are easily accessible on the target machine. Also, I have set up SSH to establish a connection with the target board. For more details, check out the first two chapters of this &lt;a href=&#34;https://bootlin.com/doc/training/debugging/debugging-labs.pdf&#34;&gt;document&lt;/a&gt; from &lt;a href=&#34;https://bootlin.com/&#34;&gt;Bootlin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;gdb-setup-for-embedded-systems&#34;&gt;GDB setup for embedded systems&lt;/h2&gt;
&lt;p&gt;By its default configuration, &lt;a href=&#34;https://sourceware.org/gdb/&#34;&gt;GDB&lt;/a&gt; targets binaries that are being run on the same architecture as the host system GDB is running on:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/gdbhost.png&#34; alt=&#34;using gdb for host application debugging&#34; title=&#34;using gdb for host application debugging&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot captured from &lt;a href=&#34;https://interrupt.memfault.com/blog/installing-gdb&#34;&gt;Memfault&amp;rsquo;s Interrupt page describing tools they use&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When targeting an embedded device, GDB has to be configured in a way that it supports the target architecture of the program being debugged:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/gdbtarget.png&#34; alt=&#34;using gdb for target application debugging&#34; title=&#34;using gdb for target application debugging&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Screenshot captured from &lt;a href=&#34;https://interrupt.memfault.com/blog/installing-gdb&#34;&gt;Memfault&amp;rsquo;s Interrupt page describing tools they use&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Binaries generated for embedded devices are often stripped of debug information to save storage space. This is also why native GDB should not be installed on an embedded target (around 2.5 MB on x86).&lt;/p&gt;
&lt;p&gt;For that reason, remote debugging is preferred. ARCH-linux-gdb is used on the development host instead of the native GDB allowing the developer to use all features that native GDB provides. On the target side, gdbserver is used (around 400 KB on arm). It allows connecting to a fully featured remote GDB. This server handles requests from the GDB client, such as setting breakpoints, reading memory or stepping through code.&lt;/p&gt;
&lt;p&gt;Before we start debugging, keep in mind that there are several lightweight graphical interfaces that make debugging easier. One is the default TUI that comes built-in with GDB that you enter by typing lay next when in GDB and the other is &lt;a href=&#34;https://github.com/cyrus-and/gdb-dashboard&#34;&gt;gdb-dashboard&lt;/a&gt; that I have just discovered recently and which I am quite fond of. It creates a .gdbinit file and populates it with sensible configuration for debugging. It enables you to use well-known shortcuts within GDB like ctrl + r for reverse searching of GDB commands you typed previously which the out-of-the-box installation of GDB does not provide. It also appends additional debug information and coloring to your console that I find quite useful.&lt;/p&gt;
&lt;p&gt;Running &lt;code&gt;./linked_list&lt;/code&gt; on the target will cause a segfault. Now, let&amp;rsquo;s start the program on the target using &lt;code&gt;gdbserver&lt;/code&gt; in multi-mode and break down what each of the commands mean:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# gdbserver --multi :2000 ./linked_list&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gdbserver&lt;/code&gt; starts the GDB server which acts as an intermediary between &lt;code&gt;./linked_list&lt;/code&gt; and a GDB client on the host machine&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--multi&lt;/code&gt; flag allows multi-process debugging and launching sessions dynamically
&lt;ul&gt;
&lt;li&gt;instead of automatically attaching to &lt;code&gt;./linked_list&lt;/code&gt; at startup, this option sets up the GDB server to accept multiple debugging sessions and wait for a remote GDB client to specify which executable to debug&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:2000&lt;/code&gt; specifies the port that the GDB server will listen on for incoming GDB client connections - &lt;code&gt;./linked_list&lt;/code&gt; normally specifies the program that GDB server will debug, but this argument is ignored because of the &lt;code&gt;--multi&lt;/code&gt; option and the target program is not launched until the remote GDB client specifies it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a separate terminal on your host machine, run &lt;code&gt;export CROSS_COMPILE=/home/$USER/debugging-labs/buildroot/output/host/arm-linux-&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this export needs to be done in each shell in which &lt;code&gt;CROSS_COMPILE&lt;/code&gt; is going to be used or added to the shell configuration file (I am using bash, so &lt;code&gt;.bashrc&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;export&lt;/code&gt; command sets the &lt;code&gt;CROSS_COMPILE&lt;/code&gt; environment variable and makes it available to all child processes indicating to the build system that the binary being built is meant to be run on a different architecture than the one you are working on&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/home/$USER/debugging-labs/buildroot/output/host/&lt;/code&gt; is the directory where Buildroot has placed the cross-compilation tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next, install &lt;code&gt;gdb-multiarch&lt;/code&gt; and run &lt;code&gt;gdb-multiarch ./linked_list&lt;/code&gt;. You have now entered GDB and inside it, run the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(gdb) target extended-remote 192.168.0.100:2000&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this allows connecting to a remote target GDB server and also reconnecting after the server restarts
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;target&lt;/code&gt; sets the target system GDB will control&lt;/li&gt;
&lt;li&gt;&lt;code&gt;extended-remote&lt;/code&gt; allows multi-process debugging where GDB starts new programs on the target or attaches to running processes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;this command is commonly used with &lt;code&gt;gdbserver&lt;/code&gt; started in &lt;code&gt;--multi&lt;/code&gt; mode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NOTE: this applies if the connection with the board was established via SSH. If it was established over a serial connection, run &lt;code&gt;target remote /dev/ttyUSB0&lt;/code&gt;, or which device it was mapped on when the board was connected to the host machine.&lt;/p&gt;
&lt;p&gt;Finally, run:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(gdb) set sysroot /home/&amp;lt;user&amp;gt;/debugging-labs/buildroot/output/staging/&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this tells GDB where to find the root filesystem of the remote target on the local, host machine where files for debugging are located&lt;/li&gt;
&lt;li&gt;when debugging remote programs, GDB might need access to shared libraries, binaries and other files from the target&amp;rsquo;s root file system which are not available on the local host machine&amp;rsquo;s filesystem
&lt;ul&gt;
&lt;li&gt;by using this setting, GDB now points to a mirror of the target&amp;rsquo;s filesystem from where it can load the correct library versions, display complete stack traces and resolve symbols for debugging&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;automating-repetitive-tasks&#34;&gt;Automating repetitive tasks&lt;/h2&gt;
&lt;p&gt;Instead of retyping exact and specific commands every time you establish a connection with a target you device, you can edit your &lt;code&gt;.gdbinit&lt;/code&gt; file which does it for you. Also, GDB has powerful Python support that it can be used to &lt;a href=&#34;https://interrupt.memfault.com/blog/automate-debugging-with-gdb-python-api&#34;&gt;automate application debugging more efficiently by utilizing GDB&amp;rsquo;s Python API&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;useful-resources&#34;&gt;Useful resources&lt;/h2&gt;
&lt;p&gt;A couple of useful sites I have found regarding using GDB is Jacob Sorber&amp;rsquo;s &lt;a href=&#34;https://www.youtube.com/watch?v=mfmXcbiRs0E&amp;amp;list=PL9IEJIKnBJjHGWPN_S9NS_Ky1-tC8ZrUI&#34;&gt;Debugging C Programs playlist&lt;/a&gt;, &lt;a href=&#34;https://interrupt.memfault.com/tags#gdb&#34;&gt;Memfault&amp;rsquo;s Interrupt GDB blogs&lt;/a&gt; and of course Bootlin&amp;rsquo;s &lt;a href=&#34;https://bootlin.com/training/debugging/&#34;&gt;Linux debugging, profiling and tracing and performance analysis training&lt;/a&gt;. I highly recommend you check out other topics of theirs if you are interested in embedded software development. Special thanks to Bootlin for providing the &lt;a href=&#34;https://github.com/bootlin/training-materials/tree/master/lab-data/debugging/nfsroot/root&#34;&gt;source code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you would like to support the work I do, consider donating &lt;a href=&#34;https://viainsita.com.hr/about&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
	</item>
	
	<item>
		<title>About</title>
		<link>https://viainsita.com.hr/about/</link>
		<pubDate>Mon, 30 Dec 2024 22:57:35 +0100</pubDate>
		
		<guid>https://viainsita.com.hr/about/</guid>
		<description>&lt;p&gt;My name is Martin Cvitić and I am an embedded software developer from Croatia.&lt;/p&gt;
&lt;p&gt;Via Insita is my personal website where I mostly write about embedded systems focusing mainly on embedded systems running Linux.&lt;/p&gt;
&lt;p&gt;General areas of my technical interest include open source software and hardware as well as cybersecurity.&lt;/p&gt;
&lt;p&gt;Thanks for stopping by!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;mailto:martincvitic19@gmail.com&#34;&gt;martincvitic19@gmail.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/martincvitic19&#34;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/users/20088312/martin-cvitic&#34;&gt;StackOverflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you would like to support my work, consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://coff.ee/viainsita&#34;&gt;buying me coffee&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;donating to my Monero address:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;48wxtnuXnv18xeYMBjoLHqZ3ySt5fMSUvPLbSSbmWacL2GDwJaBv49PPzPurCsvdBMajpk93aQgHAW8DzS6wHBNuUQFmHYS&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://viainsita.com.hr/monero.png&#34; alt=&#34;Monero QR code&#34; title=&#34;Monero QR code&#34;&gt;&lt;/p&gt;
</description>
	</item>
	
	</channel>
</rss>
