ºìÁªLinuxÃÅ»§
Linux°ïÖú

LinuxÄÚ´æ´íÎó²úÉúµÄÔ­Òò¼°µ÷ÊÔ·½·¨

·¢²¼Ê±¼ä:2007-08-25 00:00:44À´Ô´:ºìÁª×÷Õß:furshow
¡¡¡¡¶øÑÔÖ®,²úÉú¶Î´íÎó¾ÍÊÇ·ÃÎÊÁË´íÎóµÄÄÚ´æ¶Î£¬Ò»°ãÊÇÄãûÓÐȨÏÞ£¬»òÕ߸ù±¾¾Í²»´æÔÚ¶ÔÓ¦µÄÎïÀíÄÚ´æ,ÓÈÆä³£¼ûµÄÊÇ·ÃÎÊ0µØÖ·.

¡¡¡¡Ò»°ãÀ´Ëµ,¶Î´íÎó¾ÍÊÇÖ¸·ÃÎʵÄÄڴ泬³öÁËϵͳËù¸øÕâ¸ö³ÌÐòµÄÄÚ´æ¿Õ¼ä£¬Í¨³£Õâ¸öÖµÊÇÓÉgdtrÀ´±£´æµÄ£¬ËûÊÇÒ»¸ö48λµÄ¼Ä´æÆ÷£¬ÆäÖеÄ32λÊDZ£´æÓÉËüÖ¸ÏòµÄgdt±í£¬ºó13λ±£´æÏàÓ¦ÓÚgdtµÄϱ꣬×îºó3λ°üÀ¨Á˳ÌÐòÊÇ·ñÔÚÄÚ´æÖÐÒÔ¼°³ÌÐòµÄÔÚcpuÖеÄÔËÐ춱ð,Ö¸ÏòµÄgdtÊÇÓÉÒÔ64λΪһ¸öµ¥Î»µÄ±í£¬ÔÚÕâÕűíÖоͱ£´æ×ųÌÐòÔËÐеĴúÂë¶ÎÒÔ¼°Êý¾Ý¶ÎµÄÆðʼµØÖ·ÒÔ¼°Óë´ËÏàÓ¦µÄ¶ÎÏÞºÍÒ³Ãæ½»»»»¹ÓгÌÐòÔËÐ춱ð»¹ÓÐÄÚ´æÁ£¶ÈµÈµÈµÄÐÅÏ¢¡£Ò»µ©Ò»¸ö³ÌÐò·¢ÉúÁËÔ½½ç·ÃÎÊ£¬cpu¾Í»á²úÉúÏàÓ¦µÄÒì³£±£»¤£¬ÓÚÊÇsegmentation fault¾Í³öÏÖÁË.

¡¡¡¡ÔÚ±à³ÌÖÐÒÔϼ¸Àà×ö·¨ÈÝÒ×µ¼Ö¶δíÎó,»ù±¾ÊÇÊÇ´íÎóµØʹÓÃÖ¸ÕëÒýÆðµÄ

¡¡¡¡1)·ÃÎÊϵͳÊý¾ÝÇø£¬ÓÈÆäÊÇÍù ϵͳ±£»¤µÄÄÚ´æµØַдÊý¾Ý
×î³£¼û¾ÍÊǸøÒ»¸öÖ¸ÕëÒÔ0µØÖ·
¡¡¡¡2)ÄÚ´æÔ½½ç(Êý×éÔ½½ç£¬±äÁ¿ÀàÐͲ»Ò»ÖµÈ) ·ÃÎʵ½²»ÊôÓÚÄãµÄÄÚ´æÇøÓò

¡¡¡¡½â¾ö·½·¨

¡¡¡¡ÎÒÃÇÔÚÓÃC/C++ÓïÑÔд³ÌÐòµÄʱºî£¬ÄÚ´æ¹ÜÀíµÄ¾ø´ó²¿·Ö¹¤×÷¶¼ÊÇÐèÒªÎÒÃÇÀ´×öµÄ¡£Êµ¼ÊÉÏ£¬ÄÚ´æ¹ÜÀíÊÇÒ»¸ö±È½Ï·±ËöµÄ¹¤×÷£¬ÎÞÂÛÄã¶à¸ßÃ÷£¬¾­Ñé¶à·á¸»£¬ÄÑ Ãâ»áÔÚ´Ë´¦·¸Ð©Ð¡´íÎ󣬶øͨ³£ÕâЩ´íÎóÓÖÊÇÄÇôµÄdzÏÔ¶øÒ×ÓÚÏû³ý¡£µ«ÊÇÊÖ¹¤¡°³ý³æ¡±£¨debug£©£¬ÍùÍùÊÇЧÂʵÍÏÂÇÒÈÃÈËÑá·³µÄ£¬±¾ÎĽ«¾Í"¶Î´íÎó"Õâ¸ö ÄÚ´æ·ÃÎÊÔ½½çµÄ´íÎó̸̸ÈçºÎ¿ìËÙ¶¨Î»ÕâЩ"¶Î´íÎó"µÄÓï¾ä¡£
ÏÂÃ潫¾ÍÒÔϵÄÒ»¸ö´æÔڶδíÎóµÄ³ÌÐò½éÉܼ¸ÖÖµ÷ÊÔ·½·¨£º

1 dummy_function (void)
2 {
3 unsigned char *ptr = 0x00;
4 *ptr = 0x00;
5 }
6
7 int main (void)
8 {
9 dummy_function ();
10
11 return 0;
12 }

¡¡¡¡×÷Ϊһ¸öÊìÁ·µÄC/C++³ÌÐòÔ±£¬ÒÔÉÏ´úÂëµÄbugÓ¦¸ÃÊǺÜÇå³þµÄ£¬ÒòΪËü³¢ÊÔ²Ù×÷µØַΪ0µÄÄÚ´æÇøÓò£¬¶øÕâ¸öÄÚ´æÇøÓòͨ³£ÊDz»¿É·ÃÎʵĽûÇø£¬µ±È»¾Í»á³ö´íÁË¡£ÎÒÃdz¢ÊÔ±àÒëÔËÐÐËü:

xiaosuo@gentux test $ ./a.out
¶Î´íÎó

¡¡¡¡¹ûÈ»²»³öËùÁÏ£¬Ëü³ö´í²¢Í˳öÁË¡£

¡¡¡¡1.ÀûÓÃgdbÖð²½²éÕҶδíÎó:

¡¡¡¡ÕâÖÖ·½·¨Ò²ÊDZ»´óÖÚËùÊìÖª²¢¹ã·º²ÉÓõķ½·¨£¬Ê×ÏÈÎÒÃÇÐèÒªÒ»¸ö´øÓе÷ÊÔÐÅÏ¢µÄ¿ÉÖ´ÐгÌÐò£¬ËùÒÔÎÒÃǼÓÉÏ¡°-g -rdynamic"µÄ²ÎÊý½øÐбàÒ룬ȻºóÓÃgdbµ÷ÊÔÔËÐÐÕâ¸öбàÒëµÄ³ÌÐò,¾ßÌå²½ÖèÈçÏÂ:

xiaosuo@gentux test $ gcc -g -rdynamic d.c
xiaosuo@gentux test $ gdb ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) r
Starting program: /home/xiaosuo/test/a.out

Program received signal SIGSEGV, Segmentation fault.
0x08048524 in dummy_function () at d.c:4
4 *ptr = 0x00;
(gdb)

¡¡¡¡ºÃÏñ²»ÓÃÒ»²½²½µ÷ÊÔÎÒÃǾÍÕÒµ½Á˳ö´íλÖÃd.cÎļþµÄµÚ4ÐУ¬Æäʵ¾ÍÊÇÈç´ËµÄ¼òµ¥¡£

¡¡¡¡´ÓÕâÀïÎÒÃÇ»¹·¢ÏÖ½ø³ÌÊÇÓÉÓÚÊÕµ½ÁËSIGSEGVÐźŶø½áÊøµÄ¡£Í¨¹ý½øÒ»²½µÄ²éÔÄÎĵµ(man 7 signal)£¬ÎÒÃÇÖªµÀSIGSEGVĬÈÏhandlerµÄ¶¯×÷ÊÇ´òÓ¡¡±¶Î´íÎó"µÄ³ö´íÐÅÏ¢£¬²¢²úÉúCoreÎļþ£¬ÓÉ´ËÎÒÃÇÓÖ²úÉúÁË·½·¨¶þ¡£

¡¡¡¡2.·ÖÎöCoreÎļþ£º

¡¡¡¡CoreÎļþÊÇʲôÄØ£¿

