Skip to content

[Clang] clang/lld places lazily initialized inline function-local static const std::string in .data.rel.ro, causing SIGSEGV under RELRO #199619

Closed

Description

@linrrzqqq

Problem Summary

We hit a clang-built binary crash in Apache Doris when using Apache Arrow Flight.

The crash happens inside Apache Arrow's arrow::Status::message() implementation. Arrow 17.0.0 defines an empty OK-status message as a function-local static const std::string inside an inline method in status.h:

const std::string& message() const {
  static const std::string no_message = "";
  return ok() ? no_message : state_->msg;
}

In our clang-built Apache Doris BE binary, the inline static std::string object is emitted as a weak/COMDAT symbol and placed in .data.rel.ro. After relocation, RELRO makes this section read-only. However, C++ function-local static variables are lazily initialized on first execution. The first call to Status::message() tries to construct no_message at runtime, and the std::string constructor writes to the object storage in .data.rel.ro, causing SIGSEGV invalid permissions for mapped object. We suspect this is a clang/lld section placement or COMDAT/RELRO interaction issue: a lazily initialized non-trivial object is placed into a runtime read-only mapping.

$ readelf -sW doris/output/be/lib/doris_be | c++filt | grep 'Status::message.*no_message'
105229: 000000007d6958e0    32 OBJECT  WEAK   DEFAULT   28 arrow::Status::message[abi:cxx11]() const::no_message[abi:cxx11]

$ readelf -SW doris/output/be/lib/doris_be | grep '\[ *28\]'
[28] .data.rel.ro      PROGBITS        000000007d0f7720 7d0f6720 7e4208 00  WA  0   0 32

Workaround used in Apache Doris

Related PR: apache/doris#63191

We worked around this in the Doris third-party Arrow patch by avoiding the header-inline function-local static const std::string object and by making non-OK statuses return state_->msg before touching the OK-message sentinel:

const std::string& message() const {
  if (state_ != nullptr) {
    return state_->msg;
  }
  return NoMessage();
}

Toolchain

Project context:
  Apache Doris with Apache Arrow 17.0.0 built as a third-party dependency.

Build mode:
  DORIS_TOOLCHAIN=clang
  BUILD_TYPE=RELEASE
  ENABLE_PCH=false

Toolchain:
  clang version 21.1.8
  clang++ version 21.1.8
  Target: x86_64-pc-linux-gnu
  LLD 21.1.8
  gcc/g++ runtime toolchain: Gentoo GCC 15.2.0
  libstdc++ exports up to GLIBCXX_3.4.34

Linker:
  ld is a symlink to ld.lld, which points to lld.
  The effective linker is LLD 21.1.8.

Build tools:
  CMake 3.29.0
  Ninja 1.13.2
  ccache 4.5.1

Runtime / OS:
  glibc 2.34
  Linux 5.14.0-694.el9.x86_64
  x86_64 GNU/Linux

Is placing a lazily initialized function-local static const std::string from an inline function into .data.rel.ro expected behavior under clang/lld? If not, should clang or lld ensure that such objects remain in a writable section until their lazy initialization has completed?

Activity

  1. efriedma-quic commented on May 26, 2026

    @efriedma-quic
    Contributor

    Not completely sure what's happening without a testcase. But I would guess you're mixing "-std=" flags, so one version of the variable is constexpr-evaluated, and another version isn't, then somehow the two versions get confused during linking.

  2. linrrzqqq commented on Jul 13, 2026

    @linrrzqqq
    Author

    Thanks for your answer, already fixed by: apache/doris#64390

  3. added
    questionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!
    on Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    clangClang issues not falling into any other categorylldquestionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions