Potential LLVM / Linking issue on 32bit Android

There is a recurring bug on 32bit Android (armv7a) whereby s-c-f builds crash at runtime with a bus / alignment error:

libc    (11789): Fatal signal 7 (SIGBUS), code 1, fault addr 0xcc7a8e74 in tid 11789 (flowkey.testapp), pid 11789 (flowkey.testapp)
DEBUG   (11929): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
DEBUG   (11929): Build fingerprint: 'samsung/gtaxlwifixx/gtaxlwifi:8.1.0/M1AJQ/T580XXU4CRK5:user/release-keys'
DEBUG   (11929): Revision: '6'
DEBUG   (11929): ABI: 'arm'
DEBUG   (11929): pid: 11789, tid: 11789, name: flowkey.testapp  >>> com.flowkey.testapp <<<
DEBUG   (11929): signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr 0xcc7a8e74
DEBUG   (11929):     r0 00000000  r1 cc7a8e74  r2 cc77ec08  r3 00000019
DEBUG   (11929):     r4 cc7a8e6c  r5 e2069860  r6 cc788448  r7 ff816540
DEBUG   (11929):     r8 00000019  r9 00000000  sl 00000000  fp cc7a8e6c
DEBUG   (11929):     ip cc7abbac  sp ff816138  lr cc1e05af  pc cc1e05c6  cpsr 600d0030
DEBUG   (11929): 
DEBUG   (11929): backtrace:
DEBUG   (11929):     #00 pc 005895c6  /data/app/com.flowkey.testapp/lib/arm/libFoundation.so (CFStringFindWithOptionsAndLocale+61)
DEBUG   (11929):     #01 pc 0058ebff  /data/app/com.flowkey.testapp/lib/arm/libFoundation.so (CFStringHasPrefix+142)
DEBUG   (11929):     #02 pc 005a8777  /data/app/com.flowkey.testapp/lib/arm/libFoundation.so
DEBUG   (11929):     #03 pc 005a870d  /data/app/com.flowkey.testapp/lib/arm/libFoundation.so (CFURLCreateWithFileSystemPath+14)
DEBUG   (11929):     #04 pc 0055b50f  /data/app/com.flowkey.testapp/lib/arm/libFoundation.so (CFBundleGetMainBundle+70)
DEBUG   (11929):     #05 pc 001e63e4  /data/app/com.flowkey.testapp/lib/arm/libFoundation.so
DEBUG   (11929):     #06 pc 000621dd  /data/app/com.flowkey.testapp/lib/arm/libc++_shared.so (std::__ndk1::__call_once(unsigned long volatile&, void*, void (*)(void*))+84)
DEBUG   (11929):     #07 pc 00410b15  /data/app/com.flowkey.testapp/lib/arm/libswiftCore.so (swift_once+44)
DEBUG   (11929):     #08 pc 001e64e8  /data/app/com.flowkey.testapp/lib/arm/libFoundation.so ($s10Foundation6BundleC4mainACvgZ+24)

I tracked this down to an access of the builtin FILE_ID_PREAMBLE macro in _pathHasFileIDPrefix, which may or may not be implemented as a static const (my C skills are intermediate at best so bear with me):

static Boolean _pathHasFileIDPrefix(CFStringRef path)
{
    // path is not NULL, path has prefix "/.file/id=".
#if defined(__CONSTANT_CFSTRINGS__) && !DEPLOYMENT_RUNTIME_SWIFT // see rdar://44356272 — the implementation of CFSTR() in Swift is not constexpr, but the compiler will miscompile it and allow it to be assigned to static variables anyway.
    static const 
#endif
    CFStringRef fileIDPreamble = CFSTR(FILE_ID_PREAMBLE);
    return ( path && CFStringHasPrefix(path, fileIDPreamble) );
}

For some reason this access ends up being misaligned in CFStringHasPrefix leading to the above crash. Looking at the libFoundation.so binary, I can see the entire CFString section has an alignment of 4 (2**2) and, in cases where it crashes, the DATA section appears to be misaligned:

33 cfstring      00006018  00b4c46c  00b4c46c  00b4b46c  2**2
                  CONTENTS, ALLOC, LOAD, DATA

The data section from which the constant string is being read (source verified via cat /proc/<pid>/maps) needs to have an alignment of 8 to work on Android, but currently – seemingly randomly – is moving between aligned and not aligned depending on the build (sometimes the 4-alignment of the data section happens to be divisible by 8, sometimes – as again in this build – it is not).

In collaboration with @compnerd on this issue, he created https://github.com/apple/swift-corelibs-foundation/pull/2427 in the hope that it'd fix this issue. Unfortunately, the few builds in the meantime that worked seem to have been a coincidence.

Does anyone have an idea of how to fix this issue "for good"? I'm about the equivalent of the Mariana's Trench out of my depth here and need some more help from LLVM / linker gurus (beyond @compnerd, who has enough on his plate) to get this on the road again.

FWIW this is being linked with gold from NDK 16b. Also, 64bit builds do not have an issue.

Is CFString being laid correctly by the compiler in this configuration? This is generally the first constant string an app uses, which can be a canary crash for issues with constant CFStrings not being correctly set up by the compiler.

We switched to letting clang layout constant strings in 4.2 (accounting for s-c-f's layout differences via -fcf-runtime-abi=…).

(At the very least, the compiler may need to be patched to conform to the new alignment setup. @compnerd)

Terms of Service

Privacy Policy

Cookie Policy