Skip to content

"comparator is not a valid strict-weak ordering" in lld pdb writing codepath w/ libc++ debug hardening mode #163755

@zmodem

Description

@zmodem

This was raised in #156250 (comment) but I don't think it's related to the new lldb test, but rather to pdb writing in general.

Local repro on Linux with today's head (e764b6d).

Build clang and libc++ (stage0)

$ cmake -GNinja -Bstage0 -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=clang -DLLVM_ENABLE_RUNTIMES='compiler-rt;libcxx;libcxxabi;libunwind' -DLLVM_TARGETS_TO_BUILD=X86 -DLIBCXX_HARDENING_MODE=debug llvm/
$ ninja -C stage0

Use that to build lld with libc++ in debug hardening mode (stage1)

$ CC=$PWD/stage0/bin/clang CXX=$PWD/stage0/bin/clang++ CXXFLAGS=-stdlib=libc++ cmake -GNinja -Bstage1 -DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_PROJECTS=lld -DLLVM_TARGETS_TO_BUILD=X86 llvm/
$ mkdir -p stage1/lib && cp stage0/lib/x86_64-unknown-linux-gnu/*.so* stage1/lib/
$ ninja -C stage1 lld

Use that to compile and link the test file:

$ stage0/bin/clang-cl --target=x86_64-windows-msvc -Od -Z7 -std:c++20 -c /Fo/tmp/a.obj lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp
$ stage1/bin/lld-link -debug:full -nodefaultlib -entry:main /tmp/a.obj -out:/tmp/a.exe -pdb:/tmp/a.pdb
/work/llvm-project/stage0/bin/../include/c++/v1/__debug_utils/strict_weak_ordering_check.h:50: libc++ Hardening assertion !__comp(*(__first + __a), *(__first + __b)) failed: Your comparator is not a valid strict-weak ordering
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
/work/llvm-project/stage0/bin/../include/c++/v1/__debug_utils/strict_weak_ordering_check.h:50: libc++ Hardening assertion !__comp(*(__first + __a), *(__first + __b)) failed: Your comparator is not a valid strict-weak ordering
Aborted (core dumped)

Stack trace:

#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007ffff79609ff in __pthread_kill_internal (threadid=<optimized out>, signo=6) at ./nptl/pthread_kill.c:89
#2  0x00007ffff790bcc2 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007ffff78f44ac in __GI_abort () at ./stdlib/abort.c:73
#4  0x00007ffff7bb742d in std::__1::__libcpp_verbose_abort(char const*, ...) () from /work/llvm-project/stage1/bin/../lib/libc++.so.1
#5  0x0000555559f88c73 in std::__1::__check_strict_weak_ordering_sorted[abi:dn220000]<llvm::pdb::PSHashRecord*, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}>(llvm::pdb::PSHashRecord*, llvm::pdb::PSHashRecord*, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}&) (__first=0x55555d8f0200, __last=0x55555d8f0208, __comp=...)
    at /work/llvm-project/stage0/bin/../include/c++/v1/__debug_utils/strict_weak_ordering_check.h:49
#6  0x0000555559f88a6d in std::__1::__sort_impl[abi:dn220000]<std::__1::_ClassicAlgPolicy, std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}>(std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}&) (__first=..., __last=..., 
    __comp=...) at /work/llvm-project/stage0/bin/../include/c++/v1/__algorithm/sort.h:939
#7  0x0000555559f889c9 in std::__1::sort[abi:dn220000]<std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}>(std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}) (__first=..., __last=..., __comp=...)
    at /work/llvm-project/stage0/bin/../include/c++/v1/__algorithm/sort.h:945
#8  0x0000555559f8897d in llvm::sort<std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}>(std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, std::__1::__wrap_iter<llvm::pdb::PSHashRecord*>, llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const::{lambda(llvm::pdb::PSHashRecord const&, llvm::pdb::PSHashRecord const&)#1}) (Start=..., End=..., Comp=...)
    at /work/llvm-project/llvm/include/llvm/ADT/STLExtras.h:1644
#9  0x0000555559f88848 in llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1::operator()(unsigned long) const (
    this=0x7ffffffefb30, I=226) at /work/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp:255
#10 0x0000555559f8873d in llvm::function_ref<void(unsigned long)>::callback_fn<llvm::pdb::GSIHashStreamBuilder::finalizeBuckets(unsigned int, llvm::MutableArrayRef<llvm::pdb::BulkPublic>)::$_1> (callable=140737488288560, params=226) at /work/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:46
#11 0x000055555aaa73d1 in llvm::function_ref<void(unsigned long)>::operator() (this=0x7ffffffefac0, params=226)
    at /work/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:69
#12 0x000055555aaa6fa2 in llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>)::$_0::operator()() const (this=0x55555d8f0bd8)
    at /work/llvm-project/llvm/lib/Support/Parallel.cpp:302
#13 0x000055555aaa6f55 in std::__1::__invoke[abi:dn220000]<llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>)::$_0&>(llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>)::$_0&) (__args=...) at /work/llvm-project/stage0/bin/../include/c++/v1/__type_traits/invoke.h:90
#14 0x000055555aaa6f35 in std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:dn220000]<llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>)::$_0&>(llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>)::$_0&) (__args=...)
    at /work/llvm-project/stage0/bin/../include/c++/v1/__type_traits/invoke.h:350
#15 0x000055555aaa6f15 in std::__1::__invoke_r[abi:dn220000]<void, llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>)::$_0&>(llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>)::$_0&) (__args=...) at /work/llvm-project/stage0/bin/../include/c++/v1/__type_traits/invoke.h:356
#16 0x000055555aaa6ea9 in std::__1::__function::__func<llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void(unsigned long)>)::$_0, void()>::operator() (
    this=0x55555d8f0bd0) at /work/llvm-project/stage0/bin/../include/c++/v1/__functional/function.h:172
#17 0x0000555555e8c59e in std::__1::__function::__value_func<void ()>::operator()[abi:dn220000]() const (this=0x55555d8f0bd0)
    at /work/llvm-project/stage0/bin/../include/c++/v1/__functional/function.h:273
#18 0x0000555555e8b5c5 in std::__1::function<void()>::operator() (this=0x55555d8f0bd0) at /work/llvm-project/stage0/bin/../include/c++/v1/__functional/function.h:754
#19 0x000055555aaa6ccd in llvm::parallel::TaskGroup::spawn(std::__1::function<void ()>)::$_0::operator()() const (this=0x55555d8f0bd0)
    at /work/llvm-project/llvm/lib/Support/Parallel.cpp:275
#20 0x000055555aaa6ca5 in std::__1::__invoke[abi:dn220000]<llvm::parallel::TaskGroup::spawn(std::__1::function<void ()>)::$_0&>(llvm::parallel::TaskGroup::spawn(std::__1::function<void ()>)::$_0&) (__args=...) at /work/llvm-project/stage0/bin/../include/c++/v1/__type_traits/invoke.h:90
#21 0x000055555aaa6c85 in std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:dn220000]<llvm::parallel::TaskGroup::spawn(std::__1::function<void ()>)::$_0&>(llvm::parallel::TaskGroup::spawn(std::__1::function<void ()>)::$_0&) (__args=...) at /work/llvm-project/stage0/bin/../include/c++/v1/__type_traits/invoke.h:350

So I suppose this is

auto BucketCmp = [Records](const PSHashRecord &LHash,
const PSHashRecord &RHash) {
const BulkPublic &L = Records[uint32_t(LHash.Off)];
const BulkPublic &R = Records[uint32_t(RHash.Off)];
assert(L.BucketIdx == R.BucketIdx);
int Cmp = gsiRecordCmp(L.getName(), R.getName());
if (Cmp != 0)
return Cmp < 0;
// This comparison is necessary to make the sorting stable in the presence
// of two static globals with the same name. The easiest way to observe
// this is with S_LDATA32 records.
return L.SymOffset < R.SymOffset;
};
llvm::sort(B, E, BucketCmp);

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions