Skip to content

[AArch64] Zig self-hosted linker places mutable C++ data in read-only .text, causing SIGSEGV with RTLD_GLOBAL plugins #251

@xiangguomin

Description

@xiangguomin

Environment

  • hermetic_cc_toolchain: v4.1.0
  • Zig version: 0.12.0
  • Target: aarch64-linux-gnu
  • Host: x86_64-linux
  • Bazel compilation modes affected: all (fastbuild, dbg, opt)

Symptom

Any binary that loads a shared plugin via RTLD_GLOBAL (e.g. ROS2 pluginlib) crashes
with SIGSEGV at startup on AArch64. The crash occurs when the plugin writes to a mutable
C++ runtime object (e.g. std::locale::id counters) that the Zig linker placed in the
read-only .text section.

Root Cause

The Zig 0.12.0 self-hosted linker incorrectly emits mutable C++ runtime data objects into
.text instead of .bss/.data. This goes unnoticed for statically-linked executables,
but fails at runtime when a plugin is loaded with RTLD_GLOBAL because the dynamic linker
maps .text read-only.

Workaround

Force LLD for all AArch64 link steps by adding -fuse-ld=lld to all_link_actions in
toolchain/zig_cc_toolchain.bzl:

if ctx.attr.target.startswith("aarch64"):                                                                                                            
    link_flag_sets.append(                                                                                                                           
        flag_set(                                                                                                                                    
            actions = all_link_actions,                                                                                                              
            flag_groups = [flag_group(flags = ["-fuse-ld=lld"])],                                                                                    
        ),                                                                                                                                           
    )                                                                                                                                                
                                                                                                                                                     
LLD correctly places mutable objects in writable .bss/.data.                                                                                         
 
▎ Note: ctx.attr.target_cpu is always "k8" for Linux regardless of architecture.                                                                     
▎ Use ctx.attr.target (the full Zig target triple, e.g. "aarch64-linux-gnu.2.35") todetect AArch64.                                                                                                                                    
                                               

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions