From chinaunix: http://bbs.chinaunix.net/thread-3672391-1-1.html
Discussion from Linus Torvalds: https://groups.google.com/group... 41/ed9c0a0cfcd31111 an oops: Oops: 0000 [#1] preempt SMP modules linked in: capidrv kernelcapi ISDN slhc IPv6 loop dm_multipath routing gameport snd_rawmidi limit ac97_bus s limit snd_seq snd_seq_device limit snd_pcm snd_timer snd parport_pc floppy parport pcnet32 soundc Ore MII pcspkr unzip AC i2c_piix4 i2c_core button Power_Supply sr_mod sg cdrom ata_piix libata dm_snapshot dm_zero dm_mirror dm_mod buslogic sd_mod scsi_mod ext3 jbd cache has reached limit: 1726, COMM: kstopmachine not tainted (2.6.24-rc3-module #2) EIP: 0060: [] eflags: 00010092 CPU: 0eip is at list_del + 0xa/0x61eax: e0c3cc04 EBX: 00000020 ECx: 0000000e edX: dec62000esi: df6e 8f08 EDI: 000006bf EBP: dec62fb4 ESP: dec62fa4ds: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 process kstopmachine (PID: 1726, Ti = dec62000 task = df8d2d40 task. ti = dec62000) STACK: 000006bf dec62fb4 c04276c7 00000020 dec62fbc c044ab4c dec62fd0 c010936c 109c04532b4 00000000 dec62fe0 109c043de75 00000000 201710000000000000000 00000000 00000000 00000000 00000000 Call trace: [] Show _ Trace_log_lvl + 0x1a/0x2f [] primary + 0x9b/0xa3 [] show_registers + 0xa3/0x1df [] Die + 0x11f/0x200 [] do_page_fault + 0x533/0 x61a [] error_code + 0x72/0x78 [] _ unlink_module + 0xb/0xf [] do_stop + 0xb8/0x108 [] kthread + 0x3b/0x63 [] kernel_thread_helper + 0x7/0x10 ===================================== code: 6b C0 E8 2E 7E F6 FF E8 D1 16 F2 FF B8 01 00 00 00 E8 AA 1C F4 FF 89 D8 83 C4 10 5B 5d C3 90 90 90 55 E5 53 83 EC 0c 8 B 48 04 11 39 C2 74 18 89 54 24 08 89 44 24 04 C7 04 24 be 32 6b C0 EIP: [] list_del + 0xa/0x61 ss: ESP 0068: dec62fa4note: kstopmachine [1726] exited with preempt_count 11, with self-compiled vmlinux: Enable the complie with debug info option when compiling with GDB. Note This line: The EIP is at list_del + 0xa/0x61 tells us that the list_del function is as large as 0x61, while oops occurs at 0xa. Let's take a look at where list_del starts: # grep list_del/boot/system. map-2.6.24-rc3-modulec10e5234 t plist_delc10e53cc t list_delc120feb6 t klist_delc12d6d34 R _ 1_r _ 1_r _ kstrtab_klist_del so we know that when oops occurs, the EIP value is: c10e53cc + 0xa = c10e53d6 and view it with GDB: # GDB/home/ARC/build/linux-2.6/vmlinux (GDB) B * 0xc10e53d6breakpoint 1 at 0xc10e53d6: File/us R/src/linux-2.6.24-rc3/lib/list_debug.c, line 64. Look, GDB will tell you which file, which line. GDB can also be like this: # GDB sources/linux-2.6.24/vmlinux (GDB) L * do_fork + 0x1f0xc102b7ac is in do_fork (kernel/fork. c: 1385 ). 13801381 static int fork_traceflag (unsigned clone_flags) 1382 {1383 if (clone_flags & clone_untraced) 1384 return 0; 1385 else if (clone_flags & tags) {1386 if (current-> ptrace & tags) 1387 return ptrace_event_vfork; 1388} else if (clone_flags & csignal )! = Sigchld) {1389 if (current-> ptrace & pt_trace_clone) (GDB) can also directly know the line number. Or: (GDB) L * (0xffffffff8023eaf0 + 0xff)/* add an offset */2 to the address of the error function. No self-compiled vmlinux: Tips. If you see an oops on lkml or Bugzilla, but you cannot reproduce it yourself, you can only disassemble the rows starting with "Code. In this way, you can try to locate the source code. Note: The Code in Oops: line will enclose the first instruction that causes oops, that is, the first byte of the EIP value, in angle brackets. However, some system structures (such as common x86) commands are not long (different commands may have different lengths), so we need to constantly try (trial-and-error ). Linus usually uses a small program, like this: const char array [] = "\ xnn... "; int main (INT argc, char * argv []) {printf (" % P \ n ", array); * (int *) 0 = 0;} e.g. /* {* // * Note: array has 65 elements, from array [0] to array [64, the operation code = arry [43] */# include const char array [] = "\ x6b \ xc0 \ xe8 \ x2e \ x7e \ xf6 \ xFF \ xe8 \ XD1 \ x16 \ xf2 \ xFF \ xb8 \ x01 \ x00 \ x00 \ x00 \ xe8 \ xAA \ x1c \ xf4 \ xFF \ x89 \ xd8 \ x83 \ xc4 \ x10 \ x5b \ x5d \ xc3 \ x90 \ x90 \ x90 \ x55 \ x89 \ xe5 \ x53 \ x83 \ Xec \ x0c \ x8b \ x48 \ x04 \ x8b \ X11 \ x39 \ xc2 \ x74 \ X18 \ x89 \ x54 \ x24 \ x08 \ x89 \ x44 \ x24 \ x04 \ xc7 \ x04 \ x24 \ xbe \ x32 \ x6b \ xc0 "; int main (INT argc, char * argv []) {printf ("% P \ n", array); * (int *) 0 = 0 ;} /*} */compile with GCC-G and run it in GDB: [arc @ dhcp-cbjs05-218-251 ~] $ GDB hellognu GDB fedora (6.8-1. fc9) Copyright (c) 2008 Free Software Foundation, Inc. license gplv3 +: gnu gpl Version 3 or later this is free software: You are free to change and redistribute it. there is no warranty, to the extent permitted by law. type "show copying" and "show warranty" for details. this GDB was configured as "x86_64-redhat-linux-gnu "... (No debugging symbols found) (GDB) rstarting PR Ogram:/home/ARC/hello0x80484e0program stored ed signal SIGSEGV, segmentation fault. note: At this time, we can disassemble the address 0x80484e0: (GDB) disassemble encoding of handler code for Function Array: Role: imul $0xffffffe8, % eax, % role: jle, PN 0x80484dc 0x080484e6: ljmp * 0x080484e8: rcll (% Esi) 0x080484ea: repnz (bad) 0x080484ec: mov $0x1, % eax0x080484f1 4f8: add $0x10, % esp0x080484fb: Pop % tags: pushed: nop0x08048500: nop0x08048501: Push % ebp0x08048502: mov % ESP, % tags: push % ebx0x08048505: Sub $ 0xc, % esp0x08048508: mov 0x4 (% eax), % mask: mov (% ECx), % edx0x0804850d: CMP % eax, % edx0x0804850f: je 0x80485290x08048511: mov % edX, 0x8 (% ESP) 0x08048515: mov % eax, 0x4 (% ESP) 0x0804 8519: movl $ 0xc06b32be, (% ESP) 0x08048520: Add % ah, 0xa70end of assembler dump. (GDB) OK. Now you know that the wrong command is array [43], that is, mov (% ECx), % edX, that is, (% ECx) indicates an error memory address. To better match the assembly code with the C code, the kbuild subsystem of the Linux Kernel provides the following function: Any c file can be compiled into an assembly file separately. For example: make path/to/The/sourcefile. s. C is compiled into an assembly, so: Make kernel/sched. S v = 1 or: Make kernel/sched. LST v = 1 compiled *. s files sometimes need *. s file to determine the location of the bug. *. C files under any kernel build directory can be directly compiled *. s files. # Make Drivers/NET/e100.s v = 1 for the module you write, you need to have a flexible target syntax in makefile: # Cat makefileobj-M: = usb-skel.oKDIR: =/lib/modules/'uname-R'/buildtraget: = modulesdefault: Make-C $ (kdir) M = $ (shell PWD) $ (target) clean: rm-f *. O *. ko. *. CMD *. symvers *. mod. CRM-RF. tmp_versions # Make target = usb-skel.s v = 1 so that the kbuild system knows that the target you want to make is not modules, but usb-skel.s. In addition, the./scripts/decodecode file in the kernel source code directory is used to decode Oops:
./Scripts/decodecode