Skip to content

Commit 5367421

Browse files
authored
Merge pull request #69508 from al45tair/eng/PR-117590155
[Linux] Improve backtracer ELF/DWARF parsing performance.
2 parents 78adeb6 + 330085e commit 5367421

File tree

2 files changed

+30
-21
lines changed

2 files changed

+30
-21
lines changed

stdlib/public/Backtracing/FileImageSource.swift

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,56 @@ import Swift
2020

2121
enum FileImageSourceError: Error {
2222
case posixError(Int32)
23-
case truncatedRead
23+
case outOfRangeRead
2424
}
2525

2626
class FileImageSource: ImageSource {
27-
private var fd: Int32
27+
private var _mapping: UnsafeRawBufferPointer
2828

2929
public var isMappedImage: Bool { return false }
3030

3131
private var _path: String
3232
public var path: String? { return _path }
3333

34-
public lazy var bounds: Bounds? = {
35-
let size = lseek(fd, 0, SEEK_END)
36-
if size < 0 {
37-
return nil
38-
}
39-
return Bounds(base: 0, size: Size(size))
40-
}()
34+
public var bounds: Bounds? {
35+
return Bounds(base: 0, size: Size(_mapping.count))
36+
}
4137

4238
public init(path: String) throws {
4339
_path = path
44-
fd = _swift_open(path, O_RDONLY, 0)
40+
let fd = _swift_open(path, O_RDONLY, 0)
4541
if fd < 0 {
4642
throw FileImageSourceError.posixError(_swift_get_errno())
4743
}
44+
defer { close(fd) }
45+
let size = lseek(fd, 0, SEEK_END)
46+
if size < 0 {
47+
throw FileImageSourceError.posixError(_swift_get_errno())
48+
}
49+
let base = mmap(nil, Int(size), PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0)
50+
if base == nil || base! == UnsafeRawPointer(bitPattern: -1)! {
51+
throw FileImageSourceError.posixError(_swift_get_errno())
52+
}
53+
_mapping = UnsafeRawBufferPointer(start: base, count: Int(size))
4854
}
4955

5056
deinit {
51-
close(fd)
57+
munmap(UnsafeMutableRawPointer(mutating: _mapping.baseAddress),
58+
_mapping.count)
5259
}
5360

5461
public func fetch<T>(from addr: Address,
5562
into buffer: UnsafeMutableBufferPointer<T>) throws {
56-
while true {
57-
let size = MemoryLayout<T>.stride * buffer.count
58-
let result = pread(fd, buffer.baseAddress, size, off_t(addr))
59-
60-
if result < 0 {
61-
throw FileImageSourceError.posixError(_swift_get_errno())
63+
let start = Int(addr)
64+
_ = try buffer.withMemoryRebound(to: UInt8.self) { byteBuf in
65+
guard _mapping.indices.contains(start) else {
66+
throw FileImageSourceError.outOfRangeRead
6267
}
63-
64-
if result != size {
65-
throw FileImageSourceError.truncatedRead
68+
let slice = _mapping[start...]
69+
guard slice.count >= byteBuf.count else {
70+
throw FileImageSourceError.outOfRangeRead
6671
}
67-
break
72+
byteBuf.update(from: slice)
6873
}
6974
}
7075
}

stdlib/public/Backtracing/modules/OS/Libc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include <sys/types.h>
2222
#include <sys/stat.h>
2323

24+
#if __has_include(<sys/mman.h>)
25+
#include <sys/mman.h>
26+
#endif
27+
2428
#if __has_include(<dlfcn.h>)
2529
#include <dlfcn.h>
2630
#endif

0 commit comments

Comments
 (0)