The default action of certain signals is to cause a process to terminate and produce a core dump file, a disk file containing an image of the process's memory at the time of termination. A list of the signals which cause a process to dump core can be found in signal(7).

¡¡¡¡ÒÔÉÏ×ÊÁÏÕª×Ôman page(man 5 core)¡£²»¹ýÆæ¹ÖÁË£¬ÎÒµÄϵͳÉϲ¢Ã»ÓÐÕÒµ½coreÎļþ¡£ºóÀ´£¬ÒäÆðΪÁ˽¥ÉÙϵͳÉϵÄÀ­»øÎļþµÄÊýÁ¿£¨±¾ÈËÓÐЩ½àñ±£¬ÕâÒ²ÊÇÎÒϲ»¶GentooµÄÔ­Òò Ö®Ò»£©£¬½ûÖ¹ÁËcoreÎļþµÄÉú³É£¬²é¿´ÁËÒÔϹûÕæÈç´Ë£¬½«ÏµÍ³µÄcoreÎļþµÄ´óСÏÞÖÆÔÚ512K´óС£¬ÔÙÊÔ:

xiaosuo@gentux test $ ulimit -c
0
xiaosuo@gentux test $ ulimit -c 1000
xiaosuo@gentux test $ ulimit -c
1000
xiaosuo@gentux test $ ./a.out
¶Î´íÎó (core dumped)
xiaosuo@gentux test $ ls
a.out core d.c f.c g.c pango.c test_iconv.c test_regex.c


¡¡¡¡coreÎļþÖÕÓÚ²úÉúÁË£¬ÓÃgdbµ÷ÊÔһϿ´¿´°É:

xiaosuo@gentux test $ gdb ./a.out core
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".


warning: Can't read pathname for load map: ÊäÈë/Êä³ö´íÎó.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x08048524 in dummy_function () at d.c:4
4 *ptr = 0x00;

¡¡¡¡»¹ÊÇÒ»²½¾Í¶¨Î»µ½ÁË´íÎóËùÔڵأ¬Åå·þÒ»ÏÂLinux/UnixϵͳµÄ´ËÀàÉè¼Æ¡£
½Ó×Å¿¼ÂÇÏÂÈ¥£¬ÒÔÇ°ÓÃwindowsϵͳϵÄieµÄʱºî£¬ÓÐʱ´ò¿ªÄ³Ð©ÍøÒ³£¬»á³öÏÖ¡°ÔËÐÐʱ´íÎó¡±£¬Õâ¸öʱºîÈç¹ûÇ¡ºÃÄãµÄ»úÆ÷ÉÏÓÖ×°ÓÐwindowsµÄ±àÒëÆ÷µÄ»°£¬Ëû»áµ¯³öÀ´Ò»¸ö¶Ô»°¿ò£¬ÎÊÄãÊÇ·ñ½øÐе÷ÊÔ£¬Èç¹ûÄãÑ¡ÔñÊÇ£¬±àÒëÆ÷½«±»´ò¿ª£¬²¢½øÈëµ÷ÊÔ״̬£¬¿ªÊ¼µ÷ÊÔ¡£

¡¡¡¡LinuxÏÂÈçºÎ×öµ½ÕâЩÄØ£¿ÎҵĴóÄÔ·ÉËÙµØÐýת×Å£¬ÓÐÁË£¬ÈÃËüÔÚSIGSEGVµÄhandlerÖе÷ÓÃgdb£¬ÓÚÊǵÚÈý¸ö·½·¨ÓÖµ®ÉúÁË£º

¡¡¡¡3.¶Î´íÎóʱÆô¶¯µ÷ÊÔ:

#include
#include
#include
#include

void dump(int signo)
{
char buf[1024];
char cmd[1024];
FILE *fh;

snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
if(!(fh = fopen(buf, "r")))
exit(0);
if(!fgets(buf, sizeof(buf), fh))
exit(0);
fclose(fh);
if(buf[strlen(buf) - 1] == 'n')
buf[strlen(buf) - 1] = '';
snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());
system(cmd);

exit(0);
}

void
dummy_function (void)
{
unsigned char *ptr = 0x00;
*ptr = 0x00;
}

int
main (void)
{
signal(SIGSEGV, &dump);
dummy_function ();

return 0;
}


¡¡¡¡±àÒëÔËÐÐЧ¹ûÈçÏ£º

xiaosuo@gentux test $ gcc -g -rdynamic f.c
xiaosuo@gentux test $ ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

