ftrace for MIPS
A message that is not in the archive (sent off-list or not yet received): 1255995599.17795.15.camel@falcon
A message that is not in the archive (sent off-list or not yet received): [email protected]
added CC to linux-mips and lkml.
Quoted 10 lines · Wu Zhangjin
Quoted 8 lines
3. to handle the non-leaf function(hijack the return address), we need to get the stack address of the return address, but it's not easy to get it in MIPS, search the return address in the stack space is not reliable, searching the text is
dangerous(pagefault..., have tried probe_kernel_read(), just hang there!), so, a clean solution maybe hacking gcc via pushing ra to 0(sp) or another "fixed"(fixed offset) stack address or recording the offset and transfer it to_mcount.
Quoted 9 lines
Have you figured out why you can't find the text? If mcount is called, you most definitely must have stored ra somewhere.
As for the hang with probe kernel read, I wonder if you need to disable tracing before using it. Or at least have a way not to recurs. I'm looking at
probe_kernel_read, and it looks like it would also be traced.Looking at x86 and powerpc, we hand do the probing.
Just added tracing_stop() and tracing_start() around probe_kernel_read(), it works(not hang again), and i can get the stack address of the ra register(return address) now, but failed when trying to hijack the return address via writing &return_to_handler in the stack address:
I can write hijack some of the addresses, but failed with this error at last:
Unable to handle kernel paging request at 0000000000000000, epc =
0000000000000000, ra = 000000000000.
Need to check which registers is missing when saving/restoring for _mcount:
NESTED(ftrace_graph_caller, PT_SIZE, ra)
MCOUNT_SAVE_REGS
PTR_S v0, PT_R2(sp)
MCOUNT_SET_ARGS
jal prepare_ftrace_return
nop
/* overwrite the parent as &return_to_handler: v0 -> $1(at) */
move $1, v0
PTR_L v0, PT_R2(sp)
MCOUNT_RESTORE_REGS
RETURN_BACK
END(ftrace_graph_caller)
.align 2
.globl return_to_handlerreturn_to_handler:
PTR_SUBU sp, PT_SIZE
PTR_S v0, PT_R2(sp)
jal ftrace_return_to_handler
nop
/* restore the real parent address: v0 -> ra */
move ra, v0
PTR_L v0, PT_R2(sp)
PTR_ADDIU sp, PT_SIZE
jr ra
...
.macro MCOUNT_SAVE_REGS
PTR_SUBU sp, PT_SIZE
PTR_S ra, PT_R31(sp)
PTR_S AT, PT_R1(sp)
PTR_S a0, PT_R4(sp)
PTR_S a1, PT_R5(sp)
PTR_S a2, PT_R6(sp)
PTR_S a3, PT_R7(sp)
#ifdef CONFIG_64BIT
PTR_S a4, PT_R8(sp)
PTR_S a5, PT_R9(sp)
PTR_S a6, PT_R10(sp)
PTR_S a7, PT_R11(sp)
#endif
.endm
.macro MCOUNT_RESTORE_REGS
PTR_L ra, PT_R31(sp)
PTR_L AT, PT_R1(sp)
PTR_L a0, PT_R4(sp)
PTR_L a1, PT_R5(sp)
PTR_L a2, PT_R6(sp)
PTR_L a3, PT_R7(sp)
#ifdef CONFIG_64BIT
PTR_L a4, PT_R8(sp)
PTR_L a5, PT_R9(sp)
PTR_L a6, PT_R10(sp)
PTR_L a7, PT_R11(sp)#endif
PTR_ADDIU sp, PT_SIZE
Regards,
Wu Zhangjin
Quoted 1 line · Wu Zhangjin
Just added
tracing_stop()andtracing_start()around
That seems a bit heavy handed. I still think writing it in "asm" the way x86 and powerpc do is the best.
Quoted 10 lines
probe_kernel_read(), it works(not hang again), and i can get the stack address of the ra register(return address) now, but failed when trying to hijack the return address via writing&return_to_handlerin the stack address:I can write hijack some of the addresses, but failed with this error at last:
Unable to handle kernel paging request at 0000000000000000, epc =0000000000000000, ra = 000000000000.
hmm, looks like you jumped to "0"
Quoted 6 lines
Need to check which registers is missing when saving/restoring for
_mcount:
NESTED(ftrace_graph_caller, PT_SIZE, ra)
Quoted 9 lines
MCOUNT_SAVE_REGS
PTR_S v0, PT_R2(sp)
MCOUNT_SET_ARGS
jal prepare_ftrace_return
nop
/* overwrite the parent as &return_to_handler: v0 -> $1(at) */
move $1, v0 I'm confused here? I'm not exactly sure what the above is doing. Is $1 a register (AT)? And how is this register used before calling mcount?
Quoted 11 lines
PTR_L v0, PT_R2(sp) MCOUNT_RESTORE_REGS RETURN_BACK END(ftrace_graph_caller) .align 2 .globl return_to_handler
return_to_handler:
PTR_SUBUsp,PT_SIZE
PTR_Sv0,PT_R2(sp)
BTW, is v0 the only return register? I know x86 can return two different registers depending on what it returns. What happens if a function returns a 64 bit value on a 32bit box? Does it use two registers for that?
-- Steve
Quoted 48 lines
jal
ftrace_return_to_handler
nop/* restore the real parent address: v0 -> ra */
move ra, v0
PTR_Lv0,PT_R2(sp)
PTR_ADDIUsp,PT_SIZEjr ra
...
.macro MCOUNT_SAVE_REGS PTR_SUBU sp, PT_SIZE PTR_S ra, PT_R31(sp) PTR_S AT, PT_R1(sp) PTR_S a0, PT_R4(sp) PTR_S a1, PT_R5(sp) PTR_S a2, PT_R6(sp) PTR_S a3, PT_R7(sp) #ifdef CONFIG_64BIT PTR_S a4, PT_R8(sp) PTR_S a5, PT_R9(sp) PTR_S a6, PT_R10(sp) PTR_S a7, PT_R11(sp) #endif .endm .macro MCOUNT_RESTORE_REGS PTR_L ra, PT_R31(sp) PTR_L AT, PT_R1(sp) PTR_L a0, PT_R4(sp) PTR_L a1, PT_R5(sp) PTR_L a2, PT_R6(sp) PTR_L a3, PT_R7(sp) #ifdef CONFIG_64BIT PTR_L a4, PT_R8(sp) PTR_L a5, PT_R9(sp) PTR_L a6, PT_R10(sp) PTR_L a7, PT_R11(sp)#endif
PTR_ADDIUsp,PT_SIZERegards,
Wu Zhangjin
Hi, all
Just made it(function graph tracer for MIPS) work :-)
The problem is that: the stack offset should be from 0 to PT_SIZE(304), but I mask it with 0xff(256), which is totally wrong.
Here is an example, the stack address of ra(return address) should be (s8 + ffbf0128 & 0xfff).
ffffffff801dad10 <do_sync_read>:
ffffffff801dad10: 67bdfed0 daddiu sp,sp,-304 ffffffff801dad14: ffbe0120 sd s8,288(sp) ffffffff801dad18: 03a0f02d move s8,sp ffffffff801dad1c: ffbf0128 sd ra,296(sp) ffffffff801dad20: ffb30118 sd s3,280(sp) ffffffff801dad24: ffb20110 sd s2,272(sp) ffffffff801dad28: ffb10108 sd s1,264(sp) ffffffff801dad2c: ffb00100 sd s0,256(sp) ffffffff801dad30: 03e0082d move at,ra ffffffff801dad34: 0c042ab0 jal ffffffff8010aac0
<_mcount>ffffffff801dad38: 00020021 nop
Thanks! will send the patches out later.
Regards,
Wu Zhangjin
Quoted 107 lines · Steven Rostedt
Quoted 1 line · Wu Zhangjin
Just added
tracing_stop()andtracing_start()aroundThat seems a bit heavy handed. I still think writing it in "asm" the way x86 and powerpc do is the best.
Quoted 10 lines
probe_kernel_read(), it works(not hang again), and i can get the stack address of the ra register(return address) now, but failed when trying to hijack the return address via writing&return_to_handlerin the stack address:I can write hijack some of the addresses, but failed with this error at last:
Unable to handle kernel paging request at 0000000000000000, epc =0000000000000000, ra = 000000000000.
hmm, looks like you jumped to "0"
Quoted 6 lines
Need to check which registers is missing when saving/restoring for
_mcount:
NESTED(ftrace_graph_caller, PT_SIZE, ra)Quoted 9 lines
MCOUNT_SAVE_REGS PTR_S v0, PT_R2(sp) MCOUNT_SET_ARGS jal prepare_ftrace_return nop /* overwrite the parent as &return_to_handler: v0 -> $1(at) */ move $1, v0I'm confused here? I'm not exactly sure what the above is doing. Is $1 a register (AT)? And how is this register used before calling mcount?
Quoted 11 lines
PTR_L v0, PT_R2(sp) MCOUNT_RESTORE_REGS RETURN_BACK END(ftrace_graph_caller) .align 2 .globl return_to_handler
return_to_handler:
PTR_SUBUsp,PT_SIZE
PTR_Sv0,PT_R2(sp)BTW, is v0 the only return register? I know x86 can return two different registers depending on what it returns. What happens if a function returns a 64 bit value on a 32bit box? Does it use two registers for that?
-- Steve
Quoted 48 lines
jal
ftrace_return_to_handler
nop/* restore the real parent address: v0 -> ra */
move ra, v0
PTR_Lv0,PT_R2(sp)
PTR_ADDIUsp,PT_SIZEjr ra
...
.macro MCOUNT_SAVE_REGS PTR_SUBU sp, PT_SIZE PTR_S ra, PT_R31(sp) PTR_S AT, PT_R1(sp) PTR_S a0, PT_R4(sp) PTR_S a1, PT_R5(sp) PTR_S a2, PT_R6(sp) PTR_S a3, PT_R7(sp) #ifdef CONFIG_64BIT PTR_S a4, PT_R8(sp) PTR_S a5, PT_R9(sp) PTR_S a6, PT_R10(sp) PTR_S a7, PT_R11(sp) #endif .endm .macro MCOUNT_RESTORE_REGS PTR_L ra, PT_R31(sp) PTR_L AT, PT_R1(sp) PTR_L a0, PT_R4(sp) PTR_L a1, PT_R5(sp) PTR_L a2, PT_R6(sp) PTR_L a3, PT_R7(sp) #ifdef CONFIG_64BIT PTR_L a4, PT_R8(sp) PTR_L a5, PT_R9(sp) PTR_L a6, PT_R10(sp) PTR_L a7, PT_R11(sp)#endif
PTR_ADDIUsp,PT_SIZERegards,
Wu Zhangjin
Quoted 21 lines · Wu Zhangjin
Hi, all
Just made it(function graph tracer for MIPS) work :-)
The problem is that: the stack offset should be from 0 to
PT_SIZE(304), but I mask it with 0xff(256), which is totally wrong.Here is an example, the stack address of ra(return address) should be (s8 +
ffbf0128&0xfff).
ffffffff801dad10<do_sync_read>:ffffffff801dad10: 67bdfed0 daddiu sp,sp,-304 ffffffff801dad14: ffbe0120 sd s8,288(sp) ffffffff801dad18: 03a0f02d move s8,sp ffffffff801dad1c: ffbf0128 sd ra,296(sp) ffffffff801dad20: ffb30118 sd s3,280(sp) ffffffff801dad24: ffb20110 sd s2,272(sp) ffffffff801dad28: ffb10108 sd s1,264(sp) ffffffff801dad2c: ffb00100 sd s0,256(sp) ffffffff801dad30: 03e0082d move at,ra ffffffff801dad34: 0c042ab0 jal ffffffff8010aac0
Quoted 4 lines
<
_mcount>ffffffff801dad38: 00020021 nopThanks! will send the patches out later.
Great to hear that it works! When I get my cross compiling working I'll test out your patches.
I'll also probably update them to use the asm() over the probe and tracing_disable(). That method is very inefficient.
Good work!
-- Steve
Hello.
Quoted 11 lines · Steven Rostedt
Quoted 11 lines
Need to check which registers is missing when saving/restoring for
_mcount:
NESTED(ftrace_graph_caller, PT_SIZE, ra)MCOUNT_SAVE_REGS PTR_S v0, PT_R2(sp) MCOUNT_SET_ARGS jal prepare_ftrace_return nop
Quoted 5 lines
Quoted 2 lines
/* overwrite the parent as
&return_to_handler: v0 -> $1(at) */
move $1, v0I'm confused here? I'm not exactly sure what the above is doing. Is $1 a register (AT)?
Yes.
Quoted 13 lines
And how is this register used before calling mcount?
Quoted 10 lines
PTR_L v0, PT_R2(sp) MCOUNT_RESTORE_REGS RETURN_BACK END(ftrace_graph_caller) .align 2 .globl return_to_handler
return_to_handler:
PTR_SUBUsp,PT_SIZE
PTR_Sv0,PT_R2(sp)
Quoted 4 lines
BTW, is v0 the only return register? I know x86 can return two different registers depending on what it returns. What happens if a function returns a 64 bit value on a 32bit box? Does it use two registers for that?
Yes, there's also v1 register.
WBR, Sergei
Quoted 15 lines · Sergei Shtylyov
Hello.
Quoted 11 lines · Steven Rostedt
Quoted 11 lines
Need to check which registers is missing when saving/restoring for
_mcount:
NESTED(ftrace_graph_caller, PT_SIZE, ra)MCOUNT_SAVE_REGS PTR_S v0, PT_R2(sp) MCOUNT_SET_ARGS jal prepare_ftrace_return nop
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
/* overwrite the parent as
&return_to_handler: v0 -> $1(at) */
move $1, v0I'm confused here? I'm not exactly sure what the above is doing. Is $1 a register (AT)?
Yes.
Have replaced it by AT, thanks!
Quoted 14 lines
Quoted 13 lines
And how is this register used before calling mcount?
Quoted 10 lines
PTR_L v0, PT_R2(sp) MCOUNT_RESTORE_REGS RETURN_BACK END(ftrace_graph_caller) .align 2 .globl return_to_handler
return_to_handler:
PTR_SUBUsp,PT_SIZE
PTR_Sv0,PT_R2(sp)
Quoted 7 lines
Quoted 4 lines
BTW, is v0 the only return register? I know x86 can return two different registers depending on what it returns. What happens if a function returns a 64 bit value on a 32bit box? Does it use two registers for that?
Yes, there's also v1 register.
Thanks, added.
Regards,
Wu Zhangjin