Debug analysis: PC pointer analysis error based on kernel error information

Publisher:快乐航程Latest update time:2024-08-13 Source: cnblogs Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

When you write a driver, have you noticed that when we write the driver incorrectly and the kernel crashes, a lot of error messages will be printed.


If we go back to our program and check the code line by line, it will be time-consuming and some logical errors will be difficult for us to see.


So can we find the problem in this pile of error messages?


Here we simulate an error, still using the driver code err_led.c in the previous article to modify the code in the driver. Of course, you can use other driver codes for testing.


1 40 static int key_open(struct inode *inode, struct file *file)

2 41 {

3 42 printk("<0>function open!nn");

4 43

5 44 base_iomux = 0x43FAC000;

6 45 MUX_CTL &= ~(0x07 << 0);

7 46 MUX_CTL |= (0X05 << 0); //Set to ALT5 GPIO3_23 ERR_LED

8 47

9 48 //MUX_CTL

10 49 return 0;

11 50 }


If you directly set base_iomux = the actual physical address, you will definitely get an error.


Load and compile, and as we wish, the kernel crash information is successfully printed:

e70df5f4055a9a531c1349e91267c9f4_ZdevbS2dVDtolhVpT7DTVg0wEZ89e+b4+GS69W8vfOCdRC872IuloP8BIGNc9hmjNwsAAAAASUVORK5CYII=.png

Next, let's analyze whether we can find any clues from this information. Let's witness the moment of miracle together.


1 root@EasyARM-iMX257 ~# echo 1 > /dev/err_led_dev

2 function open!

3

4 Unable to handle kernel paging request at virtual address 43fac060

5 //Cannot access virtual address 43fac060, because the driver accesses virtual addresses, and the address 43fac060 is not mapped, so it cannot be accessed

6

7pgd = c3b8c000

8 [43fac060] *pgd=00000000

9 Internal error: Oops: 5 [#2] PREEMPT

10 Modules linked in: err_led mymsg gpio [ Tainted: G D (2.6.31-207-g7286c01 #692)

11 //When an error occurs, the modules loaded by the system include err_led mymsg gpio

12

13 PC is at key_open+0x18/0x54 [err_led]

14 //PC is the instruction address where the error occurred. The function where the error occurred is key_open, offset 0x18. In fact, it is already very obvious here.

15

16 LR is at key_open+0x10/0x54 [err_led]

17 //LR register value

18

19 pc : [] lr : [] psr: 60000013

20 //The value of the pc pointer when an error occurs: bf010128

twenty one

22 sp: c32c3e70 ip: c046708f fp: 00095ab0

23 r10: c3b9aae0 r9: c320 r4: 00000001

24 r3 : 00000000 r2 : 00000000 r1 : 43facfff r0 : 43fac000

25 //The values ​​of each register when executing this error

26

27 Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user

28 Control: 0005317f Table: 83b8c000 DAC: 000000 limit = 0xc32c2270)

29

30 //When an error occurs, stack information

31

32 Stack: (0xc32c2000 c00bb9d0 0000000b c3 c31790c8 00000000 c00bb7fc c380f0a0 c31b6398 c00b66b4

33 3ea0: c32c3ef8 c3b9aae0 c3885660 c32c3e0b76d4

34 3ec0: 00000000 c3885660 c32c3ef0 00000000 c32c3ef0 c00c4288 00000000 000001b6

35 3ee0: 00020241 00000000 00000000 00000000000b

36 3f00: c3b91005 c380f2200000 00005402 00000036

37 3f20: 00000000 c00c5698 c31498a0 fffffff7 be880704 c00c5d34 c32c3f84 00 c3879d60 00000003 c380f0a0 c31b6398 00000000 00020241

38 3f60: 000001b6 ffffff9c 00000000 c0029f24 c3b91000 00000003 00095ab0 c00b6444

39 3f80: 00000022 00000000 000001b6 000932ac 00000001 00000005 c0029f24 c32c2000

40 3fa0: 40138000 c0029da0 000001b6 000932000000

41 3fc0: 000001b6 000932ac 00000001 00000005 00000000 000933f8 40138000 00095ab0

42 3fe0: 000903ac be8803d8 00035c28 400d110x18/0x54 [err_led]) from [] (chrdev_open+0x1d4/0x1f4)

43 [] (chrdev_open+0x1d4/0x1f4) from [] (__dentry_open+0x18c/0x2ac)

44 [] (__dentry_open+0x18c/0x2ac) from [] (nameidata_to_filp+0x44/0x5c)

45 [] (nameidata_to_filp+0x44/0x5c) from [] (do_filp_open+0x3e4/0x7e8)

46 [] (do_filp_open+0x3e4/0x7e8) from [] (do_sys_open+0x5c/0x114)

47 [114) from [] (ret_fast_syscall+0x0/0x2c)

48 Code: e24dd004 eb40e05c e59f1030 e59f0030 (e5113f9f)

49 ---[ end trace c4bb5578ca399f8a ]---

50 process '/sbin/getty -L ttymxc0 115200 vt100' (pid 1832) exited. Scheduling for restart.

51 starting pid 1833, tty '': '/sbin/getty -L ttymxc0 115200 vt100'

52 CC) 4.1.2

53 root filesystem built on Tue, 13 Aug 2013 02:31:56 -0700

54 Freescale Semiconductor, Inc.

55

56

57 //If the kernel configuration option selects kernel's FRAME_POINTER

58 -->kernel hacking

59 - - → - - > kernel debugging (DEBUG_KERNEL)

60 //Here will print the rough backtrace information, that is, a series of kernel pointer call information.

61 Backtrace:


Sometimes the pc value will only give an address, not the function.



1. According to the PC value above, find the address where the error occurs: System.map


First determine whether the address belongs to the kernel: look at linux-2.6.31/System.map in the source code directory


1 root@Lover snow:/home/study/nfs_home/system/linux-2.6.31# vi System.map

2 1 c0004000 A swapper_pg_dir

3 2 c0008000 T __init_begin

4 3 c0008000 T _sinittext

5 4 c0008000 T stext

6 5 c0008000 T _stext

7 6 c0008034 t __enable_mmu

8 ..........

9 32128 c04a0d64 b ratelimit.21298

10 32129 c04a0d68 b pipe_version_lock

11 32130 c04a0d68 b pipe_version_rpc_waitqueue

12 32131 c04a0db4 b rsc_table

13 32132 c04a1db4 b rsi_table

14 32133 c04a1eb8 B krb5_seq_lock

15 32134 c04a1ec0 b i.21559

16 32135 c04a1ec8 b wireless_nlevent_queue

17 32136 c04a1ed4 B __bss_stop

18 32137 c04a1ed4 B _end


It can be found that the kernel address range is c0004000 ~ c04a1ed4. If it belongs to this range, it is a kernel error.



If it is not in scope in System.map, then it belongs to the program loaded by insmod.]


Because our PC value is bf010128, it definitely does not belong to the kernel.



2. Assuming it is an error introduced by a loaded driver, how do I determine which driver it is?


/proc/kallsyms


First, look at the address range of the loaded driver's function.cat /proc/kallsyms > 1.txt


Run cat /proc/kallsyms > 1.txt on the development board


Check PC = bf010128 in 1.txt

28484 bf0100ec t key_read [err_led]

28485 bf0100ec t $a [err_led]

28486 bf01010c t $d [err_led]

28487 bf010110 t key_open [err_led]

28488 bf010110 t $a [err_led]

28489 bf010154 t $d [err_led]

28490 bf010164 t $a [err_led]

28491 bf010248 t $d [err_led]

28492 bf01024c t key_irq_exit [err_led]

28493 bf01024c t $a [err_led]

28494 bf0102ac t $d [err_led]


You can find: the addresses of all programs in our program,


We find the place close to the PC value and smaller than it, and we can find that the program we are debugging is in key_open.


t: static function


T: Global function


Then, using this found address plus our offset address, we can find our error.



3. Found our driver err_led.ko disassembly


1 root@Lover snow:/home/study/nfs_home/module/36_my_proc_prink/test#

2 arm-none-linux-gnueabi-objdump -D err_led.ko > err_led.txt

3 root@Lover snow:/home/study/nfs_home/module/36_my_proc_prink/test#

4 vi err_led.txt

5 Below is the disassembly code of our err_led.ko:

6 Find the key_open function in the disassembled code and add the offset 0x18

7

8 84 00000110 :

9 85 110: e52de004 str lr, [sp, #-4]!

10 86 114: e59f0038 ldr r0, [pc, #56] ; 154 <.text+0x154>

11 87 118: e24dd004 sub sp, sp, #4; 0x4

12 88 11c: ebfffffe bl 0

13 89 120: e59f1030 ldr r1, [pc, #48] ; 158 <.text+0x158>

14 90 124: e59f0030 ldr r0, [pc, #48] ; 15c <.text+0x15c>

15 91 128: e5113f9f ldr r3, [r1, #-3999]

16 92 12c: e3c33007 bic r3, r3, #7; 0x7 //R3 &= ~(0x07)

17 93 130: e5013f9f str r3, [r1, #-3999]

18 94 134: e5112f9f ldr r2, [r1, #-3999]

19 95 138: e59f3020 ldr r3, [pc, #32] ; 160 <.text+0x160>

20 96 13c: e3822005 orr r2, r2, #5; 0x5 //R3 |= 0x05

21 97 140: e5830000 str r0, [r3]

22 98 144: e3a00000 mov r0, #0 ; 0x0



As shown in the code above, it is easy to find the error address.


Analyzing the assembly code:


Next is the time to examine the compilation skills.


According to the assembly code, the C language code is derived:


From the above, we can infer R3 &= ~(0x07) and R3 |= 0x05, and then match them with the program:


1 40 static int key_open(struct inode *inode, struct file *file)

2 41 {

3 42 printk("<0>function open!nn");

4 43

5 44 base_iomux = 0x43FAC000;

6 45 MUX_CTL &= ~(0x07 << 0);

7 46 MUX_CTL |= (0X05 << 0); //Set to ALT5 GPIO3_23 ERR_LED

8 47

9 48 //MUX_CTL

10 49 return 0;

11 50 }


It can be found that they are exactly the same. So we get that there is an error in MUX_CTL.


According to MUX_CTL, we can naturally get base_iomux, which has an error.


Attach the driver: err_led.c

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #include

10 #include

11 #include

12 #include

13 #include

14

15 #define Driver_NAME "err_led_dev"

16 #define DEVICE_NAME "err_led_dev"

17

18 static int major = 0;

19

20 //auto to create device node

21 static struct class *drv_class = NULL;

22 static struct class_device *drv_class_dev = NULL;

twenty three

24 //Register base address;

25 static unsigned long base_iomux; //iomux base address 0X 43FA C000 - 0X 43FA FFFF

26 static unsigned long base_gpio3; //gpio3 0X 53FA 4000 - 0X 53FA 7FFF

[1] [2] [3]
Reference address:Debug analysis: PC pointer analysis error based on kernel error information

Previous article:Debug analysis: Analyze errors based on kernel error information stack information
Next article:Debugging and analysis of the implementation of mymsg and myprintk under proc in imx257

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号