mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Backtracing][Linux] Fix crash handler for musl.
Musl's `clone()` wrapper returns `EINVAL` if you try to use `CLONE_THREAD`, which seems a bit wrong (certainly it is in this particular application, since we *really* don't care whether the thread is a valid C library thread at this point). Also properly support ELF images that are built with a base address other than zero (this typically isn't an issue for dynamically linked programs, as they will be relocated at runtime anyway, but for statically linked binaries it's very common to set the base address to a non-zero value). rdar://154282813
This commit is contained in:
@@ -49,6 +49,15 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DEBUG_MEMSERVER 0
|
||||
|
||||
#if DEBUG_MEMSERVER
|
||||
#include <stdio.h>
|
||||
#define memserver_error(x) perror(x)
|
||||
#else
|
||||
#define memserver_error(x)
|
||||
#endif
|
||||
|
||||
#include "swift/Runtime/Backtrace.h"
|
||||
|
||||
#include <cstring>
|
||||
@@ -86,8 +95,8 @@ ssize_t safe_read(int fd, void *buf, size_t len) {
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = read(fd, buf, len);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0)
|
||||
} while (ret <= 0 && errno == EINTR);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
total += ret;
|
||||
ptr += ret;
|
||||
@@ -106,8 +115,8 @@ ssize_t safe_write(int fd, const void *buf, size_t len) {
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = write(fd, buf, len);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0)
|
||||
} while (ret <= 0 && errno == EINTR);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
total += ret;
|
||||
ptr += ret;
|
||||
@@ -657,20 +666,28 @@ memserver_start()
|
||||
int fds[2];
|
||||
|
||||
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
memserver_error("memserver_start: socketpair failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memserver_fd = fds[0];
|
||||
ret = clone(memserver_entry, memserver_stack + sizeof(memserver_stack),
|
||||
#if MEMSERVER_USE_PROCESS
|
||||
0,
|
||||
#else
|
||||
CLONE_THREAD | CLONE_VM | CLONE_FILES
|
||||
| CLONE_FS | CLONE_IO | CLONE_SIGHAND,
|
||||
#ifndef __musl__
|
||||
// Can't use CLONE_THREAD on musl because the clone() function
|
||||
// there returns EINVAL if we do.
|
||||
CLONE_THREAD | CLONE_SIGHAND |
|
||||
#endif
|
||||
CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_IO,
|
||||
#endif
|
||||
NULL);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
memserver_error("memserver_start: clone failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if MEMSERVER_USE_PROCESS
|
||||
memserver_pid = ret;
|
||||
@@ -718,7 +735,7 @@ memserver_entry(void *dummy __attribute__((unused))) {
|
||||
int fd = memserver_fd;
|
||||
int result = 1;
|
||||
|
||||
#if MEMSERVER_USE_PROCESS
|
||||
#if MEMSERVER_USE_PROCESS || defined(__musl__)
|
||||
prctl(PR_SET_NAME, "[backtrace]");
|
||||
#endif
|
||||
|
||||
@@ -743,8 +760,10 @@ memserver_entry(void *dummy __attribute__((unused))) {
|
||||
ssize_t ret;
|
||||
|
||||
ret = safe_read(fd, &req, sizeof(req));
|
||||
if (ret != sizeof(req))
|
||||
if (ret != sizeof(req)) {
|
||||
memserver_error("memserver: terminating because safe_read() returned wrong size");
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t addr = req.addr;
|
||||
uint64_t bytes = req.len;
|
||||
@@ -761,15 +780,19 @@ memserver_entry(void *dummy __attribute__((unused))) {
|
||||
resp.len = ret;
|
||||
|
||||
ret = safe_write(fd, &resp, sizeof(resp));
|
||||
if (ret != sizeof(resp))
|
||||
if (ret != sizeof(resp)) {
|
||||
memserver_error("memserver: terminating because safe_write() failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (resp.len < 0)
|
||||
break;
|
||||
|
||||
ret = safe_write(fd, memserver_buffer, resp.len);
|
||||
if (ret != resp.len)
|
||||
if (ret != resp.len) {
|
||||
memserver_error("memserver: terminating because safe_write() failed (2)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
addr += resp.len;
|
||||
bytes -= resp.len;
|
||||
|
||||
Reference in New Issue
Block a user