Hash :
f62405c5
        
        Author :
  
        
        Date :
2022-10-31T18:47:52
        
      
Add utilities to get the Android backtrace
* Added getBacktraceInfo(), which returns the backtrace information
  from the ANGLE code, including the addresses and the symbols if
  possible
  * Returns the data in an instance of the new class BacktraceInfo.
  * In order to access this function, backtrace_utils.h has been
    included in vk_utils.h
* New GN flag to make use of this feature:
  * angle_enable_unwind_backtrace_support
    * Current only available on Android (debug mode)
  * If the flag is disabled, getBacktraceInfo() returns an empty
    object.
* Added functions in util/ (per platform) to print the BacktraceInfo
  data.
  * Example of usage:
      angle::printBacktraceInfo(angle::getBacktraceInfo());
* Minor edit: Moved cstdint from android_util.cpp to its header.
Bug: b/258475923
Change-Id: I6115462a1a2845d40c7cafc14ce52df09ecdcf34
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3995843
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Charlie Lao <cclao@google.com>
Commit-Queue: Amirali Abdolrashidi <abdolrashidi@google.com>
      
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
//
// Copyright 2022 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.
//
// backtrace_utils_android.cpp:
//   Implements the functions related to the backtrace info class for Android platforms.
//
#include "backtrace_utils.h"
#include <dlfcn.h>
#include <unwind.h>
namespace
{
// Size limit for the backtrace obtained from the device.
constexpr uint32_t kMaxBacktraceSize = 16;
struct UnwindCallbackFnState
{
    UnwindCallbackFnState() : current(nullptr), end(nullptr) {}
    UnwindCallbackFnState(void **current, void **end) : current(current), end(end) {}
    void **current;
    void **end;
};
// Unwind callback function, which is called until the end of stack is reached.
_Unwind_Reason_Code unwindCallbackFn(struct _Unwind_Context *context, void *args)
{
    auto *state = reinterpret_cast<UnwindCallbackFnState *>(args);
    // Get the instruction pointer.
    uintptr_t ip = _Unwind_GetIP(context);
    if (ip == 0)
    {
        return _URC_NO_REASON;
    }
    // The buffer is populated at the current location with the instruction pointer address. The
    // current value is incremented to prepare for the next entry in the stack trace. Once "current"
    // gets to "end", the callback should stop.
    if (state->current == state->end)
    {
        return _URC_END_OF_STACK;
    }
    *state->current++ = reinterpret_cast<void *>(ip);
    return _URC_NO_REASON;
}
}  // namespace
namespace angle
{
void BacktraceInfo::populateBacktraceInfo(void **stackAddressBuffer, size_t stackAddressCount)
{
    ASSERT(mStackAddresses.empty() && mStackSymbols.empty());
    for (size_t i = 0; i < stackAddressCount; i++)
    {
        void *stackAddr = stackAddressBuffer[i];
        mStackAddresses.push_back(stackAddr);
        // Get the symbol if possible. dladdr() returns 0 on failure.
        Dl_info dlInfo;
        if (dladdr(stackAddr, &dlInfo) != 0 && dlInfo.dli_sname)
        {
            mStackSymbols.emplace_back(dlInfo.dli_sname);
        }
        else
        {
            mStackSymbols.emplace_back("unknown_symbol");
        }
    }
    ASSERT(mStackAddresses.size() == mStackSymbols.size());
}
BacktraceInfo getBacktraceInfo()
{
    void *stackAddrBuffer[kMaxBacktraceSize];
    UnwindCallbackFnState unwindFnState(stackAddrBuffer, stackAddrBuffer + kMaxBacktraceSize);
    _Unwind_Backtrace(unwindCallbackFn, &unwindFnState);
    // The number of the collected IPs is shown by how far "current" has moved.
    auto stackAddressCount = static_cast<size_t>(unwindFnState.current - stackAddrBuffer);
    BacktraceInfo backtraceInfo;
    backtraceInfo.populateBacktraceInfo(stackAddrBuffer, stackAddressCount);
    return backtraceInfo;
}
// The following function has been defined in each platform separately.
// - void printBacktraceInfo(BacktraceInfo backtraceInfo);
}  // namespace angle