This article describes ABI and toolchain considerations about systems
without a Memory Management Unit (MMU). We will focus on FDPIC and the
in-development FDPIC ABI for RISC-V, with updates as I delve deeper into
the topic.
Embedded systems often lack MMUs, relying on real-time operating
systems (RTOS) like VxWorks or special Linux configurations
(CONFIG_MMU=n). In these systems, the offset between the
text and data segments is often not knwon at compile time. Therefore, a
dedicated register is typically set to somewhere in the data segment and
writable data is accessed relative to this register.
Why is the offset not knwon at compile time? There are primarily two
reasons.
First, eXecute in Place (XIP), where code resides in ROM while the
data segment is copied to RAM. Therefore, the offset between the text
and data segments is often not knwon at compile time.
Second, all processes share the same address space without MMU.
However, it is still desired for these processes to share text segments.
Therefore needs a mechanism for code to find its corresponding data.
This article describes some notes about z/Architecture
with a focus on the ELF ABI and ELF linkers. An lld/ELF patch
sparked my motivation to study the architecture and write this post.
z/Architecture
is a big-endian mainframe computer architecture supporting 24-bit,
31-bit, and 64-bit addressing modes. It is the latest generation in a
lineage stretching back to the 1964 with IBM System/360 (32-bit
general-purpose registers and 24-bit addressing). This lineage includes
System/370 (1970), System/370 Extended Architecture (1983), Enterprise
Systems Architecture/370 (1988), and Enterprise Systems Architecture/390
(1990). For a deeper dive into the design choices behind
z/Architecture's extension from ESA/390, you can refer to
"Development and attributes of z/Architecture."
function coverage: determines whether each function been
executed.
line coverage (aka statement coverage): determines whether every
line has been executed.
branch coverage: ensures that both the true and false branches of
each conditional statement or the condition of each loop statement been
evaluated.
Condition coverage offers a more fine-grained evaluation of branch
coverage. It requires that each individual boolean subexpression
(condition) within a compound expression be evaluated to both true and
false. For example, in the boolean expression
if (a>0 && f(b) && c==0), each of
a>0, f(b), and c==0, condition
coverage would require tests that:
These patches are expected to be included in the upcoming LLVM 18.1
release. To obtain TLSDESC code sequences, compile your program with
clang --target=riscv64-linux -fpic -mtls-dialect=desc.
I have also modified musl-clang (clang wrapper). Adjust
~/musl/out/rv64/obj/musl-clang to use
--target=riscv64-linux-musl. Adjust
~/musl/out/rv64/obj/ld.musl-clang to define
cc="/tmp/Rel/bin/clang --target=riscv64-linux-gnu" and
invoke exec /tmp/Rel/bin/ld.lld "$@" -lc.
During my development of the linker patch, the Clang Driver patch was
actually not ready yet. I used a more hacky approach by compiling using
GCC, replacing some assembly fragments with TLSDESC code sequences, and
assemblying using Clang.
Compile b.c to bb.s. Replace
general-dynamic code sequences (e.g.
la.tls.gd a0,tls0; call __tls_get_addr@plt) with TLSDESC,
e.g.
My journey with the LLVM project began with a deep dive into the
world of lld and binary utilities. Countless hours were spent unraveling
the intricacies of object file formats and shaping LLVM's relevant
components. Though my interests have since broadened, object file
formats remain a personal fascination, often drawing me into discussions
around potential changes within LLVM.
This article compares several prominent object file formats, drawing
upon my experience and insights.
At the heart of each format lies the representation of essential
components like symbols, sections, and relocations. For each control
structure, We'll begin with ELF, a widely used format, before venturing
into the landscapes of other notable formats.
Made -fsanitize=function work for C and non-x86
architectures
Fixed several major problems of assembler implementation of RISC-V
linker relaxation
clangSema: %lb recognization for printf/scanf, checking
the failure memory order for atomic_compare_exchange-family
built-in functions, -Wc++11-narrowing-const-reference
llvm-objdump: @plt symbols for x86
.plt.got, mapping symbol improvements,
--disassemble-symbols changes, etc
Supported R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 for
.uleb128 directives
gcov: fix instrumentation crashes when using inline variables,
#line, and #include, made llvm-cov gcov work
with a smaller stack size
LTO: fixed local ifunc for ThinLTO, reported errors when parsing
module-level inline assembly
CodeLayout: fixed a correctness bug and improved performance to be
suitable for lld/ELF --call-graph-profile-sort=hfsort
default
Reviewed many commits. A lot of people don't add a
Reviewed By: tag. Anyway, counting commits with the tag can
give an underestimate.
For approximately 10 years, reviews.llvm.org functioned as the code
view site for the LLVM project, utilizing a Phabricator instance. This
website hosted numerous invaluable code review discussions. However,
following LLVM's transition
to GitHub pull requests, there arises a necessity for a read-only
archive of the existing Phabricator instance. (https://archive.org/
archives a subset of the reviews.llvm.org/Dxxxxx
pages.)
The intent is to eliminate a SQL engine. Phabicator operates on a complex
database scheme. To minimize time investment, the most feasible
approach seems to involve downloading the static HTML pages and
employing a lightweight scraping process.
Raphaël Gomès developed phab-archive
to serve a read-only archive for Mercurial's Phabricator instance. I have modified
the code to suit reviews.llvm.org.
The DNS records of reviews.llvm.org have been pointed to the archive website.
This article describes section layout and its interaction with
dynamic loaders and huge pages.
Let's begin with a Linux x86-64 example involving global variables
exhibiting various properties such as read-only versus writable,
zero-initialized versus non-zero, and more.