Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lld 16 appears to have a threading-related memory leak on some Android AArch64 devices #62165

Open
finagolfin opened this issue Apr 16, 2023 · 29 comments

Comments

@finagolfin
Copy link

finagolfin commented Apr 16, 2023

I see random crashes when linking, that always go away if I run the same command again, ie it's usually not repeatable. This is only since the LLVM 16 update, LLVM 15 worked well, as noted in termux/termux-packages#15867.

Sometimes, it'll just segfault:

error: link command failed with exit code 1 (use -v to see invocation)
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /data/data/com.termux/files/usr/bin/ld.lld --sysroot=/data/data/com.termux/files -pie -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=4096 --hash-style=gnu -rpath=/data/data/com.termux/files/usr/lib --eh-frame-hdr -m aarch64linux -dynamic-linker /system/bin/linker64 -o ...
clang-16: error: unable to execute command: Segmentation fault
clang-16: error: linker command failed due to signal (use -v to see invocation)

Other times, it'll claim issues with memory tagging:

error: link command failed with exit code 1 (use -v to see invocation)
Pointer tag for 0xe2a9a7d900000000 was truncated, see 'https://source.android.com/devices/tech/debug/tagged-pointers'.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
clang-16: error: unable to execute command: Aborted
clang-16: error: linker command failed due to signal (use -v to see invocation)

Most likely, this is a memory leak that sometimes causes segfaults.

I tried to reproduce on Ubuntu 20.04 x86_64 by building a Swift package repeatedly with the official Clang 16.0.0 build on GitHub Actions, but could not after 50+ builds of a couple Swift packages, implying this is an issue only on AArch64 or some Bionic interaction.

If someone could test LLD 16 on linux AArch64 and report their results, should help narrow this down, may be related to prior LLD issues #58056 or #60456.

@llvmbot
Copy link
Member

llvmbot commented Apr 16, 2023

@llvm/issue-subscribers-lld-elf

@DimitryAndric
Copy link
Collaborator

Can you run the link commands with the option --reproduce=basename_of_tarball added, and then save one of those tarballs if it segfaults? Otherwise it may be difficult or impossible to reproduce such a problem on somebody else's system.

@finagolfin
Copy link
Author

@futurejones, do you think you could try to reproduce with lld 16 on your AArch64 server, by using a script similar to the github Action script I linked but with the official lld 16.0.1 build for linux AArch64?

@DimitryAndric, that just saves the command line and object files used? I doubt it is specific to certain build input, as I see it randomly across various projects when linking, something like a 1-3% failure rate.

@DimitryAndric
Copy link
Collaborator

Well, it is pretty much impossible to fix an issue if it cannot be reproduced reliably. If you are really experiencing totally random crashes, I would first assume your hardware is faulty, but that can usually be tested by e.g. memtest, or running the build on another known-good system.

@finagolfin
Copy link
Author

@DimitryAndric, unlikely to be hardware-related since lld 15 was working well, and I think @xtkoba said he reproduced on other hardware in the linked Termux issue. My guess would be some AArch64-specific codegen issue, which is why I asked for more testing on linux AArch64.

As for tracking it down, I would try running repeatedly on a system where this is happening with a replayable debugger like rr, then try to work back from the segfault to the presumed leak. That is why checking linux AArch64 is important, as much better tools like rr are available there.

@DimitryAndric
Copy link
Collaborator

It is useful to attach a tarball of a crashed instance here, since it might be difficult for somebody else to reproduce your exact build environment, etc. That is usually the trickiest part of finding the cause for bugs.

@finagolfin
Copy link
Author

OK, I will take a look at what that --reproduce flag does, and see if it can be used to reproduce this issue.

@xtkoba
Copy link
Contributor

xtkoba commented Apr 16, 2023

@buttaface Probably you misunderstand something. This has not reproduced for me yet.

@finagolfin
Copy link
Author

I was able to reproduce fairly quickly, when building Swift NIO on my Android AArch64 phone with swift build -Xlinker --reproduce=droid-aarch64.tar, which I then had to gzip for github to accept: droid-aarch64.tar.gz.

If you want to try it out with the same lld 16.0.1 that crashed for me, install the Termux app on an Android device and then run pkg install lld. Of course, a subsequent run worked fine, so you may have to repeat several times to get it to crash again.

@finagolfin
Copy link
Author

Still seeing this with 16.0.2, will try on other Android devices next to rule out the bad hardware possibility mentioned.

@finagolfin
Copy link
Author

I tried the Swift build above on an Android tablet and saw an lld crash on the first run. I then tried it around 15 times on another Android phone, no crash so far, will keep trying to make sure.

