Commit 2edec864 by Jamie Madill Committed by Commit Bot

Improve stack backtraces on Linux.

This switches the Linux crash handler to use addr2line when it is available. Addr2line is much better at converting addresses into readable information. The downside is that we must use a system call to a binary since it's not easy to integrate with addr2line source. Bug: angleproject:5239 Change-Id: I13cbaa4ba30166718fb12d924c76ba4f2675453c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2515265Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Tim Van Patten <timvp@google.com>
parent 38016632
...@@ -206,13 +206,6 @@ config("build_id_config") { ...@@ -206,13 +206,6 @@ config("build_id_config") {
ldflags = [ "-Wl,--build-id" ] ldflags = [ "-Wl,--build-id" ]
} }
# Useful for more informative stack traces.
config("better_linux_stack_traces") {
if (angle_better_stack_traces) {
ldflags = [ "-Wl,--export-dynamic" ]
}
}
_use_copy_compiler_dll = angle_has_build && is_win && target_cpu != "arm64" _use_copy_compiler_dll = angle_has_build && is_win && target_cpu != "arm64"
# Windows ARM64 is available since 10.0.16299 so no need to copy # Windows ARM64 is available since 10.0.16299 so no need to copy
......
...@@ -156,7 +156,6 @@ if (!defined(angle_zlib_compression_utils_dir)) { ...@@ -156,7 +156,6 @@ if (!defined(angle_zlib_compression_utils_dir)) {
angle_common_configs = [ angle_common_configs = [
angle_root + ":angle_release_asserts_config", angle_root + ":angle_release_asserts_config",
angle_root + ":better_linux_stack_traces",
angle_root + ":constructor_and_destructor_warnings", angle_root + ":constructor_and_destructor_warnings",
angle_root + ":extra_warnings", angle_root + ":extra_warnings",
angle_root + ":internal_config", angle_root + ":internal_config",
...@@ -167,22 +166,9 @@ angle_remove_configs = [] ...@@ -167,22 +166,9 @@ angle_remove_configs = []
if (angle_has_build) { if (angle_has_build) {
angle_remove_configs += [ "//build/config/compiler:default_include_dirs" ] angle_remove_configs += [ "//build/config/compiler:default_include_dirs" ]
} }
angle_better_stack_traces = (is_debug || dcheck_always_on) &&
(is_linux || is_chromeos) && !is_asan && !is_cfi
if (angle_has_build && is_clang) { if (angle_has_build && is_clang) {
angle_remove_configs += [ "//build/config/clang:find_bad_constructs" ] angle_remove_configs += [ "//build/config/clang:find_bad_constructs" ]
# Disabled to enable better stack traces.
if (angle_better_stack_traces) {
# This line causes in-class-inline-functions in glslang to be weak symbols. The KHR dEQP tests
# link against glslang as well as libGLESv2.so, resulting in angle_deqp_khr_gles*_tests to link
# those weak symbols. Due to glslang's usage of a global variable in InitializeDll.cpp, a bug
# is created where ANGLE sometimes calls into its own copy of glslang and sometimes the KHR
# dEQP's version, with the two copies of the global variable being inconsistent.
# Commented out until the underlying issue is resolved. http://anglebug.com/4123
# angle_remove_configs += [ "//build/config/gcc:symbol_visibility_hidden" ]
}
} }
set_defaults("angle_executable") { set_defaults("angle_executable") {
......
...@@ -11,9 +11,14 @@ ...@@ -11,9 +11,14 @@
#include "util/test_utils.h" #include "util/test_utils.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/system_utils.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA) #if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA)
# if defined(ANGLE_PLATFORM_APPLE) # if defined(ANGLE_PLATFORM_APPLE)
...@@ -28,6 +33,7 @@ ...@@ -28,6 +33,7 @@
# include <cxxabi.h> # include <cxxabi.h>
# include <dlfcn.h> # include <dlfcn.h>
# include <execinfo.h> # include <execinfo.h>
# include <libgen.h>
# include <signal.h> # include <signal.h>
# include <string.h> # include <string.h>
# endif // defined(ANGLE_PLATFORM_APPLE) # endif // defined(ANGLE_PLATFORM_APPLE)
...@@ -102,6 +108,9 @@ static void Handler(int sig) ...@@ -102,6 +108,9 @@ static void Handler(int sig)
# elif defined(ANGLE_PLATFORM_POSIX) # elif defined(ANGLE_PLATFORM_POSIX)
// Can control this at a higher level if required.
# define ANGLE_HAS_ADDR2LINE
void PrintStackBacktrace() void PrintStackBacktrace()
{ {
printf("Backtrace:\n"); printf("Backtrace:\n");
...@@ -112,6 +121,86 @@ void PrintStackBacktrace() ...@@ -112,6 +121,86 @@ void PrintStackBacktrace()
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
# if defined(ANGLE_HAS_ADDR2LINE)
std::string module(symbols[i], strchr(symbols[i], '('));
// We need an absolute path to get to the executable and all of the various shared objects,
// but the caller may have used a relative path to launch the executable, so build one up if
// we don't see a leading '/'.
if (module.at(0) != GetPathSeparator())
{
const Optional<std::string> &cwd = angle::GetCWD();
if (!cwd.valid())
{
std::cout << "Error getting CWD for Vulkan layers init." << std::endl;
}
else
{
std::string absolutePath = cwd.value();
size_t lastPathSepLoc = module.find_last_of(GetPathSeparator());
std::string relativePath = module.substr(0, lastPathSepLoc);
// Remove "." from the relativePath path
// For example: ./out/LinuxDebug/angle_perftests
size_t pos = relativePath.find('.');
if (pos != std::string::npos)
{
// If found then erase it from string
relativePath.erase(pos, 1);
}
// Remove the overlapping relative path from the CWD so we can build the full
// absolute path.
// For example:
// absolutePath = /home/timvp/code/angle/out/LinuxDebug
// relativePath = /out/LinuxDebug
pos = absolutePath.find(relativePath);
if (pos != std::string::npos)
{
// If found then erase it from string
absolutePath.erase(pos, relativePath.length());
}
module = absolutePath + GetPathSeparator() + module;
}
}
std::string substring(strchr(symbols[i], '+') + 1, strchr(symbols[i], ')'));
pid_t pid = fork();
if (pid < 0)
{
std::cout << "Error: Failed to fork()";
}
else if (pid > 0)
{
int status;
waitpid(pid, &status, 0);
// Ignore the status, since we aren't going to handle it anyway.
}
else
{
// Child process executes addr2line
const std::vector<const char *> &commandLineArgs = {
"/usr/bin/addr2line", // execv requires an absolute path to find addr2line
"-s",
"-p",
"-f",
"-C",
"-e",
module.c_str(),
substring.c_str()};
// Taken from test_utils_posix.cpp::PosixProcess
std::vector<char *> argv;
for (const char *arg : commandLineArgs)
{
argv.push_back(const_cast<char *>(arg));
}
argv.push_back(nullptr);
execv(argv[0], argv.data());
std::cout << "Error: Child process returned from exevc()";
_exit(EXIT_FAILURE); // exec never returns
}
# else
Dl_info info; Dl_info info;
if (dladdr(stack[i], &info) && info.dli_sname) if (dladdr(stack[i], &info) && info.dli_sname)
{ {
...@@ -130,6 +219,7 @@ void PrintStackBacktrace() ...@@ -130,6 +219,7 @@ void PrintStackBacktrace()
} }
} }
printf(" %s\n", symbols[i]); printf(" %s\n", symbols[i]);
# endif // defined(ANGLE_HAS_ADDR2LINE)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment