chromium/third_party/angle/util/posix/crash_handler_posix.cpp

//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// crash_handler_posix:
//    ANGLE's crash handling and stack walking code. Modified from Skia's:
//     https://github.com/google/skia/blob/master/tools/CrashHandler.cpp
//

#include "util/test_utils.h"

#include "common/FixedVector.h"
#include "common/angleutils.h"
#include "common/string_utils.h"
#include "common/system_utils.h"

#include <fcntl.h>
#include <inttypes.h>
#include <stdio.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_APPLE)
// We only use local unwinding, so we can define this to select a faster implementation.
#define UNW_LOCAL_ONLY
#        include <cxxabi.h>
#        include <libunwind.h>
#        include <signal.h>
#    elif defined(ANGLE_PLATFORM_POSIX)
// We'd use libunwind here too, but it's a pain to get installed for
// both 32 and 64 bit on bots.  Doesn't matter much: catchsegv is best anyway.
#        include <cxxabi.h>
#        include <dlfcn.h>
#        include <execinfo.h>
#        include <libgen.h>
#        include <link.h>
#        include <signal.h>
#        include <string.h>
#    endif  // defined(ANGLE_PLATFORM_APPLE)
#endif      // !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA)

// This code snippet is coped from Chromium's base/posix/eintr_wrapper.h.
#if defined(NDEBUG)
#define HANDLE_EINTR
#else
#define HANDLE_EINTR(x)
#endif  // NDEBUG

namespace angle
{
#if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_FUCHSIA)

void PrintStackBacktrace()
{
    // No implementations yet.
}

void InitCrashHandler(CrashCallback *callback)
{
    // No implementations yet.
}

void TerminateCrashHandler()
{
    // No implementations yet.
}

#else
namespace
{
CrashCallback *gCrashHandlerCallback;
}  // namespace

#    if defined(ANGLE_PLATFORM_APPLE)

void PrintStackBacktrace()
{
    printf("Backtrace:\n");

    unw_context_t context;
    unw_getcontext(&context);

    unw_cursor_t cursor;
    unw_init_local(&cursor, &context);

    while (unw_step(&cursor) > 0)
    {
        static const size_t kMax = 256;
        char mangled[kMax];
        unw_word_t offset;
        unw_get_proc_name(&cursor, mangled, kMax, &offset);

        int ok          = -1;
        char *demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &ok);
        printf("    %s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset);
        if (ok)
        {
            free(demangled);
        }
    }
    printf("\n");
}

static void Handler(int sig)
{
    printf("\nSignal %d:\n", sig);

    if (gCrashHandlerCallback)
    {
        (*gCrashHandlerCallback)();
    }

    PrintStackBacktrace();

    // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
    _Exit(sig);
}

#    elif defined(ANGLE_PLATFORM_POSIX)

// Can control this at a higher level if required.
#define ANGLE_HAS_ADDR2LINE

#        if defined(ANGLE_HAS_ADDR2LINE)
namespace
{
// The following code was adapted from Chromium's "stack_trace_posix.cc".
// Describes a region of mapped memory and the path of the file mapped.
struct MappedMemoryRegion
{};

MemoryRegionArray;

bool ReadProcMaps(std::string *proc_maps)
{}

bool ParseProcMaps(const std::string &input, MemoryRegionArray *regions_out)
{}

// Set the base address for each memory region by reading ELF headers in
// process memory.
void SetBaseAddressesForMemoryRegions(MemoryRegionArray &regions)
{}

// Parses /proc/self/maps in order to compile a list of all object file names
// for the modules that are loaded in the current process.
// Returns true on success.
bool CacheMemoryRegions(MemoryRegionArray &regions)
{}

constexpr size_t kAddr2LineMaxParameters =;
Addr2LineCommandLine;

void CallAddr2Line(const Addr2LineCommandLine &commandLine)
{}

constexpr size_t kMaxAddressLen =;
AddressBuffer;

const char *ResolveAddress(const MemoryRegionArray &regions,
                           const std::string &resolvedModule,
                           const char *address,
                           AddressBuffer &buffer)
{}
// This is only required when the current CWD does not match the initial CWD and could be replaced
// by storing the initial CWD state globally. It is only changed in vulkan_icd.cpp.
std::string RemoveOverlappingPath(const std::string &resolvedModule)
{}
}  // anonymous namespace
#        endif  // defined(ANGLE_HAS_ADDR2LINE)

void PrintStackBacktrace()
{}

static void Handler(int sig)
{}

#    endif  // defined(ANGLE_PLATFORM_APPLE)

static constexpr int kSignals[] =;

void InitCrashHandler(CrashCallback *callback)
{}

void TerminateCrashHandler()
{}

#endif  // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_FUCHSIA)

}  // namespace angle