Skip to content

Commit 76f2351

Browse files
authored
Merge pull request #82624 from al45tair/eng/PR-154282813
[Backtracing][Linux] Fix crash handler for musl.
2 parents da3d9f3 + b498b39 commit 76f2351

File tree

3 files changed

+55
-17
lines changed

3 files changed

+55
-17
lines changed

stdlib/public/RuntimeModule/Elf.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,8 +1064,8 @@ struct ElfSymbolTable<SomeElfTraits: ElfTraits>: ElfSymbolTableProtocol {
10641064
continue
10651065
}
10661066

1067-
// Ignore anything undefined
1068-
if symbol.st_shndx == SHN_UNDEF {
1067+
// Ignore anything undefined or absolute
1068+
if symbol.st_shndx == SHN_UNDEF || symbol.st_shndx == SHN_ABS {
10691069
continue
10701070
}
10711071

@@ -1190,6 +1190,8 @@ final class ElfImage<SomeElfTraits: ElfTraits>
11901190
var sectionHeaders: [Traits.Shdr]?
11911191
var shouldByteSwap: Bool { return header.shouldByteSwap }
11921192

1193+
var imageBase: ImageSource.Address
1194+
11931195
@_specialize(kind: full, where SomeElfTraits == Elf32Traits)
11941196
@_specialize(kind: full, where SomeElfTraits == Elf64Traits)
11951197
required init(source: ImageSource,
@@ -1222,11 +1224,21 @@ final class ElfImage<SomeElfTraits: ElfTraits>
12221224

12231225
var phdrs: [Traits.Phdr] = []
12241226
var phAddr = ImageSource.Address(header.e_phoff)
1227+
var minAddr: Traits.Address? = nil
12251228
for _ in 0..<header.e_phnum {
12261229
let phdr = maybeSwap(try source.fetch(from: phAddr, as: Traits.Phdr.self))
12271230
phdrs.append(phdr)
12281231
phAddr += ImageSource.Address(header.e_phentsize)
1232+
1233+
if phdr.p_type == .PT_LOAD {
1234+
if let oldMinAddr = minAddr {
1235+
minAddr = min(oldMinAddr, phdr.p_vaddr)
1236+
} else {
1237+
minAddr = phdr.p_vaddr
1238+
}
1239+
}
12291240
}
1241+
imageBase = ImageSource.Address(exactly: minAddr ?? 0)!
12301242
programHeaders = phdrs
12311243

12321244
if source.isMappedImage {

stdlib/public/RuntimeModule/SymbolicatedBacktrace.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,6 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
466466
for frame in backtrace.frames {
467467
let address = frame.adjustedProgramCounter
468468
if let imageNdx = theImages.indexOfImage(at: address) {
469-
let relativeAddress = ImageSource.Address(
470-
address - theImages[imageNdx].baseAddress
471-
)
472469
let name = theImages[imageNdx].name ?? "<unknown>"
473470
var symbol: Symbol = Symbol(imageIndex: imageNdx,
474471
imageName: name,
@@ -527,13 +524,19 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
527524
if let hit = cache.lookup(path: theImages[imageNdx].path) {
528525
switch hit {
529526
case let .elf32Image(image):
527+
let relativeAddress = ImageSource.Address(
528+
address - theImages[imageNdx].baseAddress
529+
) + image.imageBase
530530
if let theSymbol = lookupSymbol(image: image,
531531
at: imageNdx,
532532
named: name,
533533
address: relativeAddress) {
534534
symbol = theSymbol
535535
}
536536
case let .elf64Image(image):
537+
let relativeAddress = ImageSource.Address(
538+
address - theImages[imageNdx].baseAddress
539+
) + image.imageBase
537540
if let theSymbol = lookupSymbol(image: image,
538541
at: imageNdx,
539542
named: name,

stdlib/public/runtime/CrashHandlerLinux.cpp

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@
4949
#include <string.h>
5050
#include <unistd.h>
5151

52+
#define DEBUG_MEMSERVER 0
53+
54+
#if DEBUG_MEMSERVER
55+
#include <stdio.h>
56+
#define memserver_error(x) perror(x)
57+
#else
58+
#define memserver_error(x)
59+
#endif
60+
5261
#include "swift/Runtime/Backtrace.h"
5362

5463
#include <cstring>
@@ -86,8 +95,8 @@ ssize_t safe_read(int fd, void *buf, size_t len) {
8695
ssize_t ret;
8796
do {
8897
ret = read(fd, buf, len);
89-
} while (ret < 0 && errno == EINTR);
90-
if (ret < 0)
98+
} while (ret <= 0 && errno == EINTR);
99+
if (ret <= 0)
91100
return ret;
92101
total += ret;
93102
ptr += ret;
@@ -106,8 +115,8 @@ ssize_t safe_write(int fd, const void *buf, size_t len) {
106115
ssize_t ret;
107116
do {
108117
ret = write(fd, buf, len);
109-
} while (ret < 0 && errno == EINTR);
110-
if (ret < 0)
118+
} while (ret <= 0 && errno == EINTR);
119+
if (ret <= 0)
111120
return ret;
112121
total += ret;
113122
ptr += ret;
@@ -657,20 +666,28 @@ memserver_start()
657666
int fds[2];
658667

659668
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
660-
if (ret < 0)
669+
if (ret < 0) {
670+
memserver_error("memserver_start: socketpair failed");
661671
return ret;
672+
}
662673

663674
memserver_fd = fds[0];
664675
ret = clone(memserver_entry, memserver_stack + sizeof(memserver_stack),
665676
#if MEMSERVER_USE_PROCESS
666677
0,
667678
#else
668-
CLONE_THREAD | CLONE_VM | CLONE_FILES
669-
| CLONE_FS | CLONE_IO | CLONE_SIGHAND,
679+
#ifndef __musl__
680+
// Can't use CLONE_THREAD on musl because the clone() function
681+
// there returns EINVAL if we do.
682+
CLONE_THREAD | CLONE_SIGHAND |
683+
#endif
684+
CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_IO,
670685
#endif
671686
NULL);
672-
if (ret < 0)
687+
if (ret < 0) {
688+
memserver_error("memserver_start: clone failed");
673689
return ret;
690+
}
674691

675692
#if MEMSERVER_USE_PROCESS
676693
memserver_pid = ret;
@@ -718,7 +735,7 @@ memserver_entry(void *dummy __attribute__((unused))) {
718735
int fd = memserver_fd;
719736
int result = 1;
720737

721-
#if MEMSERVER_USE_PROCESS
738+
#if MEMSERVER_USE_PROCESS || defined(__musl__)
722739
prctl(PR_SET_NAME, "[backtrace]");
723740
#endif
724741

@@ -743,8 +760,10 @@ memserver_entry(void *dummy __attribute__((unused))) {
743760
ssize_t ret;
744761

745762
ret = safe_read(fd, &req, sizeof(req));
746-
if (ret != sizeof(req))
763+
if (ret != sizeof(req)) {
764+
memserver_error("memserver: terminating because safe_read() returned wrong size");
747765
break;
766+
}
748767

749768
uint64_t addr = req.addr;
750769
uint64_t bytes = req.len;
@@ -761,15 +780,19 @@ memserver_entry(void *dummy __attribute__((unused))) {
761780
resp.len = ret;
762781

763782
ret = safe_write(fd, &resp, sizeof(resp));
764-
if (ret != sizeof(resp))
783+
if (ret != sizeof(resp)) {
784+
memserver_error("memserver: terminating because safe_write() failed");
765785
goto fail;
786+
}
766787

767788
if (resp.len < 0)
768789
break;
769790

770791
ret = safe_write(fd, memserver_buffer, resp.len);
771-
if (ret != resp.len)
792+
if (ret != resp.len) {
793+
memserver_error("memserver: terminating because safe_write() failed (2)");
772794
goto fail;
795+
}
773796

774797
addr += resp.len;
775798
bytes -= resp.len;

0 commit comments

Comments
 (0)