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.
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 releaseon armv7 (on the Raspberry Pi), I get a segfault with an address boundary error. Backtrace from gdbI 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 usesIntandRangewhich we have seen that doesn't quite work correctly on 32-bit platforms:swift-profile-recorder/Sources/ProfileRecorderSampleConversion/NativeELFSymboliser/ImageSource.swift
Lines 363 to 372 in 21fd9ae
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.