[libc-commits] [libc] [libc] Enable ifunc support in static startup (PR #182841)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Tue Feb 24 02:01:55 PST 2026


https://github.com/kaladron updated https://github.com/llvm/llvm-project/pull/182841

>From 5038e354ed23ffb0bf19f1a69a847907fc3712fe Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Sun, 22 Feb 2026 15:06:43 +0000
Subject: [PATCH 1/3] [libc] Enable ifunc support in static startup

Static libc startup now resolves ifunc targets before `main()` runs.

This enables static binaries to use ifunc-based dispatch during early process
startup, so optimized implementations can be selected based on CPU features.
Without this relocation step in startup, those targets are not ready when
program code begins executing.

This change:
- adds IRELATIVE relocation handling for x86_64, AArch64, and RISC-V,
- reads `AT_HWCAP` / `AT_HWCAP2` from auxv and passes them to resolvers where
  required (notably AArch64),
- runs IRELATIVE processing after base-address discovery and before TLS setup,
- adds integration tests for both the ifunc path and the no-ifunc path.
- Changed the load bias type for ptrdiff_t to intptr_t to align with
  IRELATIVE handling, which uses intptr_t for load bias calculations.
---
 libc/hdr/CMakeLists.txt                       |  9 ++++
 libc/include/llvm-libc-macros/elf-macros.h    |  8 +++-
 libc/startup/linux/CMakeLists.txt             |  4 ++
 libc/startup/linux/aarch64/CMakeLists.txt     | 16 +++++++
 libc/startup/linux/aarch64/irelative.cpp      | 39 +++++++++++++++
 libc/startup/linux/do_start.cpp               | 21 ++++++--
 libc/startup/linux/irelative.h                | 34 +++++++++++++
 libc/startup/linux/riscv/CMakeLists.txt       | 16 +++++++
 libc/startup/linux/riscv/irelative.cpp        | 46 ++++++++++++++++++
 libc/startup/linux/x86_64/CMakeLists.txt      | 16 +++++++
 libc/startup/linux/x86_64/irelative.cpp       | 36 ++++++++++++++
 .../integration/startup/linux/CMakeLists.txt  | 14 ++++++
 .../startup/linux/irelative_no_ifunc_test.cpp | 16 +++++++
 .../startup/linux/irelative_test.cpp          | 48 +++++++++++++++++++
 14 files changed, 319 insertions(+), 4 deletions(-)
 create mode 100644 libc/startup/linux/aarch64/irelative.cpp
 create mode 100644 libc/startup/linux/irelative.h
 create mode 100644 libc/startup/linux/riscv/irelative.cpp
 create mode 100644 libc/startup/linux/x86_64/irelative.cpp
 create mode 100644 libc/test/integration/startup/linux/irelative_no_ifunc_test.cpp
 create mode 100644 libc/test/integration/startup/linux/irelative_test.cpp

diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index 6362c10788b2b..cb8ade0604ba7 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -266,6 +266,15 @@ add_proxy_header_library(
     libc.include.stdint
 )
 
+add_proxy_header_library(
+  elf_macros
+  HDRS
+    elf_macros.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-macros.elf_macros
+    libc.include.elf
+)
+
 add_gen_header(
   elf_proxy
   YAML_FILE
diff --git a/libc/include/llvm-libc-macros/elf-macros.h b/libc/include/llvm-libc-macros/elf-macros.h
index 6857b6681bfa2..625f64cc6335a 100644
--- a/libc/include/llvm-libc-macros/elf-macros.h
+++ b/libc/include/llvm-libc-macros/elf-macros.h
@@ -1,4 +1,4 @@
-//===-- Definition of macros from elf.h -----------------------------------===//
+//===-- Definition of macros from elf.h ------------------------ *- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -32,4 +32,10 @@
 #define ELF64_R_TYPE(i) ((i) & 0xffffffffL)
 #define ELF64_R_INFO(s, t) (((s) << 32) + ((t) & 0xffffffffL))
 
+// Architecture-specific IRELATIVE relocation types
+
+#define R_X86_64_IRELATIVE 37
+#define R_AARCH64_IRELATIVE 1032
+#define R_RISCV_IRELATIVE 58
+
 #endif // LLVM_LIBC_MACROS_ELF_MACROS_H
diff --git a/libc/startup/linux/CMakeLists.txt b/libc/startup/linux/CMakeLists.txt
index 1caabcd9179d0..015b08780da23 100644
--- a/libc/startup/linux/CMakeLists.txt
+++ b/libc/startup/linux/CMakeLists.txt
@@ -107,6 +107,7 @@ add_object_library(
     do_start.cpp
   HDRS
     do_start.h
+    irelative.h
   DEPENDS
     libc.config.app_h
     libc.hdr.elf_proxy
@@ -117,6 +118,8 @@ add_object_library(
     libc.src.__support.OSUtil.linux.auxv
     libc.src.__support.OSUtil.osutil
     libc.src.__support.threads.thread
+    libc.src.__support.macros.config
+    libc.startup.linux.${LIBC_TARGET_ARCHITECTURE}.irelative
     libc.src.stdlib.exit
     libc.src.stdlib.atexit
     libc.src.unistd.environ
@@ -131,6 +134,7 @@ merge_relocatable_object(
   crt1
   .${LIBC_TARGET_ARCHITECTURE}.start
   .${LIBC_TARGET_ARCHITECTURE}.tls
+  .${LIBC_TARGET_ARCHITECTURE}.irelative
   .do_start
   .gnu_property_section
 )
diff --git a/libc/startup/linux/aarch64/CMakeLists.txt b/libc/startup/linux/aarch64/CMakeLists.txt
index 5564f0a8f687e..d6e7662d158e2 100644
--- a/libc/startup/linux/aarch64/CMakeLists.txt
+++ b/libc/startup/linux/aarch64/CMakeLists.txt
@@ -23,3 +23,19 @@ add_startup_object(
     -fno-omit-frame-pointer
     -ffreestanding # To avoid compiler warnings about calling the main function.
 )
+
+add_startup_object(
+  irelative
+  SRC
+    irelative.cpp
+  DEPENDS
+    libc.hdr.link_macros
+    libc.hdr.elf_macros
+    libc.hdr.stdint_proxy
+    libc.src.__support.macros.config
+  COMPILE_OPTIONS
+    -fno-stack-protector
+    -fno-omit-frame-pointer
+    -ffreestanding
+    -fno-builtin
+)
diff --git a/libc/startup/linux/aarch64/irelative.cpp b/libc/startup/linux/aarch64/irelative.cpp
new file mode 100644
index 0000000000000..22ba78e636418
--- /dev/null
+++ b/libc/startup/linux/aarch64/irelative.cpp
@@ -0,0 +1,39 @@
+//===-- Implementation of apply_irelative_relocs (AArch64) ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "startup/linux/irelative.h"
+#include "hdr/elf_macros.h"
+#include "hdr/link_macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+void apply_irelative_relocs(intptr_t base, unsigned long hwcap,
+                            unsigned long hwcap2) {
+  for (const ElfW(Rela) *rela = __rela_iplt_start; rela != __rela_iplt_end;
+       ++rela) {
+    if (ELF64_R_TYPE(rela->r_info) != R_AARCH64_IRELATIVE)
+      continue;
+
+    // AArch64 resolvers receive hwcap and hwcap2.
+    // Use unsigned arithmetic to avoid undefined behavior on signed overflow,
+    // which can occur with very large binaries or high load addresses.
+    uintptr_t resolver_addr =
+        static_cast<uintptr_t>(base) + static_cast<uintptr_t>(rela->r_addend);
+    auto resolver =
+        reinterpret_cast<uintptr_t (*)(unsigned long, unsigned long)>(
+            resolver_addr);
+    uintptr_t result = resolver(hwcap, hwcap2);
+
+    // Write the resolved function pointer to the target location.
+    uintptr_t target_addr = static_cast<uintptr_t>(base) + rela->r_offset;
+    *reinterpret_cast<uintptr_t *>(target_addr) = result;
+  }
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/startup/linux/do_start.cpp b/libc/startup/linux/do_start.cpp
index 65adfb50bccba..b1faaf7d90dd3 100644
--- a/libc/startup/linux/do_start.cpp
+++ b/libc/startup/linux/do_start.cpp
@@ -18,6 +18,7 @@
 #include "src/stdlib/exit.h"
 #include "src/unistd/environ.h"
 #include "startup/linux/gnu_property_section.h"
+#include "startup/linux/irelative.h"
 
 #include <sys/mman.h>
 #include <sys/syscall.h>
@@ -86,6 +87,8 @@ static TLSDescriptor tls;
   // denoted by an AT_NULL entry.
   ElfW(Phdr) *program_hdr_table = nullptr;
   uintptr_t program_hdr_count = 0;
+  unsigned long hwcap = 0;
+  unsigned long hwcap2 = 0;
   auxv::Vector::initialize_unsafe(
       reinterpret_cast<const auxv::Entry *>(env_end_marker + 1));
   auxv::Vector auxvec;
@@ -100,12 +103,18 @@ static TLSDescriptor tls;
     case AT_PAGESZ:
       app.page_size = aux_entry.val;
       break;
+    case AT_HWCAP:
+      hwcap = aux_entry.val;
+      break;
+    case AT_HWCAP2:
+      hwcap2 = aux_entry.val;
+      break;
     default:
       break; // TODO: Read other useful entries from the aux vector.
     }
   }
 
-  ptrdiff_t base = 0;
+  intptr_t base = 0;
   app.tls.size = 0;
   ElfW(Phdr) *tls_phdr = nullptr;
   [[maybe_unused]] ElfW(Phdr) *gnu_property_phdr = nullptr;
@@ -113,9 +122,9 @@ static TLSDescriptor tls;
   for (uintptr_t i = 0; i < program_hdr_count; ++i) {
     ElfW(Phdr) &phdr = program_hdr_table[i];
     if (phdr.p_type == PT_PHDR)
-      base = reinterpret_cast<ptrdiff_t>(program_hdr_table) - phdr.p_vaddr;
+      base = reinterpret_cast<intptr_t>(program_hdr_table) - phdr.p_vaddr;
     if (phdr.p_type == PT_DYNAMIC && _DYNAMIC)
-      base = reinterpret_cast<ptrdiff_t>(_DYNAMIC) - phdr.p_vaddr;
+      base = reinterpret_cast<intptr_t>(_DYNAMIC) - phdr.p_vaddr;
     if (phdr.p_type == PT_TLS)
       tls_phdr = &phdr;
     if (phdr.p_type == PT_GNU_PROPERTY)
@@ -123,6 +132,12 @@ static TLSDescriptor tls;
     // TODO: adjust PT_GNU_STACK
   }
 
+  // Process IRELATIVE relocations (ifunc resolvers).
+  // Skips when no ifuncs are present in the binary.
+  if (reinterpret_cast<uintptr_t>(__rela_iplt_start) !=
+      reinterpret_cast<uintptr_t>(__rela_iplt_end))
+    apply_irelative_relocs(base, hwcap, hwcap2);
+
   app.tls.address = tls_phdr->p_vaddr + base;
   app.tls.size = tls_phdr->p_memsz;
   app.tls.init_size = tls_phdr->p_filesz;
diff --git a/libc/startup/linux/irelative.h b/libc/startup/linux/irelative.h
new file mode 100644
index 0000000000000..0845ce22a7e68
--- /dev/null
+++ b/libc/startup/linux/irelative.h
@@ -0,0 +1,34 @@
+//===-- Implementation header for IRELATIVE relocations -------- *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_STARTUP_LINUX_IRELATIVE_H
+#define LLVM_LIBC_STARTUP_LINUX_IRELATIVE_H
+
+#include "hdr/link_macros.h"
+#include "hdr/stdint_proxy.h"
+#include "src/__support/macros/config.h"
+
+extern "C" {
+[[gnu::weak, gnu::visibility("hidden")]] extern const ElfW(Rela)
+    __rela_iplt_start[]; // NOLINT
+[[gnu::weak, gnu::visibility("hidden")]] extern const ElfW(Rela)
+    __rela_iplt_end[]; // NOLINT
+}
+
+namespace LIBC_NAMESPACE_DECL {
+
+// Process IRELATIVE relocations (ifunc resolvers).
+// base is the load bias (actual load address − link-time address).  It is
+// intptr_t (signed) because it is a difference; it is negative if the binary
+// loaded below its link address. (unlikely but possible in principle)
+void apply_irelative_relocs(intptr_t base, unsigned long hwcap,
+                            unsigned long hwcap2);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_STARTUP_LINUX_IRELATIVE_H
diff --git a/libc/startup/linux/riscv/CMakeLists.txt b/libc/startup/linux/riscv/CMakeLists.txt
index 2a61f8289067d..61c912909dbb4 100644
--- a/libc/startup/linux/riscv/CMakeLists.txt
+++ b/libc/startup/linux/riscv/CMakeLists.txt
@@ -24,3 +24,19 @@ add_startup_object(
     -fno-omit-frame-pointer
     -ffreestanding # To avoid compiler warnings about calling the main function.
 )
+
+add_startup_object(
+  irelative
+  SRC
+    irelative.cpp
+  DEPENDS
+    libc.hdr.link_macros
+    libc.hdr.elf_macros
+    libc.hdr.stdint_proxy
+    libc.src.__support.macros.config
+  COMPILE_OPTIONS
+    -fno-stack-protector
+    -fno-omit-frame-pointer
+    -ffreestanding
+    -fno-builtin
+)
diff --git a/libc/startup/linux/riscv/irelative.cpp b/libc/startup/linux/riscv/irelative.cpp
new file mode 100644
index 0000000000000..b8c36bbc7d353
--- /dev/null
+++ b/libc/startup/linux/riscv/irelative.cpp
@@ -0,0 +1,46 @@
+//===-- Implementation of apply_irelative_relocs (RISC-V) -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "startup/linux/irelative.h"
+#include "hdr/elf_macros.h"
+#include "hdr/link_macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// RISC-V may be 32-bit or 64-bit. ElfW(Rela) handles the struct type,
+// but we need the correct R_TYPE extraction macro.
+static LIBC_INLINE constexpr unsigned get_r_type(uintptr_t info) {
+#ifdef __LP64__
+  return ELF64_R_TYPE(info);
+#else
+  return ELF32_R_TYPE(info);
+#endif
+}
+
+void apply_irelative_relocs(intptr_t base, unsigned long /*hwcap*/,
+                            unsigned long /*hwcap2*/) {
+  for (const ElfW(Rela) *rela = __rela_iplt_start; rela != __rela_iplt_end;
+       ++rela) {
+    if (get_r_type(rela->r_info) != R_RISCV_IRELATIVE)
+      continue;
+
+    // RISC-V resolvers take no arguments (same as x86_64).
+    // Use unsigned arithmetic to avoid undefined behavior on signed overflow,
+    // which can occur with very large binaries or high load addresses.
+    uintptr_t resolver_addr =
+        static_cast<uintptr_t>(base) + static_cast<uintptr_t>(rela->r_addend);
+    auto resolver = reinterpret_cast<uintptr_t (*)(void)>(resolver_addr);
+    uintptr_t result = resolver();
+
+    uintptr_t target_addr = static_cast<uintptr_t>(base) + rela->r_offset;
+    *reinterpret_cast<uintptr_t *>(target_addr) = result;
+  }
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/startup/linux/x86_64/CMakeLists.txt b/libc/startup/linux/x86_64/CMakeLists.txt
index 4f482eaf5d18e..6eebc734a06a7 100644
--- a/libc/startup/linux/x86_64/CMakeLists.txt
+++ b/libc/startup/linux/x86_64/CMakeLists.txt
@@ -28,3 +28,19 @@ add_startup_object(
     -ffreestanding
     -fno-builtin
 )
+
+add_startup_object(
+  irelative
+  SRC
+    irelative.cpp
+  DEPENDS
+    libc.hdr.link_macros
+    libc.hdr.elf_macros
+    libc.hdr.stdint_proxy
+    libc.src.__support.macros.config
+  COMPILE_OPTIONS
+    -fno-stack-protector
+    -fno-omit-frame-pointer
+    -ffreestanding
+    -fno-builtin
+)
diff --git a/libc/startup/linux/x86_64/irelative.cpp b/libc/startup/linux/x86_64/irelative.cpp
new file mode 100644
index 0000000000000..60d5c81ac36a7
--- /dev/null
+++ b/libc/startup/linux/x86_64/irelative.cpp
@@ -0,0 +1,36 @@
+//===-- Implementation of apply_irelative_relocs (x86_64) -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "startup/linux/irelative.h"
+#include "hdr/elf_macros.h"
+#include "hdr/link_macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+void apply_irelative_relocs(intptr_t base, unsigned long /*hwcap*/,
+                            unsigned long /*hwcap2*/) {
+  for (const ElfW(Rela) *rela = __rela_iplt_start; rela != __rela_iplt_end;
+       ++rela) {
+    if (ELF64_R_TYPE(rela->r_info) != R_X86_64_IRELATIVE)
+      continue;
+
+    // x86_64 resolvers take no arguments.
+    // Use unsigned arithmetic to avoid undefined behavior on signed overflow,
+    // which can occur with very large binaries or high load addresses.
+    uintptr_t resolver_addr =
+        static_cast<uintptr_t>(base) + static_cast<uintptr_t>(rela->r_addend);
+    auto resolver = reinterpret_cast<uintptr_t (*)(void)>(resolver_addr);
+    uintptr_t result = resolver();
+
+    uintptr_t target_addr = static_cast<uintptr_t>(base) + rela->r_offset;
+    *reinterpret_cast<uintptr_t *>(target_addr) = result;
+  }
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/integration/startup/linux/CMakeLists.txt b/libc/test/integration/startup/linux/CMakeLists.txt
index 511b16d613026..83baa8e1b2844 100644
--- a/libc/test/integration/startup/linux/CMakeLists.txt
+++ b/libc/test/integration/startup/linux/CMakeLists.txt
@@ -49,3 +49,17 @@ add_integration_test(
   SRCS
     init_fini_array_test.cpp
 )
+
+add_integration_test(
+  startup_irelative_test
+  SUITE libc-startup-tests
+  SRCS
+    irelative_test.cpp
+)
+
+add_integration_test(
+  startup_irelative_no_ifunc_test
+  SUITE libc-startup-tests
+  SRCS
+    irelative_no_ifunc_test.cpp
+)
diff --git a/libc/test/integration/startup/linux/irelative_no_ifunc_test.cpp b/libc/test/integration/startup/linux/irelative_no_ifunc_test.cpp
new file mode 100644
index 0000000000000..631c5bb92c77e
--- /dev/null
+++ b/libc/test/integration/startup/linux/irelative_no_ifunc_test.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of apply_irelative_relocs (no ifunc) test ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "startup/linux/irelative.h"
+#include "test/IntegrationTest/test.h"
+
+TEST_MAIN() {
+  ASSERT_EQ(reinterpret_cast<uintptr_t>(__rela_iplt_start),
+            reinterpret_cast<uintptr_t>(__rela_iplt_end));
+  return 0;
+}
diff --git a/libc/test/integration/startup/linux/irelative_test.cpp b/libc/test/integration/startup/linux/irelative_test.cpp
new file mode 100644
index 0000000000000..0fda65c95660b
--- /dev/null
+++ b/libc/test/integration/startup/linux/irelative_test.cpp
@@ -0,0 +1,48 @@
+//===-- Implementation of apply_irelative_relocs test ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "test/IntegrationTest/test.h"
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(ifunc)
+
+// Two trivial implementations that return different constants.
+static int impl_a() { return 42; }
+static int impl_b() { return 84; }
+
+// The resolver function. On x86_64 this takes no arguments; on AArch64 it
+// receives (hwcap, hwcap2). We use extern "C" to ensure C linkage for the
+// ifunc attribute.
+extern "C" {
+// Declare the resolver to return a generic function pointer.
+// For testing, unconditionally select impl_a.
+void *my_ifunc_resolver() {
+  (void)impl_b; // Suppress unused warning.
+  return reinterpret_cast<void *>(impl_a);
+}
+}
+
+// Declare the ifunc. The compiler and linker will generate an IRELATIVE
+// relocation that calls my_ifunc_resolver at startup.
+extern "C" int my_ifunc() __attribute__((ifunc("my_ifunc_resolver")));
+
+TEST_MAIN() {
+  // If IRELATIVE processing works correctly, my_ifunc() should call impl_a
+  // and return 42.
+  ASSERT_EQ(my_ifunc(), 42);
+  return 0;
+}
+
+#else
+
+TEST_MAIN() { return 0; }
+
+#endif

>From 8004aaa40aff8a95fb0c8a02053dd55286c87eed Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Tue, 24 Feb 2026 09:38:40 +0000
Subject: [PATCH 2/3] [libc] Move IRELATIVE relocation constants to elf.yaml

Move R_X86_64_IRELATIVE, R_AARCH64_IRELATIVE, and R_RISCV_IRELATIVE
from the hand-written llvm-libc-macros/elf-macros.h into elf.yaml so
they are generated alongside the rest of the ELF definitions.

Add hdr/elf_proxy.h to the per-arch irelative.cpp files so the
R_*_IRELATIVE constants (now generated from elf.yaml) are visible.
hdr/elf_macros.h is retained for the functional ELF{32,64}_R_TYPE
macros, which cannot be expressed as plain integer constants in the
YAML. Update the corresponding CMakeLists DEPENDS entries to match.
---
 libc/include/elf.yaml                      | 7 +++++++
 libc/include/llvm-libc-macros/elf-macros.h | 8 +-------
 libc/startup/linux/aarch64/CMakeLists.txt  | 1 +
 libc/startup/linux/aarch64/irelative.cpp   | 1 +
 libc/startup/linux/riscv/CMakeLists.txt    | 1 +
 libc/startup/linux/riscv/irelative.cpp     | 1 +
 libc/startup/linux/x86_64/CMakeLists.txt   | 1 +
 libc/startup/linux/x86_64/irelative.cpp    | 1 +
 8 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/libc/include/elf.yaml b/libc/include/elf.yaml
index 6cb9122e013a9..aac04119f5f55 100644
--- a/libc/include/elf.yaml
+++ b/libc/include/elf.yaml
@@ -440,6 +440,13 @@ macros:
     macro_value: '0xc0000002'
   - macro_name: GNU_PROPERTY_X86_FEATURE_1_SHSTK
     macro_value: '0x00000002'
+  # Architecture-specific IRELATIVE relocation types
+  - macro_name: R_X86_64_IRELATIVE
+    macro_value: 37
+  - macro_name: R_AARCH64_IRELATIVE
+    macro_value: 1032
+  - macro_name: R_RISCV_IRELATIVE
+    macro_value: 58
 types:
   - type_name: Elf32_Addr
   - type_name: Elf32_Chdr
diff --git a/libc/include/llvm-libc-macros/elf-macros.h b/libc/include/llvm-libc-macros/elf-macros.h
index 625f64cc6335a..6857b6681bfa2 100644
--- a/libc/include/llvm-libc-macros/elf-macros.h
+++ b/libc/include/llvm-libc-macros/elf-macros.h
@@ -1,4 +1,4 @@
-//===-- Definition of macros from elf.h ------------------------ *- C++ -*-===//
+//===-- Definition of macros from elf.h -----------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -32,10 +32,4 @@
 #define ELF64_R_TYPE(i) ((i) & 0xffffffffL)
 #define ELF64_R_INFO(s, t) (((s) << 32) + ((t) & 0xffffffffL))
 
-// Architecture-specific IRELATIVE relocation types
-
-#define R_X86_64_IRELATIVE 37
-#define R_AARCH64_IRELATIVE 1032
-#define R_RISCV_IRELATIVE 58
-
 #endif // LLVM_LIBC_MACROS_ELF_MACROS_H
diff --git a/libc/startup/linux/aarch64/CMakeLists.txt b/libc/startup/linux/aarch64/CMakeLists.txt
index d6e7662d158e2..f873b290fb2dd 100644
--- a/libc/startup/linux/aarch64/CMakeLists.txt
+++ b/libc/startup/linux/aarch64/CMakeLists.txt
@@ -31,6 +31,7 @@ add_startup_object(
   DEPENDS
     libc.hdr.link_macros
     libc.hdr.elf_macros
+    libc.hdr.elf_proxy
     libc.hdr.stdint_proxy
     libc.src.__support.macros.config
   COMPILE_OPTIONS
diff --git a/libc/startup/linux/aarch64/irelative.cpp b/libc/startup/linux/aarch64/irelative.cpp
index 22ba78e636418..bc9eb280cedc4 100644
--- a/libc/startup/linux/aarch64/irelative.cpp
+++ b/libc/startup/linux/aarch64/irelative.cpp
@@ -8,6 +8,7 @@
 
 #include "startup/linux/irelative.h"
 #include "hdr/elf_macros.h"
+#include "hdr/elf_proxy.h"
 #include "hdr/link_macros.h"
 #include "src/__support/macros/config.h"
 
diff --git a/libc/startup/linux/riscv/CMakeLists.txt b/libc/startup/linux/riscv/CMakeLists.txt
index 61c912909dbb4..3a8ce5fecdecb 100644
--- a/libc/startup/linux/riscv/CMakeLists.txt
+++ b/libc/startup/linux/riscv/CMakeLists.txt
@@ -32,6 +32,7 @@ add_startup_object(
   DEPENDS
     libc.hdr.link_macros
     libc.hdr.elf_macros
+    libc.hdr.elf_proxy
     libc.hdr.stdint_proxy
     libc.src.__support.macros.config
   COMPILE_OPTIONS
diff --git a/libc/startup/linux/riscv/irelative.cpp b/libc/startup/linux/riscv/irelative.cpp
index b8c36bbc7d353..f27ce8dd3bfaf 100644
--- a/libc/startup/linux/riscv/irelative.cpp
+++ b/libc/startup/linux/riscv/irelative.cpp
@@ -8,6 +8,7 @@
 
 #include "startup/linux/irelative.h"
 #include "hdr/elf_macros.h"
+#include "hdr/elf_proxy.h"
 #include "hdr/link_macros.h"
 #include "src/__support/macros/config.h"
 
diff --git a/libc/startup/linux/x86_64/CMakeLists.txt b/libc/startup/linux/x86_64/CMakeLists.txt
index 6eebc734a06a7..44259944078d6 100644
--- a/libc/startup/linux/x86_64/CMakeLists.txt
+++ b/libc/startup/linux/x86_64/CMakeLists.txt
@@ -36,6 +36,7 @@ add_startup_object(
   DEPENDS
     libc.hdr.link_macros
     libc.hdr.elf_macros
+    libc.hdr.elf_proxy
     libc.hdr.stdint_proxy
     libc.src.__support.macros.config
   COMPILE_OPTIONS
diff --git a/libc/startup/linux/x86_64/irelative.cpp b/libc/startup/linux/x86_64/irelative.cpp
index 60d5c81ac36a7..52cc24e3d2ce0 100644
--- a/libc/startup/linux/x86_64/irelative.cpp
+++ b/libc/startup/linux/x86_64/irelative.cpp
@@ -8,6 +8,7 @@
 
 #include "startup/linux/irelative.h"
 #include "hdr/elf_macros.h"
+#include "hdr/elf_proxy.h"
 #include "hdr/link_macros.h"
 #include "src/__support/macros/config.h"
 

>From a565f6fa94ed3adac4b4cfec0d726d99e5ca7c15 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Tue, 24 Feb 2026 09:42:29 +0000
Subject: [PATCH 3/3] [libc] Add R_ARM_RELATIVE and sort the macros

---
 libc/include/elf.yaml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libc/include/elf.yaml b/libc/include/elf.yaml
index aac04119f5f55..1b5e01123582f 100644
--- a/libc/include/elf.yaml
+++ b/libc/include/elf.yaml
@@ -441,12 +441,14 @@ macros:
   - macro_name: GNU_PROPERTY_X86_FEATURE_1_SHSTK
     macro_value: '0x00000002'
   # Architecture-specific IRELATIVE relocation types
-  - macro_name: R_X86_64_IRELATIVE
-    macro_value: 37
   - macro_name: R_AARCH64_IRELATIVE
     macro_value: 1032
+  - macro_name: R_ARM_IRELATIVE
+    macro_value: 160
   - macro_name: R_RISCV_IRELATIVE
     macro_value: 58
+  - macro_name: R_X86_64_IRELATIVE
+    macro_value: 37
 types:
   - type_name: Elf32_Addr
   - type_name: Elf32_Chdr



More information about the libc-commits mailing list