Skip to content

Address boundary error crash when profiling release builds on 32-bit arm #58

@jessezamora

Description

@jessezamora

This is something I did not notice before since I was only profiling debug apps. But, it seems that whenever I try to profile an app built with -c release on armv7 (on the Raspberry Pi), I get a segfault with an address boundary error. Backtrace from gdb

Thread 9 "SGLTN-TP-#0" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xae4ff300 (LWP 2510)]
0xb6d8c4c4 in bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) () from /usr/lib/swift/linux/libswiftCore.so
(gdb) bt
#0  0xb6d8c4c4 in bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) () from /usr/lib/swift/linux/libswiftCore.so
#1  0x00da1894 in generic specialization <_ProfileRecorderSampleConversion.Elf32Traits> of _ProfileRecorderSampleConversion.ElfImage.uuid.getter : [Swift.UInt8]? (self=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/NativeELFSymboliser/Elf.swift:1293
#2  0x00da25e0 in generic specialization <_ProfileRecorderSampleConversion.Elf32Traits> of _ProfileRecorderSampleConversion.ElfImage.debugImage.getter : _ProfileRecorderSampleConversion.ElfImage<A>? (self=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/NativeELFSymboliser/Elf.swift:1535
#3  0x00dc33a4 in generic specialization <_ProfileRecorderSampleConversion.Elf32Traits> of _ProfileRecorderSampleConversion.ElfImage._getSymbolTable(debug: Swift.Bool) -> _ProfileRecorderSampleConversion.ElfSymbolTable<A> (
    debug=..., self=...)
    at .build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/NativeELFSymboliser/Elf.swift:1715
#4  0x00dc34a0 in generic specialization <_ProfileRecorderSampleConversion.Elf32Traits> of _ProfileRecorderSampleConversion.ElfImage.symbolTable.getter : _ProfileRecorderSampleConversion.ElfSymbolTable<A> (self=...)
    at .build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/NativeELFSymboliser/Elf.swift:1707
#5  generic specialization <_ProfileRecorderSampleConversion.Elf32Traits> of _ProfileRecorderSampleConversion.ElfImage.lookupSymbol(address: A.Address) -> _ProfileRecorderSampleConversion.ImageSymbol? (address=...,
    self=...)
    at .build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/NativeELFSymboliser/Elf.swift:1745
#6  0x00dc4510 in _ProfileRecorderSampleConversion.AnyElfImage.lookupRealAndInlinedFrames(address: Swift.UInt64, logger: Logging.Logger) -> [_ProfileRecorderSampleConversion.ImageSymbol]? (address=..., logger=..., self=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:85
#7  0x00dc565c in closure #1 (inout [Swift.String : _ProfileRecorderSampleConversion.AnyElfImage]) -> Swift.Result<[_ProfileRecorderSampleConversion.ImageSymbol], _ProfileRecorderSampleConversion.LockedELFSourceCacheReference.Error> in _ProfileRecorderSampleConversion.LockedELFSourceCacheReference.lookup(library: _ProfileRecorderSampleConversion.DynamicLibMapping, fileVirtualAddressIP: Swift.UInt, logger: Logging.Logger) -> Swift.Result<[_ProfileRecorderSampleConversion.ImageSymbol], _ProfileRecorderSampleConversion.LockedELFSourceCacheReference.Error> ()
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:180
#8  0x00dce6d4 in generic specialization <[Swift.String : _ProfileRecorderSampleConversion.AnyElfImage], Swift.Result<[_ProfileRecorderSampleConversion.ImageSymbol], _ProfileRecorderSampleConversion.LockedELFSourceCacheReference.Error>> of NIOConcurrencyHelpers.NIOLockedValueBox.withLockedValue<A>((inout A) throws -> A1) throws -> A1 ()
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:221
#9  _ProfileRecorderSampleConversion.LockedELFSourceCacheReference.lookup(library: _ProfileRecorderSampleConversion.DynamicLibMapping, fileVirtualAddressIP: Swift.UInt, logger: Logging.Logger) -> Swift.Result<[_ProfileRecorderSampleConversion.ImageSymbol], _ProfileRecorderSampleConversion.LockedELFSourceCacheReference.Error> (library=..., fileVirtualAddressIP=..., logger=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:161
#10 _ProfileRecorderSampleConversion.NativeELFSymboliser.symbolise(fileVirtualAddressIP: Swift.UInt, library: _ProfileRecorderSampleConversion.DynamicLibMapping, logger: Logging.Logger) throws -> _ProfileRecorderSampleConversion.SymbolisedStackFrame (fileVirtualAddressIP=..., library=..., logger=..., self=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:221
#11 0x00dc587c in protocol witness for _ProfileRecorderSampleConversion.Symbolizer.symbolise(fileVirtualAddressIP: Swift.UInt, library: _ProfileRecorderSampleConversion.DynamicLibMapping, logger: Logging.Logger) throws -> _ProfileRecorderSampleConversion.SymbolisedStackFrame in conformance _ProfileRecorderSampleConversion.NativeELFSymboliser : _ProfileRecorderSampleConversion.Symbolizer in _ProfileRecorderSampleConversion ()
    at .build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/NativeELFSymboliser/ImageSource.swift:307
