2013年8月15日 星期四

用 python gdb 客製化 backtrace 的結果 (2)

之前寫的指令 bt 加上參數 -s, 使用 -s 時, 會一併記錄 backtrace 每個 frame 附近的原始碼。

以下是一個範例輸出:

(gdb) bt -s
#0   A::hello at b.cpp:8
  | class A
  | {
  | public:
  |   void hello(int n)
  |   {
->|     std::cout << n << std::endl;
  |   }
  |
  |   void foo(int n)
  |   {

#1   A::bar at b.cpp:18
  |     bar(n + 1);
  |   }
  |
  |   void bar(int n)
  |   {
->|     hello(n + 10);
  |   }
  | };
  |
  | int main(void) {

#2   A::foo at b.cpp:13
  |     std::cout << n << std::endl;
  |   }
  |
  |   void foo(int n)
  |   {
->|     bar(n + 1);
  |   }
  |
  |   void bar(int n)
  |   {

#3   main at b.cpp:24
  |   }
  | };
  |
  | int main(void) {
  |   A a;
->|   a.foo(5);
  |   return 0;
  | }

修改後的 python script 如下:

import gdb
def read_source_code(filename, target_line, num_lines):
with open(filename, 'r') as fr:
target_line -= 1
lines = [' | ' + line[:-1] for line in fr]
lines[target_line] = '->| ' + lines[target_line][4:]
offset = num_lines / 2
return lines[target_line - offset : target_line + offset]
class ShorternBacktraceCommand(gdb.Command):
'''Show a backtrace without argument info in each frame.'''
def __init__(self):
super(ShorternBacktraceCommand, self).__init__ ("bt",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE)
def invoke(self, arg, from_tty):
# Parse arguments.
show_source = False
num = 0;
args = arg.split()
for s in args:
if s == '-s':
show_source = True
else:
try:
num = int(s)
except Exception, e:
pass
# Extract frame info.
frames = []
f = gdb.newest_frame()
fn = 0
while f is not None:
symtab_and_line = gdb.Frame.find_sal(f)
frame_name = gdb.Frame.name(f)
if frame_name:
outs = (
fn,
frame_name,
symtab_and_line.symtab.filename,
symtab_and_line.line,
)
else:
outs = (fn, '??', 'unknown', 0)
head = '#%-2d %s at %s:%s' % outs
codes = None
if show_source and frame_name:
codes = read_source_code(symtab_and_line.symtab.fullname(),
symtab_and_line.line,
10)
frames.append((head, codes))
f = gdb.Frame.older(f)
fn += 1
# Hold the subset.
if num > 0:
frames = frames[:num]
elif num < 0:
frames = frames[len(frames) + num:]
# Print the result.
for head, codes in frames:
print head
if codes:
for line in codes:
print line
print
ShorternBacktraceCommand()
view raw backtrace.py hosted with ❤ by GitHub

作法大致和 《用 python gdb 客製化 backtrace 的結果》一樣, 只是改取檔案的 fullname, 再自己讀出相關的原始碼。這部份用 python 實作, 相當地輕鬆寫意。

沒有留言:

張貼留言

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...