[Backtracing] Add warning suppression option, enable it for tests.

The backtracing code will warn you if you attempt to forcibly enable
backtracing for a privileged executable.  This is apparently upsetting
the Driver/filelists.swift test.

Since we want to force it on for tests, so that we will definitely get
backtraces, add an option to suppress warning messages, and turn that
on for tests as well.

rdar://144497613
This commit is contained in:
Alastair Houghton
2025-02-14 09:54:04 +00:00
parent 09003d6f11
commit 0bc76dae80
8 changed files with 96 additions and 42 deletions

View File

@@ -105,6 +105,10 @@ follows:
| | | Otherwise, Swift will locate the binary relative |
| | | to the runtime library, or using ``SWIFT_ROOT``. |
+-----------------+---------+--------------------------------------------------+
| warnings | enabled | Set to ``suppressed`` to disable warning output |
| | | related to the state of the backtracer. This is |
| | | sometimes useful for testing. |
+-----------------+---------+--------------------------------------------------+
(*) On macOS, this defaults to ``no`` rather than ``yes``.

View File

@@ -135,6 +135,9 @@ SWIFT_RUNTIME_STDLIB_INTERNAL BacktraceSettings _swift_backtraceSettings = {
// symbolicate
Symbolication::Full,
// suppressWarnings
false,
// swiftBacktracePath
NULL,
@@ -333,9 +336,11 @@ BacktraceInitializer::BacktraceInitializer() {
if (!_swift_backtraceSettings.swiftBacktracePath) {
if (_swift_backtraceSettings.enabled == OnOffTty::On) {
swift::warning(0,
"swift runtime: unable to locate swift-backtrace; "
"disabling backtracing.\n");
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unable to locate swift-backtrace; "
"disabling backtracing.\n");
}
}
_swift_backtraceSettings.enabled = OnOffTty::Off;
}
@@ -354,9 +359,11 @@ BacktraceInitializer::BacktraceInitializer() {
#if !SWIFT_BACKTRACE_ON_CRASH_SUPPORTED
if (_swift_backtraceSettings.enabled != OnOffTty::Off) {
swift::warning(0,
"swift runtime: backtrace-on-crash is not supported on "
"this platform.\n");
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: backtrace-on-crash is not supported on "
"this platform.\n");
}
_swift_backtraceSettings.enabled = OnOffTty::Off;
}
#else
@@ -371,9 +378,11 @@ BacktraceInitializer::BacktraceInitializer() {
// /path/to/some/setuid/binary
//
// i.e. when you're trying to force matters.
swift::warning(0,
"swift runtime: backtrace-on-crash is not supported for "
"privileged executables.\n");
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: backtrace-on-crash is not supported for "
"privileged executables.\n");
}
_swift_backtraceSettings.enabled = OnOffTty::Off;
}
@@ -457,10 +466,12 @@ BacktraceInitializer::BacktraceInitializer() {
swiftBacktracePath,
SWIFT_BACKTRACE_BUFFER_SIZE);
if (!len) {
swift::warning(0,
"swift runtime: unable to convert path to "
"swift-backtrace: %08lx; disabling backtracing.\n",
::GetLastError());
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unable to convert path to "
"swift-backtrace: %08lx; disabling backtracing.\n",
::GetLastError());
}
_swift_backtraceSettings.enabled = OnOffTty::Off;
}
#endif // !defined(SWIFT_RUNTIME_FIXED_BACKTRACER_PATH)
@@ -470,9 +481,11 @@ BacktraceInitializer::BacktraceInitializer() {
#if !defined(SWIFT_RUNTIME_FIXED_BACKTRACER_PATH)
size_t len = strlen(_swift_backtraceSettings.swiftBacktracePath);
if (len > SWIFT_BACKTRACE_BUFFER_SIZE - 1) {
swift::warning(0,
"swift runtime: path to swift-backtrace is too long; "
"disabling backtracing.\n");
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: path to swift-backtrace is too long; "
"disabling backtracing.\n");
}
_swift_backtraceSettings.enabled = OnOffTty::Off;
} else {
memcpy(swiftBacktracePath,
@@ -489,19 +502,23 @@ BacktraceInitializer::BacktraceInitializer() {
#if !defined(SWIFT_RUNTIME_FIXED_BACKTRACER_PATH)
if (!writeProtectMemory(swiftBacktracePath,
sizeof(swiftBacktracePath))) {
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unable to protect path to "
"swift-backtrace at %p; disabling backtracing.\n",
swiftBacktracePath);
_swift_backtraceSettings.enabled = OnOffTty::Off;
}
_swift_backtraceSettings.enabled = OnOffTty::Off;
}
#endif
if (!writeProtectMemory(swiftBacktraceEnv,
sizeof(swiftBacktraceEnv))) {
swift::warning(0,
"swift runtime: unable to protect environment "
"for swift-backtrace at %p; disabling backtracing.\n",
swiftBacktraceEnv);
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unable to protect environment "
"for swift-backtrace at %p; disabling backtracing.\n",
swiftBacktraceEnv);
}
_swift_backtraceSettings.enabled = OnOffTty::Off;
}
#endif
@@ -512,9 +529,11 @@ BacktraceInitializer::BacktraceInitializer() {
if (_swift_backtraceSettings.enabled == OnOffTty::On) {
ErrorCode err = _swift_installCrashHandler();
if (err != 0) {
swift::warning(0,
"swift runtime: crash handler installation failed; "
"disabling backtracing.\n");
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: crash handler installation failed; "
"disabling backtracing.\n");
}
}
}
#endif
@@ -631,12 +650,14 @@ _swift_processBacktracingSetting(llvm::StringRef key,
_swift_backtraceSettings.timeout = count * 3600;
if (_swift_backtraceSettings.timeout < 0) {
swift::warning(0,
"swift runtime: bad backtracing timeout %ds\n",
_swift_backtraceSettings.timeout);
if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: bad backtracing timeout %ds\n",
_swift_backtraceSettings.timeout);
}
_swift_backtraceSettings.timeout = 0;
}
} else {
} else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: bad backtracing timeout '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -648,7 +669,7 @@ _swift_processBacktracingSetting(llvm::StringRef key,
_swift_backtraceSettings.algorithm = UnwindAlgorithm::Fast;
else if (value.equals_insensitive("precise"))
_swift_backtraceSettings.algorithm = UnwindAlgorithm::Precise;
else {
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unknown unwind algorithm '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -665,7 +686,7 @@ _swift_processBacktracingSetting(llvm::StringRef key,
_swift_backtraceSettings.preset = Preset::Medium;
else if (value.equals_insensitive("full"))
_swift_backtraceSettings.preset = Preset::Full;
else {
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unknown backtracing preset '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -675,7 +696,7 @@ _swift_processBacktracingSetting(llvm::StringRef key,
_swift_backtraceSettings.threads = ThreadsToShow::All;
else if (value.equals_insensitive("crashed"))
_swift_backtraceSettings.threads = ThreadsToShow::Crashed;
else {
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unknown threads setting '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -687,7 +708,7 @@ _swift_processBacktracingSetting(llvm::StringRef key,
_swift_backtraceSettings.registers = RegistersToShow::All;
else if (value.equals_insensitive("crashed"))
_swift_backtraceSettings.registers = RegistersToShow::Crashed;
else {
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unknown registers setting '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -699,7 +720,7 @@ _swift_processBacktracingSetting(llvm::StringRef key,
_swift_backtraceSettings.images = ImagesToShow::All;
else if (value.equals_insensitive("mentioned"))
_swift_backtraceSettings.images = ImagesToShow::Mentioned;
else {
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unknown registers setting '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -711,7 +732,7 @@ _swift_processBacktracingSetting(llvm::StringRef key,
_swift_backtraceSettings.limit = -1;
else if (!value.getAsInteger(0, limit) && limit > 0)
_swift_backtraceSettings.limit = limit;
else {
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: bad backtrace limit '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -721,7 +742,7 @@ _swift_processBacktracingSetting(llvm::StringRef key,
// (If you think the next line is wrong, see above.)
if (!value.getAsInteger(0, top) && top >= 0)
_swift_backtraceSettings.top = top;
else {
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: bad backtrace top count '%.*s'\n",
static_cast<int>(value.size()), value.data());
@@ -758,7 +779,20 @@ _swift_processBacktracingSetting(llvm::StringRef key,
std::free(const_cast<char *>(_swift_backtraceSettings.swiftBacktracePath));
_swift_backtraceSettings.swiftBacktracePath = path;
#endif // !defined(SWIFT_RUNTIME_FIXED_BACKTRACER_PATH)
} else {
} else if (key.equals_insensitive("warnings")) {
if (value.equals_insensitive("suppressed")
|| value.equals_insensitive("disabled")
|| value.equals_insensitive("off"))
_swift_backtraceSettings.suppressWarnings = true;
else if (value.equals_insensitive("enabled")
|| value.equals_insensitive("on"))
_swift_backtraceSettings.suppressWarnings = false;
else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unknown warnings setting '%.*s'\n",
static_cast<int>(value.size()), value.data());
}
} else if (!_swift_backtraceSettings.suppressWarnings) {
swift::warning(0,
"swift runtime: unknown backtracing setting '%.*s'\n",
static_cast<int>(key.size()), key.data());

View File

@@ -121,6 +121,7 @@ struct BacktraceSettings {
bool cache;
OutputTo outputTo;
Symbolication symbolicate;
bool suppressWarnings;
const char *swiftBacktracePath;
const char *outputPath;
};

View File

@@ -5,7 +5,7 @@ config.substitutions.insert(0, ('%build-irgen-test-overlays',
'%target-swift-frontend -enable-objc-interop -disable-objc-attr-requires-foundation-module -emit-module -enable-library-evolution -o %t -sdk %S/Inputs %S/Inputs/ObjectiveC.swift && '
'%target-swift-frontend -enable-objc-interop -emit-module -enable-library-evolution -o %t -sdk %S/Inputs %S/Inputs/Foundation.swift -I %t'))
config.substitutions.insert(0, ('%build-irgen-test-overlays\(mock-sdk-directory: ([^)]+)\)',
config.substitutions.insert(0, (r'%build-irgen-test-overlays\(mock-sdk-directory: ([^)]+)\)',
SubstituteCaptures(r'%target-swift-frontend -enable-objc-interop -disable-objc-attr-requires-foundation-module -emit-module -enable-library-evolution -o %t -sdk \1 \1/ObjectiveC.swift && '
r'%target-swift-frontend -enable-objc-interop -emit-module -enable-library-evolution -o %t -sdk \1 \1/Foundation.swift -I %t')))

View File

@@ -59,12 +59,12 @@ config.substitutions.insert(0, ('%target-interop-build-clang', '%target-clang -
config.substitutions.insert(0, ('%target-interop-build-clangxx', '%target-clangxx --std=gnu++14 ' + clang_opt))
# Test parsing of the generated C++ header in different C++ language modes.
config.substitutions.insert(0, ('%check-interop-cxx-header-in-clang\(([^)]+)\)',
config.substitutions.insert(0, (r'%check-interop-cxx-header-in-clang\(([^)]+)\)',
SubstituteCaptures(r'%check-cxx-header-in-clang -std=c++14 -Wno-padded -Wno-c11-extensions -D_LIBCPP_CSTDLIB ' + clang_compile_opt + r'\1 && '
r'%check-cxx-header-in-clang -std=c++17 -Wno-padded -Wno-c11-extensions -D_LIBCPP_CSTDLIB ' + clang_compile_opt + r'\1 && '
r'%check-cxx-header-in-clang -std=c++20 -Wno-padded -Wno-c11-extensions -D_LIBCPP_CSTDLIB ' + clang_compile_opt + r'\1')))
# Test parsing of the generated C header in different C language modes.
config.substitutions.insert(0, ('%check-interop-c-header-in-clang\(([^)]+)\)',
config.substitutions.insert(0, (r'%check-interop-c-header-in-clang\(([^)]+)\)',
SubstituteCaptures(r'%check-c-header-in-clang -std=c99 -Wno-padded -Wno-c11-extensions -Wno-pre-c11-compat \1 && '
r'%check-c-header-in-clang -std=c11 -Wno-padded -Wno-pre-c11-compat \1')))

View File

@@ -24,5 +24,5 @@ config.target_playground_build_run_swift_parameterized = SubstituteCaptures(
escape_for_substitute_captures(config.target_run))
)
config.substitutions.append(('%target-playground-build-run-swift\(([^)]+)\)',
config.substitutions.append((r'%target-playground-build-run-swift\(([^)]+)\)',
config.target_playground_build_run_swift_parameterized))

View File

@@ -551,7 +551,7 @@ if backtracing is not None:
backtrace_on_crash = lit_config.params.get('backtrace_on_crash', None)
if backtrace_on_crash is not None:
config.environment['SWIFT_BACKTRACE'] = 'enable=on'
config.environment['SWIFT_BACKTRACE'] = 'enable=on,warnings=suppressed'
# Make an explicit setting in the environment override whatever we did above
swift_backtrace = os.environ.get('SWIFT_BACKTRACE')
@@ -2973,7 +2973,7 @@ if hasattr(config, 'target_link_sdk_future_version'):
config.substitutions.append(('%target-link-sdk-future-version',
config.target_link_sdk_future_version))
run_filecheck = '%s %s --allow-unused-prefixes --sanitize BUILD_DIR=%s --sanitize SOURCE_DIR=%s --use-filecheck %s %s %s' % (
run_filecheck = '%s %s --allow-unused-prefixes --sanitize BUILD_DIR=%s --sanitize SOURCE_DIR=%s --ignore-runtime-warnings --use-filecheck %s %s %s' % (
shell_quote(sys.executable),
shell_quote(config.PathSanitizingFileCheck),
# LLVM Lit performs realpath with the config path, so all paths are relative

View File

@@ -61,6 +61,11 @@ constants.""")
"to standard output",
action="store_true")
parser.add_argument(
"--ignore-runtime-warnings",
help="Ignore warnings from the Swift runtime",
action="store_true")
args, unknown_args = parser.parse_known_args()
if args.enable_windows_compatibility:
@@ -82,6 +87,16 @@ constants.""")
slashes_re, re.escape(pattern)),
replacement, stdin)
# Because we force the backtracer on in the tests, we can get runtime
# warnings about privileged programs. Suppress those, and also the
# warning it might emit if backtracing isn't supported on the test platform.
# Additionally, suppress warnings about unknown backtracer options, since
# we might want to add new ones to the lit tests and we should ignore
# messages from the system copy of the runtime in that case.
if args.ignore_runtime_warnings:
stdin = re.sub(r'^swift runtime: (backtrace-on-crash is not '
r'supported|unknown) .*\n', "", stdin, flags=re.M)
if args.dry_run:
print(stdin)
return 0