[PATCH] Fix agent code generate bug of ref

Hui Zhu
2013-03-10T05:01:08Z

[-- Attachment #1: Type: text/plain, Size: 3258 bytes --]

Hi,

I meet a issue with tracepoint and Linux kernel is:
(gdb) list update_curr
590 cfs_rq->load_unacc_exec_time += delta_exec;
591 #endif
592 }
593
594 static void update_curr(struct cfs_rq *cfs_rq)
595 {
596 struct sched_entity *curr = cfs_rq->curr;
597 u64 now = rq_of(cfs_rq)->clock;
598 unsigned long delta_exec;
599
(gdb)
600 if (unlikely(!curr))
601 return;
602
603 /*
604 * Get the amount of time the current task was running
605 * since the last time we changed load (this cannot
606 * overflow on 32 bits):
607 */
608 delta_exec = (unsigned long)(now - curr->exec_start);
609 if (!delta_exec)
(gdb) trace 609
Tracepoint 1 at 0xffffffff8104ced6: file
/home/teawater/kernel/taobao-kernel/tmp/linux-2.6.32-220.23.1.el5/kernel/sched_fair.c,
line 609.
(gdb) actions
Enter actions for tracepoint 1, one per line.
End with a line saying just "end".
>collect now
>end
(gdb) tstart

Then it will failed in kernel part, the address that send to kernel to
collect is 0x978. But the right address of now is 0xffff880002215578.

I check the agent code that is got is:
(gdb) maintenance agent -at sched_fair.c:609, now
Scope: 0xffffffff8104ced6
Reg mask: 20
0 reg 5
3 const16 128
6 add
7 ref8
8 const16 2232
11 add
12 const8 8
14 trace
15 end

I think ref8 is not right because this acode try to get a address from
Linux kernel. It should be ref64.
I check the code of function dwarf2_compile_expr_to_ax:
case DW_OP_deref:
case DW_OP_deref_size:
{
int size;

if (op == DW_OP_deref_size)
size = *op_ptr++;
else
size = addr_size;

switch (size)
{
case 8:
ax_simple (expr, aop_ref8);
aop_ref8 means ref 8 bits. So use addr_size is not right, I add first
patch fix-op_deref-size.txt to change addr_size to addr_size_bits.
Then the first issue is fixed.

And I found that GDB generate right code the collect value from
0xffff880002215578.

But after that, I still got error when I tfind:
(gdb) tfind
Found trace frame 0, tracepoint 1
#0 update_curr (cfs_rq=0xffff880002214d28, cfs_rq@entry=<error
reading variable: PC not available>)
at /home/teawater/kernel/taobao-kernel/tmp/linux-2.6.32-220.23.1.el5/kernel/sched_fair.c:609
609 if (!delta_exec)
(gdb) p now
Cannot access memory at address 0xffff880002214da8

This issue is because aop just collect value of now, but not ref
address. But GDB need this value.
So I add second patch trace_def_if_trace.txt to call ax_trace_quick if need.

Then the aop will be changed to:
(gdb) maintenance agent -at sched_fair.c:609, now
Scope: 0xffffffff8104ced6
Reg mask: 20
0 reg 5
3 const16 128
6 add
7 trace_quick 8
9 ref64
10 const16 2232
13 add
14 const8 8
16 trace
17 end

Then all the issue of this tracepoint is fixed. But I failed with
make a test code with it. So I just can repeoduce in this Linux
kernel code.

I suggest the next release just this 2 patches because this 2 issue
will affect some code of aop.

Thanks,
Hui

2013-03-10 Hui Zhu <hui_zhu@mentor.com>

* dwarf2loc.c (dwarf2_compile_expr_to_ax): Change addr_size to
addr_size_bits if DW_OP_deref.

2013-03-10 Hui Zhu <hui_zhu@mentor.com>

* dwarf2loc.c (dwarf2_compile_expr_to_ax): Call ax_trace_quick
if need.

[-- Attachment #2: fix-op_deref-size.txt --]
[-- Type: text/plain, Size: 259 bytes --]

--- a/dwarf2loc.c
+++ b/dwarf2loc.c
@@ -2929,7 +2929,7 @@ dwarf2_compile_expr_to_ax (struct agent_
if (op == DW_OP_deref_size)
size = *op_ptr++;
else
- size = addr_size;
+ size = addr_size_bits;

switch (size)
{

[-- Attachment #3: trace_def_if_trace.txt --]
[-- Type: text/plain, Size: 256 bytes --]

--- a/dwarf2loc.c
+++ b/dwarf2loc.c
@@ -2931,6 +2931,9 @@ dwarf2_compile_expr_to_ax (struct agent_
else
size = addr_size_bits;

+ if (trace_kludge)
+ ax_trace_quick (expr, size / 8);
+
switch (size)
{
case 8: