<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Can Gulmez</title>
    <description>The latest articles on DEV Community by Can Gulmez (@cangulmez).</description>
    <link>https://dev.to/cangulmez</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3457100%2F58231770-b49c-45be-a12c-22330682820e.png</url>
      <title>DEV Community: Can Gulmez</title>
      <link>https://dev.to/cangulmez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cangulmez"/>
    <language>en</language>
    <item>
      <title>Embedded Linux Development - Part 6</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Tue, 21 Apr 2026 09:03:18 +0000</pubDate>
      <link>https://dev.to/cangulmez/embedded-linux-development-part-6-122k</link>
      <guid>https://dev.to/cangulmez/embedded-linux-development-part-6-122k</guid>
      <description>&lt;p&gt;In this tutorial, I will continue to discuss embedded Linux development with &lt;em&gt;ssh&lt;/em&gt; server activation. Previously, I've entered into BeagleBone Black over J1 serial header with a USB-UART converter. In here, I will show that how to enter into it with ssh command.&lt;/p&gt;

&lt;p&gt;Firstly, there are two important points that you have to do. I've already did these in previous tutorials. Firstly, I compiled the kernel with &lt;em&gt;USB Gadget&lt;/em&gt; module and secondly, I installed &lt;em&gt;openssh-server&lt;/em&gt; package into the rootfs. USB gadget module enables the USB connection as the virtual ethernet adapter.&lt;/p&gt;

&lt;p&gt;Let's do required settings for both side. Use the J1 serial header again to enter into the BeagleBone Black.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosfzwghyeth0o8qm9j16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosfzwghyeth0o8qm9j16.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Type the "root" and the password. Also creating a normal user is good practice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@can:/# useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash can
root@can:/# passwd can
root@can:/# usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;can
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've created a user named "can" and set the its password. After that go to the your home directory and create a bash script. I named it as &lt;em&gt;setup-usb-gadget.sh&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@can:/home/can#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;setup-usb-gadget.sh
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open and copy this into that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;INTERFACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"usb0"&lt;/span&gt;
&lt;span class="nv"&gt;IP_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"198.168.7.2/24"&lt;/span&gt;

&lt;span class="c"&gt;# Load the g_ether kernel module that creates the ethernet virtual link.&lt;/span&gt;
modprobe g_ether

&lt;span class="c"&gt;# Configure the link interface.&lt;/span&gt;
ip addr flush dev &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INTERFACE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
ip &lt;span class="nb"&gt;link set&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INTERFACE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; up
ip addr add &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IP_ADDR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; dev &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INTERFACE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Ensure that SSH is running.&lt;/span&gt;
systemctl start ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, I loaded the &lt;em&gt;g_ether&lt;/em&gt; module into the kernel. It's the name of USB gadget module. I will create &lt;em&gt;usb0&lt;/em&gt; interface. After that I set it as "up" and its IP address as "198.168.7.2". You can give any IP address, doesn't matter. But generally, "198.168.7.2" is used. Lastly make sure that ssh server is enabled.&lt;/p&gt;

&lt;p&gt;Set the executable permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@can:/home/can#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./setup-usb-gadget.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then run it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@can:/home/can#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./setup-usb-gadget.sh 
&lt;span class="go"&gt;[  644.487501] g_ether gadget.0: HOST MAC f6:b0:84:e3:dc:c2
[  644.493125] g_ether gadget.0: MAC e2:87:7a:43:97:1d
[  644.498588] g_ether gadget.0: Ethernet Gadget, version: Memorial Day 2008
[  644.505565] g_ether gadget.0: g_ether ready
[  644.522283] PM: Cannot get wkup_m3_ipc handle
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, list the available interface on BeagleBone Black:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@can:/home/can#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip addr show
&lt;span class="gp"&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
&lt;span class="go"&gt;    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
&lt;/span&gt;&lt;span class="gp"&gt;2: sit0@NONE: &amp;lt;NOARP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 1480 qdisc noop state DOWN group default qlen 1000
&lt;span class="go"&gt;    link/sit 0.0.0.0 brd 0.0.0.0
&lt;/span&gt;&lt;span class="gp"&gt;3: eth0: &amp;lt;BROADCAST,MULTICAST&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 1500 qdisc noop state DOWN group default qlen 1000
&lt;span class="go"&gt;    link/ether 64:8c:bb:f2:25:78 brd ff:ff:ff:ff:ff:ff
&lt;/span&gt;&lt;span class="gp"&gt;4: usb0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
&lt;span class="go"&gt;    link/ether e2:87:7a:43:97:1d brd ff:ff:ff:ff:ff:ff
    inet 198.168.7.2/24 brd 198.168.7.255 scope global usb0
       valid_lft forever preferred_lft forever
    inet6 fe80::e087:7aff:fe43:971d/64 scope link 
       valid_lft forever preferred_lft forever
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see the "usb0" interface. That's enough for BeagleBone Black. Let's continue with host side. Open a new terminal and list the available interfaces on host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip addr show
&lt;span class="gp"&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
&lt;span class="go"&gt;    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
&lt;/span&gt;&lt;span class="gp"&gt;2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
&lt;span class="go"&gt;    link/ether e8:6a:64:19:45:15 brd ff:ff:ff:ff:ff:ff
&lt;/span&gt;&lt;span class="gp"&gt;3: wlp2s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 1500 qdisc noqueue state UP group default qlen 1000
&lt;span class="go"&gt;    link/ether b0:fc:36:c1:cf:eb brd ff:ff:ff:ff:ff:ff
    inet 10.152.197.93/24 brd 10.152.197.255 scope global dynamic noprefixroute wlp2s0
       valid_lft 3521sec preferred_lft 3521sec
    inet6 fe80::18fc:91fe:ea80:8fad/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
&lt;/span&gt;&lt;span class="gp"&gt;4: docker0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 1500 qdisc noqueue state DOWN group default 
&lt;span class="go"&gt;    link/ether fa:47:d4:7a:67:3e brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
&lt;/span&gt;&lt;span class="gp"&gt;13: enxf6b084e3dcc2: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mtu 1500 qdisc fq_codel state UP group default qlen 1000
&lt;span class="go"&gt;    link/ether f6:b0:84:e3:dc:c2 brd ff:ff:ff:ff:ff:ff
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BeagleBone Black seems as "enxf6b084e3dcc2" for now. You probably see the different name. It doesn't matter. As wee did in BeagleBone Black, let's do the same things at host side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ip addr flush dev enxf6b084e3dcc2
&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;enxf6b084e3dcc2 up
&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ip addr add 198.168.7.1/24 dev enxf6b084e3dcc2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I assigned the IP address "198.168.7.1" to host (I did "198.168.7.2" for BeagleBone Black).&lt;/p&gt;

&lt;p&gt;Lastly, ping BeagleBone Black interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ping 198.168.7.2
&lt;span class="go"&gt;PING 198.168.7.2 (198.168.7.2) 56(84) bytes of data.
64 bytes from 198.168.7.2: icmp_seq=1 ttl=64 time=0.904 ms
64 bytes from 198.168.7.2: icmp_seq=2 ttl=64 time=0.351 ms
64 bytes from 198.168.7.2: icmp_seq=3 ttl=64 time=0.449 ms
64 bytes from 198.168.7.2: icmp_seq=4 ttl=64 time=0.478 ms
64 bytes from 198.168.7.2: icmp_seq=5 ttl=64 time=0.585 ms
64 bytes from 198.168.7.2: icmp_seq=6 ttl=64 time=0.477 ms
^C
--- 198.168.7.2 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5114ms
rtt min/avg/max/mdev = 0.351/0.540/0.904/0.176 ms
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's okey 🥳🥳🥳🥳. You can connect to BeagleBone Black with ssh command for now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ssh can@198.168.7.2
&lt;span class="go"&gt;can@198.168.7.2's password: 
&lt;/span&gt;&lt;span class="gp"&gt;Linux can 6.14.0-ge8b471285262 #&lt;/span&gt;1 SMP Mon Apr 13 12:31:38 +03 2026 armv7l
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;The programs included with the Debian GNU/Linux system are free software;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Jan  1 00:43:51 2000 from 198.168.7.1
&lt;/span&gt;&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;setup-usb-gadget.sh
&lt;/span&gt;&lt;span class="gp"&gt;can@can:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;span class="gp"&gt;can@can:/home$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;span class="gp"&gt;can@can:/$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;bin  boot  dev  etc  home  lib  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need anymore J1 serial header. You can use it within the ssh terminal for now. Also you can set the setup-usb-gadget.sh as startup script so that it runs automatically after the boot.&lt;/p&gt;

&lt;p&gt;In next tutorial, I will inspect the &lt;em&gt;uEnv.txt&lt;/em&gt; file and u-boot console. You can make many interesting tricks in there.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;p&gt;Simmonds C., Mastering Embedded Linux Programming, Packt Publishing, 2015&lt;br&gt;
Embedded Linux system development training, Bootlin, 2024&lt;/p&gt;

</description>
      <category>linux</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Embedded Linux Development - Part 5</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Tue, 14 Apr 2026 13:18:52 +0000</pubDate>
      <link>https://dev.to/cangulmez/embedded-linux-development-part-5-13d9</link>
      <guid>https://dev.to/cangulmez/embedded-linux-development-part-5-13d9</guid>
      <description>&lt;p&gt;Until here, I've talked about the embedded Linux development in four stage: toolchain, bootloader, Linux kernel, rootfs. In this tutorial, I will create a SD card image including these and then run it in BeagleBone Black.&lt;/p&gt;

&lt;p&gt;Firstly, let's remember that what I've produced from these stages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;MLO&lt;/em&gt; (second-stage bootloader)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;u-boot.img&lt;/em&gt; (main bootloader)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;uEnv.txt&lt;/em&gt; (commands for the bootloader)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;zImage&lt;/em&gt; (compressed the kernel image)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;am335x-boneblack.dtb&lt;/em&gt; (device tree for the kernel)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Debian rootfs&lt;/em&gt; (including the kernel modules)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How can I create a SD card image including all of these?&lt;/p&gt;

&lt;p&gt;Firstly, I need to create two partitions, one for booting and second for rootfs. So plugin the SD card into the PC (I'm on Ubuntu) and create the partitions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;parted &lt;span class="nt"&gt;-s&lt;/span&gt; /dev/sdX mklabel msdos &lt;span class="c"&gt;# parition table and partitions&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;parted &lt;span class="nt"&gt;-s&lt;/span&gt; /dev/sdX mkpart primary fat32 1MiB 65MiB &lt;span class="c"&gt;# boot partition (FAT32, 64MB)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;parted &lt;span class="nt"&gt;-s&lt;/span&gt; /dev/sdX &lt;span class="nb"&gt;set &lt;/span&gt;1 boot on &lt;span class="c"&gt;# make it first parititon&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;parted &lt;span class="nt"&gt;-s&lt;/span&gt; /dev/sdX mkpart primary ext4 65MiB 100% &lt;span class="c"&gt;# rootfs parititon (ext4, rest of SD card)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;mkfs.vfat &lt;span class="nt"&gt;-F&lt;/span&gt; 32 &lt;span class="nt"&gt;-n&lt;/span&gt; boot /dev/sdX1 &lt;span class="c"&gt;# format the boot partition&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;mkfs.ext4 &lt;span class="nt"&gt;-L&lt;/span&gt; rootfs /dev/sdX2 &lt;span class="c"&gt;# format the rootfs partition&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, I created the "boot" partition which was formatted with FAT32 and "rootfs" partition with ext4. Why did I create two distinct partitions? The first reason is that the kernel loads and runs the rootfs. So the bootloader cannot reside in the rootfs because of the bootloader runs before the kernel. Second reason is that the bootloader works with FAT32 better (even if the FAT32 size is much bigger).&lt;/p&gt;

&lt;p&gt;After that, copy the MLO, u-boot.img, uEnv.txt, zImage, am335x-boneblack.dtb into the "boot" partition. Also copy the your rootfs content into the "rootfs" partition.&lt;/p&gt;

&lt;p&gt;That's it. The SD card is ready to run the BeagleBone Black. So plugin the SD card and then power up the board. Well how to enter into the Debian rootfs? There is a J1 header besides the P9. It's the serial port. Pin 1 is GND, 4 is RX and 5 is TX. Use FT232R converter to connect these pins to PC.&lt;/p&gt;

&lt;p&gt;To see the outputs, open a terminal and the type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;screen /dev/ttyUSBX 115200 &lt;span class="c"&gt;# or /dev/ttyACMX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot the BeagleBone Black and then you will see the u-boot and the kernel messages. Lastly, you will see the login session:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkoq0bpsnhesqbe5fnwsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkoq0bpsnhesqbe5fnwsj.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Type the "root" and the password (you set it in previous tutorial). That's it. You are in the BeagleBone Black terminal.&lt;/p&gt;

&lt;p&gt;You can do whatever you want after that 🥳🥳🥳.&lt;/p&gt;

&lt;p&gt;In the next tutorial, I will show that how to use &lt;em&gt;ssh&lt;/em&gt; command so that you can easily make connection over USB cable, not needing to J1 header.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;p&gt;Simmonds C., Mastering Embedded Linux Programming, Packt Publishing, 2015&lt;br&gt;
Embedded Linux system development training, Bootlin, 2024&lt;/p&gt;

</description>
      <category>programming</category>
      <category>computerscience</category>
      <category>linux</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Embedded Linux Development - Part 4</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Mon, 13 Apr 2026 17:15:36 +0000</pubDate>
      <link>https://dev.to/cangulmez/embedded-linux-development-part-4-2j83</link>
      <guid>https://dev.to/cangulmez/embedded-linux-development-part-4-2j83</guid>
      <description>&lt;p&gt;In this tutorial, I will go with the fourth stage of embedded Linux development which is the rootfs.&lt;/p&gt;

&lt;p&gt;Every Linux-based system have a filesystem. If you are on GNU/Linux, you already probably know it and how it structured.&lt;/p&gt;

&lt;p&gt;Apart from that embedded Linux needs a few special applications to start up the system. The &lt;em&gt;init&lt;/em&gt; is the first program that runs on user-space so that its process ID always is 1. This init program is responsible for start the other user-space applications and services like shell. It generally resides at &lt;em&gt;/sbin/init&lt;/em&gt;, &lt;em&gt;/etc/init&lt;/em&gt;, &lt;em&gt;/bin/init&lt;/em&gt; or so on. The kernel try to find it and then run.&lt;/p&gt;

&lt;p&gt;The organization of a Linux rootfs in terms of directories is well-defined by the &lt;em&gt;Filesystem Hierarchy Standard&lt;/em&gt;. The general hierarchy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/bin&lt;/em&gt;: Basic programs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/boot&lt;/em&gt;: Kernel images, configurations and booting tools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/dev&lt;/em&gt;: Device files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/etc&lt;/em&gt;: System-wide configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/home&lt;/em&gt;: Directory for the users home utilities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/lib&lt;/em&gt;: Basic libraries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/media&lt;/em&gt;: Mount points for removable media&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/mnt&lt;/em&gt;: Mount point for a temporarily mounted filesystem&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/proc&lt;/em&gt;: Mount point for the proc virtual filesystem&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/root&lt;/em&gt;: How directory of the root user&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/run&lt;/em&gt;: Run-time variable data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/sbin&lt;/em&gt;: Basic system programs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/sys&lt;/em&gt;: Mount point of the sysfs virtual filesystem&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/tmp&lt;/em&gt;: Temporary files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/usr&lt;/em&gt;: User-specific utilities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;/var&lt;/em&gt;: Variable data files, for system services&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So in summary, I need to create a Linux rootfs and then put the required applications in there. I also want to build a development environment. For example, I want to run python 3 scripts, compiling C/C++ programs, or so on. But how? &lt;/p&gt;

&lt;p&gt;There are three options here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Building everything from scratch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A minimal &lt;em&gt;BusyBox&lt;/em&gt; rootfs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Debian rootfs with &lt;em&gt;debootstap&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which option is for me? &lt;/p&gt;

&lt;p&gt;Building everything from scratch means that creating the directories and then fetch the every program, package, library by hand. It means the hell of package dependency! It's not for me.&lt;/p&gt;

&lt;p&gt;A minimal rootfs can be created with BusyBox easily. It can create the classic Linux directories and put the core utilities in there like &lt;em&gt;cp&lt;/em&gt;, &lt;em&gt;mkdir&lt;/em&gt;, &lt;em&gt;ls&lt;/em&gt; or so on. If you're making embedded Linux system first time and just focusing on a "running" system, BusyBox is for you. But I need more. I wanna create a development environment!&lt;/p&gt;

&lt;p&gt;The right tool is debootstrap program. It creates a base Debian rootfs including the utilities that we're using everyday like &lt;em&gt;apt&lt;/em&gt;, &lt;em&gt;systemctl&lt;/em&gt;, &lt;em&gt;vi&lt;/em&gt;, or so on. This Debian rootfs is around ~200MB, while BusyBox rootfs is ~1MB.&lt;/p&gt;

&lt;p&gt;By the way, if you want to go with BusyBox rootfs (while I'm not), below is the required commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://git.busybox.net/busybox
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;busybox
&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- defconfig
&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- menuconfig &lt;span class="c"&gt;# optional&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- &lt;span class="nv"&gt;CONFIG_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;path/to/linux/rootfs &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's focus on debootstrap. Firstly download it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;qemu-user-static debootstrap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, I also installed &lt;em&gt;qemu-user-static&lt;/em&gt; which lets me to run the ARM binaries onto x86_64.&lt;/p&gt;

&lt;p&gt;Let's create the base Debian rootfs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;debootstrap &lt;span class="nt"&gt;--arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;armhf &lt;span class="nt"&gt;--foreign&lt;/span&gt; bookworm path/to/linux/rootfs http://deb.debian.org/debian
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo chroot &lt;/span&gt;path/to/linux/rootfs /debootstrap/debootstrap &lt;span class="nt"&gt;--second-stage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, &lt;em&gt;bookworm&lt;/em&gt; is the nickname of Debian 12 which is the last stable version. &lt;/p&gt;

&lt;p&gt;These two commands download the rootfs and then unpack it. So it takes some time (~30 minutes in my case). Don't forget, these just fetch the &lt;em&gt;required&lt;/em&gt; and &lt;em&gt;important&lt;/em&gt; packages from the Debian database, not fully OS.&lt;/p&gt;

&lt;p&gt;The rootfs is ready to be used. But there are some tricks that you always must do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /usr/bin/qemu-arm-static &amp;lt;path/to/linux/rootfs&amp;gt;/usr/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also want to install the additional packages and make some settings. For example, you always must set the password. That means I need to run this rootfs on my Ubuntu host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo chroot &lt;/span&gt;path/to/linux/rootfs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First thing you must is to update the password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@can:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;passwd
&lt;span class="go"&gt;New password: 
Retype new password: 
passwd: password updated successfully
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the additional packages if you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;root@can:/#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;gcc python3 vim openssh-server &lt;span class="c"&gt;# and what you need&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, make sure that you install the openssh-server. It's required for &lt;em&gt;ssh&lt;/em&gt; command. &lt;/p&gt;

&lt;p&gt;Lastly, I need to install the kernel modules in this rootfs. Go back to the kernel source and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- &lt;span class="nv"&gt;INSTALL_MOD_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;path/to/linux/rootfs modules_install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. I created the proper Debian rootfs that I can make software development. In the next tutorial, I will use the all artifacts coming from u-boot, the kernel and the rootfs to make SD card image.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;p&gt;Simmonds C., Mastering Embedded Linux Programming, Packt Publishing, 2015&lt;br&gt;
Embedded Linux system development training, Bootlin, 2024&lt;/p&gt;

</description>
      <category>programming</category>
      <category>lowcode</category>
      <category>linux</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Embedded Linux Development - Part 3</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Mon, 13 Apr 2026 14:02:29 +0000</pubDate>
      <link>https://dev.to/cangulmez/embedded-linux-development-part-3-6hm</link>
      <guid>https://dev.to/cangulmez/embedded-linux-development-part-3-6hm</guid>
      <description>&lt;p&gt;In this tutorial, I'll go with the third stage of embedded Linux development. That's the Linux kernel.&lt;/p&gt;

&lt;p&gt;It's the responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Manage all the hardware resources: CPU, memory, I/O.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a set of portable, architecture and hardware independent APIs to allow user space applications and libraries to use the hardware resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle concurrent accesses and usage of hardware resources set of system calls.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The kernel provides about 400 system calls that provide the services like opening the disk file, forking the new process, managing the memory or so on. These system calls are defined in &lt;em&gt;/usr/include/x86_64-linux-gnu/asm/unistd.h&lt;/em&gt; like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9
#define __NR_mprotect 10
#define __NR_munmap 11
#define __NR_brk 12
&lt;/span&gt;
&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In user-space applications, we generally don't use these system calls directly. These system calls are wrapped by the standard POSIX C library. If you're a programmer, you already know it.&lt;/p&gt;

&lt;p&gt;Let's start with downloading Linux kernel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have the 6.14 kernel (slightly older, but doesn't matter). As you see that the kernel contains thousands of device drivers, filesystem drivers, network protocols and other configurable items. &lt;/p&gt;

&lt;p&gt;As I did previously at u-boot stage, the first thing is to configure the kernel according to BeagleBone Black over configuration files (ends with &lt;em&gt;_defconfig&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Which configuration file should be used for BeagleBone Black? It's &lt;em&gt;omap2plus_defconfig&lt;/em&gt; under &lt;em&gt;linux/arch/arm/configs&lt;/em&gt; (OMAP is the processor family including the AM335x Sitara processor by TI).&lt;/p&gt;

&lt;p&gt;So let's configure the kernel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- omap2plus_defconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will create the &lt;em&gt;.config&lt;/em&gt; and write the associated configs in it. &lt;/p&gt;

&lt;p&gt;As I said, this configuration file includes the generic AM335x Sitara processor configs. To customize and tailor the kernel further:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make menuconfig &lt;span class="c"&gt;# or xconfig (for Qt-based)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will open the terminal-based GUI window to select/unselect the configurable items like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a6ql4jcidk6pidcck8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a6ql4jcidk6pidcck8n.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're unfamiliar or newer, I DON'T recommend it. But I need to make an important configuration in here about the &lt;em&gt;USB gadget&lt;/em&gt; support. As I will explain in the next tutorail, I wanna use the &lt;em&gt;ssh&lt;/em&gt; command to make connection with BeagleBone Black. If you don't make it, you're totally free.&lt;/p&gt;

&lt;p&gt;Navigate to &lt;em&gt;Device Drivers --&amp;gt; USB Support --&amp;gt; USB Gadget Support --&amp;gt; USB Gadget precomposed configurations --&amp;gt; Ethernet Gadget (with CDC Ethernet support)&lt;/em&gt;, type "M" and then exit by saving. It will create the virtual USB link so that I can use the ssh command to connect to BeagleBone Black. I will explain it in the last tutorial in detail.&lt;/p&gt;

&lt;p&gt;By the way, you will see the "*" and "M" marks as you navigate the configs. "*" means that the configs will be embedded into the kernel image, while "M" means that the configs is built as modules. These are plugins that can be loaded/unloaded dynamically at runtime to the kernel.&lt;/p&gt;

&lt;p&gt;After configured the kernel, for now, you're ready to build the required outputs. &lt;/p&gt;

&lt;p&gt;Which outputs exactly should be built from the kernel source? Three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;zImage&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;am335x-boneblack.dtb&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;kernel modules&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;zImage is the compressed the Linux kernel image. am335x-boneblack.dtb is the &lt;em&gt;device tree blob&lt;/em&gt; that describes the hardware connected to the kernel. The kernel modules also are being compiled externally, not embedded into the kernel image.&lt;/p&gt;

&lt;p&gt;In here, I have to explain the device tree concept. It's the description of the hardware that the kernel manages at runtime. As you expect, the kernel must know the hardware that it will manage. It's written generally by the processor vendor or development board engineers. The device tree corresponding to BeagleBone Black is the &lt;em&gt;am335x-boneblack.dts&lt;/em&gt; under &lt;em&gt;linux/arch/arm/boot/dts/ti/omap&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To produces these outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; zImage dtbs modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will take for a while (~1 hours in my case). After that you will see the zImage under &lt;em&gt;linux/arch/arm/boot&lt;/em&gt; and am335x-boneblack.dtb under &lt;em&gt;linux/arch/arm/boot/dts/ti/omap&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The kernel modules are compiled ending with &lt;em&gt;.ko&lt;/em&gt; suffix. After the rootfs is being created, I will install these kernel modules in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- &lt;span class="nv"&gt;INSTALL_MOD_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;path/to/linux/rootfs modules_install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But DON'T do it for now. I need to create a rootfs firstly and then install the kernel modules in there. I will show it in the next tutorial.&lt;/p&gt;

&lt;p&gt;That's it. I've produced the three essential components from the kernel source: zImage, am335x-boneblack.dtb, and kernel modules. In the next tutorial, I will interest with the rootfs.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;p&gt;Simmonds C., Mastering Embedded Linux Programming, Packt Publishing, 2015&lt;br&gt;
Embedded Linux system development training, Bootlin, 2024&lt;/p&gt;

</description>
      <category>programming</category>
      <category>linux</category>
      <category>lowcode</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Embedded Linux Development - Part 2</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Sun, 12 Apr 2026 19:10:26 +0000</pubDate>
      <link>https://dev.to/cangulmez/embedded-linux-development-part-2-3klh</link>
      <guid>https://dev.to/cangulmez/embedded-linux-development-part-2-3klh</guid>
      <description>&lt;p&gt;In this post, I will continue the embedded Linux development series with second stage which is the bootloader.&lt;/p&gt;

&lt;p&gt;Firstly, a bit theoretical background.&lt;/p&gt;

&lt;p&gt;The bootloader is a piece of code responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic hardware initialization&lt;/li&gt;
&lt;li&gt;Loading of an application binary, usually an operating
system kernel, from flash storage, from the network, or from another type of non-volatile storage&lt;/li&gt;
&lt;li&gt;Possible decompression of the application binary&lt;/li&gt;
&lt;li&gt;Execution of the application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Besides these basic functions, most bootloaders provide a shell or menu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Menu to select the operating system to load&lt;/li&gt;
&lt;li&gt;Shell with commands to load data from storage or network, inspect memory, perform hardware testing/diagnostics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Boot process highly is depended to processor. Let's focus on AM335x Sitara (ARM) booting sequence. &lt;/p&gt;

&lt;p&gt;Most embedded processors include a &lt;em&gt;ROM code&lt;/em&gt; that implements the initial step of the boot process. It's called the &lt;em&gt;first-stage loader&lt;/em&gt;. This ROM code is written by the processor vendor directly built into the processor. That means, it cannot be changed or updated by the others. It initializes the CPU and internal SRAM. It also searches the &lt;em&gt;MLO&lt;/em&gt; from NAND/NOR flash, from USB, from SD card, from eMMC, etc.&lt;/p&gt;

&lt;p&gt;MLO is a file that you need to produce from the bootloader source code. It's called also &lt;em&gt;second-program loader (SPL)&lt;/em&gt;. Its mission is to initialize the DDR RAM and run the main bootloader.&lt;/p&gt;

&lt;p&gt;The main bootloader initializes the hardware and then loads the Linux kernel and then jump to it. I will use the &lt;em&gt;U-Boot&lt;/em&gt;. It's the mostly used bootloader in embedded world.&lt;/p&gt;

&lt;p&gt;In summary, the booting process: &lt;em&gt;ROM code --&amp;gt; MLO (SPL) --&amp;gt; U-Boot --&amp;gt; Linux kernel&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So after compiled the u-boot, I expect these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MLO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;u-boot.img&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's produce these.&lt;/p&gt;

&lt;p&gt;Firstly, download the u-boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://source.denx.de/u-boot/u-boot.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look at the source code, you will see that the u-boot supports a lot of processors and boards. So first thing you should do is to configure the u-boot over configuration files (ends with &lt;em&gt;*_defconfig&lt;/em&gt;) under &lt;em&gt;u-boot/configs&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;But which exactly configuration file corresponds to BeagleBone Black? The answer is &lt;em&gt;am335x_evm_defconfig&lt;/em&gt;. It's generic AM335x Sitara processor configuration file.&lt;/p&gt;

&lt;p&gt;To use this configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make am335x_evm_defconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will create the &lt;em&gt;.config&lt;/em&gt; file and write the configs in it. The important point is that you never edit this file by hand.&lt;/p&gt;

&lt;p&gt;To customize and tailor this configs further:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make menuconfig     &lt;span class="c"&gt;# or xconfig (for Qt-based)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will open the terminal-based GUI to select/unselect the configs. If you are unfamiliar or newer, you should NOT do it. Because it will show the tons of different configs and it can seem messy. The previous command already made the generic required configs.&lt;/p&gt;

&lt;p&gt;After setting up the configs, let's build the outputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm &lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm-linux-gnueabihf- 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will take for a while. Because it will compile the tons of source file and then link them together. The output will be like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;...&lt;span class="o"&gt;)&lt;/span&gt;

  AR      spl/fs/fat/built-in.o
  CC      spl/fs/fs_internal.o
  AR      spl/fs/built-in.o
  CC      spl/net/arp.o
  CC      spl/net/bootp.o
  CC      spl/net/eth-uclass.o
  CC      spl/net/eth_common.o
  CC      spl/net/net.o
  CC      spl/net/ping.o
  CC      spl/net/tftp.o
  AR      spl/net/built-in.o
  LDS     spl/u-boot-spl.lds
  LD      spl/u-boot-spl
  OBJCOPY spl/u-boot-spl-nodtb.bin
  COPY    spl/u-boot-spl.bin
  MKIMAGE MLO
  MKIMAGE MLO.byteswap
  SYM     spl/u-boot-spl.sym
  MKIMAGE u-boot-dtb.img
  OFCHK   .config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that you can see the u-boot/MLO, u-boot/u-boot.img and a lots of other files. &lt;/p&gt;

&lt;p&gt;As I said before, I need the MLO and u-boot.img and will use these in further. For now, just keeps these in mind.&lt;/p&gt;

&lt;p&gt;There is also one more important file that I need. It's &lt;em&gt;uEnv.txt&lt;/em&gt; and used by the u-boot when loading the Linux kernel. It consists of the key-value pairs that tell some command to u-boot. So create a new file named of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vim uEnv.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And write the following commands in it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;bootpart&lt;/span&gt;=&lt;span class="m"&gt;0&lt;/span&gt;:&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;devtype&lt;/span&gt;=&lt;span class="n"&gt;mmc&lt;/span&gt;
&lt;span class="n"&gt;bootdir&lt;/span&gt;=
&lt;span class="n"&gt;bootfile&lt;/span&gt;=&lt;span class="n"&gt;zImage&lt;/span&gt;
&lt;span class="n"&gt;bootpartition&lt;/span&gt;=&lt;span class="n"&gt;mmcblk0p2&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;=&lt;span class="n"&gt;ttyS0&lt;/span&gt;,&lt;span class="m"&gt;115200&lt;/span&gt;&lt;span class="n"&gt;n8&lt;/span&gt;
&lt;span class="n"&gt;loadaddr&lt;/span&gt;=&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x82000000&lt;/span&gt;
&lt;span class="n"&gt;fdtaddr&lt;/span&gt;=&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x88000000&lt;/span&gt;
&lt;span class="n"&gt;set_mmc1&lt;/span&gt;=&lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; $&lt;span class="n"&gt;board_name&lt;/span&gt; = &lt;span class="n"&gt;A33515BB&lt;/span&gt;; &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;setenv&lt;/span&gt; &lt;span class="n"&gt;bootpartition&lt;/span&gt; &lt;span class="n"&gt;mmcblk1p2&lt;/span&gt;; &lt;span class="n"&gt;fi&lt;/span&gt;
&lt;span class="n"&gt;set_bootargs&lt;/span&gt;=&lt;span class="n"&gt;setenv&lt;/span&gt; &lt;span class="n"&gt;bootargs&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt;=${&lt;span class="n"&gt;console&lt;/span&gt;} &lt;span class="n"&gt;root&lt;/span&gt;=/&lt;span class="n"&gt;dev&lt;/span&gt;/${&lt;span class="n"&gt;bootpartition&lt;/span&gt;} &lt;span class="n"&gt;rw&lt;/span&gt; &lt;span class="n"&gt;rootfstype&lt;/span&gt;=&lt;span class="n"&gt;ext4&lt;/span&gt; &lt;span class="n"&gt;rootwait&lt;/span&gt;
&lt;span class="n"&gt;uenvcmd&lt;/span&gt;=&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;set_mmc1&lt;/span&gt;; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;set_bootargs&lt;/span&gt;;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;loadimage&lt;/span&gt;;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;loadfdt&lt;/span&gt;;&lt;span class="n"&gt;printenv&lt;/span&gt; &lt;span class="n"&gt;bootargs&lt;/span&gt;;&lt;span class="n"&gt;bootz&lt;/span&gt; ${&lt;span class="n"&gt;loadaddr&lt;/span&gt;} - ${&lt;span class="n"&gt;fdtaddr&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end of this series, you will fully understand what these are. But basically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;the console name is set to ttyS0 and baud rate to 115200.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the Linux kernel name is defined as &lt;em&gt;zImage&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the address that Linux kernel image will be placed is set to 0x82000000 and the address that device tree blob will be placed to 0x88000000.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;set the boot environment and load the Linux kernel with &lt;em&gt;bootz&lt;/em&gt; command.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save it and then keep this file in mind as being MLO and u-boot.img.&lt;/p&gt;

&lt;p&gt;That's it. You've produced the three components related to bootloader stage. In next post, I will interest with Linux kernel itself.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;p&gt;Simmonds C., Mastering Embedded Linux Programming, Packt Publishing, 2015&lt;br&gt;
Embedded Linux system development training, Bootlin, 2024&lt;/p&gt;

</description>
      <category>linux</category>
      <category>programming</category>
      <category>lowcode</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Embedded Linux Development - Part 1</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Sun, 12 Apr 2026 12:53:51 +0000</pubDate>
      <link>https://dev.to/cangulmez/embedded-linux-development-1-3pbc</link>
      <guid>https://dev.to/cangulmez/embedded-linux-development-1-3pbc</guid>
      <description>&lt;p&gt;In today, I'm beginning a new series about embedded Linux development. I'll show that how to build an end-to-end embedded Linux system from scratch by hand.&lt;/p&gt;

&lt;p&gt;I'll fetch the associated every stuffs from source code and then build the corresponding outputs.&lt;/p&gt;

&lt;p&gt;I will target the &lt;strong&gt;BeagleBone Black Rev C&lt;/strong&gt; board. I will compile the everything for that board. So you need the following things for this series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;BeagleBone Black Rev C&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;USB Mini-B to USB-A cable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FTDI FT232R converter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SD card&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, embedded Linux development consists of four components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Toolchain&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bootloader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Linux kernel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rootfs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, I will explain the toolchain that I need for all development sequence.&lt;/p&gt;

&lt;p&gt;The toolchain is the first element of embedded Linux and the starting point of the project.&lt;/p&gt;

&lt;p&gt;A toolchain is the set of tools that compiles source code into executables that can run on your target device, and includes many binaries for the different purposes. Usually, toolchains for Linux are based on components from the GNU project. A standard GNU toolchain consists of three main components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Binutils&lt;/em&gt; is a set of tools to generate and manipulate binaries for a given architecture. Common binaries: &lt;em&gt;as&lt;/em&gt;, &lt;em&gt;ld&lt;/em&gt;, &lt;em&gt;ar&lt;/em&gt;, &lt;em&gt;randlib&lt;/em&gt;, &lt;em&gt;objdump&lt;/em&gt;, &lt;em&gt;readelf&lt;/em&gt;, &lt;em&gt;size&lt;/em&gt;, &lt;em&gt;nm&lt;/em&gt;, &lt;em&gt;strings&lt;/em&gt;, &lt;em&gt;strip&lt;/em&gt;, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;GCC&lt;/em&gt; is the main compiler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;C library&lt;/em&gt; is used to interract with the kernel. The programming interface to the UNIX operating system is defined in the C language, which is defined by the POSIX standards. The C library is the implementation of the interface.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In here, there are two types of toolchain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Native&lt;/em&gt;: This toolchain runs on the same type of system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Cross&lt;/em&gt;: This toolchain run on a different type of system than the target.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Almost all embedded Linux development is done using a cross development toolchain. Because doing embedded development, there is always a split between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;host&lt;/em&gt;, the development workstation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;target&lt;/em&gt;, which is the embedded system&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are connected by various means: almost always a serial line for debugging purposes, frequently a network connection, sometimes a JTAG interface for low-level stuffs.&lt;/p&gt;

&lt;p&gt;Many UNIX/Linux toolchains rely on architecture tuple names to identify machines. You probably compiled many programs on your host already and used the &lt;em&gt;gcc&lt;/em&gt; command. But it's actually a shorthand. You can exactly see it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gcc &lt;span class="nt"&gt;-dumpmachine&lt;/span&gt;
&lt;span class="go"&gt;x86_64-linux-gnu
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples: &lt;em&gt;arm-linux-gnueabihf&lt;/em&gt;, &lt;em&gt;mips64el-linux-gnu&lt;/em&gt;, &lt;em&gt;arm-none-eabi-&lt;/em&gt; etc.&lt;/p&gt;

&lt;p&gt;These tuples are 3 or 4 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The architecture name: &lt;em&gt;arm&lt;/em&gt;, &lt;em&gt;riscv&lt;/em&gt;, &lt;em&gt;mips64el&lt;/em&gt;, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optionally, a vendor name, which is free-form string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An operating system name, or &lt;em&gt;none&lt;/em&gt; when not targeting an operating system.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, these are the pre-built toolchains. If you want, you can also create your own toolchain with &lt;em&gt;crosstool-ng&lt;/em&gt;. It's another post topic. But shortly, when building a toolchain, the ABI used to generate binaries needs to be defined. ABI, &lt;em&gt;Application Binary Interface&lt;/em&gt;, defines the calling conventions (how function arguments are passed, how the return value is passed, how system calls are made or so on) and the organization of structures. All binaries in a system are typically compiled with the same ABI, and the kernel must understand this ABI.&lt;/p&gt;

&lt;p&gt;Anyway, I gave you the enough theoretical toolchain background. Let's go with our concern.&lt;/p&gt;

&lt;p&gt;Which toolchain should be used for BeagleBone Black?&lt;/p&gt;

&lt;p&gt;You have to know the used ARM processor in here. BeageBone Black has AM335x Sitara processor which is based on ARM-A8 (ARMv7), 32-bit architecture. So the toolchain for that is the &lt;em&gt;gcc-arm-linux-gnueabihf&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The first thing in implementing embedded Linux is to install it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;gcc-arm-linux-gnueabihf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that validate it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;arm-linux-gnueabihf-gcc &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="go"&gt;arm-linux-gnueabihf-gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
Copyright (C) 2023 Free Software Foundation, Inc.
&lt;/span&gt;&lt;span class="gp"&gt;This is free software;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;see the &lt;span class="nb"&gt;source &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;copying conditions.  There is NO
&lt;span class="gp"&gt;warranty;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;not even &lt;span class="k"&gt;for &lt;/span&gt;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You have the required toolchain and ready to go with the bootloader.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;p&gt;Simmonds C., Mastering Embedded Linux Programming, Packt Publishing, 2015&lt;br&gt;
Embedded Linux system development training, Bootlin, 2024&lt;/p&gt;

</description>
      <category>linux</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>POSIX Shared Memory</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Wed, 08 Apr 2026 12:47:19 +0000</pubDate>
      <link>https://dev.to/cangulmez/posix-shared-memory-1l1n</link>
      <guid>https://dev.to/cangulmez/posix-shared-memory-1l1n</guid>
      <description>&lt;p&gt;POSIX shared memory allows to us to share a mapped region between unrelated processes without needing to create a corresponding  file.&lt;/p&gt;

&lt;p&gt;Linux uses a dedicated &lt;code&gt;tmpfs&lt;/code&gt; file system mounted under the directory &lt;code&gt;/dev/shm&lt;/code&gt;. This file system has kernel persistance - the shared memory objects that it contains will persists even if no process currently has them open, but they will be lost if the system is shut down.&lt;/p&gt;

&lt;p&gt;To use a POSIX shared memory object, we perform two steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use the &lt;code&gt;shm_open()&lt;/code&gt; function to open an object with a specified name. The &lt;code&gt;shm_open()&lt;/code&gt; function is analogous to the &lt;code&gt;open()&lt;/code&gt; system call. It either creates a new shared memory object or opens an existing object. As its function result, &lt;code&gt;shm_open()&lt;/code&gt; returns a file descriptor referring to the object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the file descriptor obtained in the previous step in a call to &lt;code&gt;mmap()&lt;/code&gt; that specifies &lt;code&gt;MAP_SHARED&lt;/code&gt; in the flags argument. This maps the shared memory object into the process's virtual address space.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt;        /* For mode constants */&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt;           /* For O_* constants */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;shm_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;oflag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode_t&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;shm_unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; argument identifies the shared memory object to be created or opened. The &lt;code&gt;oflags&lt;/code&gt; argument is a mask of bits of O_* as being in &lt;code&gt;open()&lt;/code&gt; system call.&lt;/p&gt;

&lt;p&gt;At any point, we can apply &lt;code&gt;fstat()&lt;/code&gt; to the file descriptor returned by &lt;code&gt;shm_open()&lt;/code&gt; in order to obtain a &lt;code&gt;stat&lt;/code&gt; structure whose contain information about the shared memory object.&lt;/p&gt;

&lt;p&gt;Example of creating a POSIX shared memory is &lt;a href="https://github.com/CanGulmez/Linux-Programming-Interface/blob/main/pshm/pshm_create.c" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After created the memory object, we of course want to read and write the data into that. Data reading program is &lt;a href="https://github.com/CanGulmez/Linux-Programming-Interface/blob/main/pshm/pshm_write.c" rel="noopener noreferrer"&gt;here&lt;/a&gt; and writing program is &lt;a href="https://github.com/CanGulmez/Linux-Programming-Interface/blob/main/pshm/pshm_read.c" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;SUSv3 requires that POSIX shared memory objects have at least kernel persistence; that is, they continue to exist until they are explicitly removed or the system is rebooted. When a shared memory object is no longer required, it should be removed using &lt;code&gt;shm_unlink()&lt;/code&gt;. The example program of its usage is &lt;a href="https://github.com/CanGulmez/Linux-Programming-Interface/blob/main/pshm/pshm_unlink.c" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In summary, a POSIX shared memory object is used to share a region of memory between unrelated processes without creating an underlying disk file. To do this, we replace the call to &lt;code&gt;open()&lt;/code&gt; that normally precedes &lt;code&gt;mmap()&lt;/code&gt; with a call to &lt;code&gt;shm_open()&lt;/code&gt;. The &lt;code&gt;shm_open()&lt;/code&gt; call creates a file in a memory-based file system, and we can employ traditional file descriptor system calls to perform various operations on this virtual file. In particular, &lt;code&gt;ftruncate()&lt;/code&gt; must be used to set the size of the shared memory object, since initially it has a length of zero.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>lowcode</category>
      <category>gnu</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Flashing and Debugging A Firmware in Detail</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Tue, 10 Mar 2026 20:38:32 +0000</pubDate>
      <link>https://dev.to/cangulmez/flashing-and-debugging-a-firmware-in-detail-d3f</link>
      <guid>https://dev.to/cangulmez/flashing-and-debugging-a-firmware-in-detail-d3f</guid>
      <description>&lt;p&gt;In this tutorial, I will inspect, flash and debug a firmware written for STM32F446RE microcontroller. To accomplish this, we need some dedicated tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;openocd&lt;/li&gt;
&lt;li&gt;arm-none-eabi-*&lt;/li&gt;
&lt;li&gt;gdb-multiarch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;openocd is the primarily tool that we have to get. It's used as bridge between your host machine and debugger hardware. (I'm using use ST-Link hardware in this time). I will use it to connect to the debugger hardware. arm-none-eabi-* tools are the ARM toolchain   used in development of the firmware. gdb-multiarch is the debugger too.&lt;/p&gt;

&lt;p&gt;You can get these tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openocd gcc-arm-none-eabi gdb-multiarch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: I'm on Ubuntu 24.04, gcc-arm-none-eabi tools don't include the gdb debugger like arm-none-eabi-gdb. So that gdb-multiarch is being installed externally. On some distribution, the gdb debugger comes with gcc-arm-none-eabi.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Suppose that I have a firmware called "firmware.elf" and wanna inspect it as first step. &lt;/p&gt;

&lt;p&gt;The first thing that you should do probably is to determine the firmware itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file firmware.elf
&lt;span class="go"&gt;firmware.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;file&lt;/em&gt; command simply outputs the firmware properties like the endiannes, architecture, or so on. You can see easily that this firmware was written for 32-bit ARM Cortex.&lt;/p&gt;

&lt;p&gt;We can see also the section sizes (in bytes) of the firmware with &lt;em&gt;arm-none-eabi-size&lt;/em&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;arm-none-eabi-size firmware.elf
&lt;span class="go"&gt;   text    data     bss     dec     hex filename
   5252      20    1732    7004    1b5c firmware.elf
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are not familiar with sections of the executables, I've wrote many tutorials that explains the ELF executable. You can look at there.&lt;/p&gt;

&lt;p&gt;If you exactly wanna see the contents of the firmware, &lt;em&gt;arm-none-eabi-objdump&lt;/em&gt; is the primarily tool for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="nb"&gt;arm&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;eabi&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;objdump&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;j&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;firmware&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;elf&lt;/span&gt;

&lt;span class="nl"&gt;firmware&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nl"&gt;elf&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;     &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="nv"&gt;format&lt;/span&gt; &lt;span class="nv"&gt;elf32&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;littlearm&lt;/span&gt;


&lt;span class="nl"&gt;Disassembly&lt;/span&gt; &lt;span class="nb"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;section&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;

&lt;span class="err"&gt;(...)&lt;/span&gt;

&lt;span class="nl"&gt;0800079c&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
 &lt;span class="err"&gt;800079&lt;/span&gt;&lt;span class="nb"&gt;c&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;b500&lt;/span&gt;        &lt;span class="nv"&gt;push&lt;/span&gt;    &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;lr&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
 &lt;span class="err"&gt;800079&lt;/span&gt;&lt;span class="nb"&gt;e&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;b091&lt;/span&gt;        &lt;span class="nv"&gt;sub&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt; &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="mh"&gt;0x44&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;a0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f000&lt;/span&gt; &lt;span class="nv"&gt;f8ac&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;80008&lt;/span&gt;&lt;span class="nv"&gt;fc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;HAL_Init&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;a4&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f000&lt;/span&gt; &lt;span class="nv"&gt;f82c&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;8000800&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;configOscClk&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;a8&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f000&lt;/span&gt; &lt;span class="nv"&gt;f844&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;8000834&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;configDebugPort&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;ac&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4911&lt;/span&gt;        &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;r1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;   &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80007&lt;/span&gt;&lt;span class="nv"&gt;f4&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x58&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;ae&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;d12&lt;/span&gt;        &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;r5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;   &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80007&lt;/span&gt;&lt;span class="nv"&gt;f8&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x5c&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;b0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;c12&lt;/span&gt;        &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;r4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;   &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80007&lt;/span&gt;&lt;span class="nv"&gt;fc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x60&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;b2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4668&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;b4&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f7ff&lt;/span&gt; &lt;span class="nv"&gt;ff08&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;80005&lt;/span&gt;&lt;span class="nv"&gt;c8&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;strcpy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;b8&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4668&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;ba&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f7ff&lt;/span&gt; &lt;span class="nv"&gt;ff81&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;80006&lt;/span&gt;&lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;strlen&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;be&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f04f&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="nv"&gt;ff&lt;/span&gt;   &lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt;   &lt;span class="nv"&gt;r3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;4294967295&lt;/span&gt; &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="mh"&gt;0xffffffff&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;c2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;b282&lt;/span&gt;        &lt;span class="nv"&gt;uxth&lt;/span&gt;    &lt;span class="nv"&gt;r2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;c4&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4669&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;c6&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;480&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;        &lt;span class="nv"&gt;ldr&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;   &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80007&lt;/span&gt;&lt;span class="nv"&gt;fc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x60&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;)&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;c8&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f000&lt;/span&gt; &lt;span class="nv"&gt;fdc2&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;8001350&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;cc&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4629&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;r5&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;ce&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4668&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;d0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f7ff&lt;/span&gt; &lt;span class="nv"&gt;fefa&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;80005&lt;/span&gt;&lt;span class="nv"&gt;c8&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;strcpy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;d4&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4668&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;d6&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f7ff&lt;/span&gt; &lt;span class="nv"&gt;ff73&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;80006&lt;/span&gt;&lt;span class="nv"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;strlen&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;da&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f04f&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="nv"&gt;ff&lt;/span&gt;   &lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt;   &lt;span class="nv"&gt;r3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;4294967295&lt;/span&gt; &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="mh"&gt;0xffffffff&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;de&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;b282&lt;/span&gt;        &lt;span class="nv"&gt;uxth&lt;/span&gt;    &lt;span class="nv"&gt;r2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;e0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4669&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;sp&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;e2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;4620&lt;/span&gt;        &lt;span class="nv"&gt;mov&lt;/span&gt; &lt;span class="nv"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;r4&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;e4&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f000&lt;/span&gt; &lt;span class="nv"&gt;fdb4&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;8001350&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;e8&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f44f&lt;/span&gt; &lt;span class="mi"&gt;707&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;   &lt;span class="nv"&gt;mov&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt;   &lt;span class="nv"&gt;r0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;   &lt;span class="no"&gt;@&lt;/span&gt; &lt;span class="mh"&gt;0x3e8&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;ec&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;f000&lt;/span&gt; &lt;span class="nv"&gt;f8b2&lt;/span&gt;   &lt;span class="nv"&gt;bl&lt;/span&gt;  &lt;span class="mi"&gt;8000954&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;HAL_Delay&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;f0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;e7ec&lt;/span&gt;        &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;cc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x30&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;f2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="nv"&gt;bf00&lt;/span&gt;        &lt;span class="nv"&gt;nop&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;f4&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;0800146&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt;    &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;word&lt;/span&gt;   &lt;span class="mh"&gt;0x0800146c&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;f8&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;08001489&lt;/span&gt;    &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;word&lt;/span&gt;   &lt;span class="mh"&gt;0x08001489&lt;/span&gt;
 &lt;span class="err"&gt;80007&lt;/span&gt;&lt;span class="nb"&gt;fc&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="mi"&gt;20000084&lt;/span&gt;    &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;word&lt;/span&gt;   &lt;span class="mh"&gt;0x20000084&lt;/span&gt;

&lt;span class="err"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, you see the &lt;em&gt;main()&lt;/em&gt; function in &lt;em&gt;.text&lt;/em&gt; section of the firmware. At left, the address of the machine code were being displayed. At center, you see the machine code corresponding to assembly instructions that is at right side.&lt;/p&gt;

&lt;p&gt;Inspecting the contents of ELF executable is huge topic. It has many variants and view-of-points in there.&lt;/p&gt;

&lt;p&gt;"Flashing" term means writing the dedicated sections of the firmware into the flash memory area of the microcontroller. It's done with many different ways. But I will show you openocd tool.&lt;/p&gt;

&lt;p&gt;In here, I have to define that how exactly does openocd work. It actually creates a server into the host machine with given configuration files. After starting the server session, you need to connect to that server over telnet or gdb. &lt;/p&gt;

&lt;p&gt;Let's do it. Firstly, connect the microcontroller to the host machine. Then open a terminal session and type this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;openocd &lt;span class="nt"&gt;-f&lt;/span&gt; interface/stlink.cfg &lt;span class="nt"&gt;-f&lt;/span&gt; target/stm32f4x.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, I gave the two configuration files. First is the interface. As I said, I use the ST-Link connection. Second is the target file. It defines the target architecture. The openocd comes a bunch of configuration files. So search it and find the appropriate configuration files.&lt;/p&gt;

&lt;p&gt;You will see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
&lt;/span&gt;&lt;span class="gp"&gt;Info : auto-selecting first available session transport "hla_swd". To override use 'transport select &amp;lt;transport&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'.
&lt;/span&gt;&lt;span class="go"&gt;Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 2000 kHz
Info : STLINK V2J33M25 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.224656
Info : [stm32f4x.cpu] Cortex-M4 r0p1 processor detected
Info : [stm32f4x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f4x.cpu on 3333
Info : Listening on port 3333 for gdb connections
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The openocd attached the 4444 port to telnet and 3333 port to gdb. So that I will bind the 3333 port in the gdb session.&lt;/p&gt;

&lt;p&gt;Secondly, open the second terminal and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gdb-multiarch firmware.elf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the moment, you are in the gdb session. In here, bind to the 3333 port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;(gdb) target remote localhost:3333
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now, you are in the control and responsible for the all flashing and debugging operations.&lt;/p&gt;

&lt;p&gt;To flash the firmware, use these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;(gdb) monitor reset halt
(gdb) load
(gdb) monitor reset halt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are tons of commands you can type in the gdb session. We can split these commands in two categories. &lt;em&gt;monitor &lt;/em&gt; commands directly are run by the openocd command. Other commands are run by the gdb itself.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;load&lt;/em&gt; is the main command to flash the firmware. Before and after that command, resetting and halting the CPU execution is good practice. Output will be like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loading section .isr_vector, size 0x1c4 lma 0x8000000
Loading section .text, size 0x126c lma 0x8000200
Loading section .rodata, size 0x4c lma 0x800146c
Loading section .ARM, size 0x8 lma 0x80014b8
Loading section .init_array, size 0x4 lma 0x80014c0
Loading section .fini_array, size 0x4 lma 0x80014c4
Loading section .data, size 0xc lma 0x80014c8
Start address 0x08001400, load size 5272
Transfer rate: 9 KB/sec, 753 bytes/write.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means that the firmware successfully was flashed 🥳.&lt;/p&gt;

&lt;p&gt;If you just wanna flash the firmware and not debugging, this following command is enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;openocd &lt;span class="nt"&gt;-f&lt;/span&gt; interface/stlink.cfg &lt;span class="nt"&gt;-f&lt;/span&gt; target/stm32f4x.cfg &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"program firmware.elf verify reset exit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of dealing with two terminal sessions, above command is just the one-step operation.&lt;/p&gt;

&lt;p&gt;The main reason opening the second gdb session is to make the debugging. If you did the debugging previously, you will be familiar with these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;(gdb) break main
(gdb) continue
(gdb) next
(gdb) finish
(gdb) print var
(gdb) x/16wx *ptr
(gdb) set var
(gdb) list
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The debugging operations are huge and will not fit into a single tutorial as you guest. So that I don't wanna dive into the these and other operations. But I wanna give you a good reference: &lt;em&gt;The Art of Debugging with GDB, DDD, and Eclipse&lt;/em&gt; written by Norman Matloff and Peter Jay Salzman.&lt;/p&gt;

&lt;p&gt;Until here, I gave a overall explanation the end-to-end pipeline. I'll explain the other stuffs in further. &lt;/p&gt;

</description>
      <category>lowcode</category>
      <category>c</category>
      <category>linux</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Simple Code Injection into ELF Executable</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Tue, 03 Mar 2026 12:44:18 +0000</pubDate>
      <link>https://dev.to/cangulmez/simple-code-injection-into-elf-executable-2i2o</link>
      <guid>https://dev.to/cangulmez/simple-code-injection-into-elf-executable-2i2o</guid>
      <description>&lt;p&gt;In this tutorial, I will explain an code injection technique into ELF executable.&lt;/p&gt;

&lt;p&gt;Firstly, you need to understand the ELF executable, its contents, sections, symbol table or so on. I've written a dedicated article previously. So if you don't have any information about ELF, please read it firstly and then come here again.&lt;/p&gt;

&lt;p&gt;Let's say we have the following source file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Simple Code Injection
 */&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile this source file and then run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcc main.c &lt;span class="nt"&gt;-o&lt;/span&gt; main &lt;span class="p"&gt;;&lt;/span&gt; ./main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you will see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#0
#1
#2
#3
#4
#5
#6
#7
#8
#9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, I will change the &lt;em&gt;num = 10&lt;/em&gt; to &lt;em&gt;num = 5&lt;/em&gt; so that the output will be #0 to #4. &lt;/p&gt;

&lt;p&gt;To accomplish this, I need to find the corresponding machine instruction/s. According to your background, you need to know that &lt;em&gt;num&lt;/em&gt; variable will be in the &lt;em&gt;.text&lt;/em&gt; section of ELF executable. Because it is the local variable. To display the .text section of the program, &lt;em&gt;objdump&lt;/em&gt; is the primarily tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;objdump &lt;span class="nt"&gt;-j&lt;/span&gt; .text &lt;span class="nt"&gt;-d&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will be as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt;0000000000001149&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="err"&gt;1149&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;f3&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="nv"&gt;fa&lt;/span&gt;             &lt;span class="nv"&gt;endbr64&lt;/span&gt;
    &lt;span class="err"&gt;114&lt;/span&gt;&lt;span class="nl"&gt;d:&lt;/span&gt;   &lt;span class="err"&gt;55&lt;/span&gt;                      &lt;span class="nf"&gt;push&lt;/span&gt;   &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;
    &lt;span class="err"&gt;114&lt;/span&gt;&lt;span class="nl"&gt;e:&lt;/span&gt;   &lt;span class="err"&gt;48&lt;/span&gt; &lt;span class="err"&gt;89&lt;/span&gt; &lt;span class="nf"&gt;e5&lt;/span&gt;                &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rsp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;
    &lt;span class="err"&gt;1151&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;48&lt;/span&gt; &lt;span class="err"&gt;83&lt;/span&gt; &lt;span class="nf"&gt;ec&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;             &lt;span class="nv"&gt;sub&lt;/span&gt;    &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rsp&lt;/span&gt;
    &lt;span class="err"&gt;1155&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;89&lt;/span&gt; &lt;span class="err"&gt;7&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt; &lt;span class="nv"&gt;ec&lt;/span&gt;                &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x14&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;1158&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;48&lt;/span&gt; &lt;span class="err"&gt;89&lt;/span&gt; &lt;span class="err"&gt;75&lt;/span&gt; &lt;span class="nf"&gt;e0&lt;/span&gt;             &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rsi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;115&lt;/span&gt;&lt;span class="nl"&gt;c:&lt;/span&gt;   &lt;span class="nf"&gt;c7&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="nv"&gt;fc&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;    &lt;span class="nv"&gt;movl&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0xa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;1163&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;c7&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="nv"&gt;f8&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;    &lt;span class="nv"&gt;movl&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;116&lt;/span&gt;&lt;span class="nl"&gt;a:&lt;/span&gt;   &lt;span class="nf"&gt;eb&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;                   &lt;span class="nv"&gt;jmp&lt;/span&gt;    &lt;span class="mi"&gt;1189&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x40&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="err"&gt;116&lt;/span&gt;&lt;span class="nl"&gt;c:&lt;/span&gt;   &lt;span class="err"&gt;8&lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="nv"&gt;f8&lt;/span&gt;                &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;
    &lt;span class="err"&gt;116&lt;/span&gt;&lt;span class="nl"&gt;f:&lt;/span&gt;   &lt;span class="err"&gt;89&lt;/span&gt; &lt;span class="nf"&gt;c6&lt;/span&gt;                   &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;esi&lt;/span&gt;
    &lt;span class="err"&gt;1171&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;48&lt;/span&gt; &lt;span class="err"&gt;8&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt; &lt;span class="mi"&gt;05&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;    &lt;span class="nv"&gt;lea&lt;/span&gt;    &lt;span class="mh"&gt;0xe8c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nv"&gt;rip&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rax&lt;/span&gt;        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;2004&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_IO_stdin_used&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="err"&gt;1178&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;48&lt;/span&gt; &lt;span class="err"&gt;89&lt;/span&gt; &lt;span class="nf"&gt;c7&lt;/span&gt;                &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rdi&lt;/span&gt;
    &lt;span class="err"&gt;117&lt;/span&gt;&lt;span class="nl"&gt;b:&lt;/span&gt;   &lt;span class="nf"&gt;b8&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;          &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;
    &lt;span class="err"&gt;1180&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;e8&lt;/span&gt; &lt;span class="nv"&gt;cb&lt;/span&gt; &lt;span class="nv"&gt;fe&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt; &lt;span class="nv"&gt;ff&lt;/span&gt;          &lt;span class="nv"&gt;call&lt;/span&gt;   &lt;span class="mi"&gt;1050&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;printf@plt&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="err"&gt;1185&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;83&lt;/span&gt; &lt;span class="err"&gt;45&lt;/span&gt; &lt;span class="nf"&gt;f8&lt;/span&gt; &lt;span class="mi"&gt;01&lt;/span&gt;             &lt;span class="nv"&gt;addl&lt;/span&gt;   &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;1189&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;8&lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="nv"&gt;f8&lt;/span&gt;                &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;
    &lt;span class="err"&gt;118&lt;/span&gt;&lt;span class="nl"&gt;c:&lt;/span&gt;   &lt;span class="err"&gt;3&lt;/span&gt;&lt;span class="nf"&gt;b&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="nv"&gt;fc&lt;/span&gt;                &lt;span class="nv"&gt;cmp&lt;/span&gt;    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;0x4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;
    &lt;span class="err"&gt;118&lt;/span&gt;&lt;span class="nl"&gt;f:&lt;/span&gt;   &lt;span class="err"&gt;7&lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt;                   &lt;span class="nv"&gt;jl&lt;/span&gt;     &lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x23&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="err"&gt;1191&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;b8&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;          &lt;span class="nv"&gt;mov&lt;/span&gt;    &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;
    &lt;span class="err"&gt;1196&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;c9&lt;/span&gt;                      &lt;span class="nv"&gt;leave&lt;/span&gt;
    &lt;span class="err"&gt;1197&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;c3&lt;/span&gt;                      &lt;span class="nv"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which machine instruction/s corresponds to &lt;em&gt;num = 10&lt;/em&gt;? You need to know reading the assembly instructions in here. The answer is the &lt;strong&gt;movl   $0xa,-0x4(%rbp)&lt;/strong&gt; assembly instruction. Because the stack pointer of the program was enlarged by 4 bytes (&lt;em&gt;int&lt;/em&gt; holds 4 bytes of memory) to lower address and put the immediate 0xA value. So that I need to change the 0xA value to 0x5. &lt;/p&gt;

&lt;p&gt;After the found required assembly instruction, I need to determine the memory address of it. If you look at center column, the machine instruction is &lt;strong&gt;c7 45 fc 0a 00 00 00&lt;/strong&gt;. In here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;c7: the opcode of &lt;em&gt;movl&lt;/em&gt; register&lt;/li&gt;
&lt;li&gt;45 fc: the displacement of -0x4(%rbp)&lt;/li&gt;
&lt;li&gt;0a 00 00 00: the immediate value, 0xA (little-endian)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;c7 byte resides at 0x115c address so that 0a byte at 0x115f.&lt;/p&gt;

&lt;p&gt;To change that byte, I'm gonna use &lt;em&gt;hexedit&lt;/em&gt; program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hexedit ./main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xykdj3162c4xy1fq0pv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xykdj3162c4xy1fq0pv.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, you move to 0x115F address and change the 0x0A value to 0x05. Save the changes and then run the program again. You will see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#0
#1
#2
#3
#4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You injected the new code in the ELF executable 🥳. &lt;/p&gt;

&lt;p&gt;This technique is simple and powerful. But there are some limitations. The most important one is that you should not shift the byte addresses, just replace it. If you wanna change the entire ELF executable addresses, you need the other techniques. That's the next article's topic.&lt;/p&gt;

</description>
      <category>c</category>
      <category>lowcode</category>
      <category>computerscience</category>
      <category>linux</category>
    </item>
    <item>
      <title>ELF Executable Analysis in Detail</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Tue, 24 Feb 2026 20:03:28 +0000</pubDate>
      <link>https://dev.to/cangulmez/elf-executable-analysis-in-detail-3p5i</link>
      <guid>https://dev.to/cangulmez/elf-executable-analysis-in-detail-3p5i</guid>
      <description>&lt;p&gt;In everyday, we run some kind of programs to handle our works. There are many type of programs, GUIs, CLIs, TUIs or so on. But at low level, there are two kind of program formats: PE (Portable Executable) for Windows and ELF (Executable and Linkable Format) for Linux. &lt;/p&gt;

&lt;p&gt;In this tutorial, I will explain the ELF executables in detail.&lt;/p&gt;

&lt;p&gt;Firstly, let's start with the overall layout:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpujvtc64w38ocjvh6zc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpujvtc64w38ocjvh6zc.png" alt=" " width="387" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you see, an ELF executable consists of four layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Executable Header&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Program Headers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Section Headers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Executable Header
&lt;/h3&gt;

&lt;p&gt;Every ELF file starts with an &lt;em&gt;executable header&lt;/em&gt;, which is just a structured series of bytes telling you that it's an ELF file, what kind of ELF file it is, and where in the file to find all the other contents. It's defined as follow in /usr/include/elf.h:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdurlu5pmfkinz7utvied.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdurlu5pmfkinz7utvied.png" alt=" " width="589" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_ident&lt;/em&gt;: The executable header starts with a 16-byte array. First 4-byte, magic value, identifying the file as an ELF binary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_type&lt;/em&gt;: The type of the executable. For example REL means relocatable object file, EXEC means executable binary and DYN means dynamic libraries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_machine&lt;/em&gt;: The architecture that the executable is intended to run on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_version&lt;/em&gt;: The version of the ELF specification (always 1, I really don't know why it exists 😂).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_entry&lt;/em&gt;: The virtual address at which execution should start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_phoff&lt;/em&gt;, &lt;em&gt;e_shoff&lt;/em&gt;: The file offsets to the beginning of the program header table and the section header table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_flags&lt;/em&gt;: The flags specific to the architecture for which the binary is compiled (typically 0 for x86_64).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;e_ehsize&lt;/em&gt;: The size of the executable header, in bytes (for 64-bit systems, it's always 64).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see the executable header with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ readelf -h ./prog
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1400
  Start of program headers:          64 (bytes into file)
  Start of section headers:          135496 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 28
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Section Headers
&lt;/h3&gt;

&lt;p&gt;The code and data in an ELF binary are logically divided into continuous nonoverlapping chunks called &lt;strong&gt;section&lt;/strong&gt;s. Sections don't have any predetermined structure; instead, the structure of each section varies depending on the contents. So every section is described in &lt;em&gt;section header table&lt;/em&gt;. It's defined as follow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrorlbmbp2grio4ulyfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrorlbmbp2grio4ulyfa.png" alt=" " width="582" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_name&lt;/em&gt;: The index of the sections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_type&lt;/em&gt;: Every section has a type, indicated by an integer field. Common types: PROBITS for machine instructions, SYMTAB for static symbol table, DYNSYM for dynamic symbol table, STRTAB for string tables, REL(A) for relocation entries used by the linker, DYNAMIC for information needed for dynamic linking or so on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_flags&lt;/em&gt;: The section flags. Common flags: W means the section is writable, A means the content of the section are to be loaded into memory when executing the executable, X means the section is executable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_addr, sh_offset, sh_size&lt;/em&gt;: The virtual address, file offset (in bytes from the start&lt;br&gt;
of the file), and size (in bytes) of the sections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_link&lt;/em&gt;: Sometimes, there are relationships between sections. This field keeps the index count of the related sections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_info&lt;/em&gt;: Additional information about sections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_addralign&lt;/em&gt;: Some sections may need to be aligned in memory in a particular way for efficiency of memory accesses. The values 0 and 1 are reserved to indicate no special alignment needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;sh_entsize&lt;/em&gt;: Some sections contain a table of well-defined data structures. For such sections, this field indicates the size in bytes of each entry in the table. When the field is unused, it is set to zero.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see the section headers with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ readelf --sections --wide ./prog
There are 29 section headers, starting at offset 0x21148:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000000318 000318 00001c 00   A  0   0  1
  [ 2] .note.gnu.property NOTE            0000000000000338 000338 000030 00   A  0   0  8
  [ 3] .note.gnu.build-id NOTE            0000000000000368 000368 000024 00   A  0   0  4
  [ 4] .note.ABI-tag     NOTE            000000000000038c 00038c 000020 00   A  0   0  4
  [ 5] .gnu.hash         GNU_HASH        00000000000003b0 0003b0 000028 00   A  6   0  8
  [ 6] .dynsym           DYNSYM          00000000000003d8 0003d8 000378 18   A  7   1  8
  [ 7] .dynstr           STRTAB          0000000000000750 000750 00016d 00   A  0   0  1
  [ 8] .gnu.version      VERSYM          00000000000008be 0008be 00004a 02   A  6   0  2
  [ 9] .gnu.version_r    VERNEED         0000000000000908 000908 000080 00   A  7   2  8
  [10] .rela.dyn         RELA            0000000000000988 000988 0000d8 18   A  6   0  8
  [11] .rela.plt         RELA            0000000000000a60 000a60 0002d0 18  AI  6  24  8
  [12] .init             PROGBITS        0000000000001000 001000 00001b 00  AX  0   0  4
  [13] .plt              PROGBITS        0000000000001020 001020 0001f0 10  AX  0   0 16
  [14] .plt.got          PROGBITS        0000000000001210 001210 000010 10  AX  0   0 16
  [15] .plt.sec          PROGBITS        0000000000001220 001220 0001e0 10  AX  0   0 16
  [16] .text             PROGBITS        0000000000001400 001400 018c54 00  AX  0   0 16
  [17] .fini             PROGBITS        000000000001a054 01a054 00000d 00  AX  0   0  4
  [18] .rodata           PROGBITS        000000000001b000 01b000 002ee8 00   A  0   0 16
  [19] .eh_frame_hdr     PROGBITS        000000000001dee8 01dee8 0005fc 00   A  0   0  4
  [20] .eh_frame         PROGBITS        000000000001e4e8 01e4e8 001914 00   A  0   0  8
  [21] .init_array       INIT_ARRAY      0000000000020cc0 020cc0 000008 08  WA  0   0  8
  [22] .fini_array       FINI_ARRAY      0000000000020cc8 020cc8 000008 08  WA  0   0  8
  [23] .dynamic          DYNAMIC         0000000000020cd0 020cd0 000200 10  WA  7   0  8
  [24] .got              PROGBITS        0000000000020ed0 020ed0 000130 08  WA  0   0  8
  [25] .data             PROGBITS        0000000000021000 021000 000010 00  WA  0   0  8
  [26] .bss              NOBITS          0000000000021020 021010 000010 00  WA  0   0 32
  [27] .comment          PROGBITS        0000000000000000 021010 00002b 01  MS  0   0  1
  [28] .shstrtab         STRTAB          0000000000000000 02103b 00010a 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sections
&lt;/h3&gt;

&lt;p&gt;In previous chapter, you see that the ELF executable has a set of sections at which each section has a special meaning. For now, let me explain these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;.init and .fini&lt;/em&gt;: The &lt;em&gt;.init&lt;/em&gt; section contains machine code that performs initialization before the &lt;em&gt;main()&lt;/em&gt; function and &lt;em&gt;.fini&lt;/em&gt; runs after it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;.text&lt;/em&gt;: This section is where the main code of the executable resides that we've wrote. It's the main concern for binary analysis or reverse engineering efforts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;.bss, .data, .rodata&lt;/em&gt;: There sections are where the program variables live. According to the declaration style, the variable goes into one of the three sections. For example, &lt;em&gt;initialized&lt;/em&gt; global variables live in &lt;em&gt;.data&lt;/em&gt;, &lt;em&gt;uninitialized&lt;/em&gt; global variables live in &lt;em&gt;.bss&lt;/em&gt; and &lt;em&gt;constant&lt;/em&gt; variables live in &lt;em&gt;.rodata&lt;/em&gt;. Don't forget that the local variables go in the stack, so &lt;em&gt;.text&lt;/em&gt;, not into one of these sections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;.rel.* and .rela.*&lt;/em&gt;: These sections contain the information used by the linker for performing relocations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;.dynamic&lt;/em&gt;: It contains the "road map" for dynamic linker when loading and setting up the ELF executable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an example, you can inspect a specific section with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ objdump -j .text -d ./prog

./prog:     file format elf64-x86-64

Disassembly of section .text:

0000000000001400 &amp;lt;.text&amp;gt;:
    1400:       f3 0f 1e fa             endbr64
    1404:       31 ed                   xor    %ebp,%ebp
    1406:       49 89 d1                mov    %rdx,%r9
    1409:       5e                      pop    %rsi
    140a:       48 89 e2                mov    %rsp,%rdx
    140d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    1411:       50                      push   %rax
    1412:       54                      push   %rsp
    1413:       45 31 c0                xor    %r8d,%r8d
    1416:       31 c9                   xor    %ecx,%ecx
    1418:       48 8d 3d 48 15 00 00    lea    0x1548(%rip),%rdi        # 2967 &amp;lt;rand@plt+0x1577&amp;gt;
    141f:       ff 15 b3 fb 01 00       call   *0x1fbb3(%rip)        # 20fd8 &amp;lt;rand@plt+0x1fbe8&amp;gt;
    1425:       f4                      hlt
    1426:       66 2e 0f 1f 84 00 00    cs nopw 0x0(%rax,%rax,1)
    142d:       00 00 00 
    1430:       48 8d 3d d9 fb 01 00    lea    0x1fbd9(%rip),%rdi        # 21010 &amp;lt;rand@plt+0x1fc20&amp;gt;
    1437:       48 8d 05 d2 fb 01 00    lea    0x1fbd2(%rip),%rax        # 21010 &amp;lt;rand@plt+0x1fc20&amp;gt;
    143e:       48 39 f8                cmp    %rdi,%rax
    1441:       74 15                   je     1458 &amp;lt;rand@plt+0x68&amp;gt;
    1443:       48 8b 05 96 fb 01 00    mov    0x1fb96(%rip),%rax        # 20fe0 &amp;lt;rand@plt+0x1fbf0&amp;gt;
    144a:       48 85 c0                test   %rax,%rax
    144d:       74 09                   je     1458 &amp;lt;rand@plt+0x68&amp;gt;
    144f:       ff e0                   jmp    *%rax
    1451:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Program Headers
&lt;/h3&gt;

&lt;p&gt;The program header table provides a &lt;em&gt;segment view&lt;/em&gt; of the binary, as opposed to the &lt;em&gt;section view&lt;/em&gt; provided by the section header table. It's defined as follow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8ju6auuns4gk64up863.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8ju6auuns4gk64up863.png" alt=" " width="453" height="118"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4azsq1vx1s8vi1bos53x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4azsq1vx1s8vi1bos53x.png" alt=" " width="453" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;p_type&lt;/em&gt;: The type of segments. Common types: LOAD means the segment are intended to be loaded into memory, INTERP means the segment contains &lt;em&gt;.interp&lt;/em&gt; section providing name of the interpreter that is to be used to load the executable, DYNAMIC means the segment contains the &lt;em&gt;.dynamic&lt;/em&gt; section, which tells the interpreter how to parse and prepare the binary for execution, PHDR means the segment encompasses the program header table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;p_flags&lt;/em&gt;: The runtime access permissions for the segments. Common flags: X means executable, R means readable, W means writable or so on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;p_offset, p_vaddr, p_paddr, p_filesz, p_memsz&lt;/em&gt;: These equals to &lt;em&gt;sh_offset&lt;/em&gt;, &lt;em&gt;sh_addr&lt;/em&gt;, &lt;em&gt;sh_size&lt;/em&gt; fields in the section headers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;p_align&lt;/em&gt;: It's equal to &lt;em&gt;sh_addralign&lt;/em&gt; field.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see the program headers with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ readelf --segments --wide ./prog

Elf file type is DYN (Position-Independent Executable file)
Entry point 0x1400
There are 13 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x0002d8 0x0002d8 R   0x8
  INTERP         0x000318 0x0000000000000318 0x0000000000000318 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000d30 0x000d30 R   0x1000
  LOAD           0x001000 0x0000000000001000 0x0000000000001000 0x019061 0x019061 R E 0x1000
  LOAD           0x01b000 0x000000000001b000 0x000000000001b000 0x004dfc 0x004dfc R   0x1000
  LOAD           0x020cc0 0x0000000000020cc0 0x0000000000020cc0 0x000350 0x000370 RW  0x1000
  DYNAMIC        0x020cd0 0x0000000000020cd0 0x0000000000020cd0 0x000200 0x000200 RW  0x8
  NOTE           0x000338 0x0000000000000338 0x0000000000000338 0x000030 0x000030 R   0x8
  NOTE           0x000368 0x0000000000000368 0x0000000000000368 0x000044 0x000044 R   0x4
  GNU_PROPERTY   0x000338 0x0000000000000338 0x0000000000000338 0x000030 0x000030 R   0x8
  GNU_EH_FRAME   0x01dee8 0x000000000001dee8 0x000000000001dee8 0x0005fc 0x0005fc R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x020cc0 0x0000000000020cc0 0x0000000000020cc0 0x000340 0x000340 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 
   03     .init .plt .plt.got .plt.sec .text .fini 
   04     .rodata .eh_frame_hdr .eh_frame 
   05     .init_array .fini_array .dynamic .got .data .bss 
   06     .dynamic 
   07     .note.gnu.property 
   08     .note.gnu.build-id .note.ABI-tag 
   09     .note.gnu.property 
   10     .eh_frame_hdr 
   11     
   12     .init_array .fini_array .dynamic .got 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Until here, I gave you the overall, a bit detailed, presentation about the ELF executable. For next articles, I will dive into the binary analysis techniques in deeply for Linux.&lt;/p&gt;

&lt;p&gt;Resource:&lt;/p&gt;

&lt;p&gt;Andriesse D., Practical Binary Analysis, no starch press, San Francisco.&lt;/p&gt;

</description>
      <category>c</category>
      <category>gcc</category>
      <category>lowcode</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>How to build a firmware using Makefile?</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Sun, 21 Dec 2025 12:46:38 +0000</pubDate>
      <link>https://dev.to/cangulmez/how-to-build-a-firmware-using-makefile-3flm</link>
      <guid>https://dev.to/cangulmez/how-to-build-a-firmware-using-makefile-3flm</guid>
      <description>&lt;p&gt;In embedded programming, we trust IDEs like STM32CubeIDE, Keil or so on. These IDEs give us just some buttons and UIs to build, flash, and debug the source code that we've written for a MCU. But, I think that every engineer that works on this field have to know that how these steps are made by hand.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will show building a firmware written for STM32F446RE MCU with just using a single Makefile.&lt;/p&gt;

&lt;p&gt;Below is the project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ tree
.
├── bin/
├── drivers/
│   ├── CMSIS/
│   ├── STM32F446RETX_FLASH.ld
│   └── STM32F4xx_HAL_Driver/
├── lib/
├── Makefile
└── src/
    ├── it.c
    ├── main.c
    ├── main.h
    └── peripheral.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Firstly, which libraries do we need to have?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HAL library&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CMSIS library&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Linker script&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Startup/system code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;arm-none-eabi-* tools&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've put the all required libraries/scripts into &lt;strong&gt;/drivers&lt;/strong&gt; directory. Please download these using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git clone &lt;span class="nt"&gt;--recurse-submodules&lt;/span&gt; https://github.com/STMicroelectronics/STM32CubeF4.git
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;gcc-arm-none-eabi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, HAL library is used to program the peripherals and CMSIS for ARM-Cortex itself. These are the most important libraries that we have to get. &lt;/p&gt;

&lt;p&gt;Apart from that, we also need some special files. First is the &lt;strong&gt;linker script&lt;/strong&gt;. It includes the memory layout of microcontroller. Sometimes, it comes from above command. But if you cannot find it there, please install it externally. Another file is the &lt;strong&gt;startup code&lt;/strong&gt;. It's written in Assembly language. As its name suggests, it's the first code that runs in microcontroller. Basically, it includes the &lt;strong&gt;Reset_Handler&lt;/strong&gt; and a branch that jumps into &lt;strong&gt;main()&lt;/strong&gt; function in your source code. Also &lt;strong&gt;system code&lt;/strong&gt; includes the some generic and general definitions.&lt;/p&gt;

&lt;p&gt;After downloaded and explained the required ones, Let's write the &lt;strong&gt;Makefile&lt;/strong&gt; step by step:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Toolchain definitions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CC&lt;/span&gt;              &lt;span class="o"&gt;:=&lt;/span&gt; arm-none-eabi-gcc
&lt;span class="nv"&gt;OBJCOPY&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; arm-none-eabi-objcopy
&lt;span class="nv"&gt;SIZE&lt;/span&gt;            &lt;span class="o"&gt;:=&lt;/span&gt; arm-none-eabi-size
&lt;span class="nv"&gt;RM&lt;/span&gt;              &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;span class="nv"&gt;FILE&lt;/span&gt;            &lt;span class="o"&gt;:=&lt;/span&gt; file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. MCU-specific definitions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;DEVICE_FAMILY&lt;/span&gt;        &lt;span class="o"&gt;:=&lt;/span&gt; STM32F4xx
&lt;span class="nv"&gt;DEVICE_MODEL&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; STM32F446xx
&lt;span class="nv"&gt;DEVICE_VARIANT&lt;/span&gt;       &lt;span class="o"&gt;:=&lt;/span&gt; STM32F446RETx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Compiler and linker flags&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CORTEX_FLAGS&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nt"&gt;-mthumb&lt;/span&gt; &lt;span class="nt"&gt;-mcpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cortex-m4 &lt;span class="nt"&gt;-mfpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fpv4-sp-d16 &lt;span class="nt"&gt;-mfloat-abi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hard
&lt;span class="nv"&gt;COMMON_FLAGS&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nt"&gt;-g3&lt;/span&gt; &lt;span class="nt"&gt;-Os&lt;/span&gt; &lt;span class="nt"&gt;-ffunction-sections&lt;/span&gt; &lt;span class="nt"&gt;-fdata-sections&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt;
&lt;span class="nv"&gt;AS_FLAGS&lt;/span&gt;             &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt; assembler-with-cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, we've defined some flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;-mthumb&lt;/strong&gt; means that the firmware uses thumb (16-bit) instruction set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;-mcpu=cortex-m4&lt;/strong&gt; means the ARM-Cortex series itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;-mfpu=fpv4-sp-d16&lt;/strong&gt; and &lt;strong&gt;-mfloat-abi=hard&lt;/strong&gt; means that floating-point operations can be done in the firmware.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Include paths&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;MAIN_INC&lt;/span&gt;        &lt;span class="o"&gt;:=&lt;/span&gt; ./src
&lt;span class="nv"&gt;CMSIS_INC&lt;/span&gt;       &lt;span class="o"&gt;:=&lt;/span&gt; ./drivers/CMSIS/Include
&lt;span class="nv"&gt;CMSIS_DEV_INC&lt;/span&gt;   &lt;span class="o"&gt;:=&lt;/span&gt; ./drivers/CMSIS/Device/ST/STM32F4xx/Include
&lt;span class="nv"&gt;HAL_INC&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; ./drivers/STM32F4xx_HAL_Driver/Inc
&lt;span class="nv"&gt;CMSIS_DSP_INC&lt;/span&gt;   &lt;span class="o"&gt;:=&lt;/span&gt; ./drivers/CMSIS/DSP/Include
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, we specified the header files that are used in the source code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Source and special files&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;MAIN_SRC&lt;/span&gt;        &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard ./src/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;HAL_SRC&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard ./drivers/STM32F4xx_HAL_Driver/Src/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;SYSTEM_SRC&lt;/span&gt;      &lt;span class="o"&gt;:=&lt;/span&gt; ./drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c
&lt;span class="nv"&gt;STARTUP_CODE&lt;/span&gt;    &lt;span class="o"&gt;:=&lt;/span&gt; ./drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f446xx.S
&lt;span class="nv"&gt;LINKER_SCRIPT&lt;/span&gt;   &lt;span class="o"&gt;:=&lt;/span&gt; ./drivers/STM32F446RETX_FLASH.ld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Sorthands and build definitions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;DEFINES&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;DEVICE_FAMILY&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;DEVICE_MODEL&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;DEVICE_VARIANT&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                        &lt;span class="nt"&gt;-DUSE_HAL_DRIVER&lt;/span&gt;

&lt;span class="nv"&gt;SOURCES&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;MAIN_SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;HAL_SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SYSTEM_SRC&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;OBJECTS&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;notdir &lt;span class="p"&gt;$(&lt;/span&gt;patsubst %.c,%.o,&lt;span class="p"&gt;$(&lt;/span&gt;SOURCES&lt;span class="p"&gt;)))&lt;/span&gt; startup_stm32f446xx.o
&lt;span class="nv"&gt;INCLUDES&lt;/span&gt;            &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;MAIN_INC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;CMSIS_DEV_INC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;CMSIS_INC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;HAL_INC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                        &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;CMSIS_DSP_INC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;CFLAGS&lt;/span&gt;          &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CORTEX_FLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;COMMON_FLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;DEFINES&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;INCLUDES&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;AFLAGS&lt;/span&gt;          &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CORTEX_FLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;AS_FLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;DEFINES&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;INCLUDES&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;LDFLAGS&lt;/span&gt;         &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CORTEX_FLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LINKER_SCRIPT&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                        &lt;span class="nt"&gt;-Wl&lt;/span&gt;,--gc-sections,--relax &lt;span class="nt"&gt;--specs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nano.specs &lt;span class="nt"&gt;--specs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nosys.specs &lt;span class="se"&gt;\&lt;/span&gt;
                    &lt;span class="nt"&gt;-Wl&lt;/span&gt;,--start-group &lt;span class="nt"&gt;-lc&lt;/span&gt; &lt;span class="nt"&gt;-lm&lt;/span&gt; &lt;span class="nt"&gt;-lnosys&lt;/span&gt; &lt;span class="nt"&gt;-Wl&lt;/span&gt;,--end-group
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, I mostly did the string operations and manipulations. But some points are interesting and need some explanations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Firstly, I've grouped the sources and libraries and converted the source file suffixes into object file formats.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, I've created three total flags that will be used for compiling, assembling, and linking phases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In linker flags, I put the linker script. As you noticed, this step will be done after the compiling the source files. I also linked the some libraries. &lt;strong&gt;-lc&lt;/strong&gt; is the standard C library. In firmware, we use often string manipulation functions (&lt;strong&gt;strlen()&lt;/strong&gt;, &lt;strong&gt;strcat()&lt;/strong&gt;, &lt;strong&gt;strcpy()&lt;/strong&gt; or so on), &lt;strong&gt;snprint()&lt;/strong&gt;, &lt;strong&gt;memset()&lt;/strong&gt;, or similar ones. &lt;strong&gt;-lm&lt;/strong&gt; is the math library as you know. &lt;strong&gt;-lnosys&lt;/strong&gt; means that I'm just implementing the bare-metal firmware, there is no such as kernel or fully OS.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Output files&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;FIRMWARE_ELF&lt;/span&gt;    &lt;span class="o"&gt;:=&lt;/span&gt; firmware.elf
&lt;span class="nv"&gt;FIRMWARE_BIN&lt;/span&gt;    &lt;span class="o"&gt;:=&lt;/span&gt; firmware.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generally, we use the ELF file when flashing and debugging. ELF executable includes the both machine code, metadata, debug information, symbol table or similar stuffs. In contrast, BIN executable just includes the machine code. If you look at the size of both, you will use the ELF executable is much bigger! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. The recipe&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"----- Building the source files -----"&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;
    &lt;span class="p"&gt;@$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;AFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;STARTUP_CODE&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;@$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SOURCES&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"\n------------------------------------"&lt;/span&gt;
    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"----- Linking the object files -----"&lt;/span&gt;
    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"------------------------------------"&lt;/span&gt;
    &lt;span class="err"&gt;@$(CC)&lt;/span&gt; &lt;span class="err"&gt;$(LDFLAGS)&lt;/span&gt; &lt;span class="err"&gt;$(OBJECTS)&lt;/span&gt; &lt;span class="err"&gt;-o&lt;/span&gt; &lt;span class="err"&gt;$(FIRMWARE_ELF)&lt;/span&gt;
    &lt;span class="err"&gt;@$(OBJCOPY)&lt;/span&gt; &lt;span class="err"&gt;-O&lt;/span&gt; &lt;span class="err"&gt;binary&lt;/span&gt; &lt;span class="err"&gt;$(FIRMWARE_ELF)&lt;/span&gt; &lt;span class="err"&gt;$(FIRMWARE_BIN)&lt;/span&gt;
    &lt;span class="err"&gt;@$(RM)&lt;/span&gt; &lt;span class="err"&gt;$(OBJECTS)&lt;/span&gt;

    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"\n-------------------------------------"&lt;/span&gt;
    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"----- The firmware memory usage -----"&lt;/span&gt;
    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;
    &lt;span class="err"&gt;@$(SIZE)&lt;/span&gt; &lt;span class="err"&gt;$(FIRMWARE_ELF)&lt;/span&gt;

    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"\n-------------------------------------"&lt;/span&gt;
    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"----- The firmware binary format ----"&lt;/span&gt;
    &lt;span class="err"&gt;@echo&lt;/span&gt; &lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;
    &lt;span class="err"&gt;@$(FILE)&lt;/span&gt; &lt;span class="err"&gt;$(FIRMWARE_ELF)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, run the Makefile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it 🥳🥳🥳. You've built the both &lt;strong&gt;firmware.elf&lt;/strong&gt; and &lt;strong&gt;firmware.bin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You are ready to flash the built firmware into microcontroller with this or similar command (over ST-Link connection):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;openocd &lt;span class="nt"&gt;-f&lt;/span&gt; interface/stlink.cfg &lt;span class="nt"&gt;-f&lt;/span&gt; target/stm32f4x.cfg &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"program firmware.elf verify reset exit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>c</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>What exactly is "program" and what does it include?</title>
      <dc:creator>Can Gulmez</dc:creator>
      <pubDate>Mon, 08 Dec 2025 14:05:17 +0000</pubDate>
      <link>https://dev.to/cangulmez/what-exactly-is-a-program-and-what-does-it-include-53j3</link>
      <guid>https://dev.to/cangulmez/what-exactly-is-a-program-and-what-does-it-include-53j3</guid>
      <description>&lt;p&gt;In this article, I wanna talk about &lt;strong&gt;program&lt;/strong&gt; and &lt;strong&gt;process&lt;/strong&gt; terms that are fundamental elements in computer-science. This two terms generally are used exchangeably. But in technically, both are so different. Let's begin with explaining these terms and then deeply see the what it includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;program&lt;/strong&gt; is a file containing a range of information that describes how to construct a "process" at run time [1].&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;process&lt;/strong&gt; is an instance of an executing program [1].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the formal definations. If I try to express with my words:&lt;/p&gt;

