crash7latest> bt -s 246346
PID: 246346 TASK: ffff880280345400 CPU: 0 COMMAND: "perfquery"
#0 [ffff88015d1c3b38] __schedule+535 at ffffffff816b4fa7
#1 [ffff88015d1c3b90] schedule+62 at ffffffff816b54fe
#2 [ffff88015d1c3bb0] schedule_timeout+437 at ffffffff816b83e5
#3 [ffff88015d1c3c50] wait_for_completion+271 at ffffffff816b6a2f
#4 [ffff88015d1c3cd0] unregister_mad_agent+429 at ffffffffa02a988d [ib_mad]
#5 [ffff88015d1c3d40] ib_unregister_mad_agent+169 at ffffffffa02a9989 [ib_mad]
#6 [ffff88015d1c3d70] ib_umad_close+210 at ffffffffa03c5692 [ib_umad]
#7 [ffff88015d1c3dc0] __fput+189 at ffffffff8120e3ad
#8 [ffff88015d1c3e10] ____fput+14 at ffffffff8120e5ee
#9 [ffff88015d1c3e20] task_work_run+213 at ffffffff810a6785
#10 [ffff88015d1c3e80] do_exit+519 at ffffffff8108b5b7
#11 [ffff88015d1c3f00] do_group_exit+86 at ffffffff8108b916
#12 [ffff88015d1c3f40] sys_exit_group+23 at ffffffff8108b9d7
#13 [ffff88015d1c3f50] system_call_fastpath+18 at ffffffff816b9894
RIP: 00007f77c93dafa8 RSP: 00007ffd9b682b28 RFLAGS: 00000246
RAX: ffffffffffffffda RBX: 00007f77c96b8830 RCX: 00007f77c93dafa8
RDX: ffffffffffffffff RSI: 000000000000003c RDI: ffffffffffffffff
RBP: 00000000ffffffff R8: 00000000000000e7 R9: ffffffffffffffa8
R10: 00007f77c96bf828 R11: 0000000000000246 R12: 00007f77c96b8830
R13: 000000000000ffff R14: 0000000000608c80 R15: 00007ffd9b683320
ORIG_RAX: 00000000000000e7 CS: 0033 SS: 002b
crash7latest> whatis wait_for_completion
void wait_for_completion(struct completion *);
wait_for_complete的参数是completion, 由于这个结构包含在那个priv中,所以找到它的地址也就找到了priv的地址。
要找到它就得反汇编wait_for_complete的父函数,看看参数是怎么传递的.
crash7latest> dis -r unregister_mad_agent+429
0xffffffffa02a96e0
0xffffffffa02a96e1
0xffffffffa02a96e4
0xffffffffa02a96e6
0xffffffffa02a96e8
0xffffffffa02a96ea
0xffffffffa02a96ec
0xffffffffa02a96ed
0xffffffffa02a96f1
0xffffffffa02a96f6
0xffffffffa02a96fa
0xffffffffa02a96fe
0xffffffffa02a9701
0xffffffffa02a9704
0xffffffffa02a9708
0xffffffffa02a970c
0xffffffffa02a9711
0xffffffffa02a9715
0xffffffffa02a9719
0xffffffffa02a971d
0xffffffffa02a9720
0xffffffffa02a9724
0xffffffffa02a9726
0xffffffffa02a972a
0xffffffffa02a972c
0xffffffffa02a9730
0xffffffffa02a9733
0xffffffffa02a9737
0xffffffffa02a973d
0xffffffffa02a973f
0xffffffffa02a9741
0xffffffffa02a9743
0xffffffffa02a974b
0xffffffffa02a9755
0xffffffffa02a9759
0xffffffffa02a975f
0xffffffffa02a9763
0xffffffffa02a9767
0xffffffffa02a976a
0xffffffffa02a976c
0xffffffffa02a9773
0xffffffffa02a977a
0xffffffffa02a977d
0xffffffffa02a977f
0xffffffffa02a9783
0xffffffffa02a978a
0xffffffffa02a978e
0xffffffffa02a9792
0xffffffffa02a9795
0xffffffffa02a9799
0xffffffffa02a97a0
0xffffffffa02a97a7
0xffffffffa02a97aa
0xffffffffa02a97ad
0xffffffffa02a97b2
0xffffffffa02a97b6
0xffffffffa02a97bd
0xffffffffa02a97c4
0xffffffffa02a97c8
0xffffffffa02a97cb
0xffffffffa02a97cf
0xffffffffa02a97d1
0xffffffffa02a97d5
0xffffffffa02a97d9
0xffffffffa02a97e0
0xffffffffa02a97e4
0xffffffffa02a97e8
0xffffffffa02a97ea
0xffffffffa02a97f0
0xffffffffa02a97f3
0xffffffffa02a97f6
0xffffffffa02a97fa
0xffffffffa02a97fe
0xffffffffa02a9803
0xffffffffa02a9806
0xffffffffa02a980a
0xffffffffa02a980d
0xffffffffa02a9811
0xffffffffa02a9815
0xffffffffa02a9819
0xffffffffa02a981c
0xffffffffa02a9820
0xffffffffa02a9822
0xffffffffa02a9826
0xffffffffa02a982d
0xffffffffa02a9830
0xffffffffa02a9835
0xffffffffa02a983a
0xffffffffa02a983d
0xffffffffa02a9842
0xffffffffa02a9845
0xffffffffa02a9848
0xffffffffa02a984d
0xffffffffa02a9850
0xffffffffa02a9855
0xffffffffa02a9858
0xffffffffa02a985b
0xffffffffa02a9860
0xffffffffa02a9868
0xffffffffa02a986d
0xffffffffa02a9870
0xffffffffa02a9875
0xffffffffa02a987c
0xffffffffa02a987e
0xffffffffa02a9885
0xffffffffa02a9888
0xffffffffa02a988d
从这里看
...
0xffffffffa02a9875
0xffffffffa02a987c
0xffffffffa02a987e
0xffffffffa02a9885
0xffffffffa02a9888
0xffffffffa02a988d
...
看rdi是从r12传入的,也就是说completion的地址保存在r12中。
接下来是找r12, r12是个callee saved register, 也就是说如果一个函数要用到r12,必须先把它保存到堆栈上。那么看看wait_for_completion到底会不会保存r12,反汇编。
crash7latest> dis -r wait_for_completion+271
0xffffffff816b6920
0xffffffff816b6921
0xffffffff816b6924
0xffffffff816b6928
0xffffffff816b692c
0xffffffff816b6930
0xffffffff816b6934
0xffffffff816b6938
0xffffffff816b693c
0xffffffff816b6941
0xffffffff816b6944
...
r12被保存到-0x20(%rbp)中了,注意这是地址.
...
#3 [ffff88015d1c3c50] wait_for_completion at ffffffff816b6a2f
ffff88015d1c3c58: ffff880100020002 ffff8802646f3f58
ffff88015d1c3c68: 0000000000000001 ffff880280345400
ffff88015d1c3c78: ffffffff810b7970 ffff8802646f3f80
ffff88015d1c3c88: ffff8802646f3f80 ffffffffa02af15e
ffff88015d1c3c98: ffff88015d1c3cc8 ffff8802646f3e00
ffff88015d1c3ca8: ffff8802646f3f70 ffff8802813db838
ffff88015d1c3cb8: 0000000000000200 ffff8802646f3030
ffff88015d1c3cc8: ffff88015d1c3d38 ffffffffa02a988d
...
-0x20(%rbp)=0xffff88015d1c3cc8-0x20=ffff88015d1c3ca8, 然后读这个地址里的值就是r12的值。
crash7latest> rd 0xffff88015d1c3ca8
ffff88015d1c3ca8: ffff8802646f3f70 p?od....
r12 是 ffff8802646f3f70, completion的地址是ffff8802646f3f70, 然后算算偏移是0x170.
最终ib_mad_agent_private地址是ffff8802646f3e00。
crash7latest> whatis unregister_mad_agent
void unregister_mad_agent(struct ib_mad_agent_private *);
crash7latest> struct ib_mad_agent_private -o
struct ib_mad_agent_private {
[0] struct list_head agent_list;
[16] struct ib_mad_agent agent;
[88] struct ib_mad_reg_req *reg_req;
[96] struct ib_mad_qp_info *qp_info;
[104] spinlock_t lock;
[112] struct list_head send_list;
[128] struct list_head wait_list;
[144] struct list_head done_list;
[160] struct delayed_work timed_work;
[288] unsigned long timeout;
[296] struct list_head local_list;
[312] struct work_struct local_work;
[344] struct list_head rmpp_list;
[360] atomic_t refcount;
[368] struct completion comp;
}
SIZE: 400
crash7latest> eval 368
hexadecimal: 170
decimal: 368
octal: 560
binary: 0000000000000000000000000000000000000000000000000000000101110000
crash7latest> eval 0xffff8802646f3f70 - 0x170
hexadecimal: ffff8802646f3e00
decimal: 18446612142589165056 (-131931120386560)
octal: 1777774200114433637000
binary: 1111111111111111100010000000001001100100011011110011111000000000
crash7latest> struct ib_mad_agent_private ffff8802646f3e00
struct ib_mad_agent_private {
agent_list = {
next = 0xdead000000000100,
prev = 0xdead000000000200
},
agent = {
device = 0xffff880264400000,
qp = 0xffff8802813d9800,
mr = 0xffff8801e15bcde0,
recv_handler = 0xffffffffa03c7160
send_handler = 0xffffffffa03c5820
snoop_handler = 0x0,
context = 0xffff8802646f3000,
hi_tid = 21438,
flags = 0,
port_num = 1 '\001',
rmpp_version = 0 '\000'
},
reg_req = 0xffff8800467aa5a0,
qp_info = 0xffff8802813db980,
lock = {
{
rlock = {
raw_lock = {
{
head_tail = 917518,
tickets = {
head = 14,
tail = 14
}
}
}
}
}
},
send_list = {
next = 0xffff8801da369918,
prev = 0xffff8801da369918
},
wait_list = {
next = 0xffff8802646f3e80,
prev = 0xffff8802646f3e80
},
done_list = {
next = 0xffff8802646f3e90,
prev = 0xffff8802646f3e90
},
timed_work = {
work = {
data = {
counter = 256
},
entry = {
next = 0xffff8802646f3ea8,
prev = 0xffff8802646f3ea8
},
func = 0xffffffffa02ab1f0
},
timer = {
entry = {
next = 0x0,
prev = 0xdead000000000200
},
expires = 4329013876,
base = 0xffff880286e91682,
function = 0xffffffff810a20a0
data = 18446612142589165216,
slack = -1,
start_pid = -1,
start_site = 0x0,
start_comm = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
},
wq = 0xffff88027a50fc00,
cpu = 2
},
timeout = 0,
local_list = {
next = 0xffff8802646f3f28,
prev = 0xffff8802646f3f28
},
local_work = {
data = {
counter = 68719476704
},
entry = {
next = 0xffff8802646f3f40,
prev = 0xffff8802646f3f40
},
func = 0xffffffffa02a9270
},
rmpp_list = {
next = 0xffff8802646f3f58,
prev = 0xffff8802646f3f58
},
refcount = {
counter = 2
},
comp = {
done = 0,
wait = {
lock = {
{
rlock = {
raw_lock = {
{
head_tail = 131074,
tickets = {
head = 2,
tail = 2
}
}
}
}
}
},
task_list = {
next = 0xffff88015d1c3c80,
prev = 0xffff88015d1c3c80
}
}
}
}