Emacs Gdb Etags Cscope
ÀÌ ±ÛÀº ÇÁ·Î±×·¡¸Ó ÀÔÀå¿¡¼ Emacs, GDB, etags, cscope¸¦ ¾î¶»°Ô ÇÔ²² ¾µ ¼ö ÀÖ´Â Áö¿¡ ´ëÇÏ¿© ¼³¸íÇÕ´Ï´Ù. (Emacs¸¦ ¸ô¶óµµ »ó°ü¾ø½À´Ï´Ù.) ¶Ç, ¿ø¹®ÀÌ ÈĹèµéÀ» À§ÇØ ¾´ ±ÛÀ̶ó, ´Ù¼Ò ¹Ý¸», Çù¹Ú Åõ·Î µÇ¾î ÀÖÀ¸´Ï ÀÌ Á¡ ¾çÇØ ¹Ù¶ø´Ï´Ù. (½Å¼º±¹)
1. Áغñ»çÇ× ¶ÀÏ´Ü Emacs´Â ¼³Ä¡µÇ¾î ÀÖ´Ù°í °¡Á¤ÇÑ´Ù -- Red Hat LinuxÀÇ °æ¿ì, binary´Â /usr/bin¿¡, data´Â /usr/share/emacs¿¡ ¼³Ä¡µÈ´Ù.
¾Æ·¡ µÎ sectionÀº ¸ðµÎ CapsLock Å°¸¦ Control Å°·Î ¾²±â À§ÇÑ °ÍÀÌ´Ù. (Emacs¸¦ ¾²±â À§ÇØ ¹Ýµå½Ã ÇØ¾ß ÇÔ) ¸¸¾à Happy Hacking Keyboard¸¦ ¾²°í ÀÖ´Ù¸é ÇÒ ÇÊ¿ä ¾øÀ½.
1.1. X Window System Key ¼³Á¤ ¶¾î¶² ¸ñÀûÀ¸·Î Emacs¸¦ ¾²´øÁö »ó°ü¾øÀÌ ¹Ýµå½Ã ÇØ¾ß ÇÒ setting Áß Çϳª´Â keyboard ¼³Á¤ÀÌ´Ù. ÀÏ´Ü ¿©·¯ºÐÀÇ Å°º¸µå¿¡¼ ¾ËÆĺª 'A' key ¿ÞÂÊ¿¡ ÀÖ´Â Å°¸¦ º¸±â ¹Ù¶õ´Ù. ÀÌ Å°°¡ 'Control' Å°¶ó¸é ÀÌ ´Ü°è¸¦ ³Ñ¾î°¡µµ »ó°ü¾ø´Ù.
¿©·¯ºÐÀÌ ¾²°í ÀÖ´Â ´ëºÎºÐÀÇ Å°º¸µå´Â ÀÌ Å°°¡ 'CapsLock'ÀÏ °ÍÀÌ´Ù. ÀÌ °æ¿ì, ÀÌ Å°¸¦ 'Control' key·Î ¹Ù²Ù¾î¾ß ÇÑ´Ù. -- EmacsÀÇ ¸ðµç ´ÜÃàÅ°´Â ¾ËÆĺª 'A' key ¿ÞÂÊÀÇ Å°°¡ 'Control' key¶ó°í °¡Á¤ÇÑ ´ÙÀ½ ¸¸µé¾î Áø °ÍÀÌ´Ù. µû¶ó¼ 'Control'ÀÌ ´Ù¸¥ °÷¿¡ À§Ä¡ÇÒ °æ¿ì, Å° ÀԷ¿¡ »ó´çÇÑ ¹«¸®°¡ µû¸£¸ç, Emacs°¡ ½È¾îÁö´Â °¡Àå Å« ÀÌÀ¯°¡ µÉ °ÍÀÌ´Ù.
xmodmap ÇÁ·Î±×·¥À» ½á¼ ¿©·¯ºÐÀÇ key layoutÀ» ¹Ù²Ü ¼ö ÀÖ´Ù. ÀÏ´Ü terminalÀ» Çϳª ¶ç¿î ÈÄ, xmodmapÀ» ½ÇÇàÇÏ¸é ´ÙÀ½°ú ºñ½ÁÇÑ Ãâ·ÂÀ» ¾òÀ» ¼ö ÀÖ´Ù:
$ xmodmap xmodmap: up to 4 keys per modifier, (keycodes in parentheses): shift Shift_L (0x32), Shift_R (0x3e) lock Caps_Lock (0x42) control Control_L (0x25), Control_R (0x6d) mod1 Alt_L (0x40), Meta_L (0x73), Alt_R (0x71), Meta_R (0x74) mod2 Num_Lock (0x4d) mod3 mod4 Meta_L (0x73), Meta_R (0x74) mod5 $ _ À§ÀÇ Ãâ·Â °á°ú´Â ¿©·¯ºÐÀÇ °á°ú¿Í ¾î´À Á¤µµ ´Ù¸¦ ¼ö ÀÖ´Ù´Â °Í¿¡ ÁÖÀÇÇϱ⠹ٶõ´Ù. ÀÏ´Ü °¡Àå Áß¿äÇÑ ¶óÀÎÀº "lock"À¸·Î ½ÃÀÛÇÏ´Â ¶óÀÎÀÌ´Ù:
lock Caps_Lock (0x42) ÀÁÙÀ» ¼³¸íÇϸé, "lock"Àº "CapsLock" ±â´ÉÀ» ÇÏ´Â °ÍÀ¸·Î, ÇöÀç keycode 42¹øÀÎ Caps_Lock key°¡ ±× ¿ªÇÒÀ» ÇÑ´Ù´Â °ÍÀÌ´Ù.
´ÙÀ½ ¸í·ÉÀ» ¼öÇàÇÏ¿©, Caps_LockÀ» "lock"¿¡¼ »©¹ö¸®ÀÚ:
$ xmodmap -e "remove lock = Caps_Lock"(°á°ú°¡ ±Ã±ÝÇÏ¸é ´Ù½Ã Çѹø ¾Æ¹«·± ÀÎÀÚ¾øÀÌ xmodmapÀ» ½ÇÇàÇÏ¸é µÈ´Ù.) ±× ´ÙÀ½, Caps_LockÀ» "control"¿¡ Ãß°¡ÇÏÀÚ: $ xmodmap -e "add control = Caps_Lock"ÀÌÁ¦ xmodmapÀ» ½ÇÇàÇϸé lock°ú control lineÀÌ ´ÙÀ½°ú °°À½À» ¾Ë ¼ö ÀÖ´Ù. $ xmodmap xmodmap: up to 4 keys per modifier, (keycodes in parentheses): ... lock control Control_L (0x25), Control_R (0x6d), Caps_Lock (0x42) ... $ _ ÀÌÁ¦, X Window´Â ¿©·¯ºÐÀÇ "CapsLock"Å°¸¦ "control"·Î Çؼ®ÇÏ°Ô µÈ´Ù.
¸Å¹ø ÀÌ·± ½ÄÀ¸·Î ¹Ù²Ü ¼ö´Â ¾ø´Â ³ë¸©ÀÌ´Ù. µû¶ó¼ À§ÀÇ °úÁ¤À» script¿¡ ±â·ÏÇß´Ù°¡ X°¡ ½ÃÀÛÇÒ ¶§¸¶´Ù ÀÚµ¿À¸·Î Àоî¿À°Ô ÇØ¾ß ÇÑ´Ù.
Red Hat °è¿À̶ó¸é $HOME/.Xmodmap ÆÄÀÏ¿¡ ´ÙÀ½°ú °°ÀÌ ±â·ÏÇØ µÎ¸é µÈ´Ù.
remove lock = Caps_Lock add control = Caps_Lock ¸¶Áö¸·À¸·Î Emacs¸¦ ½ÇÇà½ÃÄѼ keyboard settingÀ» È®ÀÎÇØ º¸¶ó. CapsLock key¸¦ ½á¼ C-x C-c¸¦ ´·¯ º¸ÀÚ. Emacs°¡ Á¾·áÇÏ°Ô µÇ¸é ¼º°øÀÌ´Ù.
¾ÕÀ¸·Î Control Å°¸¦ ´©¸¦ ÇÊ¿ä°¡ ÀÖ´Ù¸é ²À CapsLock key¸¦ ½á¼ ´©¸£±â ¹Ù¶õ´Ù.
Á» ´õ ÀÚ¼¼ÇÑ »çÇ×À» ¿øÇÑ´Ù¸é 2 xmodmap man page, 3 Consistent Keyboard ConfigurationÀ» Âü°íÇϱ⠹ٶõ´Ù.
1.2. Linux Console¿¡¼ Key ¼³Á¤ ¶À§ÀÇ xmodmapÀº X Window System¿¡¼¸¸ ¾µ ¼ö ÀÖ´Â ÇÁ·Î±×·¥ÀÌ´Ù. µû¶ó¼, X¸¦ ¶ç¿ì±â Àü¿¡´Â ¾µ ¼ö ¾ø´Ù. loadkeys/showkey/dumpkeys ÇÁ·Î±×·¥À» ¾²¸é ¸¶Âù°¡Áö·Î CapsLock key¸¦ Control ±â´ÉÀ¸·Î ¹Ù²Ü ¼ö ÀÖ´Ù.
Á» ´õ ÀÚ¼¼ÇÑ »çÇ×À» ¿øÇÑ´Ù¸é 4 Linux Console HOWTO, 3 Consistent Keyboard ConfigurationÀ» Âü°íÇϱ⠹ٶõ´Ù.
2. Learn Emacs keys ¶ÀÌÁ¦ Emacs¸¦ ¾²±â À§ÇÑ ±âº»ÀûÀÎ ¼³Á¤Àº ³¡³µ´Ù. ÀÌÁ¦ Emacs¸¦ ¾²±â À§ÇÑ ±âº»ÀûÀÎ Å°µéÀ» ¹è¿ö¾ß ÇÑ´Ù.
EmacsÀÇ °ÅÀÇ ¸ðµç ±â´ÉÀº control key³ª meta key·Î ½ÃÀÛÇÑ´Ù. ´ç¿¬È÷ control key·Î´Â ¿©·¯ºÐÀÌ ÈçÈ÷ ½á¿Ô´ø ¿ÞÂÊ control key, ¿À¸¥ÂÊ control key¸¦ Æ÷ÇÔÇϸç, Áö±Ý±îÁö ÀÛ¾÷Çß´ø °á°ú·Î CapsLock keyµµ Æ÷ÇÔÇÑ´Ù. (ÀÌ CapsLock key¸¦ control key·Î ¾µ °ÍÀ» °·ÂÈ÷! ÃßõÇÑ´Ù.) Meta key´Â ÈçÈ÷ UNIX keyboard¿¡¼ "<>"·Î Ç¥½ÃµÈ Å°, ¶Ç´Â ÀÏ¹Ý PC¿ë keyboard¶ó¸é, AltÅ°°¡ ´ë½Å »ç¿ëµÈ´Ù.
ÀÌ ±Û°ú Emacs ¸Å´º¾ó¿¡¼ »ç¿ëÇϴ ǥ±â¹ýÀ¸·Î, "C-" Á¢µÎ¾î´Â control key¸¦ °°ÀÌ ´©¸£¶ó´Â ¶æÀ̸ç, "M-" Á¢µÎ¾î´Â meta key¸¦ °°ÀÌ ´©¸£¶ó´Â ¶æÀÌ´Ù. ¹°·Ð "C-M-"Àº control key¿Í meta key¸¦ µ¿½Ã¿¡ ´·¯¾ß ÇÑ´Ù´Â ¶æÀÌ´Ù. ¶ÇÇÑ tab key³ª space bar, return key, escape key ±×¸®°í function key¸¦ ³ªÅ¸³¾ ¶§¿¡´Â °¢°¢ <TAB>, <SPC>, <RET>, <ESC>, <F1>µî°ú °°ÀÌ Ç¥½ÃÇÒ °ÍÀÌ´Ù. ¸î °¡Áö ¿¹¸¦ µé¸é ´ÙÀ½°ú °°´Ù:
ÀÚ ÀÌÁ¦ ¿©±â±îÁö ¹è¿üÀ¸¸é, Emacs¸¦ ½ÇÇà½ÃÅ°°í, "C-h t"¸¦ ´·¯ tutorialÀ» ¿°í Àо±â ¹Ù¶õ´Ù. À§ tutorialÀ» ÀÐÀ» ¶§, ¾Æ·¡ Å° ¸ñ·ÏÀº ¹Ýµå½Ã ¿Ü¿ö¼ Àͼ÷ÇÏ°Ô ¾µ ÁÙ ¾Ë¾Æ¾ß ÇÏ´Â Å°µéÀ̹ǷΠ²À ¿Ü¿ö ¾²±â ¹Ù¶õ´Ù:
´Ù½Ã Çѹø °Á¶ÇÏÁö¸¸ À§ Å°µéÀº ±âº»ÀûÀ¸·Î ¾²ÀÌ´Â Å°µéÀ̹ǷΠ²À ¿Ü¿ö¼ ´É¼÷ÇÏ°Ô ¾µ ¼ö ÀÖ°Ô µÇ¾î¾ß ÇÑ´Ù. TutorialÀ» ´Ù Àоú°í, À§ Å°µéÀ» ¿Ü¿ü´Ù¸é ´ÙÀ½ ´Ü°è·Î ³Ñ¾î°¡±â ¹Ù¶õ´Ù. ÇÑ°¡Áö ´õ, ´Ù½Ã Çѹø °Á¶ÇÏÁö¸¸, Emacs¿¡¼´Â Å°º¸µå ¾ËÆĺª 'A' key ¿ÞÆí¿¡ À§Ä¡ÇÏ°í ÀÖ´Â Å°°¡ control key¶ó°í °¡Á¤ÇÏ°í ´ÜÃàÅ°µéÀÌ µðÀÚÀεǾî ÀÖÀ¸¹Ç·Î, PC keyboard »ç¿ëÀÚ¶ó¸é, ¹Ýµå½Ã ¿©±â¿¡ À§Ä¡ÇÏ°í ÀÖ´Â CapsLock key¸¦ control key·Î ¹Ù²Ù¾î ÀÛ¾÷Çϱ⠹ٶõ´Ù.
È¿°úÀûÀÎ Ä¿¼ ¿òÁ÷ÀÓÀ» À§ÇØ ¼Õ°¡¶ôÀÇ ¹èÄ¡¸¦ ´ÙÀ½°ú °°ÀÌ ÇÏÀÚ:
3. Compiling and Debugging ¶³»°¡ Emacs¸¦ ¾Ö¿ëÇÏ´Â °¡Àå Å« ÀÌÀ¯´Â compiling/debuggingÀÌ ¾î¶² editorº¸´Ù °·ÂÇϱ⠶§¹®ÀÌ´Ù. ¹«½¼ ¸»ÀÎÁö Àß ¸ð¸£°ÚÀ¸¸é µû¶óÇغ¸±â ¹Ù¶õ´Ù.
$ emacs hello.c &
#include <stdio.h>
int main(void) { printf("hello, world\n") return 0; }
Emacs´Â ¾Ë¾Æ¼ µé¿©¾²±â¸¦ ÆÇ´ÜÇؼ ºó ÄÀ» ³Ö¾îÁØ´Ù. ¿¹¸¦ µé¾î
{
printf("hello, world") ¸¦ ¾´ ´ÙÀ½, printf°¡ ÀÖ´Â ÁÙ¿¡ Ä¿¼¸¦ À§Ä¡½ÃÅ°°í, tab key¸¦ ´·¯º¸¶ó. Áß¿äÇÑ °ÍÀº Ä¿¼°¡ ²À ¸Ç ¾Õ¿¡¸¸ ÀÖÀ» ÇÊ¿ä°¡ ¾ø´Ù´Â °ÍÀÌ´Ù. Ä¿¼°¡ ±× ÁÙÀÇ ¾îµð¿¡ ÀÖ´øÁö¿¡ »ó°ü¾øÀÌ tab key¸¦ ´©¸£¸é ¹Ù·Î µé¿©¾²±â¸¦ ¼öÇàÇÏ°Ô µÈ´Ù.
$ ./a.out hello, world $ _ 4. Emacs Debugger Mode (gdb) ¶Emacs´Â ³»ºÎ¿¡ debugger(gdb)¸¦ ½ÇÇà½Ãų ¼ö ÀÖ´Â ´É·ÂÀÌ ÀÖ´Ù. ¿ø·¡ gdb´Â ¾ÆÁÖ °£´ÜÇÑ user interface¸¸À» °¡Áö°í ÀÖ¾î¼ ¹Ù·Î ¾²±â¿¡´Â ¸Å¿ì ¹ø°Å·Ó´Ù. ±×·¯³ª emacs debugger mode·Î gdb¸¦ µ¹¸®¸é, ¸Å¿ì Æí¸®ÇÏ°Ô ¾µ ¼ö ÀÖ´Ù. ¸ÕÀú ¾Æ·¡ ÇÁ·Î±×·¥À» emacs·Î ÀÛ¼ºÇÏÀÚ.
ÁÖÀÇ: Áö±Ý±îÀÚ Âø½ÇÈ÷ µû¶ó¿Ô´Ù¸é, C-x C-f buggy.c<RET>À» ÀÔ·ÂÇؼ »õ·Î buggy.c¸¦ ÆíÁýÇÏ¸é µÈ´Ù.
#include <stdio.h>
void swap(int *, int *); int main(void) { int i = 0; int j = 1; printf("i = %d, j = %d\n", i, j); swap(&i, &i); printf("i = %d, j = %d\n", i, j); return 0; } static void do_swap(int *lhs, int *rhs, int *tmp) { tmp = 0; *tmp = *lhs; *lhs = *rhs; *rhs = *tmp; } void swap(int *lhs, int *rhs) { int t; do_swap(lhs, rhs, &t); } ´Ù ÀÔ·ÂÇßÀ¸¸é C-x C-s¸¦ ´·¯ ÀúÀåÇÏ°í, M-x compile<RET>À» ´·¯ ÄÄÆÄÀÏ ¸í·ÉÀ» ÀÔ·ÂÇÒ ¼ö ÀÖ°Ô µÇ¸é, C-a C-k¸¦ ´·¯ ±âÁ¸ ÄÄÆÄÀÏ ¸í·ÉÀ» Áö¿ì°í, gcc -g buggy.c<RET>À» ÀÔ·ÂÇؼ ÄÄÆÄÀÏÇÏÀÚ. "-g" ¿É¼ÇÀ» »©¸ÔÁö ¸¶!
±× ´ÙÀ½, ÄÄÆÄÀÏ °á°ú¸¦ º¸¿©Áִ âÀ¸·Î Ä¿¼¸¦ ¿Å±ä ´ÙÀ½(c-x o), shellÀ» ¶ç¿ì°í(M-x shell<RET>) ½ÇÇàÇغ¸ÀÚ:
$ ./a.out i = 0, j = 1 Segmentation fault $ _ ÁÖÀÇÇÒ °ÍÀº, »óȲ¿¡ µû¶ó¼ "Segmentation fault"·Î ³¡³ªÁö ¾ÊÀ» ¼öµµ ÀÖ´Ù. ¾Æ¹¸µç Á¤»óÀûÀ¸·Î ³¡³ªÁø ¾ÊÀ» °ÍÀÌ´Ù. ÀÌÁ¦ M-x gdb<RET>À» ´©¸¥ ´ÙÀ½ a.out<RET>À» ÀÔ·ÂÇÏÀÚ.
ÀÌÁ¦ Ä£¼÷ÇÑ (gdb) prompt¸¦ º¼ ¼ö ÀÖÀ» °ÍÀÌ´Ù. (¹Ù·Î ¾Õ¿¡¼ a.out<RET> ´ë½Å ¹Ù·Î <RET>À» ´·¯ gdb¸¦ ½ÇÇàÇß´Ù¸é, Áö±Ý file a.out<RET>À» ÀÔ·ÂÇÒ ¼öµµ ÀÖ´Ù.)
±× ´ÙÀ½ ¹Ù·Î run<RET>À» ½ÇÇàÇÏÀÚ.
(gdb) run Starting program: /home/cinsk/src/a.out i = 0, j = 1 Program received signal SIGSEGV, Segmentation fault. 0x0804839e in do_swap () (gdb) _ ÀÌ ¼ø°£ debugger mode ⠹ݴëÂÊ¿¡´Â do_swap() ÇÔ¼öÀÇ ³»¿ëÀÌ ³ª¿À°í, segment fault°¡ ÀÏ¾î³ ¹Ù·Î ±× ÄÚµå ¾Õ¿¡´Â Á¶±×¸¶ÇÑ Ç¥½Ã(»ï°¢Çü)°¡ ³ª¿Ã °ÍÀÌ´Ù. ¹Ù·Î ÀÌ°ÍÀÌ Emacs debugger mode°¡ °¡Áø ±â´É Áß ÇϳªÀÓ. (¸¸¾à Äڵ尡 Ç¥½ÃµÇÁö ¾Ê´Â´Ù¸é ¾Æ±î ÄÄÆÄÀÏÇÒ ¶§ '-g' optionÀ» »©¸ÔÀº °æ¿ìÀ̹ǷΠ´Ù½Ã Çϱ⠹ٶõ´Ù.)
ÀÌÁ¦ bt<RET>À¸·Î ´ëÃæ ÇÁ·Î±×·¥ È帧ÀÌ ¾î¶»°Ô Èê·¯°¡´Â°¡ »ìÆ캸ÀÚ.
(gdb) bt #0 0x0804839e in do_swap () #1 0x080483ce in swap () #2 0x0804836c in main () #3 0x420156a4 in __libc_start_main () from /lib/tls/libc.so.6 (gdb) _ Àå´ãÇÏ°Ç´ë, bugÀÇ 99%´Â ÀÌ backtrace(bt) ¸í·É ¸¸À¸·Îµµ ÃæºÐÈ÷ ÇØ°áÇÒ ¼ö ÀÖ´Ù. À§ÀÇ °á°ú¸¦ º¸¸é, ÀÏ´Ü ³×¹ø° ÁÙÀº ¹«½ÃÇÏ°í, (¼¼¹ø° ÁÙ) main()ÀÌ swap()À» ºÒ·¶°í swap()ÀÌ do_swap()À» ºÒ·¶´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. Áï, segment fault°¡ ³ °÷ÀÌ ¹Ù·Î ÀÌ ±Ùó¶ó´Â °ÍÀ» ¾Ë·ÁÁÖ´Â °ÍÀÌ´Ù.
±×·¯¸é br do_swap<RET>À» ÀÔ·ÂÇؼ do_swap()¿¡ breakpoint¸¦ °É°í run<RET>À» ÀÔ·ÂÇؼ ´Ù½Ã ÇÑ ¹ø µ¹·Áº¸ÀÚ.
(gdb) br do_swap Breakpoint 1 at 0x804838f: file buggy.c, line 21. (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/cinsk/src/a.out i = 0, j = 1 Breakpoint 1, do_swap (lhs=0xbfffeb24, rhs=0xbfffeb24, tmp=0xbfffeb04) at buggy.c:21 (gdb) _ ÀÌÁ¦ n<RET>À» ÀÔ·ÂÇؼ next ¸í·ÉÀ» ¼öÇàÇÏ¸é ¼Ò½º ÄÚµå ¿ÞÆí¿¡ ÄÚµåÀÇ È帧À» ³ªÅ¸³»´Â »ï°¢Çü Ç¥½Ã°¡ ´ÙÀ½ ÁÙÀ» °¡¸®Å°´Â °ÍÀ» º¼ ¼ö ÀÖ´Ù. n<RET> ´ë½Å C-c C-nÀ» ½á¼ next ¸í·ÉÀ» ¼öÇàÇÒ ¼öµµ ÀÖ´Ù. ±×·³ step ¸í·É ´ÜÃàÅ°´Â ¹«¾ùÀϱî? °õÀÌ ¾Æ´Ï¶ó¸é C-c C-sÀÎ °ÍÀ» ÁüÀÛÇÒ ¼ö ÀÖÀ»Å×´Ï ³Ñ¾î°£´Ù.
{ tmp = 0; > *tmp = *lhs; *lhs = *rhs; *rhs = *tmp; } ¿©±â±îÁö ¿Ô°í, ¶Ç Emacsâ¿¡ º¸ÀÌ´Â ¼Ò½º¸¦ º¸¸é ¹Ù·Î ¹«¾ùÀÌ À߸øµÈ °ÍÀÎÁö ±Ý¹æ ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù. Àû¾îµµ C ¾ð¾î°¡ ¼ÅøÁö ¾Ê´Â´Ù¸é. ±×·³ "tmp = 0"À» Áö¿ì°í, (ÇöÀç Ä¿¼°¡ debugger mode â¿¡ À§Ä¡ÇÏ°í ÀÖÀ»Å×´Ï, C-x o¸¦ ´·¯¼ ¼Ò½º°¡ ³ª¿ÍÀÖ´Â ¹Ý´ëÆí âÀ¸·Î Ä¿¼¸¦ ¿Å±ä ´ÙÀ½, Ä¿¼¸¦ "tmp = 0;" ÁÙ¿¡ À§Ä¡½ÃÅ°°í C-a C-k C-k¸¦ ´·¯¼ ±× ÁÙÀ» Áö¿î´Ù.) C-x C-s¸¦ ´·¯ ÀúÀåÇÑ´Ù. ±× ´ÙÀ½À¸·Î, ÄÄÆÄÀÏÇÑ ´ÙÀ½(M-x compile<RET><RET>), ¹Ý´ëÆí âÀ¸·Î ³Ñ¾î°¡¼(C-x o), gdb ¹öÆÛ·Î ÀüȯÇÑ´Ù (C-x b<RET>).
»õ·Î ÄÄÆÄÀÏÇßÀ¸¹Ç·Î »õ·Î ÆÄÀÏÀ» Àоî¿Í¾ß ÇÑ´Ù. gdb prompt¿¡¼ "file a.out<RET>"À» ÀÔ·ÂÇؼ ´Ù½Ã ½ÇÇà ÆÄÀÏÀ» Àоî¿Â´Ù:
(gdb) file a.out A program is being debugged already. Kill it? (y or n) y Load new symbol table from "a.out"? (y or n) y Reading symbols from a.out...done. (gdb) _ ±×¸®°í ´Ù½Ã run ½ÃÄѼ(r <RET>), do_swapÀÇ ³»¿ëÀ» À¯½ÉÈ÷ ¹Ù¶óº¸±â ¹Ù¶õ´Ù.
(gdb) r Starting program: /home/cinsk/src/a.out i = 0, j = 1 Breakpoint 1, do_swap (lhs=0xbfffda34, rhs=0xbfffda34, tmp=0xbfffda14) at buggy.c:21 (gdb) _ ÀÏ´Ü, do_swap()¿¡ Àü´ÞµÈ óÀ½ µÎ°³ÀÇ ÀÎÀÚ, lhs¿Í rhs°¡ °°Àº ÁÖ¼Ò¸¦ °¡¸®Å°°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. gdb print ¸í·É(p)À¸·Î ÀÚ¼¼È÷ ÀÎÀÚ °ªµéÀ» Á¶»çÇغ¸ÀÚ.
(gdb) p *lhs $1 = 0 (gdb) p *rhs $2 = 0 (gdb) p lhs $3 = (int *) 0xbfffda34 (gdb) p rhs $4 = (int *) 0xbfffda34 (gdb) _ ¹«¾ùÀÌ ¹®Á¦Àϱî? do_swap()À» ºÎ¸¥ ÇÔ¼ö°¡ ù¹ø° ÀÎÀÚ¿Í µÎ¹ø° ÀÎÀÚ¿¡ °°Àº ÁÖ¼Ò¸¦ ³Ñ°ÜÁØ °ÍÀÌ´Ù! ´Ù½Ã Çѹø backtrace ¸í·É(bt)À¸·Î call stackÀ» Á¶»çÇغ¸ÀÚ:
(gdb) bt #0 do_swap (lhs=0xbfffda34, rhs=0xbfffda34, tmp=0xbfffda14) at buggy.c:21 #1 0x080483c7 in swap (lhs=0xbfffda34, rhs=0xbfffda34) at buggy.c:30 #2 0x0804836c in main () at buggy.c:12 #3 0x420156a4 in __libc_start_main () from /lib/tls/libc.so.6 (gdb) _ ¾ÆÇÏ! À§¸¦ Àß »ìÇǸé buggy.cÀÇ 30¹ø° ÁÙ¿¡ ÀÖ´Â swap ÇÔ¼ö°¡ do_swap()À» ºÒ·¶´Âµ¥, ±× ¶§ do_swap()¿¡ Àü´ÞµÈ óÀ½ µÎ ÀÎÀÚ°¡ °°Àº ÁÖ¼Ò°ªÀ» ³Ñ°ÜÁá´Ù´Â °ÍÀ» È®½ÇÈ÷ ¾Ë ¼ö ÀÖ´Ù. ¸¶Âù°¡Áö·Î main()ÀÌ swap()À» ºÎ¸¦ ¶§ °°Àº ÁÖ¼Ò°ªÀ» ³Ñ°Ü ÁØ °Íµµ ¾Ë ¼ö ÀÖ´Ù.
ÀÌÁ¦ stack frameÀ» ÇÑ ´Ü°è ¿Ã¶ó°¡´Â up ¸í·É(up)À» ½ÇÇà½ÃÅ°ÀÚ.
(gdb) up #1 0x080483c7 in swap (lhs=0xbfffda34, rhs=0xbfffda34) at buggy.c:30 (gdb) _ ÀÌ ¶§, ¼Ò½º â¿¡´Â Ä¿¼°¡ swap() ÇÔ¼öÀÇ 30¹ø° ÁÙ·Î À̵¿ÇÑ °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. (Emacs debugger modeÀÇ ¶Ç Çϳª ÁÁÀº ±â´É!)
swap()¿¡ º° ÀÌ»óÀÌ ¾øÀ¸¹Ç·Î ´Ù½Ã up ¸í·ÉÀ¸·Î ÇÑ ´Ü°è ¿Ã¶ó°¡ÀÚ.
(gdb) up #2 0x0804836c in main () at buggy.c:12 (gdb) _ ÀÌÁ¦ Ä¿¼´Â main() ÇÔ¼ö¿¡¼ swap()À» ºÎ¸¥ ÁÙ (12¹ø° ÁÙ)À» °¡¸®Å°°í ÀÖÀ» °ÍÀÌ´Ù. ÀÚ ¿©±â¼ ¹ö±× ¹ß°ß!
swap(&i, &i); ¸¦, ¾Æ·¡¿Í °°ÀÌ ¹Ù²Û´Ù:
swap(&i, &j); ÀÚ, ÀÌÁ¦ ´Ù½Ã ¹Ýº¹ ÀÛ¾÷¸¸ ³²¾Ò´Ù. ÀúÀåÇÏ°í(C-x C-s), ÄÄÆÄÀÏÇÏ°í(M-x compile), shellÀ» ¶ç¿ö¼(M-x shell) ½ÇÇà ÆÄÀÏ ½ÇÇàÇغ¸°í, ÀÌ»óÀÌ ¾ø´Â°¡ È®ÀÎÇغ¸ÀÚ.
¿©±â±îÁö Emacs debugger mode¿¡¼ gdb¸¦ ¾²´Â ¹ýÀ» ¾ÆÁÖ °£´ÜÈ÷ ÈÈ¾î º¸¾Ò´Ù. Á» ´õ ÀÚ¼¼ÇÑ ³»¿ëÀ» ¿øÇÑ´Ù¸é:
5. etags ¶etags¿Í emacsÀÇ °ü°è´Â ctags¿Í viÀÇ °ü°è¶ó ÇÒ ¼ö ÀÖ´Ù. etags´Â ¿©·¯ ¾ð¾î ÆÄÀϵéÀ» Àоî tag tableÀ» ¸¸µé¾îÁÖ¸ç, emacs¿¡¼ ÀÌ tag tableÀ» ¹ÙÅÁÀ¸·Î sourceµéÀ» ÀÚÀ¯·ÎÀÌ navigate ÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î ÁÖ¾îÁø ÇÔ¼ö À̸§À¸·Î ÇÔ¼öÀÇ Á¤ÀǸ¦ ã´Â´Ù´ÂÁö, º¯¼ö À̸§ÀÌ ¾²ÀÎ °÷À» ã´Â µîÀÇ ÀÏÀ» ÇÒ ¼ö ÀÖ´Ù.
ÀÏ´Ü ¼Ò½º µð·ºÅ丮 ·çÆ®¸¦ ÁöÁ¤ÇØ¾ß ÇÑ´Ù. ¿©·¯ºÐÀÌ ÀÛ¾÷ ÁßÀÎ ¼Ò½º°¡ ÀÖ´Ù¸é ±× ¼Ò½º¸¦ ½á º¸±â¸¦ ±ÇÀåÇÏ°í, ±×·¸Áö ¾Ê´Ù¸é ÀϹÝÀûÀ¸·Î /usr/src/linux¿¡ ¼³Ä¡µÇ¾î ÀÖ´Â Linux kernel source¸¦ ½á º¸ÀÚ. ¿©±â¼´Â /usr/src/linux¿¡ ¼³Ä¡µÇ¾î ÀÖ´Â Linux kernel source¸¦ °¡Áö°í ¿¹¸¦ º¸¿©ÁÙ °ÍÀÌ´Ù.
ÀÏ´Ü etags´Â ÀÛ¾÷ °á°ú¸¦ ÇöÀç µð·ºÅ丮¿¡ `TAGS'¶ó´Â ÆÄÀÏ·Î ±â·ÏÇÑ´Ù.
ÁÖÀÇ! ÀÌ ±ÛÀº /usr/src/linux¸¦ ´ë»óÀ¸·Î Çϱ⠶§¹®¿¡, ÀÏ¹Ý »ç¿ëÀÚ´Â ÀÌ µð·ºÅ丮¿¡ ¾²±â ±ÇÇÑÀÌ ¾øÀ» °ÍÀÌ´Ù. µû¶ó¼ etag °ü·Ã ÀÛ¾÷À» ÇÏ·Á¸é root·Î ÀÛ¾÷ÇÏ´øÁö, ¾Æ´Ï¸é, ÇöÀç µð·ºÅ丮¸¦ ´Ù¸¥ °÷À¸·Î ¹Ù²Ù¾î¾ß ÇÒ °ÍÀÌ´Ù.
etags°¡ ¼Ò½º ÆÄÀÏÀ» ºÐ¼®ÇÒ ¶§ ÇöÀç µð·ºÅ丮¸¸ ´ë»óÀ¸·Î Çϱ⠶§¹®¿¡ °ÅÀÇ ¸ðµç °æ¿ì find ¸í·É°ú ÇÔ²² ¾´´Ù:
$ pwd /home/cinsk/src $ find -H /usr/src/linux -name '*.[csSh]' | etags - Áï find ¸í·ÉÀÌ /usr/src/linux¿¡ ÀÖ´Â *.c *.s *.S *.h¿¡ ´ëÇÑ ¸ñ·ÏÀ» etags¿¡ ÆÄÀÌÇÁ·Î ³Ñ±â¸é, etags´Â À̸¦ stdinÀ¸·Î ¹Þ¾Æ¼, ÇöÀç µð·ºÅ丮¿¡ TAGS¶õ ÆÄÀÏ·Î (ÀÌ ¿¹¿¡¼´Â /home/cinsk/src/TAGS) ±â·ÏÇÑ´Ù.
root »ç¿ëÀÚ¶ó¸é ´ÙÀ½°ú °°ÀÌ /usr/src/linux/TAGS·Î ±â·ÏÇÏ´Â °ÍÀÌ ´õ ÆíÇÒ °ÍÀÌ´Ù:
# cd /usr/src/linux # find . -name '*.[csSh]' | etags - ÀÌÁ¦ emacs¿¡¼ ÇÑ ¼Ò½º ÆÄÀÏÀ» ºÒ·¯¿ÀÀÚ. C-x C-f·Î /usr/src/linux/include/linux/sched.h¸¦ ºÒ·¯¿ÀÀÚ.
±× ´ÙÀ½ ÀûÀýÇÑ ÇÔ¼ö À̸§À» Çϳª ã¾Æº¸ÀÚ (¿¹¸¦ µé¾î C-s sched_initÀ¸·Î sched_init() ÇÔ¼öÀÇ ¼±¾ðÀ» ãÀ» ¼ö ÀÖ´Ù).
Ä¿¼¸¦ sched_init¿¡ À§Ä¡½ÃÅ°°í, M-.¸¦ ´·¯º¸ÀÚ. ±×·¯¸é mini-buffer¿¡ ´ÙÀ½°ú °°ÀÌ ¸Þ½ÃÁö°¡ º¸ÀδÙ:
Find tag: (default sched_init) _ Áï ´Ù¸¥ À̸§À» ÀÌ °÷¿¡ ½á ³ÖÀ» ¼öµµ ÀÖ°í, ¹Ù·Î <RET>À» Ä¡¸é default °ªÀÎ `sched_init'À» ¾²°Ô µÈ´Ù.
¾ÆÁ÷ emacs¿¡°Ô tag tableÀÎ TAGS°¡ ¾îµð¿¡ ÀÖ´ÂÁö ¾Ë·ÁÁÖÁö ¾Ê¾ÒÀ¸¹Ç·Î emacs´Â tag tableÀÇ À§Ä¡¸¦ ¹¯°Ô µÈ´Ù. À̶§ ¾Æ±î TAGS°¡ ÀúÀåµÇ¾î ÀÖ´Â °÷À» ½á ÁÖ¸é, emacs´Â ÀÚµ¿À¸·Î sched_init() ÇÔ¼ö°¡ À§Ä¡ÇÑ °÷À» º¸¿©ÁØ´Ù.
¸¸¾à emacs°¡ º¸¿©ÁØ ¼Ò½º°¡ ¿øÇÏ´Â °ÍÀÌ ¾Æ´Ï¶ó¸é ´ÙÀ½ µÎ ¸í·ÉÀ¸·Î °°Àº À̸§À¸·Î °è¼Ó ãÀ» ¼ö ÀÖ´Ù:
³ª´Â À§ÀÇ ´ÜÃàÅ°¸¦ º°·Î ÁÁ¾ÆÇÏÁö ¾Ê¾Æ¼ ´ÙÀ½ ³× ÁÙÀ» $HOME/.emacs¿¡ ±â·ÏÇÏ¿©, "C-u M-.", "C-u - M-." ´ë½Å "M-]", "M-["À» ¾´´Ù:
(fset 'find-next-tag "\C-u\256") ; macro for C-u M-.
(fset 'find-prev-tag "\C-u-\256") ; macro for C-u - M-. (global-set-key "\M-]" 'find-next-tag) (global-set-key "\M-[" 'find-prev-tag) tag¿¡ °üÇÑ Á» ´õ ÀÚ¼¼ÇÑ »çÇ×Àº emacs info ÆäÀÌÁöÀÇ Tags sectionÀ» º¸±â ¹Ù¶õ´Ù.
6. cscope ¶emacs/etagsµµ ²Ï ¾µ¸¸ÇÑ ¼Ò½º Ž»ö ±â´ÉÀ» Á¦°øÇÏÁö¸¸ emacs/cscope´Â ÇÑÃþ ´õ ¹ßÀüµÈ ¼Ò½º Ž»ö ±â´ÉÀ» Á¦°øÇÑ´Ù. emacs/etags°¡ emacsÀÇ built-in package Çü½ÄÀÎ ¹Ý¸é, cscope´Â º°µµÀÇ ÆÐÅ°Áö¸¦ ¼³Ä¡ÇØ¾ß ÇϹǷΠÁ¶±Ý ¹ø°Å·Ó´Ù.
ÀÏ´Ü cscopeÀÇ È¨ÆäÀÌÁö¿¡ °¡¼ cscope¸¦ ¼³Ä¡ÇÏÀÚ -- http://cscope.sourceforge.net/
´ÙÀ½À¸·Î ¼³Ä¡ÇÏ´Â °úÁ¤À» ¾Æ·¡¿¡ º¸Àδ٠(¾Æ·¡¿¡¼ X.Y´Â cscopeÀÇ ¹öÀü¿¡ µû¶ó ´Ù¸§, ÇöÀç 15.4).
# tar -xvzf cscope-X.Y.tar.gz # cd cscope-X.Y # ./configure # make install "make install"À» Çϱâ À§Çؼ´Â root·Î ·Î±äÇÒ ÇÊ¿ä°¡ ÀÖÀ» °ÍÀÌ´Ù. ´ÙÀ½À¸·Î À§¿¡ ÀÌ¾î¼ ´ÙÀ½°ú °°Àº °úÁ¤µµ ÇÊ¿äÇÏ´Ù.
# cd contrib # cd xcscope # cp cscope-indexer /usr/local/bin # cp xcscope.el /usr/share/emacs/site-lisp/ À§ °úÁ¤¿¡¼ /usr/share/emacs/site-lisp/ÀÇ À§Ä¡´Â emacs°¡ ¼³Ä¡µÈ °÷¿¡ µû¶ó ´Ù¸£Áö¸¸, emacs -batch ¸í·ÉÀ» ¼öÇàÇؼ ÈùÆ®¸¦ ¾òÀ» ¼ö ÀÖ´Ù:
$ emacs -batch Loading /usr/share/emacs/site-lisp/site-start.d/aspell-init.el (source)... Loading /usr/share/emacs/site-lisp/site-start.d/lang.emacs.el (source)... Loading /usr/share/emacs/site-lisp/lang/lang-ko.el (source)... Loading /usr/share/emacs/site-lisp/site-start.d/po-mode-init.el (source)... $ _ Âü°í ÀÌ´Â system-wide ¼³Á¤ ¹æ¹ýÀ̸ç, root ±ÇÇÑÀ» ¾òÀ» ¼ö ¾ø´Ù¸é cscope¸¦ ¿©·¯ºÐÀÇ µð·ºÅ丮¿¡ ¼³Ä¡ÇÏ°í (¾Æ±î ¼³Ä¡ÇÒ ¶§ "./configure --prefix=$HOME"À» ¾´´ÙµçÁö..), cscope-indexerµµ ¿©·¯ºÐÀÇ $PATH¿¡ µé¾î ÀÖ´Â °÷, ¿¹¸¦ µé¸é $HOME/bin¿¡ ¼³Ä¡ÇÏ°í, ¸¶Áö¸·À¸·Î `xcscope.el'µµ emacs load path¿¡ Ãß°¡ÇØ¾ß ÇÑ´Ù; emacs load path¿¡ °üÇÑ °ÍÀº 1À» Âü°íÇϱ⠹ٶõ´Ù.
¸¶Áö¸·À¸·Î ¾Æ±î º¹»çÇÑ `xcscope.el'À» ¿¾î¼ Àо°í ¾î¶»°Ô $HOME/.emacs ÆÄÀÏÀ» ¼öÁ¤ÇØ¾ß ÇÏ´ÂÁö Àо°í Àû¿ëÇϱ⠹ٶõ´Ù.
¿©±â±îÁö ³¡³µ´Ù¸é emacs¸¦ ½ÇÇà½ÃÅ°ÀÚ.
cscope°¡ Á¦´ë·Î µ¿ÀÛÇϱâ À§Çؼ´Â cscope database¸¦ ¸¸µé¾î¾ß ÇÑ´Ù; emacs¿¡¼ M-x cscope-index-file<RET>À» ÀÔ·ÂÇÏ°í ¿øÇÏ´Â µð·ºÅ丮(/usr/src/linux)¸¦ ÀÔ·ÂÇÑ´Ù. (Âü°í. /usr/src/linux´Â ²Ï Å« ¼Ò½ºÀ̹ǷΠ»ó´çÇÑ ½Ã°£ÀÌ ÇÊ¿äÇÒ °ÍÀÌ´Ù.)
À§ ÀÛ¾÷ÀÌ ³¡³µ´Ù¸é /usr/src/linux/¿¡ cscope.out°ú cscope.files¶ó´Â ÆÄÀÏÀÌ ¸¸µé¾î Áú °ÍÀÌ´Ù.
ÀÌÁ¦ etags¸¦ ¹è¿ï¶§¿Í ¸¶Âù°¡Áö·Î /usr/src/linux/include/linux/sched.h¸¦ ¿ÀÚ(C-x C-f). ´ÙÀ½À¸·Î sched_init¿¡ Ä¿¼¸¦ À§Ä¡½ÃÅ°°í "C-c s d"·Î ¿øÇÏ´Â Á¤ÀǸ¦ ãÀ» ¼ö ÀÖ´Ù (¾Æ·¡ ´ÜÃàÅ° Âü°í).
etags/cscope¸¦ Àß ¾²±â¸¸ Çϸé À¢¸¸ÇÑ source ºÐ¼®Àº ¹«³È÷ ÇØ°áÇÒ ¼ö ÀÖÁö¸¸, Á» ´õ °·ÂÇϰųª ÆíÁý ±â´É º¸´Ù source ºÐ¼® Àü¿ë ÅøÀ» ã°í ÀÖ´Ù¸é, ¾Æ·¡ ÅøÀ» ½á º¸±â ¹Ù¶õ´Ù:
|