Attaching to program: /home/xiaosuo/test/a.out, process 9563
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7ee4b53 in waitpid () from /lib/libc.so.6
#2 0xb7e925c9 in strtold_l () from /lib/libc.so.6
#3 0x08048830 in dump (signo=11) at f.c:22
#4
#5 0x0804884c in dummy_function () at f.c:31
#6 0x08048886 in main () at f.c:38


¡¡¡¡ÔõôÑù£¿ÊDz»ÊÇÒÀ¾ÉºÜ¿á£¿

¡¡¡¡ÒÔÉÏ·½·¨¶¼ÊÇÔÚϵͳÉÏÓÐgdbµÄÇ°ÌáϽøÐеģ¬Èç¹ûûÓÐÄØ£¿ÆäʵglibcΪÎÒÃÇÌṩÁË´ËÀàÄܹ»dumpÕ»ÄÚÈݵĺ¯Êý´Ø£¬Ïê¼û/usr/include/execinfo.h£¨ÕâЩº¯Êý¶¼Ã»ÓÐÌṩman page£¬ÄѹÖÎÒÃÇÕÒ²»µ½£©£¬ÁíÍâÄãÒ²¿ÉÒÔͨ¹ýgnuµÄÊÖ²á½øÐÐѧϰ¡£

¡¡¡¡4.ÀûÓÃbacktraceºÍobjdump½øÐзÖÎö£º

¡¡¡¡ÖØдµÄ´úÂëÈçÏÂ:

#include
#include
#include
#include

/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
unsigned char *ptr = 0x00;
*ptr = 0x00;
}

void dump(int signo)
{
void *array[10];
size_t size;
char **strings;
size_t i;

size = backtrace (array, 10);
strings = backtrace_symbols (array, size);

printf ("Obtained %zd stack frames.n", size);

for (i = 0; i < size; i++)
printf ("%sn", strings[i]);

free (strings);

exit(0);
}

int
main (void)
{
signal(SIGSEGV, &dump);
dummy_function ();

return 0;
}


¡¡¡¡±àÒëÔËÐнá¹ûÈçÏ£º

xiaosuo@gentux test $ gcc -g -rdynamic g.c
xiaosuo@gentux test $ ./a.out
Obtained 5 stack frames.
./a.out(dump+0x19) [0x80486c2]
[0xffffe420]
./a.out(main+0x35) [0x804876f]
/lib/libc.so.6(__libc_start_main+0xe6) [0xb7e02866]
./a.out [0x8048601]

¡¡¡¡Õâ´ÎÄã¿ÉÄÜÓÐЩʧÍû,ËƺõûÄܸø³ö×ã¹»µÄÐÅÏ¢À´±êʾ´íÎó,²»¼±,ÏÈ¿´¿´ÄÜ·ÖÎö³öÀ´Ê²Ã´°É,ÓÃobjdump·´»ã±à³ÌÐò,ÕÒµ½µØÖ·0x804876f¶ÔÓ¦µÄ´úÂëλÖÃ:

xiaosuo@gentux test $ objdump -d a.out



8048765: e8 02 fe ff ff call 804856c
804876a: e8 25 ff ff ff call 8048694
804876f: b8 00 00 00 00 mov $0x0,%eax
8048774: c9 leave

¡¡¡¡ÎÒÃÇ»¹ÊÇÕÒµ½ÁËÔÚÄĸöº¯Êý(dummy_function)Öгö´íµÄ,ÐÅÏ¢ÒÑÈ»²»ÊǺÜÍêÕû,²»¹ýÓÐ×ܱÈûÓкõİ¡!

¡¡¡¡ºó¼Ç£º

¡¡¡¡±¾Îĸø³öÁË·ÖÎö"¶Î´íÎó"µÄ¼¸ÖÖ·½·¨,²»ÒªÈÏΪÕâÊÇÓë¿×ÒÒ¼ºÏÈÉúµÄ"»Ø"×ÖËÄÖÖд·¨Ò»ÑùµÄŶ,ÒòΪÿÖÖ·½·¨¶¼ÓÐÆä×ÔÉíµÄÊÊÓ÷¶Î§ºÍÊÊÓû·¾³,Çë×ÃÇéʹÓÃ,»ò×ñÒ½Öö¡£
ÎÄÕÂÆÀÂÛ

¹²ÓÐ 0 ÌõÆÀÂÛ