Why does ld64 require DWARF personality symbols to be extern?

The linker seems to require my exception handling personality symbol to have external visibility. This is a problem because the symbol being visible can cause consumers of my static library to run into link failures due to name collision. I would like the symbol to be local.

To see what I mean, create test.s:

; ld64 fails to link unless the following line is uncommented:
; .private_extern _my_personality
;
; lld version 15 links successfully either way.
.align 4
_my_personality:
  ret

.global _fun
.align 4
_fun:
  .cfi_startproc
  ; 0x9b = DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4
  .cfi_personality 0x9b, _my_personality
  ; This encodes DW_CFA_GNU_args_size, which compact unwind can't encode.
  ; Also repros with .cfi_escape 0
  .cfi_escape 0x2e, 0x10
  ret
  .cfi_endproc

Then run as test.s -o test.o && clang -shared test.o.

This is the error I get:

Undefined symbols for architecture arm64:
  "_my_personality", referenced from:
      Dwarf Exception Unwind Info (__eh_frame) in cat.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I'm posting test.s just so there is a self-contained test case. In practice this is for Ruby and the personality function is _rust_eh_personality.

LLVM's LLD (version 15) links fine when the symbol is local, but I can't force users to use LLD.

It would be nice if ld64 can allow linking when the symbol is local.

I'm using XCode 14. So ld64-820.1 and clang-1400.0.29.202.

Why does ld64 require DWARF personality symbols to be extern?
 
 
Q