No correlation to amount of memory, crashing devices have 6 and 8 GB of RAM, whereas non-crashing phone has 8 GB. Both crashing devices have a Snapdragon 865 CPU, whereas non-crashing has an Exynos chip, chip-specific AArch64 codegen issue?

@finagolfin
Copy link
Author

Now tried it more than two dozen times on the Exynos without a single lld 16.0.2 crash. I'll keep trying, but it looks like this bug might be specific to certain AArch64 CPUs.

@MaskRay
Copy link
Member

MaskRay commented Apr 24, 2023

I was able to reproduce fairly quickly, when building Swift NIO on my Android AArch64 phone with swift build -Xlinker --reproduce=droid-aarch64.tar, which I then had to gzip for github to accept: droid-aarch64.tar.gz.

I have checked a -fsanitize=leak build of lld trunk.

LLD_IN_TEST=1 /tmp/Rel/bin/ld.lld @response.txt links successfully for your droid-aarch64.tar.gz. If you are able to find some issues on some of your AArch64 CPUs, it may indicate a codegen bug on AArch64. Nevertheless, this issue isn't really in lld.

@llvmbot
Copy link
Member

llvmbot commented Apr 24, 2023

@llvm/issue-subscribers-backend-aarch64

@finagolfin
Copy link
Author

@MaskRay, what platform was the lld you used run on? As indicated earlier, I can only reproduce when running lld on some Android AArch64 devices right now, so I mentioned this is likely an AArch64 codegen bug, as lld is built by the patched clang in the Android NDK.

@finagolfin
Copy link
Author

@DanAlbert, does this failure mode ring any bells for you? I just saw your rr pull for Android, rr-debugger/rr#3433, does rr work well for you and does it need higher privileges like root/adb? Maybe I can use rr on Android to track this down.

@DanAlbert
Copy link
Member

DanAlbert commented Apr 24, 2023

rr is nowhere near ready for debugging apps. If all you have is a binary that can run out of /data/local/tmp, you might be able to use it (I genuinely don't know, we've only been testing it for platform use cases so far).

@finagolfin
Copy link
Author

@Sonicadvance1, you appear to be the only person to ever get a commit into this project with Snapdragon in the log message, 045d84f. The Android NDK devs say these chip-specific issues are not their domain, android/ndk#1884.

Any idea how we can get Qualcomm to look into this seeming issue with some of their SoCs?

@smithp35
Copy link
Collaborator

I think it is unlikely to be a particular issue with the SoC. It is more likely to be what features that particular SoC enables.

Does this reproduce at all on a linux aarch64 host, or has that not been tried yet? If we can reproduce outside of an Android phone then this will be much easier to reproduce. Without that I think you may need to add your own trace to LLD and run it on the device to find out where the crash is. Building LLD with debug information may also help as it may end up with a better stack trace when it crashes.

Given the error message sometimes says "Pointer tag for 0xe2a9a7d900000000 was truncated" I expect this is something to do with the information in https://source.android.com/docs/security/test/tagged-pointers this says:

