首页 » 网站推广 » php若何调试coredump技巧_gdb从一个指针开始调试core dump

php若何调试coredump技巧_gdb从一个指针开始调试core dump

访客 2024-11-19 0

扫一扫用手机浏览

文章目录 [+]

从一个指针开始

除了进程的core dump, 还有一条有用的日志:

2022-10-10 12:25:02.233 7f57d70bf700 1 []-- [v2:192.168.56.102:6824/2753553827,v1:192.168.56.102:6825/2753553827] --> v1:192.168.56.103:6801/1057529 -- osd_op(unknown.0.17:3466 1.22 1:44de85d6:::client_192.168.56.101:head [omap-get-vals-by-keys] snapc 0=[] ondisk+read+known_if_redirected+full_force e132) v8-- 0x7f57f457d600 con 0x7f57f44f2000

从这条日志得知问题发生的时候,ceph-mds 是用的con工具(0x7f57f44f2000) 向OSD进行IO要求的。
而这个指针地址便是我们打开宝藏的钥匙。

php若何调试coredump技巧_gdb从一个指针开始调试core dump

思路

C++程序主流还是用的面向工具编程范式,常日都是利用一个类来聚合干系的变量。
然后工具实例之间相互存在引用。
上面提到的指针0x7f57f44f2000 便是AsyncConnection的实列。
不变式:虽然不同的进程,工具地址不同,但是工具内变量之间的偏移是确定。
比如我想知道当前ceph-mds跟哪些节点建立了网络连接,我只要知道async_msgr的指针地址,就可以知道所有的网络连接。
而async_msgr地址是AsyncConnection实例的成员变量。

php若何调试coredump技巧_gdb从一个指针开始调试core dump
(图片来自网络侵删)

以下是gdb的python插件脚本

class AsyncConnection(): def __init__(self, addr) : self.addr = addr self.msgr = read_ptr(addr+96) # 偏移量96是之前剖析有符号表的时候,记录的。
class AsyncMessenger(): def __init__(self, addr): self.addr = addr conns_addrs = UnorderedMap(addr+1792, allocator_sz=0) # 1792 同上

因此通过AsyncConnection(0x7f57f44f2000) ,得到AsyncMessenger地址为0x7f57f365a000,进一步地就可以知道所有的连接信息

更大的困难

我真正想得到的是mds(class MDSDaemon)工具的地址,由于只要拿到它的信息,基本上所有的数据构造信息都能看了。

class MDSDaemon : public Dispatcher {AsyncMessenger messenger; // messenger偏移量是768}

现在我知道了AsyncMessenger的地址0x7f57f365a000,怎么反向推导出MDSDaemon实列的地址addr, 知足下面的等式:

read_ptr (addr + 768) = 0x7f57f365a000注: read_ptr方法的功能:从一个内存地址读取8个字节。

而能解此方程方法便是遍历内存。

遍历内存

ceph-mds进程利用的是tcmalloc库来管理内存分布,我们要做的实在便是去剖析tcmalloc的数据构造,而tcmalloc是开源组件,它的debug symbol很随意马虎获取。
tcmalloc剖析不展开,网上很多资源。
下面代码的基本逻辑便是

gdb 命令info variables pageheap_拿到pageheap_地址在pageheap_里遍历已经分配的span在span里面搜索知足一定大小的内存块在知足条件的内存块偏移量768的地方搜索0x7f57f365a000

def walk_heap(page_heap, call_back): # the first level for index, leaf_ptr in page_heap.pagemap_.root.items(): print("{0} -> {1}".format(index, my_hex(leaf_ptr))) leaf = Leaf(leaf_ptr) for indx, span_ptr in leaf.values.items(): span = SpanItem(span_ptr) # only check INUSE span if span.location != 0: continue # cut span to chunks span.parse() call_back(span)def get_chunk_func(blk_sz, offset, value): def callback_func(span): if span.blk_sz < blk_sz: return for chunk in span.chunks: v = read_ptr(chunk.addr + offset) if v == value: print("Congratuation, you got it!") span.display() chunk.display() return callback_funccall_back_func = get_chunk_func(2144, 768, 0x7f57f365a000)walk_heap(heap, call_back_func)运行结果

(gdb) source theap.py 65199 -> 0x7f57f22c3000Congratuation, you got it!Span(0x7f57f22442c0): objects:0x7f57f365c400, location:INUSE, next:0x7f57e8071c20, chunk count:7, blk size:23040x7f57f365a900~23040x7f57f365a900 便是我们要找的MDSDaemon地址,至此我们得到了打开宝藏大门的钥匙。
小结

在ToB领域,碰着的困难常日是在有限的信息下如何快速地定位问题;而core dump信息无疑是最大的信息来源。
通过利用gdb python API可以让剖析core dump变得更系统,更有效;剖析的过程通过脚本化也随意马虎沉淀下来。

标签:

相关文章

招商蛇口中国房地产龙头企业,未来可期

招商蛇口(股票代码:001979),作为中国房地产企业的领军企业,自成立以来始终秉持“以人为本,追求卓越”的经营理念,致力于打造高...

网站推广 2025-02-18 阅读1 评论0