1. When the drive is wrong , such as , The memory address accessed is illegal , You'll print a bunch of oops come out

1.1 With LED Drive as an example

take open() Function ioremap() Screen out , Using physical address directly GPIOF, As shown in the figure below :
 Insert picture description here

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 :

2. Next , Let's analyze oops:

Unable to handle kernel paging request at virtual address 56000050 // Unable to process virtual address for kernel page request 56000050pgd = c3850000[56000050] *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  (2.6.22.6 #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

2.1 The backtracking information above , Represents the entire calling process of the function

For example, the backtracking information above shows :

sys_open()->do_sys_open()->do_filp_open()->nameidata_to_filp()->chrdev_open()->first_drv_open();

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 :
 Insert picture description here
//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)

2.2 And some kernels have different environments ,opps Or it may not print out :

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():
 Insert picture description here
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 

perhaps :

#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
 Insert picture description here

2.5 Then the driver will generate disassembly :

arm-linux-objdump -D 26th_segmentfault.ko >26th_segmentfault.dis // Disassembly 

2.6 Open disassembly :

As shown in the figure below , On the left is kallsyms.txt, On the right is 26th_segmentfault.dis Disassembly
 Insert picture description here
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 :
 Insert picture description here

3. If the wrong driver is located in the address value of the kernel

3.1 Or to 26th_segmentfault.c For example , First, add the kernel :

#cp 26th_segmentfault.c   /linux-2.6.22.6/drivers/char/  // Copy the problem driver to the character driver directory 

#vi Makefile

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

3.3 In the root directory of the kernel source code through :

# arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux.dis

Disassemble the whole kernel , vmlinux: Uncompressed kernel

3.4 vi vmlinux.dis, And then through oops The information of PC Value directly to find the address

The next chapter will analyze the function calls through stack information
cheng :http://www.cnblogs.com/lifexy/p/8011966.html