# Advances in Lightweight Cross-Architecture Procedural Debugging

Jonathan Brossard

► To cite this version:

Jonathan Brossard. Advances in Lightweight Cross-Architecture Procedural Debugging. SRC-DAV IEEE/IFIP Workshop on Secure and Resilient Communication for Drones and Autonomous Vehicle Networks, IEEE/IFIP, Jun 2025, Paris, France. hal-05120728

HAL Id: hal-05120728

https://hal.science/hal-05120728v1

Submitted on 19 Jun 2025

HAL is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_1.png" /></figure>
# Advances in Lightweight Cross-Architecture Procedural Debugging

Jonathan Brossard

CEDRIC/ISID

Conservatoire National des Arts et Métiers

Paris, France

jonathan.brossard@lecnam.net

*Abstract*—As embedded software is becoming more and more prevalent in mission-critical devices such as self-driving vehicles or medical equipment, Product Security Incident Response Teams (PSIRTs) face the need to debug software across multiple architectures, often different from their host desktop machines. Concomitantly, recent updates to the European legislative framework, in particular the NIS2 and Cyber Resilience Act mandate that critical vulnerabilities be reported on a daily basis. To help bridge the gap between those upcoming regulations and the reality of the industry, this article focuses on facilitating cross-architecture vulnerability validation via partial proofs of vulnerabilities by leveraging binary libification and lightweight procedural debugging.

*Index Terms*—Libification, Reverse Engineering, JIT binary translation, NIS2, CRA, lightweight debugging

## I. INTRODUCTION

Recent enhancements to the European legal framework governing Cloud service security require that Product Security Incident Response Teams (PSIRTs) operating in Europe report newly discovered vulnerabilities affecting their products and services to their respective national authorities within 24 hours. Specifically, Directive (EU) 2022/2555, known as NIS2 [1], mandates the assessment and reporting of security vulnerabilities within this timeframe.

In 2024, the NIST publicly disclosed over 40,000 vulnerabilities in the form of CVEs [3], a significant increase from approximately 29,000 in 2023. This surge leaves PSIRT teams facing the formidable challenge of assessing their services' exposure to more than 100 newly reported vulnerabilities each day. While tools like Software Bills of Materials (SBOMs) have emerged to ease this burden by automating the identification of potential vulnerabilities [21]—based solely on the versions of binaries present in containers—recent studies [22] have raised serious concerns about the reliability and reproducibility of SBOMs. As a result, PSIRT teams are often required to manually validate vulnerabilities flagged through SBOM monitoring tools [8] via extensive debugging efforts. Critically, a specific version of a software component may or may not be affected by a vulnerability, and its CVSS [4] score can vary significantly depending on compilation options [13] [14], details that are currently not captured by major SBOM standards [23] [5] [24] [28].

In this article, we devise new methodologies to quickly validate the existence of vulnerabilities in compiled binaries,

without access to their source code, since shipping compiled programs is common practice in the industry [16]. Focusing primarily on embedded devices, we will detail how binary libification and procedural debugging may be leveraged to produce partial proofs of vulnerabilities cross-architecture. Because market research over the past decade indicate an overwhelming use of GNU/Linux as a base OS in embedded devices, with a market penetration ranging from 40% to 60% depending on industry verticals [19] [17] [18], we shall focus primarily on debugging GNU/Linux, but will generalize our methodologies to other operating systems where applicable.

Our contribution to cross-architecture libification and procedural debugging is implemented into the Witchcraft Compiler Collection, a reverse engineering framework published under a permissive dual MIT/BSD license [32]. Our implementation of the Witchcraft tracer, an extension of the venerable *ltrace* [20] debugging tool is published under the GPL-2 open-source license.

## II. PREVIOUS WORK

In this section, we offer a brief summary of our recent work in the field of reverse engineering ELF binaries, with the aim to provide fundamental knowledge for the subsequent sections, where we will aim at generalizing those findings to achieve cross-architecture debugging.

### A. Overview of binary Libification

In “Introduction to Procedural Debugging through Binary Libification” [30], we introduced the concept of *Binary libification*, which refers to the process of converting a dynamically linked ELF [11] executable into a shared library. This allows vulnerable functions to be called directly, which circumvents the traditional reachability problem [26] over the callgraph of the binary, which is undecidable. This mechanism provides flexibility in inspecting and interacting with memory corruption vulnerabilities by simplifying how functions are invoked and observed.

### B. Overview of procedural debugging

This paper also introduces *Procedural debugging* [30], a technique used to analyze vulnerabilities by executing specific program functions without having to write entire exploits, focusing on intra-procedural triggers generation. This method
enables developers to focus on problematic code paths without needing full program execution, making it easier to understand and mitigate issues like memory corruption in complex C/C++ applications.

Transforming an ELF executable into a shared library requires no complex control-flow nor data-flow analysis, but consists in refactoring oELF headers and the .dynamic section, which is deterministic, fast and reliable.

### C. Overview of partial proofs of vulnerabilities

The paper “Toward Partial Proofs of Vulnerabilities” [15] introduces the Witchcraft Shell (WSH), a procedural debugger designed to help validate the presence of vulnerabilities in compiled ELF executables without requiring source code. WSH addresses this by *libifying executables*: transforming them into shared libraries, allowing direct, contextless function calls via a scripting interface (Lua). This bypasses the undecidable “reachability problem” [26] in vulnerability analysis, enabling researchers to trigger and test vulnerabilities in isolation. The tool is open-source and part of the Witchcraft Compiler Collection (WCC).

Our approach centers on *partial proofs of vulnerabilities*, where WSH scripts can demonstrate exploitability without proving full reachability in the target application. For example, the paper includes scripts to test OpenSSL for CVEs like CVE-2022-3602. While this method does not guarantee real-world exploitability (e.g., if vulnerable code is unreachable in practice), it streamlines initial validation. The paper highlights WSH’s utility for product security teams, offering a lightweight way to replicate bugs and test patches. By focusing on procedural debugging and binary scripting, WSH bridges gaps in vulnerability assessment for closed-source or binary-distributed software.

### D. Overview of automated functions annotations

Once ELF executables are libified into shared libraries, they may be loaded by the dynamic linker into the address space of an other application using the `dlopen()` function of the dynamic linker. However, their prototypes are initially unknown. In “Automatic Functions Annotations through Concrete Procedural Debugging and ELF Libification” [27], we devise a methodology to recover function prototypes through selective concrete procedural execution, by using carefully chosen arguments. This technique allows to recover function annotation similar to the Microsoft Source Code Annotation Language (SAL) [9], where arguments read from, or written to, are clearly identified.

### E. Overview of automatic binary unstripping

Calling functions from a libified shared library does not strictly require those functions to be exposed. However, knowing their location in memory is required, and identifying them by names instead of offsets greatly simplifies debugging. Because the latest versions of GCC [12] and Clang [2] alike hide non explicitely exported functions by using the `-fvisibility=hidden` flag by default [29], hence preventing their

<figure><img src="image_2.png" /><figcaption>Fig. 1. Libification in the compilation toolchain.</figcaption></figure>

respective symbols to be emitted in the dynamic symbol table, it becomes desirable to `unstrip` [25] those binaries, meaning to recover their function locations and names.

In “Unstripping Cloud Container ELF binaries” [10], we introduce automated methods to recover debugging information in stripped Linux binaries focusing primarily on the x86_64 architecture. We present `wunstrip`, a tool that leverages segment headers, dynamic symbols, and exception handling frame information (`.eh_frame` and `.eh_frameASC sections) to reconstruct function names and addresses, offering novel techniques to bypass traditional control-flow analysis limitations. When available, the tool also makes use of build IDs and external debug symbols from distributions’ debuginfod services [7], alongside object file fingerprinting, to enhance accuracy.

## III. TOWARDS CROSS-PLATFORM LIGHTWEIGHT PROCEDURAL DEBUGGING

### A. Relinking libified shared libraries

In our previous work, we emphasized how modifying the ELF headers and .dynamic sections of an ELF dynamically linked binary allow the transormation of an executable into a shared library, with the aim to load it via the `dlopen()` function from the API exposed by the dynamic linker. Because those transformations do not involve any control-flow nor data-flow analysis, they work across architectures and operating systems, as long as the target binary is an ELF. The mechanism of libification is represented in *figure 1*, where an ELF executable is turned into a shared library.

However, if loading binaries as pluggins at run-time via `dlopen()` is useful mostly for debugging, they do not reflect the standard use of shared libraries by C/C++ developpers, where shared libraries are linked at compile-time. Would it be therefor possible to link an executable at compile-time with a libified share library ?

To empirically test this idea, we chose the apache2 web-server as it is a rather complex binary because in particular of its high number of binary dependencies. For instance, under Ubuntu 24.04 x86_64, apache 2.4.58 is directly linked against 4 shared libraries (`libpcre2-8.so.0`, `libaprutil-1.so.0`, `libapr-1.so.0`, `libc.so.6`), and 7 recursively (including `libexpat.so.1`,
libcrypt.so.1, libuuid.so.1). Using the witchcraft linker, we may turn it into a libified shared library, named for instance apache2.so. In order to test the correct arguments passing to this function, we select a function from apache, ap_parse_log_level(). This function translates a human readable word representing a log level (from emerg, alert, crit, error, warn, notice, info, debug, trace1..trace8) passed as its firts argument as a string, and writes it into a pointer to an integer representing its log priority for apache, passed as a second argument.

The prototype of ap_parse_log_level() is:

```c
char *ap_parse_log_level
(const char *str, int *val);
```

To empirically verify if we can in fact use our newly generated (libified) apache2.so within a new application, we create the following C code named ap2loglevel.c, that aims at invoking ap_parse_log_level():

```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
```

```c
char *ap_parse_log_level(const char *str,
    int *val);
```

```c
int main (int argc, char **argv) {
    int i = 0;
    char *ret = 0;
    if (argc < 2) {
        printf("Usage: %s <loglevel>\n",
               argv[0]);
        exit(EXIT_SUCCESS);
    }
    ret = ap_parse_log_level(argv[1], &i);
    if (!ret) {
        printf("log level: %d\n", i);
    } else {
        printf("%s\n", ret);
    }
    return 0;
}
```

We compile ap2loglevel.c using the following command line:

```
cp /usr/sbin/apache2 ./apache2.so
wld -ls ./apache2.so
gcc ap2loglevel.c -o ap2loglevel -lc \
./apache2.so
```

This command line produces a dynamically linked ELF binary named ap2loglevel, dynamically linked against apache2.so as well as the system's glibc, who takes a human readable log level as an argument and outputs its corresponding integer value by invoking ap_parse_log_level() within the libified version of apache2.

To validate the proper working of this technique of libification and subsequent relinking, we first put it to the test on several versions of Ubuntu on x86_64, using docker containers, the goal being to ensure its is functional over versions of gcc spanning over the last decade. The results are reproduced in the Table I below:

<table><caption>TABLE I
LIBIFICATION+RELINKING RESULTS</caption><thead><tr><td>Version</td><td>Codename</td><td>Year</td><td>GCC version</td><td>Relinking</td><td>Run</td></tr></thead><tbody><tr><td>24.04</td><td>noble</td><td>2024</td><td>12.3.0</td><td>OK</td><td>OK</td></tr><tr><td>22.04</td><td>jammy</td><td>2022</td><td>11.2.0</td><td>OK</td><td>OK</td></tr><tr><td>20.04</td><td>focal</td><td>2020</td><td>9.3.0</td><td>OK</td><td>OK</td></tr><tr><td>18.04</td><td>bionic</td><td>2018</td><td>7.3.0</td><td>OK</td><td>OK</td></tr><tr><td>16.04</td><td>xenial</td><td>2016</td><td>5.3.1</td><td>OK</td><td>OK</td></tr><tr><td>14.04</td><td>trusty</td><td>2014</td><td>4.8.2</td><td>OK</td><td>OK</td></tr></tbody></table>

Since we managed to perform a libification plus relinking of apache2 over x86_64 in a reliable fashion, we test this technique cross-architecture, using, once again docker. Thanks to the transparent JIT binary translation of qemu [33], it is possible to run docker images of multiple architectures on a x86_64 host by registering the appropriate binfmt handler with the kernel [34]. This time, we used Debian Trixie as a gest operating system, the host running Ubuntu 24.04. The results are reproduced in the table Table II below:

<table><caption>TABLE II
CROSS-ARCHITECTURE LIBIFICATION+RELINKING RESULTS</caption><thead><tr><td>Architecture</td><td>Operating System</td><td>Libification</td><td>Relinking</td><td>Run</td></tr></thead><tbody><tr><td>aarch64</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>alpha</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>amd64</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>arm</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>hpna</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>i386</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>loong64</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>m68k</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>mips64le</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>ppc</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>ppc64</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>ppc164</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>riscv64</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>s390x</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>sh4</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr><tr><td>sparc64</td><td>Debian 13 (Trixie)</td><td>OK</td><td>OK</td><td>OK</td></tr></tbody></table>

Those simple experiments tend to validate the fact that libification and relinking is reliable cross-architecture, and supported by the standard gcc toolchain for over a decade.

## B. Procedural debugging on non x86_64 architectures

Since we managed to libify and relink executables in the previous section, it seems natural to move on to procedural debugging. In this section, we aim to generalize the technique of libifying arbitrary dynamically-linked ELF executables, and load them within the wsh procedural debugger for manual analysis.

Our previous work has shown that such a technique works on x86_64. We would like to generalize it to more embedded architectures. To this aim, we once again instrument docker
to run guest images of a different architecture than the host x86_64 architecture. We automate the build of the Witchcraft Linker `wld`, the Witchcraft Shell `wsh`, and attempt to libify all the binaries of the guest distribution (via the use of a chroot within the docker) before loading the libified binaries via `dlopen()` using a simple loader. The code of the loader is reproduced below for reference:

```c
#include <stdio.h>
#include <stdlib.h>
#include <.h>
#include <dlfn.h>
#include <errno.h>
#include <string.h>
```

```c
int main(int argc, char **argv) {
    void *handle;
```

```c
handle = dlopen(argv[1], RTLD_LAZY);
if (handle <= 0) {
    printf(" !! ERROR : %s\n", dlerror());
    exit(EXIT_FAILURE);
}
```

```c
printf("Loading of Library successful\n");
return 0;
}
```

Typically, this loader takes an ELF executable or shared library as an input, and attempts to load it within its own address space using `dlopen()`.

We use Debian 12 Bookworm as a guest Operating System. In order to libify binaries without affecing the proper working of the guest Operating System, we create a chroot with the base image of the guest Operating System within the guest docker image. Systemd fails to install properly within the chroot, and therefor binaries linked against systemd and its shared libraries will not be libifiable. We therefor distinguish the total number of binaries within the chroot from the ones that we may libify, the latter being the ones not linked against systemd's shared libraries. We also report whether `wld` and `wsh` build properly on those docker images.

The experimental results are reproduced in the table *Table III* below:

<table><caption>TABLE III
CROSS-ARCHITECTURE CHROOT LIBIFICATION RESULTS</caption><thead><tr><th>Architecture</th><th>Binaries</th><th>Libifiable</th><th>Libified</th><th>Failed</th><th>wld</th><th>wsh</th></tr></thead><tbody><tr><td>i386</td><td>399</td><td>351</td><td>351</td><td>0</td><td>Yes</td><td>Yes</td></tr><tr><td>amd64</td><td>399</td><td>366</td><td>366</td><td>0</td><td>Yes</td><td>Yes</td></tr><tr><td>ppcel64</td><td>413</td><td>369</td><td>369</td><td>0</td><td>Yes</td><td>Yes</td></tr><tr><td>s390x</td><td>429</td><td>392</td><td>392</td><td>0</td><td>Yes</td><td>No</td></tr><tr><td>mips64le</td><td>395</td><td>367</td><td>367</td><td>0</td><td>Yes</td><td>No</td></tr><tr><td>arm</td><td>396</td><td>348</td><td>348</td><td>0</td><td>Yes</td><td>Yes</td></tr><tr><td>aarch64</td><td>396</td><td>364</td><td>364</td><td>0</td><td>Yes</td><td>Yes</td></tr></tbody></table>

On the s390x and mips64le architectures, all the dependencies to the Witchcraft Shell `wsh` have not been ported yet and therefor its compilation using pre-built packages is

not straightforward. We otherwise see that the libification and run-time loading of libified ELF executables is functional for all of the executables of the base distribution of Debian 12 Bookworm, for all the architectures considered. Compilation of the Witchcraft Linker `wld` is functional on all architectures, even though libification can be performed on any host architecture, irrelevant of the target architecture (meaning all the libifications above may be performed directly on x86_64 for instance).

To facilitate the replication of those tests, the Docker images have been made public via: https://doi.org/10.5281/zenodo.15292934.

### C. Cross-architecture Procedural Debugging without Docker

The techniques introduced in the previous section, leveraging docker and qemu to perform a JIT binary translation, are arguably more lightweight than the traditional way to debug applications across architectures, relying on a GDB server running on a virtual machine. However, the need for docker itself doesn't seem like a very strong requirement. How about performing cross-architecture Procedural Debugging without the use of docker ? Not only this would allow an auditor to work on smaller architectures, where Debian hasn't been ported (for instance Xtensa or Blackfin), but this would ultimetaly simplify debugging by radically miminizing the complexity of cross-architecture to its bare minimum : without namespaces nor isolation engine of any sort.

In order to leverage the JIT on-the-fly binary translation of Qemu [33] in user-mode without the use of docker, we register the qemu binfmt entries with the host kernel. We then cross-compile the Witchcraft Shell `wsh` alone to the target architecture, and invoke it on the host transparently, in spite of its foreign architecture. Any binary loaded within `wsh` will also be translated on the fly thanks to qemu. The user-mode of qemu consists on a simple shared library loaded within the address space of the application to be executed. As such, the procedural debugger `wsh`, the target executable(s) or libraries, their dependencies and the qemu JIT binary translation engine share a single address space, as depicted in figure 2. We name this cross-architecture procedural debugging technique lightweight, since it minimalistically consists in a single userland process.

We have cross-compiled `wsh` for several architectures, and tested the cross-architecture loading of libified executables successfully, as seen in the table *Table VI* below:

<table><caption>TABLE IV
CROSS-ARCHITECTURE DEBUGGING RESULTS</caption><thead><tr><th>Architecture</th><th>Cross-architecture debugging</th></tr></thead><tbody><tr><td>i386</td><td>OK</td></tr><tr><td>arm</td><td>OK</td></tr><tr><td>aarch64</td><td>OK</td></tr></tbody></table>

Those early results seem to validate the use of cross-compiling `wsh` and using the JIT binary translation feature of qemu to perform lightweight procedural debugging, instead
<figure><img src="image_3.png" /><figcaption>Fig. 2. Address space of lightweight cross-architecture procedural debugger.</figcaption></figure>

of relying on remote hardware or virtual machines to debug
embedded devices.

D. Replaying execution traces, cross-architecture

Since *wsh* makes arbitrary ELF executables scritables by
performing a binary reflection of the C/C++ api of the executa-
bles loaded in memory, exposing them to the Lua interpreter
(hereby producing a mix of Lua and C/C++ we name C+,
for "more or less C"), it becomes tempting to leverage
this feature to replay debugging traces. In particular, where
venerable tracers like strace [31] or ltrace [20] produce traces
of execution at system-call level, and library-level respectively,
it is tempting to modify those tools to output valid C++ scripts,
rather than simple text, that may be replayed to simulate the
execution of arbitrary ELF executables, possibly on an other
machine or architecture.

We publish *wltrace*, a patch to ltrace allowing the generation of C++ scripts, that may be replayed via *wsh* after some manual editing: https://doi.org/10.5281/zenodo.15293075

IV. CONCLUSION AND FUTURE WORK

In this article, we’ve introduced a number of new method-
ologies to help in the dynamic analysis of ELF binaries across
architectures. Their evaluation produced conclusive results to
demonstrate their usefulness. The tools *wsh* and *wltrace* have
been released under a permissive dual MIT/BSD license and a
GPL-2 license respectively, with the hope to benefit the greater
security community.

REFERENCES

[1] European Union, "Directive (EU) 2022/2555 of the European Parliament and of the Council of 14 December 2022 on measures for a high common level of cybersecurity across the Union", Official Journal of the European Union, L 333, 27.12.2022, p. 80-152

[2] Clang Development Team, "Clang: a C language family frontend for LLVM", 2025. [Online] Available: https://clang.llvm.org/

[3] The MITRE Corporation, "Common Vulnerabilities and Exposures, CVE Metrics and Data", 2025. [Online] Available: https://www.cve.org/about/Metrics

[4] Figueroa-Lorenzo, S., AĀ±orga, J., and Arrizabalaga S, "A survey of IoT protocols: A measure of vulnerability risk analysis based on CVSS.", ACM Computing Surveys (CSUR), 53(2), 1-53.

[5] The Open Web Application Security Project, "CycloneDX 1.6 JSON Documentation", 2024. [Online] Available: https://cyclonedx.org/docs/1.6/json/

[6] Frank Ch. Eigler and the elfutils developers, "debuginfod-find: A Tool for Debugging Information Retrieval". [Online] Available: https://sourceware.org/elfutils/documentation/debuginfod.html

[7] "Debuginfod - ELF utilities", 2025. [Online] Available: https://sourceware.org/elfutils/Debuginfod.html

[8] LU, Qinghua, ZHU, Liming, XU, Xiwei, et al., "Responsible-AI-by-design: a pattern collection for designing responsible artificial intelligence systems.", IEEE Software, 2023, vol. 40, no 3, p. 63-71.

[9] Robertson, Colin. Using SAL Annotations to Reduce C/C++ Code Defects, Technical report, Microsoft Developer Network, 2015.

[10] Brossard, Jonathan, Unstripping Cloud Container ELF binaries, In: Proceedings of IEEE International Conference on Emerging Technologies and Computing ICETC2025, Brest, France. IEEE, 2025.

[11] The Tool Interface Standard (TIS) Committee, "Tool Interface Standard (TIS) Portable Formats Specification, Version 1.2", May 1995

[12] GCC Development Team, "GCC, the GNU Compiler Collection", 2025, https://gcc.gnu.org/

[13] Pirry, Conor, Hector Marco-Gisbert, and Carolyn Begg, "A review of memory errors exploitation in x86-64.", Computers 9.2 (2020), p. 48.

[14] Li, Senyang, et al., "Hardware-Based Software Control Flow Integrity: Review on the State-of-the-Art Implementation Technology.", IEEE Access 11 (2023): 133255-133280.

[15] Brossard, Jonathan. Toward Partial Proofs of Vulnerabilities. In : 2024 IEEE Secure Development Conference (SecDev). IEEE, 2024. p. 180-182.

[16] ALAMOUDI, Emad, MEHMOOD, Rashid, ALJUDAIBI, Wajdi, et al. Open source and open data licenses in the smart infrastructure era: Review and license selection frameworks. Smart Infrastructure and Applications: Foundations for Smarter Cities and Societies, 2020, p. 537-559.

[17] Distribution of operating systems used for Internet-of-Things (IoT) devices, as of 2016, Statista, 2016. [Online]. Available: https://www.statista.com/statistics/659581/worldwide-internet-of-things-survey-operating-systems/

[18] Dan Mandell and Chris Rommel, Edge Gateways, Industrial PCs & Embedded OT Servers: Market Intelligence Report, VDC Research, 2024. [Online]. Available: https://www.vdcresearch.com/Coverage/IoT-Tech/reports/24-Edge-Gateways-IF.html

[19] Eclipse Foundation, 2024 IoT & Embedded Developer Survey Report. 2024. [Online]. Available: https://outreach.eclipse.foundation/iot-embedded-developer-survey-2024

[20] Branco, Rodrigo Rubira. Ltrace internals. In : Proceedings of the Linux Symposium. Ottawa, ON, Canada, 2007. p. 41-52.

[21] Eggers, Shannon Leigh, et al., "The Benefits of a Software Bill of Materials Program at Nuclear Facilities.", Jul. 2023. https://doi.org/10.13182/NPICHMIT23-42305

[22] YU, Sheng, SONG, Wei, HU, Xunchao, et al. "On the correctness of metadata-based SBOM generation: A differential analysis approach.", 2024 54th Annual IEEE/IFIP International Conference on Dependable Systems and Networks (DSN). IEEE, 2024. p. 29-36.

[23] National Telecommunications and Information Administration (NTIA), "SBOM Minimum Elements Report", July 2021

[24] SPDX Working Group, "SPDX - Software Package Data Exchange v3.0", https://spdx.dev/, April 2024

[25] Brian Raiter, "sstrip : truncates ELF files to remove non-program content". [Online] Available: https://www.muppetlabs.com/ breadbox/-software/elfkickers.html

[26] RICE, Henry Gordon. Classes of recursively enumerable sets and their decision problems. Transactions of the American Mathematical society, 1953, vol. 74, no 2, p. 358-366.

[27] Brossard, Jonathan, Automatic Functions Annotations through Concrete Procedural Debugging and ELF Libification, In: Proceedings of the 40th ACM/SIGAPP Symposium On Applied Computing, 2025, Catania, Italy, March 31st - April 4th, 2025.

[28] National Telecommunications and Information Administration (NTIA), "Draft Requirements for Sharing of Vulnerability Status Information - VEX", October 2020

[29] GNU Compiler Collection (GCC) Developers, "GCC Wiki: Symbol Visibility", 2025. [Online] Available: https://gcc.gnu.org/wiki/Visibility

[30] Brossard, Jonathan. Introduction to procedural debugging through binary libification. In : 18th USENIX WOOT Conference on Offensive Technologies (WOOT 24). 2024. p. 17-25.

[31] strace developers, strace [Online]. Available: https://github.com/strace/strace [Accessed: 28-Apr-2025].
[32] Brossard, Jonathan, The Witchcraft Compiler Collection, 2025. [Online] Available: https://github.com/endrazine/wcc

[33] BELLARD, Fabrice. QEMU, a fast and portable dynamic translator. In: USENIX annual technical conference, FREENIX Track. 2005. p. 10-5555.

[34] "QEMU User Emulation," Debian Wiki. [Online]. Available: https://wiki.debian.org/QemuUserEmulation. [Accessed: Apr. 28, 2025].

[35] Roland McGrath, "Build ID - Fedora Project Wiki", https://fedoraproject.org/wiki/RolandMcGrath/BuildID, May 2008

[36] Roland McGrath, Original buildid implementation in Binutils' linker, https://sourceware.org/legacy-ml/binutils/2007-07/msg00012.html, 2007