我正在尝试追踪 Linux 内核中的一些 refcnt 泄漏(特别是在 ax.25 子系统中)。我正在尝试查看对
netdev_put
的调用是否与对 netdev_hold
的调用平衡,为此,我使用如下断点:
break netdev_hold
commands
silent
if $_regex(dev->name, "ax")
printf "netdev_hold %s r:%d u:%d n:%d\n", dev->name, dev->dev_refcnt->refs->counter, dev->refcnt_tracker->untracked->refs->counter, dev->refcnt_tracker->no_tracker->refs->counter
end
continue
end
break netdev_put
commands
silent
if $_regex(dev->name, "ax")
printf "netdev_put %s r:%d u:%d n:%d\n", dev->name, dev->dev_refcnt->refs->counter, dev->refcnt_tracker->untracked->refs->counter, dev->refcnt_tracker->no_tracker->refs->counter
end
continue
end
目标是仅在处理
ax*
接口时打印信息。这在大多数情况下都有效,除了偶尔会导致:
value has been optimized out
这会导致 gdb 返回到
(gdb)
提示符。有没有办法忽略这个错误,以便 gdb 在任何情况下都能继续?我不知道如何在 gdb 中编写“如果指定的变量可用”。
我想我应该清楚,我不想禁用优化 - 当
netdev_{hold,put}
不可用时调用 dev
的情况不是我感兴趣的情况。
使用链接的解决方案作为灵感,我最终编写了一个新的“is_optimized_out”便利函数,如下所示:
class IsOptimizedOutFunction(gdb.Function):
def __init__ (self):
super ().__init__ ("is_optimized_out")
def invoke (self, arg):
val = gdb.parse_and_eval(arg.string())
return val.is_optimized_out
IsOptimizedOutFunction()
这让我可以编写这样的 gdb 脚本:
break netdev_hold
commands
silent
if ! $is_optimized_out("dev")
if $_regex(dev->name, "ax")
printf "netdev_hold %s r:%d u:%d n:%d\n", dev->name, dev->dev_refcnt->refs->counter, dev->refcnt_tracker->untracked->refs->counter, dev->refcnt_tracker->no_tracker->refs->counter
end
end
continue
end
这正是我想要的;
printf
仅在为 netdev_hold
设备调用 ax*
时执行,并且如果 dev
的值不可用,则不会中止。