我正在开发通过NDK与Android一起使用的本机应用程序.我需要在backtrace()发生崩溃时调用该函数.问题是<execinfo.h>NDK 没有 .
有没有其他方法来获得回溯?
我正在为Android(仅限ARM)编写这个,但我相信通用Linux的原理也是如此.
我正在尝试从信号处理程序中捕获堆栈跟踪,以便我可以在应用程序崩溃时记录它.这就是我想出来的用法<unwind.h>.
初始化:
struct sigaction signalhandlerDescriptor;
memset(&signalhandlerDescriptor, 0, sizeof(signalhandlerDescriptor));
signalhandlerDescriptor.sa_flags = SA_SIGINFO;
signalhandlerDescriptor._u._sa_sigaction = signalHandler;
sigaction(SIGSEGV, &signalhandlerDescriptor, 0);
Run Code Online (Sandbox Code Playgroud)
代码本身:
struct BacktraceState
{
void** current;
void** end;
void* pc;
};
inline _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg)
{
BacktraceState* state = static_cast<BacktraceState*>(arg);
state->pc = (void*)_Unwind_GetIP(context);
if (state->pc)
{
if (state->current == state->end)
return _URC_END_OF_STACK;
else
*state->current++ = reinterpret_cast<void*>(state->pc);
}
return _URC_NO_REASON;
}
inline size_t captureBacktrace(void** addrs, size_t max, unsigned long pc)
{
BacktraceState state = {addrs, addrs + max, …Run Code Online (Sandbox Code Playgroud) 我的问题与其他有关故障地址的问题有所不同.我正在尝试实现一个可怕的黑客来从信号处理程序确定信号是否通过检查保存的指令指针处的代码并将其与主机体系结构的可能的系统调用条目指令进行比较来中断系统调用或普通用户代码.继续前进.这是实现正确的POSIX线程取消的一部分,它不会受到我在旧问题中描述的竞争条件和资源泄漏的影响:
如果这种方法不可靠或不正确,我也想听听原因.
我试图在我的Android NDK应用程序中捕获SIGSEGV等信号以进行调试.为此,我设置了一个名为的sigaction.
我现在正试图获得通话的堆栈.问题是_Unwind_Backtrace只能在当前堆栈和sigaction上运行它自己的堆栈.
那么,有没有办法获得接收信号的执行指针的堆栈?(基本上告诉_Unwind_Backtrace放松另一个堆栈而不是当前?)
我应该指出:
使用backtrace()和backtrace_symbols()不是选项,因为这些功能未在Android NDK中提供
我正在使用GDB来调查本地设备上的崩溃.我不想替换GDB,我希望能够在向他发送测试版本时从客户端接收有意义的堆栈跟踪.
编辑:使用Android的libcorkscrew从系统/核心所建议的法登,但是当我使用它的unwind_backtrace_signal_arch功能,我得到一个奇怪的回溯不代表死机我都试过了.
首先:这个问题已经被问了几次,有些答案很有用,但没有一个提供有效的解决方案.我开始尝试这个答案的代码.令人惊讶的是,它做了它的事情,但是有一个很大的问题:调用这个代码的唯一方法我可以想到的是SIGSEGV处理程序,它有自己的堆栈 - 因此我无法得到我崩溃的应用程序的实际堆栈就像那样.
然后,我尝试合并这个答案.它稍微好一点 - 它产生堆栈的第一项(发生崩溃的方法).但那是 - 没有实际的回溯.因此,只要崩溃发生在第三方库(或标准库)中,此信息就毫无意义.
如何进一步改进代码并最终获得我糟糕的崩溃应用程序的堆栈跟踪?
PS在Android 4.0.3和Android 5.0上测试过,到目前为止行为是一样的.我想支持至少5.0和最近的早期版本,如4.3-4.4.
我的最终目标是转储用户空间堆栈。
我尝试将以下cpp文件构建为android平台上的可执行文件。因此,通过调用tryToGetStack(),可以在运行时获取可执行文件的调用堆栈。
#include <utils/CallStack.h>
namespace android
{
extern "C" void tryToGetStack()
{
CallStack stack;
stack.update();
stack.dump("");
}
}
Run Code Online (Sandbox Code Playgroud)
并将lib设置添加到Android.mak,因为CallStack.tpp在libutils中
LOCAL_SHARED_LIBRARIES + = libutils
但是我总是收到错误消息:
错误:未定义对“ android :: CallStack :: CallStack()”的引用
错误:未定义对“ android :: CallStack :: update(int,int)”的引用
...
似乎可执行文件在链接时解析符号,而不是在运行时加载.so文件?我会丢失某些东西还是Android构建系统存在某些限制吗?
我知道这是一个简单的问题,但我确实需要帮助...
更新1
我尝试将代码添加到另一个可执行文件中。结果是一样的...有人知道android构建系统的规则吗?
更新2
我的控制台中有一些关键字“ target StaticExecutable:...”,我认为这就是答案。
android ×4
android-ndk ×4
linux ×4
c++ ×3
stack-trace ×3
backtrace ×2
c ×2
signals ×2
arm ×1
build ×1
callstack ×1
cancellation ×1
pthreads ×1