Android4.2 Emulator Kernel Debugging

This article will discuss something about Android4.2 kernel debugging,i won’t tell you how to set up the environment , if you want to know how,please review this article : Android Linux内核编译调试 , but that article still contains some errors, for example , the command to open an emulator that can be debugged is as below:

emulator -verbose -show-kernel -netfast -kernel  kernel/goldfish/arch/arm/boot/zImage -sdcardsdcard.img  -partition-size 1024 -datauserdata.img -qemu -gdbtcp::1234 -S

After set up the environment,we can use gdb to connect to the emulator:

arm-linux-androideabi-gdb  /xxx/kernel/goldfish/vmlinux
targetremotelocalhost:1234

1.how to get sys_call_table

In kernel mode, sys call is the most important thing that can communicate with user mode, sys call table contains all the sys call’s addr. so, how could we get sys call table’s addr? I got two ways to get that addr:

  1. get sys call table’s addr by calculating the offset.
  2. read from system.map

For the first way,we can use code like below:

void get_sys_call_table(){
 
 // Interrupt tables are loaded in high memory in android starting at 0xffff0000
 
 void *swi_table_addr=(long *)0xffff0008; // Known address of Software Interrupt handler
 unsigned long offset_from_swi_vector_adr=0;
 unsigned long *swi_vector_adr=0;
 
 offset_from_swi_vector_adr=((*(long *)swi_table_addr)&0xfff)+8;
 swi_vector_adr=*(unsigned long *)(swi_table_addr+offset_from_swi_vector_adr);
 
 while(swi_vector_adr++){
 if(((*(unsigned long *)swi_vector_adr)&0xfffff000)==0xe28f8000){ // Copy the entire sys_call_table from the offset_from_swi_vector_adr starting the hardware interrupt table
 offset_from_swi_vector_adr=((*(unsigned long *)swi_vector_adr)&0xfff)+8;  // 0xe28f8000 is end of interrupt space. Hence we stop.
 sys_call_table=(void *)swi_vector_adr+offset_from_swi_vector_adr;
 break;
 }
 }
 return;
}

The system.map contains kernel function address,you can find sys_call_table’s addr in this file:

c0032d84 T sys_call_table
c0033334 t sys_syscall
c003335c t sys_fork_wrapper
...

use gdb to see sys call table’s items:

2.break at sys call’s entry

In Android, r7 register contains sys call num,through instruction “svc 0″ to enter kernel mode. so, if we want to debug a sys call directly, just set a breakpoint at sys call’s entry . The entry is at arch/arm/kernel/entry-common.S :

ENTRY(vector_swi)
 subsp, sp, #S_FRAME_SIZE
 stmiasp, {r0 - r12} @ Callingr0 - r12
 addr8, sp, #S_PC
 stmdbr8, {sp, lr}^ @ Callingsp, lr
 mrsr8, spsr @ calledfromnon-FIQmode, sook.
 strlr, [sp, #S_PC] @ Save calling PC
 strr8, [sp, #S_PSR] @ Save CPSR
 strr0, [sp, #S_OLD_R0] @ Save OLD_R0
 zero_fp
 
 /*
* Get the system call number.
*/
 
#if defined(CONFIG_OABI_COMPAT)
 
 /*
* If we have CONFIG_OABI_COMPAT then we need to look at the swi
* value to determine if it is an EABI or an old ABI call.
*/
#ifdef CONFIG_ARM_THUMB
 tstr8, #PSR_T_BIT
 movner10, #0 @ no thumb OABI emulation
 ldreqr10, [lr, #-4] @ get SWI instruction
#else
 ldrr10, [lr, #-4] @ get SWI instruction
  A710( and ip, r10, #0x0f000000 @ check for SWI )
  A710( teqip, #0x0f000000 )
  A710( bne .Larm710bug )
#endif
 
#elif defined(CONFIG_AEABI)
 
 /*
* Pure EABI user space always put syscall number into scno (r7).
*/
  A710( ldrip, [lr, #-4] @ get SWI instruction )
  A710( and ip, ip, #0x0f000000 @ check for SWI )
  A710( teqip, #0x0f000000 )
  A710( bne .Larm710bug )
 
#elif defined(CONFIG_ARM_THUMB)
 
 /* Legacy ABI only, possibly thumb mode. */
 tstr8, #PSR_T_BIT @ this is SPSR from save_user_regs
 addnescno, r7, #__NR_SYSCALL_BASE @ put OS number in
 ldreqscno, [lr, #-4]
 
#else
 
 /* Legacy ABI only. */
 ldrscno, [lr, #-4] @ get SWI instruction
  A710( and ip, scno, #0x0f000000 @ check for SWI )
  A710( teqip, #0x0f000000 )
  A710( bne .Larm710bug )
 
#endif
 
#ifdef CONFIG_ALIGNMENT_TRAP
 ldrip, __cr_alignment
 ldrip, [ip]
 mcrp15, 0, ip, c1, c0 @ updatecontrolregister
#endif
 enable_irq
 
 get_thread_infotsk
 adrtbl, sys_call_table @ loadsyscalltablepointer
 ldrip, [tsk, #TI_FLAGS] @ check for syscall tracing
 
#if defined(CONFIG_OABI_COMPAT)
 /*
* If the swi argument is zero, this is an EABI call and we do nothing.
*
* If this is an old ABI call, get the syscall number into scno and
* get the old ABI syscall table address.
*/
 bicsr10, r10, #0xff000000
 eornescno, r10, #__NR_OABI_SYSCALL_BASE
 ldrnetbl, =sys_oabi_call_table
#elif !defined(CONFIG_AEABI)
 bicscno, scno, #0xff000000 @ mask off SWI op-code
 eorscno, scno, #__NR_SYSCALL_BASE @ check OS number
#endif
 
 stmdbsp!, {r4, r5} @ pushfifthand sixthargs
 tstip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
 bne__sys_trace
 
 cmpscno, #NR_syscalls

we can set a breakpoint at this instruction:

bne__sys_trace

use conditional breakpoint to monitor some special sys call:

b arch/arm/kernel/entry-common.S:265 if $r7==0xf0002

稿源:IT Dreamer (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 后端存储 » Android4.2 Emulator Kernel Debugging

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录