1. When the drive is wrong , such as , The memory address accessed is illegal , You'll print a bunch of oops come out
take open() Function ioremap() Screen out , Using physical address directly GPIOF, As shown in the figure below :
1.2 Then compile and load 26th_segmentfault And after executing the test program , The kernel prints oops come out , As shown in the figure below :
Unable to handle kernel paging request at virtual address 56000050 // Unable to process virtual address for kernel page request 56000050pgd = c3850000 *pgd=00000000Internal error: Oops: 5 [#1] // internal error oopsModules linked in: 26th_segmentfault // Indicates that an internal error occurred in 26th_segmentfault.ko In the driver module CPU: 0 Not tainted (188.8.131.52 #2)PC is at first_drv_open+0x78/0x12c [26th_segmentfault] //PC value : The last address of the program running successfully , be located first_drv_open() In the function , Offset value 0x78, The total size of the function 0x12cLR is at 0xc0365ed8 //LR value /* Each register value at the time of the error */pc : [<bf000078>] lr : [<c0365ed8>] psr: 80000013sp : c3fcbe80 ip : c0365ed8 fp : c3fcbe94 r10: 00000000 r9 : c3fca000 r8 : c04df960 r7 : 00000000 r6 : 00000000 r5 : bf000de4 r4 : 00000000r3 : 00000000 r2 : 56000050 r1 : 00000001 r0 : 00000052Flags: Nzcv IRQs on FIQs on Mode SVC_32 Segment user Control: c000717f Table: 33850000 DAC: 00000015Process 26th_segmentfau (pid: 813, stack limit = 0xc3fca258) // When something goes wrong , The process name is 26th_segmentfaultStack: (0xc3fcbe80 to 0xc3fcc000) // The stack information be80: c06d7660 c3e880c0 c3fcbebc c3fcbe98 c008d888 bf000010 00000000 c04df960 bea0: c3e880c0 c008d73c c0474e20 c3fb9534 c3fcbee4 c3fcbec0 c0089e48 c008d74c bec0: c04df960 c3fcbf04 00000003 ffffff9c c002c044 c380a000 c3fcbefc c3fcbee8 bee0: c0089f64 c0089d58 00000000 00000002 c3fcbf68 c3fcbf00 c0089fb8 c0089f40 bf00: c3fcbf04 c3fb9534 c0474e20 00000000 00000000 c3851000 00000101 00000001bf20: 00000000 c3fca000 c04c90a8 c04c90a0 ffffffe8 c380a000 c3fcbf68 c3fcbf48 bf40: c008a16c c009fc70 00000003 00000000 c04df960 00000002 be84ce38 c3fcbf94 bf60: c3fcbf6c c008a2f4 c0089f88 00008588 be84ce84 00008718 0000877c 00000005bf80: c002c044 4013365c c3fcbfa4 c3fcbf98 c008a3a8 c008a2b0 00000000 c3fcbfa8 bfa0: c002bea0 c008a394 be84ce84 00008718 be84ce30 00000002 be84ce38 be84ce30 bfc0: be84ce84 00008718 0000877c 00000003 00008588 00000000 4013365c be84ce58 bfe0: 00000000 be84ce28 0000266c 400c98e0 60000010 be84ce30 30002031 30002431Backtrace: // Backtracking information [<bf000000>] (first_drv_open+0x0/0x12c [26th_segmentfault]) from [<c008d888>] (chrdev_open+0x14c/0x164) r5:c3e880c0 r4:c06d7660[<c008d73c>] (chrdev_open+0x0/0x164) from [<c0089e48>] (__dentry_open+0x100/0x1e8) r8:c3fb9534 r7:c0474e20 r6:c008d73c r5:c3e880c0 r4:c04df960[<c0089d48>] (__dentry_open+0x0/0x1e8) from [<c0089f64>] (nameidata_to_filp+0x34/0x48)[<c0089f30>] (nameidata_to_filp+0x0/0x48) from [<c0089fb8>] (do_filp_open+0x40/0x48) r4:00000002[<c0089f78>] (do_filp_open+0x0/0x48) from [<c008a2f4>] (do_sys_open+0x54/0xe4) r5:be84ce38 r4:00000002[<c008a2a0>] (do_sys_open+0x0/0xe4) from [<c008a3a8>] (sys_open+0x24/0x28)[<c008a384>] (sys_open+0x0/0x28) from [<c002bea0>] (ret_fast_syscall+0x0/0x2c)Code: bf000094 bf0000b4 bf0000d4 e5952000 (e5923000)Segmentation fault
For example, the backtracking information above shows :
In the end, the mistake was first_drv_open();
If the kernel is not configured to display backtracking information , The function call procedure is not printed , You can modify the kernel's .config file , add to :
//CONFIG_FRAME_POINTER, Represents the frame pointer , use fp Register means
In the kernel , Would pass fp Registers record where functions run , Coexist in the stack , And then when something goes wrong , Pull it out of the stack fp register , Look at the calling relationship of the function , You can see the backtracking information .
(PS: If not configured , You can also analyze the function calling process directly through the stack , In the next chapter we will analyze :http://www.cnblogs.com/lifexy/p/8011966.html)
Modules linked in: 26th_segmentfault PC is at first_drv_open+0x78/0x12c [26th_segmentfault]
This information , Print only PC value , There's no way to know , What's wrong with the driver module , It's the kernel's own function ?
therefore oops The most important part of this article is this passage : pc : 
2.3 So how to determine , The PC Functions with value addresses in the kernel , Or the driver module we loaded ?
answer : It can be passed under the root directory of kernel source code “vi System.map” Check it out. , This file holds all the files in the kernel ( Symbol 、 function ) Virtual address mapping for , For example, the kernel functions in the figure below root_dev_setup():
adopt vi Ordered :0 and :$ Command line , You can see that the virtual address of the kernel is c0004000~c03cebf4
therefore ,pc value bf000078 The address value of the driver module for
2.4 When multiple drivers are loaded , How to distinguish PC Value is the address value of which driver function ?
answer : adopt /proc/kallsyms Check it out. :
#cat /proc/kallsyms //(kernel all symbols) Look at all the kernel labels ( Including kernel functions , Load driver function , Variable symbols, etc ) Address value of
#cat /proc/kallsyms> /kallsyms.txt // Put the address value in kallsyms.txt in
As shown in the figure below , stay kallsyms.txt in , find pc value bf000078 be located 26th_segmentfault Drive in first_drv_open() Function bf000000+0x78 in
arm-linux-objdump -D 26th_segmentfault.ko >26th_segmentfault.dis // Disassembly
As shown in the figure below , On the left is kallsyms.txt, On the right is 26th_segmentfault.dis Disassembly
obviously pc value bf000078, It's in disassembly 78 address :
Disassembly of section .text: //.text The starting address of the segment is 0x00<first_drv_open>:38: e59fc0e8 ldr ip, [pc, #232]; 128 <.text+0x128> //ip=.text paragraph +0x128 Contents of Li ... ...50: e585c000 str ip, [r5] //r5=.text paragraph +0x128 Contents of Li ... ...74: e5952000 ldr r2, [r5] //r2=.text paragraph +0x128 Contents of Li 78: e5923000 ldr r3, [r2] // r3=.text paragraph +0x128 Contents of Li 7c: e3c33c3f bic r3, r3, #16128 ;0x3f00 // eliminate 0x56000050 Of bit8~13... ...128: 56000050 undefined //.text paragraph +0x128 Contents of Li =0x56000050
See from above ,78 address , Mainly is to 0x56000050(r2) Put the contents of the address in r3 in . and 0x56000050 It's a physical address , stay linux It's an illegal address in my eyes , So wrong.
And find out where it went wrong first_drv_open () Function :
#cp 26th_segmentfault.c /linux-184.108.40.206/drivers/char/ // Copy the problem driver to the character driver directory
add to :
obj-y += 26th_segmentfault.o //y: Put the driver in the kernel
3.2 then make uImage After loading the new kernel , Run the test program again , It will print out opps Information
# arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux.dis
Disassemble the whole kernel , vmlinux: Uncompressed kernel
The next chapter will analyze the function calls through stack information