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:
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 : [
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 [
43 [
44 [
45 [
46 [
47 [114) from [
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
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
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- How to use a switching boost chip to solder a circuit to achieve 5-24V output
- Here is a basic CAD shortcut key
- [GD32L233C-START Review] 1. Unboxing + Environment Setup
- Maxim Basic Analog IC APP download helps you innovate analog design!
- How is the internal low-pass filter of Bh1415 designed? How is the 150pf connected to pin 3 determined?
- Its automobile inner wheel difference safety warning system
- Detailed explanation of the principles of 24 typical application circuits of capacitors
- Some experience of debugging dsp in CCS
- TI C2000 MCU DesignDRIVE Solutions for Industrial Motor Drives
- Application of reflective memory network in long-distance distributed system