如何使用gdb从核心文件获取lua堆栈跟踪 [英] How can I get the lua stack trace from a core file using gdb

查看:159
本文介绍了如何使用gdb从核心文件获取lua堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C ++应用程序(用于OS X),该应用程序将lua称为脚本语言.我正在运行大量的这些应用程序(100个),它们可以运行很长时间(几天或几周).

I have a C++ application (for OS X) that calls lua as a scripting language. I'm running a large number of these applications (100s) and they can run for a very long time (days or weeks).

有时会崩溃.而且当它崩溃时,还给我留下了一个可爱的核心文件.

Sometimes one crashes. And when it crashes it leaves me a lovely core file.

我可以在gdb中打开此核心文件,并找到应用程序崩溃的位置.我可以遍历调用堆栈并找到lua_State变量的实例.我的问题是我想看看lua调用堆栈的外观这次...

I can open this core file in gdb and find where the application crashes. I can walk the call stack and find an instance of a lua_State variable. My problem is that I'd like to see what the lua call stack looks like at this time...

请记住,由于这是核心,因此我无权访问C函数,因为C函数排除了调试lua脚本的几种常用方法.

Keep in mind that since this is a core I don't have access to calling C functions, which rules out several of the usual ways of debugging lua scripts.

我想避免通过调试钩子添加手动跟踪,因为我担心额外的性能损失和复杂性.

Id like to avoid adding manual traces through debug hooks as I'm worried about the additional performance penalties, and added complexity.

如何遍历lua内部结构以获取调用堆栈信息?

How can I traverse the lua internal structures to get at call stack information?

推荐答案

我已经创建了一个GDB脚本来完成由macs链接到的网页中的内容.它不是很漂亮,应该适当地包装到一个函数等中,但这是出于好奇.

I've created a GDB script to do the stuff in the web page linked to by macs. Its not beautiful, and should probably be properly wrapped into a function etc, but here it is for the curious.

注意:似乎网页关于lua函数的文件名是错误的.如果字符串来自 luaL_dofile(),则文件名以 @ 符号开头.如果从 lua_dostring()调用它们.在这种情况下,将 $ filename 变量设置为传递给 lua_dostring()的整个字符串,并且用户可能只对一两行上下文感兴趣.该文件.我不确定该如何解决.

NOTE: It seems that the web page is wrong about the filename for lua functions. In the case where the string comes from luaL_dofile() the filename starts with a @ symbol. If they're called from lua_dostring(). In that case the $filename variable is set to the whole of the string passed to lua_dostring() - and the user is probably only interested in one or two lines of context from that file. I wasn't sure how to fix that up.

set $p = L->base_ci
while ($p <= L->ci )
  if ( $p->func->value.gc->cl.c.isC == 1 )
    printf "0x%x   C FUNCTION", $p
    output $p->func->value.gc->cl.c.f
    printf "\n"
  else
    if ($p->func.tt==6)
      set $proto = $p->func->value.gc->cl.l.p
      set $filename = (char*)(&($proto->source->tsv) + 1)
      set $lineno = $proto->lineinfo[ $p->savedpc - $proto->code -1 ]
      printf "0x%x LUA FUNCTION : %d %s\n", $p, $lineno, $filename
    else
      printf "0x%x LUA BASE\n", $p
    end
  end
  set $p = $p+1
end

输出类似:

0x1002b0 LUA BASE
0x1002c8 LUA FUNCTION : 4 @a.lua
0x1002e0 LUA FUNCTION : 3 @b.lua
0x100310   C FUNCTION(lua_CFunction) 0x1fda <crash_function(lua_State*)>

当我从以下代码调试崩溃时:

When I debug the crash from this code:

// This is a file designed to crash horribly when run.
// It should generate a core, and it should crash inside some lua functions

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

#include <iostream>
#include <signal.h>

int crash_function(lua_State * L)
{
  raise( SIGABRT ); //This should dump core!
  return 0;
}



int main()
{
  lua_State * L = luaL_newstate();
  lua_pushcfunction(L, crash_function);
  lua_setfield(L, LUA_GLOBALSINDEX, "C");

  luaopen_base(L);
  if( 1 == luaL_dofile(L, "a.lua" ))
  {
    std::cout<<"ERROR: "<<lua_tostring(L,-1)<<std::endl;
    return 1;
  }
  if( 1 == luaL_dofile(L, "b.lua" ))
  {
    std::cout<<"ERROR: "<<lua_tostring(L,-1)<<std::endl;
    return 1;
  }

  lua_getfield(L, LUA_GLOBALSINDEX, "A");
  lua_pcall(L, 0, 0, NULL);
}

使用 a.lua

-- a.lua
-- just calls B, which calls C which should crash
function A()
  B()
end

和b.lua

-- b.lua
function B()
  C()
end

这篇关于如何使用gdb从核心文件获取lua堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