#12 0x00dc6560 in $s32_ProfileRecorderSampleConversion16CachedSymbolizerC13symboliseSlow33_744F1F21567DDA886DC65B10473A954CLLyAA20S--Type <RET> for more, q to quit, c to continue without paging--
ymbolisedStackFrameVAA0pQ0VKF (stackFrame=..., self=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:396
#13 0x00dadf5c in generic specialization <_ProfileRecorderSampleConversion.CachedSymbolizer.(State in _744F1F21567DDA886DC65B10473A954C), _ProfileRecorderSampleConversion.SymbolisedStackFrame> of NIOConcurrencyHelpers.NIOLockedValueBox.withLockedValue<A>((inout A) throws -> A1) throws -> A1 ()
    at .build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:413
#14 _ProfileRecorderSampleConversion.CachedSymbolizer.symbolise(_ProfileRecorderSampleConversion.StackFrame) throws -> _ProfileRecorderSampleConversion.SymbolisedStackFrame (stackFrame=...,
    self=...) at .build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/Symboliser.swift:404
#15 function signature specialization <Arg[3] = Dead> of _ProfileRecorderSampleConversion.PerfScriptOutputRenderer.consumeSingleSample(_: _ProfileRecorderSampleConversion.Sample, configuration: _ProfileRecorderSampleConversion.ProfileRecorderSampleConversionConfiguration, symbolizer: _ProfileRecorderSampleConversion.CachedSymbolizer) throws -> NIOCore.ByteBuffer (sample=..., configuration=..., symbolizer=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/OutputFormatRendering/PerfScript.swift:47
#16 0x00dad808 in _ProfileRecorderSampleConversion.PerfScriptOutputRenderer.consumeSingleSample(_: _ProfileRecorderSampleConversion.Sample, configuration: _ProfileRecorderSampleConversion.ProfileRecorderSampleConversionConfiguration, symbolizer: _ProfileRecorderSampleConversion.CachedSymbolizer) throws -> NIOCore.ByteBuffer ()
#17 protocol witness for _ProfileRecorderSampleConversion.ProfileRecorderSampleConversionOutputRenderer.consumeSingleSample(_: _ProfileRecorderSampleConversion.Sample, configuration: _ProfileRecorderSampleConversion.ProfileRecorderSampleConversionConfiguration, symbolizer: _ProfileRecorderSampleConversion.CachedSymbolizer) throws -> NIOCore.ByteBuffer in conformance _ProfileRecorderSampleConversion.PerfScriptOutputRenderer : _ProfileRecorderSampleConversion.ProfileRecorderSampleConversionOutputRenderer in _ProfileRecorderSampleConversion () at //<compiler-generated>:29
#18 0x00db73e8 in function signature specialization <Arg[3] = Dead> of _ProfileRecorderSampleConversion.ProfileRecorderSampleConverter.convertSync(inputRawProfileRecorderFormatPath: Swift.String, outputPath: Swift.String, underlyingSymbolizer: _ProfileRecorderSampleConversion.Symbolizer, format: _ProfileRecorderSampleConversion.ProfileRecorderOutputFormat, logger: Logging.Logger) throws -> () (fromPath=..., toPath=...,
    underlyingSymbolizer=..., logger=..., self=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/ProfileRecorderSampleConverter.swift:339
#19 0x00db3ad4 in closure #1 @Sendable () throws -> () in _ProfileRecorderSampleConversion.ProfileRecorderSampleConverter.convert(inputRawProfileRecorderFormatPath: Swift.String, outputPath: Swift.String, format: _ProfileRecorderSampleConversion.ProfileRecorderOutputFormat, logger: Logging.Logger) async throws -> () ()
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-profile-recorder/Sources/ProfileRecorderSampleConversion/ProfileRecorderSampleConverter.swift:109
#20 0x00dc1390 in partial apply forwarder for closure #1 @Sendable () throws -> () in _ProfileRecorderSampleConversion.ProfileRecorderSampleConverter.convert(inputRawProfileRecorderFormatPath: Swift.String, outputPath: Swift.String, format: _ProfileRecorderSampleConversion.ProfileRecorderOutputFormat, logger: Logging.Logger) async throws -> () ()
#21 0x00ad73d4 in partial apply forwarder for reabstraction thunk helper <A where A: Swift.Sendable> from @callee_guaranteed () -> (@out A, @error @owned Swift.Error) to @escaping @callee_guaranteed () -> (@out A, @error @out Swift.Error) ()
    at /home/usjz/.swiftpm/swift-sdks/6.2.1-RELEASE_ubuntu_jammy_armv7.artifactbundle/6.2.1-RELEASE_ubuntu_jammy_armv7/armv7-unknown-linux-gnueabihf/ubuntu-jammy.sdk/usr/lib/swift/shims/LibcShims.h:115
#22 0x00992044 in (extension in Swift):Swift.Result< where A: ~Swift.Copyable>.init(catching: () throws(B) -> A) -> Swift.Result<A, B> ()
    at .build-armv7/checkouts/swift-nio/Sources/NIOCore/EventLoopFuture.swift:846
#23 0x00ad4ff0 in closure #1 @Sendable (NIOPosix.NIOThreadPool.WorkItemState) -> () in closure #1 (Swift.CheckedContinuation<A, Swift.Error>) -> () in closure #1 () async throws -> A in NIOPosix.NIOThreadPool.runIfActive<A where A: Swift.Sendable>(@Sendable () throws -> A) async throws -> A () at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-nio/Sources/NIOPosix/NIOThreadPool.swift:464
#24 0x00ad7358 in partial apply forwarder for closure #1 @Sendable (NIOPosix.NIOThreadPool.WorkItemState) -> () in closure #1 (Swift.CheckedContinuation<A, Swift.Error>) -> () in closure #1 () async throws -> A in NIOPosix.NIOThreadPool.runIfActive<A where A: Swift.Sendable>(@Sendable () throws -> A) async throws -> A ()
    at /home/usjz/.swiftpm/swift-sdks/6.2.1-RELEASE_ubuntu_jammy_armv7.artifactbundle/6.2.1-RELEASE_ubuntu_jammy_armv7/armv7-unknown-linux-gnueabihf/ubuntu-jammy.sdk/usr/lib/swift/shims/LibcShims.h:115
#25 0x00ad2f0c in NIOPosix.NIOThreadPool.(process in _00E958AC1B6B1B72652610CF9E41E193)(identifier: Swift.Int) -> () (identifier=...,
    self=...)
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-nio/Sources/NIOPosix/NIOThreadPool.swift:541
--Type <RET> for more, q to quit, c to continue without paging--
#26 0x00ad320c in closure #2 (NIOPosix.NIOThread) -> () in NIOPosix.NIOThreadPool._start(threadNamePrefix: Swift.String) -> () ()
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-nio/Sources/NIOPosix/NIOThreadPool.swift:381
#27 0x00ad594c in partial apply forwarder for reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed NIOPosix.NIOThread) -> () to @escaping @callee_guaranteed (@in_guaranteed NIOPosix.NIOThread) -> (@out ()) ()
    at /home/usjz/.swiftpm/swift-sdks/6.2.1-RELEASE_ubuntu_jammy_armv7.artifactbundle/6.2.1-RELEASE_ubuntu_jammy_armv7/armv7-unknown-linux-gnueabihf/ubuntu-jammy.sdk/usr/lib/swift/shims/LibcShims.h:115
#28 0x00b316c8 in closure #1 (Swift.UnsafeMutableRawPointer?) -> Swift.UnsafeMutableRawPointer? in closure #1 (Swift.UnsafeMutablePointer<Swift.UInt?>) -> Swift.Int32 in static NIOPosix.ThreadOpsPosix.run(handle: inout NIOPosix.PthreadWrapper?, args: NIOPosix.Box<(body: (NIOPosix.NIOThread) -> (), name: Swift.String?)>) -> () ()
    at /home/usjz/tmp/hummingbird-examples/hello/.build-armv7/checkouts/swift-nio/Sources/NIOPosix/ThreadPosix.swift:172
#29 0xb4e4bb74 in start_thread (arg=0x79eec5c7) at pthread_create.c:442
#30 0xb4ea1ef0 in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:74 from /lib/arm-linux-gnueabihf/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

I did a little bit more investigation, and looks like there's a problem with the vendored ImageSource.fetch() method on 32-bits. The code already uses Int and Range which we have seen that doesn't quite work correctly on 32-bit platforms:

public func fetch(from address: Address,
into buffer: UnsafeMutableRawBufferPointer) throws {
let offset = Int(address)
guard bytes.count >= buffer.count &&
offset <= bytes.count - buffer.count else {
throw ImageSourceError.outOfBoundsRead
}
buffer.copyMemory(from: UnsafeRawBufferPointer(
rebasing: bytes[offset..<offset + buffer.count]))
}

But, interestingly enough it works fine in debug mode while crashing in release. I tried adding @_optimize(none) to it and it runs just fine on my release app on the Rasbperry Pi 3+ / armhf.

The fix would be in the upstream vendored code, but I wanted to note this as an issue here so it can be tracked against the swift-profile-recorder. Maybe there are some ideas on how to deal with this as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions