Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backtracing][Linux] Add Linux support to swift-backtrace. #66410

Merged
merged 17 commits into from Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
bfe8087
[Backtracing][Linux] Add Linux crash handler to the runtime.
al45tair Jun 5, 2023
dc05590
[Backtracing][Linux] Add missing CrashInfo.h header.
al45tair Jun 5, 2023
546c93d
[Backtracing][Linux] Disable backtrace-on-crash until enabling PR.
al45tair Jun 5, 2023
fe6238a
[Backtracing][Linux] Tidy a few things up after review.
al45tair Jun 6, 2023
8ee9b8b
[Backtracing][Linux] Move doc comment to header.
al45tair Jun 6, 2023
49ac8c3
[Backtracing][IRGen] Add a semantic attribute to force frame pointer.
al45tair Jun 5, 2023
33e1af1
[Backtracing][Linux] Reorganise modules for _Backtracing.
al45tair Jun 5, 2023
efa90a5
[Backtracing][Linux] Add Linux support to the _Backtracing module.
al45tair Jun 5, 2023
e3b8e51
[Backtracing][Linux] Temporarily add a default addressWidth.
al45tair Jun 5, 2023
3e2df1f
[Backtracing][Linux] Work correctly in the presence of partial reads.
al45tair Jun 6, 2023
1d8fe3b
[Backtracing][Linux] Remove status argument.
al45tair Jun 7, 2023
3791b47
[Backtracing][Linux] Add a comment about __cxa_demangle.
al45tair Jun 7, 2023
b664339
[Backtracing][Linux] Also remove the status argument from Runtime mod…
al45tair Jun 7, 2023
b25a04c
[Backtracing][Linux][Tests] Fix verify_all_overlays test.
al45tair Jun 6, 2023
7cc2446
[Backtracing][Linux] Add Linux support to swift-backtrace.
al45tair Jun 5, 2023
9379477
Revert "[Backtracing][Linux] Temporarily add a default addressWidth."
al45tair Jun 5, 2023
f61e72c
[Backtracing][Linux] Remove some stray "public" annotations.
al45tair Jun 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/SemanticAttrs.def
Expand Up @@ -144,5 +144,8 @@ SEMANTICS_ATTR(NO_PERFORMANCE_ANALYSIS, "no_performance_analysis")
// that may cause the user to think there is a bug in the compiler.
SEMANTICS_ATTR(NO_MOVEONLY_DIAGNOSTICS, "sil.optimizer.moveonly.diagnostic.ignore")

// Force the use of the frame pointer for the specified function
SEMANTICS_ATTR(USE_FRAME_POINTER, "use_frame_pointer")

#undef SEMANTICS_ATTR

49 changes: 46 additions & 3 deletions include/swift/Runtime/Backtrace.h
Expand Up @@ -17,10 +17,17 @@
#ifndef SWIFT_RUNTIME_BACKTRACE_H
#define SWIFT_RUNTIME_BACKTRACE_H

#ifdef __linux__
#include <sys/types.h>
#include <sys/wait.h>

#include <signal.h>
#endif // defined(__linux__)

#include "swift/Runtime/Config.h"
#include "swift/Runtime/CrashInfo.h"

#include "swift/shims/Visibility.h"
#include "swift/shims/CrashInfo.h"

#include <inttypes.h>

Expand Down Expand Up @@ -50,7 +57,11 @@ typedef int ErrorCode;

SWIFT_RUNTIME_STDLIB_INTERNAL ErrorCode _swift_installCrashHandler();

#ifdef __linux__
SWIFT_RUNTIME_STDLIB_INTERNAL bool _swift_spawnBacktracer(const ArgChar * const *argv, int memserver_fd);
#else
SWIFT_RUNTIME_STDLIB_INTERNAL bool _swift_spawnBacktracer(const ArgChar * const *argv);
#endif

enum class UnwindAlgorithm {
Auto = 0,
Expand Down Expand Up @@ -123,8 +134,40 @@ struct BacktraceSettings {

SWIFT_RUNTIME_STDLIB_INTERNAL BacktraceSettings _swift_backtraceSettings;

SWIFT_RUNTIME_STDLIB_SPI SWIFT_CC(swift) bool _swift_isThunkFunction(const char *mangledName);

SWIFT_RUNTIME_STDLIB_SPI
bool _swift_backtrace_isThunkFunction(const char *mangledName);

/// Try to demangle a symbol.
///
/// Unlike other entry points that do this, we try both Swift and C++ here.
///
/// @param mangledName is the symbol name to be demangled.
/// @param mangledNameLength is the length of this name.
/// @param outputBuffer is a pointer to a buffer in which to place the result.
/// @param outputBufferSize points to a variable that contains the size of the
/// output buffer.
///
/// If outputBuffer is nullptr, the function will allocate memory for the
/// result using malloc(). In this case, outputBufferSize may be nullptr;
/// if it is *not* nullptr, it will be set to the size of buffer that was
/// allocated. This is not necessarily the length of the string (it may be
/// somewhat higher).
///
/// Otherwise, the result will be written into the output buffer, and the
/// size of the result will be written into outputBufferSize. If the buffer
/// is too small, the result will be truncated, but outputBufferSize will
/// still be set to the number of bytes that would have been required to
/// copy out the full result (including a trailing NUL).
///
/// The unusual behaviour here is a consequence of the way the C++ ABI's
/// demangling function works.
///
/// @returns a pointer to the output if demangling was successful.
SWIFT_RUNTIME_STDLIB_SPI
char *_swift_backtrace_demangle(const char *mangledName,
size_t mangledNameLength,
char *outputBuffer,
size_t *outputBufferSize);
#ifdef __cplusplus
} // namespace backtrace
} // namespace runtime
Expand Down
98 changes: 98 additions & 0 deletions include/swift/Runtime/CrashInfo.h
@@ -0,0 +1,98 @@
//===--- CrashInfo.h - Swift Backtracing Crash Information ------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Defines the CrashInfo type that holds information about why the program
// crashed.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_CRASHINFO_H
#define SWIFT_CRASHINFO_H

#include <inttypes.h>

#ifdef __cplusplus
namespace swift {
namespace runtime {
namespace backtrace {
extern "C" {
#endif

// Note: The "pointers" below are pointers in a different process's address
// space, which might not even share our bitness. That is why they are
// `uint64_t`s, rather than pointers or `uintptr_t`s.

// The address of this structure in memory is passed to swift-backtrace.
struct CrashInfo {
// The thread ID for the crashing thread.
uint64_t crashing_thread;

// The signal number corresponding to this crash.
uint64_t signal;

// The fault address.
uint64_t fault_address;

#ifdef __APPLE__
// Points to the mcontext_t structure for the crashing thread; other
// threads' contexts can be recovered using Mach APIs later.
uint64_t mctx;
#elif defined(__linux__)
// The head of the thread list; points at a "struct thread" (see below).
uint64_t thread_list;
#endif
};

#ifdef __linux__

// A memory server request packet.
struct memserver_req {
// Address to read.
uint64_t addr;

// Number of bytes to read.
uint64_t len;
};

// A memory server response packet.
struct memserver_resp {
// Address that was read from.
uint64_t addr;

// Number of bytes, *or* negative to indicate an error.
int64_t len;

// Followed by len bytes of data if len > 0
};

// Holds details of a running thread.
struct thread {
// Points at the next thread.
uint64_t next;

// The thread ID for this thread.
int64_t tid;

// Points to the Linux ucontext_t structure.
uint64_t uctx;
};

#endif

#ifdef __cplusplus
} // extern "C"
} // namespace backtrace
} // namespace runtime
} // namespace swift
#endif

#endif // SWIFT_CRASHINFO_H
3 changes: 3 additions & 0 deletions include/swift/Runtime/Debug.h
Expand Up @@ -124,6 +124,9 @@ swift_dynamicCastFailure(const void *sourceType, const char *sourceName,
SWIFT_RUNTIME_EXPORT
void swift_reportError(uint32_t flags, const char *message);

SWIFT_RUNTIME_EXPORT
void swift_reportWarning(uint32_t flags, const char *message);

// Halt due to an overflow in swift_retain().
SWIFT_RUNTIME_ATTRIBUTE_NORETURN SWIFT_RUNTIME_ATTRIBUTE_NOINLINE
void swift_abortRetainOverflow();
Expand Down
6 changes: 6 additions & 0 deletions lib/IRGen/IRGenSIL.cpp
Expand Up @@ -21,6 +21,7 @@
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/SemanticAttrs.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Types.h"
#include "swift/Basic/ExternalUnion.h"
Expand Down Expand Up @@ -1854,6 +1855,11 @@ IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM, SILFunction *f)
}
}

// If we have @_semantics("use_frame_pointer"), force the use of a
// frame pointer for this function.
if (f->hasSemanticsAttr(semantics::USE_FRAME_POINTER))
CurFn->addFnAttr("frame-pointer", "all");

// Disable inlining of coroutine functions until we split.
if (f->getLoweredFunctionType()->isCoroutine()) {
CurFn->addFnAttr(llvm::Attribute::NoInline);
Expand Down
50 changes: 50 additions & 0 deletions stdlib/public/Backtracing/ArrayImageSource.swift
@@ -0,0 +1,50 @@
//===--- ArrayImageSource.swift - An image source backed by an Array -------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Defines ArrayImageSource, an image source that is backed by a Swift Array.
//
//===----------------------------------------------------------------------===//

import Swift

@_implementationOnly import OS.Libc

enum ArrayImageSourceError: Error {
case outOfBoundsRead(UInt64, UInt64)
}

struct ArrayImageSource<T>: ImageSource {
private var array: Array<T>

public init(array: Array<T>) {
self.array = array
}

public var isMappedImage: Bool { return false }
public var path: String? { return nil }
public var bounds: Bounds? {
return Bounds(base: 0, size: Size(array.count * MemoryLayout<T>.stride))
}

public func fetch<U>(from addr: Address,
into buffer: UnsafeMutableBufferPointer<U>) throws {
try array.withUnsafeBytes{
let size = Size($0.count)
let requested = Size(buffer.count * MemoryLayout<U>.stride)
if addr > size || requested > size - addr {
throw ArrayImageSourceError.outOfBoundsRead(addr, requested)
}

memcpy(buffer.baseAddress!, $0.baseAddress! + Int(addr), Int(requested))
}
}
}