&lt;p&gt;A program (or binary) is a file that includes the machine code + metadata + debug information (if the program compiled with -g flag) and process is a abstraction point that kernel creates and then allocates hardware resources like CPU, RAM, memory or similar ones.&lt;/p&gt;

&lt;p&gt;First thing that you should know is the program format. In recently, there are two type of program formats that the compilers generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ELF (Executable and Linkable Format)&lt;/li&gt;
&lt;li&gt;PE (Portable Executable)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Executable and Linkable Format
&lt;/h2&gt;

&lt;p&gt;ELF is the standard format for UNIX/Linux systems and PE for Windows. I'm currently on Ubuntu 24.10 (x86_64) so that I will explain and use ELF format. As you guest, I don't know really PE format. But there is a good reference handbook that you can look at. It's "Practical Binary Analysis" written by Dennis Andriesse.&lt;/p&gt;

&lt;p&gt;After explained the program formats, right now, let's look at the inside of the program:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2ozvdt4ayf1grr4fgmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2ozvdt4ayf1grr4fgmw.png" alt=" " width="395" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general, any program includes these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Executable header&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Program headers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Section headers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every ELF file starts with an &lt;strong&gt;executable header&lt;/strong&gt;, which is just a structured series of bytes telling you that it's and ELF file, what kind of ELF file it is, and where in the files to find all the other contents [2].&lt;/p&gt;

&lt;p&gt;You can exactly see the content of this header with &lt;strong&gt;readelf&lt;/strong&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ readelf -h ./copy
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1160
  Start of program headers:          64 (bytes into file)
  Start of section headers:          17496 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         37
  Section header string table index: 36
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In there, first four digits (7f 45) of &lt;em&gt;Magic&lt;/em&gt; series define the program format. You will see the probably different series if you are on Windows. Other properties is the self-explaining.&lt;/p&gt;

&lt;p&gt;The code and data in an ELF program are logically divided into &lt;strong&gt;sections&lt;/strong&gt;. Each section includes a specific part of your source code. And the sections in the binary are contained in the &lt;strong&gt;section header table&lt;/strong&gt;. Some sections are used to execute the machine instructions and some for other information (like symbol table used by debugger). Let's look at the section headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ readelf --sections --wide ./copy
There are 37 section headers, starting at offset 0x4458:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000000318 000318 00001c 00   A  0   0  1
  [ 2] .note.gnu.property NOTE            0000000000000338 000338 000030 00   A  0   0  8
  [ 3] .note.gnu.build-id NOTE            0000000000000368 000368 000024 00   A  0   0  4
  [ 4] .note.ABI-tag     NOTE            000000000000038c 00038c 000020 00   A  0   0  4
  [ 5] .gnu.hash         GNU_HASH        00000000000003b0 0003b0 000028 00   A  6   0  8
  [ 6] .dynsym           DYNSYM          00000000000003d8 0003d8 000180 18   A  7   1  8
  [ 7] .dynstr           STRTAB          0000000000000558 000558 0000d3 00   A  0   0  1
  [ 8] .gnu.version      VERSYM          000000000000062c 00062c 000020 02   A  6   0  2
  [ 9] .gnu.version_r    VERNEED         0000000000000650 000650 000030 00   A  7   1  8
  [10] .rela.dyn         RELA            0000000000000680 000680 0000d8 18   A  6   0  8
  [11] .rela.plt         RELA            0000000000000758 000758 0000d8 18  AI  6  24  8
  [12] .init             PROGBITS        0000000000001000 001000 00001b 00  AX  0   0  4
  [13] .plt              PROGBITS        0000000000001020 001020 0000a0 10  AX  0   0 16
  [14] .plt.got          PROGBITS        00000000000010c0 0010c0 000010 10  AX  0   0 16
  [15] .plt.sec          PROGBITS        00000000000010d0 0010d0 000090 10  AX  0   0 16
  [16] .text             PROGBITS        0000000000001160 001160 00043a 00  AX  0   0 16
  [17] .fini             PROGBITS        000000000000159c 00159c 00000d 00  AX  0   0  4
  [18] .rodata           PROGBITS        0000000000002000 002000 000040 00   A  0   0  4
  [19] .eh_frame_hdr     PROGBITS        0000000000002040 002040 000034 00   A  0   0  4
  [20] .eh_frame         PROGBITS        0000000000002078 002078 0000a8 00   A  0   0  8
  [21] .init_array       INIT_ARRAY      0000000000003d78 002d78 000008 08  WA  0   0  8
  [22] .fini_array       FINI_ARRAY      0000000000003d80 002d80 000008 08  WA  0   0  8
  [23] .dynamic          DYNAMIC         0000000000003d88 002d88 0001f0 10  WA  7   0  8
  [24] .got              PROGBITS        0000000000003f78 002f78 000088 08  WA  0   0  8
  [25] .data             PROGBITS        0000000000004000 003000 000010 00  WA  0   0  8
  [26] .bss              NOBITS          0000000000004020 003010 000010 00  WA  0   0 32
  [27] .comment          PROGBITS        0000000000000000 003010 00002b 01  MS  0   0  1
  [28] .debug_aranges    PROGBITS        0000000000000000 00303b 000030 00      0   0  1
  [29] .debug_info       PROGBITS        0000000000000000 00306b 000472 00      0   0  1
  [30] .debug_abbrev     PROGBITS        0000000000000000 0034dd 000184 00      0   0  1
  [31] .debug_line       PROGBITS        0000000000000000 003661 00017e 00      0   0  1
  [32] .debug_str        PROGBITS        0000000000000000 0037df 00031a 01  MS  0   0  1
  [33] .debug_line_str   PROGBITS        0000000000000000 003af9 00012f 01  MS  0   0  1
  [34] .symtab           SYMTAB          0000000000000000 003c28 000438 18     35  18  8
  [35] .strtab           STRTAB          0000000000000000 004060 00028c 00      0   0  1
  [36] .shstrtab         STRTAB          0000000000000000 0042ec 00016a 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main topic of this tutorial is the sections. So I wanna explain in deeply each one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.init&lt;/strong&gt; and &lt;strong&gt;.fini&lt;/strong&gt;: The machine code in these sections are used before/after the &lt;em&gt;main()&lt;/em&gt; function in program. Don't forget that we're not writing this sections. Compiler itself creates these to handle low-level (or hardware-specific) works. I don't know actually what both of them do!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.text&lt;/strong&gt;: It is the main area where we focus on binary analysis and reverse-engineering stuffs and includes the your code in machine instruction representation. If you look at there, you see that it has voluminous area and thousands of lines of machine code even if it is small program.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.bss&lt;/strong&gt;, &lt;strong&gt;.data&lt;/strong&gt; and &lt;strong&gt;.rodata&lt;/strong&gt;: These sections are writable and used to hold various variable in source code. &lt;strong&gt;.bss&lt;/strong&gt; includes the &lt;em&gt;static&lt;/em&gt; and &lt;em&gt;global uninitialized&lt;/em&gt; and &lt;strong&gt;.data&lt;/strong&gt; includes the &lt;em&gt;static&lt;/em&gt; and &lt;em&gt;global initialized&lt;/em&gt; variables. Also &lt;strong&gt;.rodata&lt;/strong&gt; consists of variables defined with &lt;em&gt;const&lt;/em&gt; keyword in code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.dynamic&lt;/strong&gt;: This is the "road map" for the kernel and dynamic linker when loading and setting up an ELF binary for executions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.init_array&lt;/strong&gt; and &lt;strong&gt;.fini_array&lt;/strong&gt;: These contains an array of pointers to functions to use as constructors/destructors. You maybe know that how to create constructor and destructor using compiler specific-tool, line one &lt;em&gt;__attribute__((constructor)) void run_before_main(void);&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.shstrtab&lt;/strong&gt;, &lt;strong&gt;.symtab&lt;/strong&gt;, &lt;strong&gt;.strtab&lt;/strong&gt;, &lt;strong&gt;.dynsym&lt;/strong&gt; and &lt;strong&gt;.dynstr&lt;/strong&gt;: The &lt;strong&gt;.shstrtab&lt;/strong&gt; section is simply an array of NULL-terminated strings that contain the names of all the sections in binary. The &lt;strong&gt;.symtab&lt;/strong&gt; contains a symbol table and &lt;strong&gt;.strtab&lt;/strong&gt; contains the symbolic names. The &lt;strong&gt;.dynsym&lt;/strong&gt; and &lt;strong&gt;.dynstr&lt;/strong&gt; are analogous to &lt;strong&gt;.symtab&lt;/strong&gt; and &lt;strong&gt;.strtab&lt;/strong&gt;, except that they contain symbols and strings needed for dynamic linking rather than static linking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.debug_&lt;/strong&gt;: These sections are used primarily by debugger (GDB) so that it has not include and machine code but just metadata about program that debugger can use later. If you don't compile the program with &lt;em&gt;-g&lt;/em&gt; option, these sections will not there.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is a part of &lt;strong&gt;.text&lt;/strong&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ objdump -j .text -d ./copy

./copy:     file format elf64-x86-64

(...)

Disassembly of section .text:

0000000000001249 &amp;lt;main&amp;gt;:
    1249:f3 0f 1e fa          endbr64
    124d:55                   push   %rbp
    124e:48 89 e5             mov    %rsp,%rbp
    1251:48 81 ec 40 04 00 00 sub    $0x440,%rsp
    1258:89 bd cc fb ff ff    mov    %edi,-0x434(%rbp)
    125e:48 89 b5 c0 fb ff ff mov    %rsi,-0x440(%rbp)
    1265:64 48 8b 04 25 28 00 mov    %fs:0x28,%rax
    126c:00 00 
    126e:48 89 45 f8          mov    %rax,-0x8(%rbp)
    1272:31 c0                xor    %eax,%eax
    1274:83 bd cc fb ff ff 03 cmpl   $0x3,-0x434(%rbp)
    127b:75 24                jne    12a1 &amp;lt;main+0x58&amp;gt;
    127d:48 8b 85 c0 fb ff ff mov    -0x440(%rbp),%rax
    1284:48 83 c0 08          add    $0x8,%rax
    1288:48 8b 00             mov    (%rax),%rax
    128b:48 8d 15 72 0d 00 00 lea    0xd72(%rip),%rdx        # 2004 &amp;lt;_IO_stdin_used+0x4&amp;gt;

(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here, we see the three columns that show the machine instructions of your program. At left side, you see the addresses of machine instructions. When running the program, stack pointer tracks these addresses. At center, you see the actual machine instructions corresponding to your code. Program counter register tracks this machine instructions. At right side, you see the assembly-level representations. When dealing with reverse-engineering, we inspect these to understand what program does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual Memory Layout
&lt;/h2&gt;

&lt;p&gt;After discussed the ELF program format, right now, I will explain the virtual memory layout of a process (running program instance). When you run the program, kernel creates a memory layout as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftw61ve9j3jviy2l7jhcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftw61ve9j3jviy2l7jhcn.png" alt=" " width="552" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've explained the &lt;strong&gt;.text, .data, .bss,&lt;/strong&gt; and &lt;strong&gt;.rodata&lt;/strong&gt; sections previously. Apart from these, you see the &lt;strong&gt;stack&lt;/strong&gt; and &lt;strong&gt;heap&lt;/strong&gt; areas.&lt;/p&gt;

&lt;p&gt;Both are the memory areas that kernel uses to execute the machine instructions. Stack area has LIFO (Last-In First-Out) model. When executing the program, kernel &lt;em&gt;pushes/pops&lt;/em&gt; the instructions in here. So it grows up to lower address space. Heap area is completely different! It has FIFO (First-In First-Out) model. Kernel uses this memory space for dynamic allocation with &lt;strong&gt;malloc()/free()&lt;/strong&gt; function family. And it grows up to upper address space. The heap address border is claimed by &lt;strong&gt;brk()&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;Until here, I wanna give you a general overview about programs and processes. If you want to dive in more, you can check and look at the below references.&lt;/p&gt;

&lt;p&gt;[1]. Kerrisk M., The Linux Programming Interface, no starch press, San Francisco, page 113.&lt;br&gt;
[2]. Andriesse D., Practical Binary Analysis, no starch press, San Francisco, page 33.&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>lowcode</category>
      <category>linux</category>
      <category>c</category>
    </item>
  </channel>
</rss>