TBI requires a [compatible kernel](https://www.kernel.org/doc/html/latest/arm64/tagged-address-abi.html#id1) that correctly handles tagged pointers passed from userspace. Android Common Kernels from 4.14 (Pixel 4) and higher feature the required [TBI patches](https://android-review.googlesource.com/c/kernel/common/+/1132334/).

Devices with the TBI support in the kernel are dynamically detected at process start time and an implementation-dependent tag is inserted into the top byte of the pointer for all heap allocations. After this, a check is run to ensure the tag hasn't been truncated when deallocating the memory.

It is possible that this only reproduces on a TBI supporting device.

@finagolfin
Copy link
Author

Does this reproduce at all on a linux aarch64 host, or has that not been tried yet?

AFAIK, not been tried, as that is still a rare configuration. Also, it is possible that whatever Snapdragon features that are causing this are not there in AArch64 server CPUs, like the Exynos bug I linked.

Building LLD with debug information may also help as it may end up with a better stack trace when it crashes.

Trying that next, with ASan enabled too, though I'm skeptical of the stack trace showing much because usually the segfault is much downstream of the actual leak.

Given the error message sometimes says "Pointer tag for 0xe2a9a7d900000000 was truncated" I expect this is something to do with the information in https://source.android.com/docs/security/test/tagged-pointers

No, a user just reported the same issue with a Snapdragon 660 device, #62605, running Android 10, and tagged pointers were not added till Android 11, aosp-mirror/platform_bionic@3b21ada, so I don't think that is a factor. More likely that some of these leaks are simply overwriting that Android malloc tag sometimes, so that failsafe is occasionally being triggered.

@Sonicadvance1
Copy link
Contributor

@Sonicadvance1, you appear to be the only person to ever get a commit into this project with Snapdragon in the log message, 045d84f. The Android NDK devs say these chip-specific issues are not their domain, android/ndk#1884.

Any idea how we can get Qualcomm to look into this seeming issue with some of their SoCs?

No idea how to contact QCom, but as said it's unlikely to be a SoC specific issue and more an issue of what features the SoC has. Tagged pointers are fairly new as an example and my devices don't even have that feature in their kernel yet. Probably more.

Alternatively, I don't do any Android development, my commit was done entirely on a Linux device.
Also I'm not yet testing LLVM 16, my distro is only shipping 15 as the latest so unlikely to ever hit this bug yet.

@finagolfin
Copy link
Author

Finally reproduced this with a lld build with debug info and ASan enabled on a Snapdragon 865 phone, got the following output when it failed (excuse the weird formatting):

=================================================================                                                     ==16606==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x0045867b1f88 at pc 0x006186e31cd8 bp 0x00732e673f90 sp 0x00732e673f88                                        READ of size 4 at 0x0045867b1f88 thread T7                     #0 0x6186e31cd4 in size /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:91:32           #1 0x6186e31cd4 in reserveForParamAndGetAddressImpl<llvm::SmallVectorTemplateBase<lld::elf::DynamicReloc, true> > /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:234:28
    #2 0x6186e31cd4 in reserveForParamAndGetAddress /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:534:12                                             #3 0x6186e31cd4 in push_back /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:566:23
    #4 0x6186e31cd4 in addReloc<true> /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.h:560:47
    #5 0x6186e31cd4 in void lld::elf::RelocationBaseSection::addReloc<true>(lld::elf::DynamicReloc::Kind, unsigned int, lld::elf::InputSectionBase&, unsigned long, lld::elf::Symbol&, long, lld::elf::RelExpr, unsigned int) /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.h:530:5                                                             #6 0x6186e3148c in addRelativeReloc<true> /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.h:514:5                                                            #7 0x6186e3148c in void addRelativeReloc<true>(lld::elf::InputSectionBase&, unsigned long, lld::elf::Symbol&, long, lld::elf::RelExpr, unsigned int) /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:867:17
    #8 0x6186e2d2b4 in (anonymous namespace)::RelocationScanner::processAux(lld::elf::RelExpr, unsigned int, unsigned long, lld::elf::Symbol&, long) const /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1094:7             #9 0x6186e3d508 in scanOne<llvm::object::ELFType<llvm::support::little, true>, const llvm::object::Elf_Rel_Impl<llvm::object::ELFType<llvm::support::little, true>, true> > /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1431:3
    #10 0x6186e3d508 in scan<llvm::object::ELFType<llvm::support::little, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<llvm::support::little, true>, true> > /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1488:5
    #11 0x6186e3d508 in void (anonymous namespace)::RelocationScanner::scanSection<llvm::object::ELFType<(llvm::support::endianness)1, true>>(lld::elf::InputSectionBase&) /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1507:5                                                        #12 0x6186e4ce34 in operator() /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1529:28
    #13 0x6186e4ce34 in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1523:15) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1
    #14 0x6186e4ce34 in __call<(lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1523:15) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__functional_base:348:9
    #15 0x6186e4ce34 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1557:16                                           #16 0x6186e4ce34 in std::__ndk1::__function::__func<void lld::elf::scanRelocations<llvm::object::ELFType<(llvm::support::endianness)1, true>>()::'lambda'(), std::__ndk1::allocator<void lld::elf::scanRelocations<llvm::object::ELFType<(llvm::support::endianness)1, true>>()::'lambda'()>, void ()>::operator()() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1731:12
    #17 0x73d332b1d8 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1884:16                                           #18 0x73d332b1d8 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:2556:12
    #19 0x73d332b1d8 in operator() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:177:7          #20 0x73d332b1d8 in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:176:49) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1
    #21 0x73d332b1d8 in __call<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:176:49) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__functional_base:348:9
    #22 0x73d332b1d8 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1557:16
    #23 0x73d332b1d8 in std::__ndk1::__function::__func<llvm::parallel::TaskGroup::spawn(std::__ndk1::function<void ()>)::$_0, std::__ndk1::allocator<llvm::parallel::TaskGroup::spawn(std::__ndk1::function<void ()>)::$_0>, void ()>::operator()() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1731:12
    #24 0x73d3328c18 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1884:16                                           #25 0x73d3328c18 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:2556:12
    #26 0x73d3328c18 in llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::work(llvm::ThreadPoolStrategy, unsigned int) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:117:7
    #27 0x73d3328fe0 in operator() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:36
    #28 0x73d3328fe0 in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1
    #29 0x73d3328fe0 in __thread_execute<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:273:5
    #30 0x73d3328fe0 in void* std::__ndk1::__thread_proxy<std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct>>, llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::ThreadPoolExecutor(llvm::ThreadPoolStrategy)::'lambda'()::operator()() const::'lambda'()>>(void*) /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:284:5
    #31 0x73c99c7298 in __pthread_start(void*) pthread_create.cpp                                                         #32 0x73c9960bdc in __start_thread clone.cpp

0x0045867b1f88 is located 8 bytes to the right of 96-byte region [0x0045867b1f20,0x0045867b1f80)
allocated by thread T0 here:                                   #0 0x73cb17f998 in malloc out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x73d336496c in safe_malloc /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/MemAlloc.h:26:18                                                              #2 0x73d336496c in llvm::SmallVectorBase<unsigned int>::mallocForGrow(void*, unsigned long, unsigned long, unsigned long&) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/SmallVector.cpp:130:19                                #3 0x6186f66c74 in mallocForGrow /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:447:48
    #4 0x6186f66c74 in llvm::SmallVectorTemplateBase<llvm::SmallVector<lld::elf::DynamicReloc, 0u>, false>::growAndAssign(unsigned long, llvm::SmallVector<lld::elf::DynamicReloc, 0u> const&) /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:397:18
    #5 0x6186f1814c in SmallVector /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:1211:11
    #6 0x6186f1814c in RelocationBaseSection /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.cpp:1589:7                                                          #7 0x6186f1814c in lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true>>::RelocationSection(llvm::StringRef, bool, unsigned int) /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.cpp:1678:7
    #8 0x618703b1d4 in make_unique<lld::elf::RelocationSection<llvm::object::ELFType<llvm::support::little, true> >, llvm::StringRef &, bool &, const unsigned int &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:3092:32
    #9 0x618703b1d4 in void lld::elf::createSyntheticSections<llvm::object::ELFType<(llvm::support::endianness)1, true>>() /home/builder/.termux-build/lld-debug/src/lld/ELF/Writer.cpp:357:22
    #10 0x6186be6b68 in lld::elf::LinkerDriver::link(llvm::opt::InputArgList&) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2807:3
    #11 0x6186bc36ac in lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:621:5
    #12 0x6186bc0acc in lld::elf::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:145:19
    #13 0x61869c6294 in lldMain(int, char const**, llvm::raw_ostream&, llvm::raw_ostream&, bool) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:168:12
    #14 0x61869c5144 in lld_main(int, char**) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:230:12
    #15 0x73c99574ec in __libc_init (/apex/com.android.runtime/lib64/bionic/libc.so+0x854ec) (BuildId: 1bcad8bca80d38bceb9089f70d394e33)
    #16 0x61869c44e4 in _start_main crtbegin.c

Thread T7 created by T1 here:                                  #0 0x73cb16faa8 in pthread_create out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:208:3                                                  #1 0x73d332804c in __libcpp_thread_create /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__threading_support:471:10
    #2 0x73d332804c in thread<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30), void> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:300:16
    #3 0x73d332804c in construct<std::__ndk1::thread, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:1921:31                                                       #4 0x73d332804c in __construct<std::__ndk1::thread, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:1784:21
    #5 0x73d332804c in construct<std::__ndk1::thread, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:1605:14
    #6 0x73d332804c in __construct_one_at_end<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/vector:924:5
    #7 0x73d332804c in emplace_back<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/vector:1683:9               #8 0x73d332804c in operator() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:17
    #9 0x73d332804c in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1
    #10 0x73d332804c in __thread_execute<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:273:5              #11 0x73d332804c in void* std::__ndk1::__thread_proxy<std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct>>, llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::ThreadPoolExecutor(llvm::ThreadPoolStrategy)::'lambda'()>>(void*) /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:284:5                                                       #12 0x73c99c7298 in __pthread_start(void*) pthread_create.cpp
    #13 0x73c9960bdc in __start_thread clone.cpp

Thread T1 created by T0 here:
    #0 0x73cb16faa8 in pthread_create out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:208:3                                                  #1 0x73d3326d48 in __libcpp_thread_create /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__threading_support:471:10                        #2 0x73d3326d48 in thread<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:30), void> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:300:16               #3 0x73d3326d48 in ThreadPoolExecutor /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:18                                                              #4 0x73d3326d48 in llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::Creator::call() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:91:38                                                         #5 0x73d33175a0 in llvm::ManagedStaticBase::RegisterManagedStatic(void* (*)(), void (*)(void*)) const /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/ManagedStatic.cpp:34:19                                                    #6 0x73d3325f90 in operator* /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/ManagedStatic.h:89:7                                                            #7 0x73d3325f90 in getDefaultExecutor /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:151:53                                                             #8 0x73d3325f90 in llvm::parallel::TaskGroup::spawn(std::__ndk1::function<void ()>) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:176:5                #9 0x73d3326688 in llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:212:10                                                 #10 0x6186bdfeac in parallelForEach<lld::elf::ELFFileBase **, (lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2605:36)> /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/Parallel.h:234:3        #11 0x6186bdfeac in parallelForEach<llvm::SmallVector<lld::elf::ELFFileBase *, 0U> &, (lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2605:36)> /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/Parallel.h:262:3
    #12 0x6186bdfeac in lld::elf::LinkerDriver::link(llvm::opt::InputArgList&) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2605:3
    #13 0x6186bc36ac in lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:621:5
    #14 0x6186bc0acc in lld::elf::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:145:19
    #15 0x61869c6294 in lldMain(int, char const**, llvm::raw_ostream&, llvm::raw_ostream&, bool) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:168:12              #16 0x61869c5144 in lld_main(int, char**) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:230:12
    #17 0x73c99574ec in __libc_init (/apex/com.android.runtime/lib64/bionic/libc.so+0x854ec) (BuildId: 1bcad8bca80d38bceb9089f70d394e33)                                             #18 0x61869c44e4 in _start_main crtbegin.c
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:91:32 in size                                      Shadow bytes around the buggy address:                       0x0018b0cf63a0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fa fa                                                       0x0018b0cf63b0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fa fa                                                       0x0018b0cf63c0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fa fa
  0x0018b0cf63d0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fa fa
  0x0018b0cf63e0: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0018b0cf63f0: fa[fa]fa fa 00 00 00 00 00 00 00 00 00 fa fa fa
  0x0018b0cf6400: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd                                                       0x0018b0cf6410: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd                                                       0x0018b0cf6420: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd                                                       0x0018b0cf6430: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd                                                       0x0018b0cf6440: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd                                                     Shadow byte legend (one shadow byte represents 8 application bytes):                                                    Addressable:           00                                  Partially addressable: 01 02 03 04 05 06 07                Heap left redzone:       fa                                Freed heap region:       fd                                Stack left redzone:      f1                                Stack mid redzone:       f2                                Stack right redzone:     f3                                Stack after return:      f5                                Stack use after scope:   f8                                Global redzone:          f9                                Global init order:       f6                                Poisoned by user:        f7                                Container overflow:      fc                                Array cookie:            ac                                Intra object redzone:    bb                                ASan internal:           fe                                Left alloca redzone:     ca                                Right alloca redzone:    cb                              ==16606==ABORTING                                          PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.           Aborted

Looks like some kind of race, which would explain why it sporadically occurs with the exact same input. I'm not too familiar with ASan output, so pasting this here in case others can read this much faster and figure it out.

This was on the very first run, then I ran the reproducible response.txt on the object files that I gzipped above about a 100 times before I got essentially the same leak again:

=================================================================
==24663==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x0049959e1ff8 at pc 0x00639605ecd8 bp 0x007820da1f90 sp 0x007820da1f88
READ of size 4 at 0x0049959e1ff8 thread T8
    #0 0x639605ecd4 in size /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:91:32
    #1 0x639605ecd4 in reserveForParamAndGetAddressImpl<llvm::SmallVectorTemplateBase<lld::elf::DynamicReloc, true> > /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:234:28
    #2 0x639605ecd4 in reserveForParamAndGetAddress /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:534:12
    #3 0x639605ecd4 in push_back /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:566:23
    #4 0x639605ecd4 in addReloc<true> /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.h:560:47
    #5 0x639605ecd4 in void lld::elf::RelocationBaseSection::addReloc<true>(lld::elf::DynamicReloc::Kind, unsigned int, lld::elf::InputSectionBase&, unsigned long, lld::elf::Symbol&, long, lld::elf::RelExpr, unsigned int) /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.h:530:5
    #6 0x639605e48c in addRelativeReloc<true> /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.h:514:5
    #7 0x639605e48c in void addRelativeReloc<true>(lld::elf::InputSectionBase&, unsigned long, lld::elf::Symbol&, long, lld::elf::RelExpr, unsigned int) /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:867:17
    #8 0x639605a2b4 in (anonymous namespace)::RelocationScanner::processAux(lld::elf::RelExpr, unsigned int, unsigned long, lld::elf::Symbol&, long) const /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1094:7
    #9 0x639606a508 in scanOne<llvm::object::ELFType<llvm::support::little, true>, const llvm::object::Elf_Rel_Impl<llvm::object::ELFType<llvm::support::little, true>, true> > /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1431:3
    #10 0x639606a508 in scan<llvm::object::ELFType<llvm::support::little, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<llvm::support::little, true>, true> > /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1488:5
    #11 0x639606a508 in void (anonymous namespace)::RelocationScanner::scanSection<llvm::object::ELFType<(llvm::support::endianness)1, true>>(lld::elf::InputSectionBase&) /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1507:5
    #12 0x6396079e34 in operator() /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1529:28
    #13 0x6396079e34 in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1523:15) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1
    #14 0x6396079e34 in __call<(lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Relocations.cpp:1523:15) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__functional_base:348:9
    #15 0x6396079e34 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1557:16
    #16 0x6396079e34 in std::__ndk1::__function::__func<void lld::elf::scanRelocations<llvm::object::ELFType<(llvm::support::endianness)1, true>>()::'lambda'(), std::__ndk1::allocator<void lld::elf::scanRelocations<llvm::object::ELFType<(llvm::support::endianness)1, true>>()::'lambda'()>, void ()>::operator()() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1731:12
    #17 0x78c496d1d8 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1884:16
    #18 0x78c496d1d8 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:2556:12
    #19 0x78c496d1d8 in operator() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:177:7
    #20 0x78c496d1d8 in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:176:49) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1
    #21 0x78c496d1d8 in __call<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:176:49) &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__functional_base:348:9
    #22 0x78c496d1d8 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1557:16
    #23 0x78c496d1d8 in std::__ndk1::__function::__func<llvm::parallel::TaskGroup::spawn(std::__ndk1::function<void ()>)::$_0, std::__ndk1::allocator<llvm::parallel::TaskGroup::spawn(std::__ndk1::function<void ()>)::$_0>, void ()>::operator()() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1731:12
    #24 0x78c496ac18 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:1884:16
    #25 0x78c496ac18 in operator() /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/functional:2556:12
    #26 0x78c496ac18 in llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::work(llvm::ThreadPoolStrategy, unsigned int) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:117:7
    #27 0x78c496afe0 in operator() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:36
    #28 0x78c496afe0 in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1
    #29 0x78c496afe0 in __thread_execute<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:273:5
    #30 0x78c496afe0 in void* std::__ndk1::__thread_proxy<std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct>>, llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::ThreadPoolExecutor(llvm::ThreadPoolStrategy)::'lambda'()::operator()() const::'lambda'()>>(void*) /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:284:5
    #31 0x78d1fa0298 in __pthread_start(void*) pthread_create.cpp
    #32 0x78d1f39bdc in __start_thread clone.cpp

0x0049959e1ff8 is located 8 bytes to the right of 112-byte region [0x0049959e1f80,0x0049959e1ff0)
allocated by thread T0 here:
    #0 0x78d354a998 in malloc out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x78c49a696c in safe_malloc /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/MemAlloc.h:26:18
    #2 0x78c49a696c in llvm::SmallVectorBase<unsigned int>::mallocForGrow(void*, unsigned long, unsigned long, unsigned long&) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/SmallVector.cpp:130:19
    #3 0x6396193c74 in mallocForGrow /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:447:48
    #4 0x6396193c74 in llvm::SmallVectorTemplateBase<llvm::SmallVector<lld::elf::DynamicReloc, 0u>, false>::growAndAssign(unsigned long, llvm::SmallVector<lld::elf::DynamicReloc, 0u> const&) /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:397:18
    #5 0x639614514c in SmallVector /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:1211:11
    #6 0x639614514c in RelocationBaseSection /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.cpp:1589:7
    #7 0x639614514c in lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true>>::RelocationSection(llvm::StringRef, bool, unsigned int) /home/builder/.termux-build/lld-debug/src/lld/ELF/SyntheticSections.cpp:1678:7
    #8 0x63962681d4 in make_unique<lld::elf::RelocationSection<llvm::object::ELFType<llvm::support::little, true> >, llvm::StringRef &, bool &, const unsigned int &> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:3092:32
    #9 0x63962681d4 in void lld::elf::createSyntheticSections<llvm::object::ELFType<(llvm::support::endianness)1, true>>() /home/builder/.termux-build/lld-debug/src/lld/ELF/Writer.cpp:357:22
    #10 0x6395e13b68 in lld::elf::LinkerDriver::link(llvm::opt::InputArgList&) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2807:3
    #11 0x6395df06ac in lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:621:5
    #12 0x6395dedacc in lld::elf::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:145:19                                                     #13 0x6395bf3294 in lldMain(int, char const**, llvm::raw_ostream&, llvm::raw_ostream&, bool) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:168:12
    #14 0x6395bf2144 in lld_main(int, char**) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:230:12      #15 0x78d1f304ec in __libc_init (/apex/com.android.runtime/lib64/bionic/libc.so+0x854ec) (BuildId: 1bcad8bca80d38bceb9089f70d394e33)
    #16 0x6395bf14e4 in _start_main crtbegin.c

Thread T8 created by T1 here:
    #0 0x78d353aaa8 in pthread_create out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:208:3
    #1 0x78c496a04c in __libcpp_thread_create /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__threading_support:471:10
    #2 0x78c496a04c in thread<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30), void> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:300:16
    #3 0x78c496a04c in construct<std::__ndk1::thread, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:1921:31
    #4 0x78c496a04c in __construct<std::__ndk1::thread, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:1784:21                                                     #5 0x78c496a04c in construct<std::__ndk1::thread, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/memory:1605:14
    #6 0x78c496a04c in __construct_one_at_end<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/vector:924:5
    #7 0x78c496a04c in emplace_back<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/vector:1683:9
    #8 0x78c496a04c in operator() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:60:17
    #9 0x78c496a04c in __invoke<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/type_traits:3874:1              #10 0x78c496a04c in __thread_execute<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, (lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:30)> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:273:5
    #11 0x78c496a04c in void* std::__ndk1::__thread_proxy<std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct>>, llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::ThreadPoolExecutor(llvm::ThreadPoolStrategy)::'lambda'()>>(void*) /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:284:5
    #12 0x78d1fa0298 in __pthread_start(void*) pthread_create.cpp
    #13 0x78d1f39bdc in __start_thread clone.cpp

Thread T1 created by T0 here:
    #0 0x78d353aaa8 in pthread_create out/lib/compiler-rt-aarch64/out/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:208:3
    #1 0x78c4968d48 in __libcpp_thread_create /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/__threading_support:471:10
    #2 0x78c4968d48 in thread<(lambda at /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:30), void> /home/builder/.termux-build/_cache/android-r25c-api-24-v2/sysroot/usr/include/c++/v1/thread:300:16
    #3 0x78c4968d48 in ThreadPoolExecutor /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:58:18
    #4 0x78c4968d48 in llvm::parallel::detail::(anonymous namespace)::ThreadPoolExecutor::Creator::call() /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:91:38                                                         #5 0x78c49595a0 in llvm::ManagedStaticBase::RegisterManagedStatic(void* (*)(), void (*)(void*)) const /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/ManagedStatic.cpp:34:19
    #6 0x78c4967f90 in operator* /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/ManagedStatic.h:89:7
    #7 0x78c4967f90 in getDefaultExecutor /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:151:53
    #8 0x78c4967f90 in llvm::parallel::TaskGroup::spawn(std::__ndk1::function<void ()>) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:176:5
    #9 0x78c4968688 in llvm::parallelFor(unsigned long, unsigned long, llvm::function_ref<void (unsigned long)>) /home/builder/.termux-build/lld-debug/src/llvm/lib/Support/Parallel.cpp:212:10
    #10 0x6395e0ceac in parallelForEach<lld::elf::ELFFileBase **, (lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2605:36)> /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/Parallel.h:234:3        #11 0x6395e0ceac in parallelForEach<llvm::SmallVector<lld::elf::ELFFileBase *, 0U> &, (lambda at /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2605:36)> /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/Support/Parallel.h:262:3
    #12 0x6395e0ceac in lld::elf::LinkerDriver::link(llvm::opt::InputArgList&) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:2605:3                                   #13 0x6395df06ac in lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:621:5
    #14 0x6395dedacc in lld::elf::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) /home/builder/.termux-build/lld-debug/src/lld/ELF/Driver.cpp:145:19                                                     #15 0x6395bf3294 in lldMain(int, char const**, llvm::raw_ostream&, llvm::raw_ostream&, bool) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:168:12
    #16 0x6395bf2144 in lld_main(int, char**) /home/builder/.termux-build/lld-debug/src/lld/tools/lld/lld.cpp:230:12      #17 0x78d1f304ec in __libc_init (/apex/com.android.runtime/lib64/bionic/libc.so+0x854ec) (BuildId: 1bcad8bca80d38bceb9089f70d394e33)
    #18 0x6395bf14e4 in _start_main crtbegin.c

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/builder/.termux-build/lld-debug/src/llvm/include/llvm/ADT/SmallVector.h:91:32 in size
Shadow bytes around the buggy address:
  0x001932b3c3a0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x001932b3c3b0: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
  0x001932b3c3c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd                                                       0x001932b3c3d0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd                                                       0x001932b3c3e0: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
=>0x001932b3c3f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa[fa]
  0x001932b3c400: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd                                                       0x001932b3c410: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
  0x001932b3c420: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x001932b3c430: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x001932b3c440: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa                                Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5                                Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6                                Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca                                Right alloca redzone:    cb
==24663==ABORTING                                          PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Aborted

Maybe a good sign that this is repeatable, though only about 2% of the time. I'll try it on some more devices next.

If you want to reproduce, install the Termux app on a Snapdragon device, get the AArch64 lld debug zip file here, and run the following commands:

pkg install lld unzip tar wget
unzip debs-aarch64-2d6083d812126e45e8336891bcbca7bbb3b975cf.zip
tar xf debs-aarch64-2d6083d812126e45e8336891bcbca7bbb3b975cf.tar
dpkg -i debs/lld-debug_16.0.4_aarch64.deb

wget https://github.com/llvm/llvm-project/files/11244684/droid-aarch64.tar.gz
tar xf droid-aarch64.tar.gz
cd droid-aarch64/

for i in {1..100}
do
ld.lld @response.txt
done

@xtkoba, would you try this on your Snapdragon device and let me know what you find?

@finagolfin
Copy link
Author

I ran the same procedure on an Android tablet with a Snapdragon 865+ and was able to reproduce quickly and multiple times. Then I tried on a phone with an Exynos 2100 more than a thousand times, without a single failure.

Clearly there is some difference on various CPUs, whether hardware features or maybe even the variance in speed of the big.little cores.

@smithp35
Copy link
Collaborator

The change to run relocation scanning in parallel is https://reviews.llvm.org/D133003 IIUC the relocations are expected to be added in per-thread relocation vectors and then merged. I can remember one issue was found https://reviews.llvm.org/D142317 but this was merged for the 16.0.0 release #60338.

To experiment with the race condition theory, could be worth trying to reproduce with --threads=1, or if you are rebuilding LLD from scratch, serialise the relocation scanning as it is done for Mips and PPC

bool serial = !config->zCombreloc || config->emachine == EM_MIPS ||
                config->emachine == EM_PPC64;

If it is as simple as LLD writing to a shared location I would expect it to reproduce on other platforms though. If my websearch of the Exynos and SnapDragon SoCs is correct then Exynos is based on a Cortex-X1 and the SnapDragon is based an A77, both of which are architecturally (not-microarchitecturally) the same.

@finagolfin
Copy link
Author

Thanks for all the relevant info, @smithp35, adding --threads=1 appears to work around the problem: no more leaks after 500+ invocations with that flag added.

I will try patching the source as you suggested, and see if that works around this problem in the Termux app.

@finagolfin
Copy link
Author

I could not reproduce after forcing that lld code to run serially, so I have pushed @smithp35's suggestion as a workaround in the Termux app, termux/termux-packages@e4dd29c.

Another Termux dev tried to reproduce with the debug build and sees this same issue on several Snapdragon devices, some more testing should determine if this is Qualcomm-specific.

@stephenhines
Copy link
Collaborator

stephenhines commented May 22, 2023

@finagolfin Are you actually using the sources for LLVM 16 or just taking the version number from somewhere in Android? Android versions aren't always the official LLVM release versions. In this case, I do see that https://reviews.llvm.org/D142317 is in the upcoming r26 compiler, but it wouldn't be in any r25 compiler (but I also don't know how you would have the parallelization patch in an r25 toolchain either, since that patch only landed in upstream in September).

@finagolfin
Copy link
Author

@stephenhines, as I explained in more detail in the NDK issue I subsequently opened, this is indeed a lightly patched LLVM 16.0.4 running on Android Snapdragon devices, after cross-compiling it with a NDK 25c toolchain from linux x86_64 with a lightly patched sysroot. Since the lld 16.0.4 I'm building on linux and running on Android has that patch you linked, I don't think it is that issue, though it may be related to some of the other issues raised in that review thread.

I have now turned off that parallelized code in lld 16.0.4 and I no longer see any segfaults when running it on Android, so the issue is clearly in that multi-threading, perhaps interacting with some Snapdragon hardware bug.

@finagolfin finagolfin changed the title lld 16 appears to have memory leaks on Android AArch64 lld 16 appears to have a threading-related memory leak on some Android AArch64 devices May 25, 2023
@finagolfin
Copy link
Author

An update: after disabling threading in lld, I no longer see this crash with the reproducer I provided, but I still see an occasional rare crash when using lld 16.0.5 to link some random project. So this bug is clearly not isolated to threading alone, but now the crashes are much more rare, ie less than 0.1%.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants