منقح جنو أو GDB: أداة قوية لتنقيح الأكواد لبرامج لينكس

نشره Fahad في

GDB logo

يلعب المنقح Debugger دورا بالغ الأهمية في أي نظام لتطوير البرمجيات. حيث لا يمكن لأي شخص أن يكتب كودا خالي من العلل من المرة الأولى. فخلال عملية التطوير، تظهر العلل (bugs) وتستلزم أن تحل حتى تتحسن جودة البرنامج. وبكل تأكيد فإن نظام التطوير لا يكتمل من دون وجود منقح. وعندما نتكلم عن مجتمع مطوري البرمجيات الحرة، فإن منقح جنو GNU Debugger هو الأفضل بلا منازع، حتى أنه يستخدم لتطوير البرامج التجارية على منصات يونكس. منقح جنو GNU Debugger ، ويعرف أيضا gdb ، يسمح لنا بأن نغوص في الكود بينما هو يعمل أو يتيح لنا معرفة ماذا كان يفعل البرنامج قبل أن ينهار. وبشكل أساسي فإن GDB يساعدنا في فعل أربعة أشياء لتمسك بالأخطاء في الشفرة المصدرية:

  • تشغيل البرنامج بخيارات محددة والتي من شأنها أن تؤثر على سلوكه العام.
  • توقيف البرنامج في شروط محددة.
  • اختبار الانهيار أو متى توقف البرنامج.
  • تغيير الشفرة و تجربة البرنامج بالشفرة المعدلة مباشرة. يمكننا أن نستخدم gdb لتنقيح البرامج المكتوبة بلغة السي والسي بلس بلس من دون أي عناء. بينما يدعم منقح gdb بشكل جزئي لغات البرمجة D و Modula-2 و Fortran.

##البدء مع منقح جنو GDB

لاستخدام GDB يجب أن تشغله من سطر الأوامر بأمر gdb، وحالما تفعل ذلك فإن سيظهر بعض المعلومات حوله، و سيدخلك في محث gdb مثلما هو يظهر بالأسفل

[root@fedora20 ~]# gdb
عينة من المخرجات
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20 Copyright (C) 2013 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". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word". (gdb)
اكتب help سيعرض لك مختلف أصناف الأوامر المتوفرة بداخل gdb. اكتب help وأتبعه باسم الصنف لاستعراض الأوامر في ذلك الصنف. اكتب help all لاستعراض كل الأوامر. يتيح منقح جنو اختصارات أسماء الأوامر إذا لم يكن هناك أي غموض. فمثلا، يمكنك أن تكتب n بدلا من next أو c بدل continue وهكذا.

##أشهر الأوامر استخداما في GDB الجدول التالي يستعرض أشهر أوامر gdb، وهي تستخدم داخل محث gdb:

| الوصف | الأمر | |------------------------------------------------------------------|------------| | تشغيل البرنامج | run | | الخروج من gdb | quit | | اطبع التعبير حيث expr يمكن أن يكون اسم متغير | print expr | | اذهب للسطر الثاني | next | | اقفز إلى داخل السطر التالي | step | | استمر من السطر الحالي إلى نهاية البرنامج أو نقطة التنقيح التالية | continue |

لاحظ الفرق بين أمر step و next. فأمر next لا يذهب لداخل الدالة إذا كان السطر التالي هو استدعاء لدالة ما، بينما أمر step يسمح بالذهاب لداخل الدالة ويعرض ما يحدث بداخلها.

##جلسة تنقيح بسيطة باستخدام GDB

لنفترض أننا كتبنا الشفرة المصدرية التالية:

// sum.c #include
int sum (int a, int b) { 
	int c; 
	c = a + b; 
	return c; 
} 

int main() { 
	int x, y, z; 
	printf("\nEnter the first number: "); 
	scanf("%d", &x); 
	printf("Enter the second number: "); 
	scanf("%d", &y); 
	z = sum (x, y); 
	printf("The sum is %d\n\n", z); 
	return 0; 
}

ومن أجل أن نستطيع أن ننقح هذه الشفرة يجب أن نترجمها باستخدام خيار -g في مترجم gcc

$ gcc -g sum.c -o sum
ثم يمكننا أن ننقح ملف sum باستخدام gdb باستخدام طريقتين: 1- عن طريق تحديد الملف كمعامل لبرنامج gdb.
$ gdb sum
2- تشغيل الملف من داخل محث gdb عن طريق أمر file
$ gdb (gdb) file sum
إذا كتبت أمر list فإن سيعرض لك سطور الشفرة المصدرية في الملف، حيث أمر list سيعرض أولا عشرة سطور والمرة الثانية سيعرض عشرة سطور التالية وهكذا.
(gdb) list 1 #include 2 3 int sum (int a, int b) { 4 int c; 5 c = a + b; 6 return c; 7 } 8 9 int main() { 10 int x, y, z;
حتى تبدأ في تشغيل البرنامج اكتب أمر run. وسينفذ البرنامج بشكل طبيعي. ولكننا نسينا أن نضع بعض نقاط التنقيح breakpoints في الشفرة المصدرية أليس كذلك؟ يمكننا تحديد نقاط التنقيح للدوال أو على مستوى السطر.
(gdb) b main
لاحظ أن استخدمت مختصر b لأمر break بعد أن وضعنا نقطة تنقيح في الدالة main سيتوقف البرنامج عند السطر 11. ويمكن فعل ذلك أيضا إذا كنت تعرف رقم السطر عن طريق كتابة:
(gdb) b sum.c:11
والآن تقدم خطوة في الشفرة المصدرية عن طريق استخدام أمر next أو n. إنه من المهم أن تدرك أن أمر next لا يذهب داخل شفرة الدالة ما لم تكن هناك نقطة تنقيح بداخلها. الآن دعنا نجرب أمر print. ضع نقطة تنقيح على دالة sum كالتالي:
(gdb) b sum Breakpoint 1 at 0x4005aa: file sum.c, line 5. (gdb) r Starting program: /root/sum
Enter the first number: 2 
Enter the second number: 3 

Breakpoint 1, sum (a=2, b=3) at sum.c:5 
5		c = a + b; 
(gdb) p a 
$1 = 2 
(gdb) p b 
$2 = 3
(gdb) c 
Continuing. 
The sum is 5 

[Inferior 1 (process 3444) exited normally]
إذا تطلب البرنامج المشغل معاملات من سطر الأوامر، فيمكنك تزويدها لأمر run بنفس الطريقة هكذا:
(gdb) run . . .
يمكنك أيضا استعراض المكتبات المشتركة في البرنامج المشغل هكذا:
(gdb) info share From To Syms Read Shared Object Library 0x00000035a6000b10 0x00000035a6019c70 Yes /lib64/ld-linux-x86-64.so.2 0x00000035a641f560 0x00000035a6560bb4 Yes /lib64/libc.so.6
##تعديل المتغيرات يتيح لنا GDB تعديل المتغيرات أثناء تنفيذ البرنامج. دعنا نجرب ذلك. كما أشرنا سابقا ضع نقطة تنقيح على السطر 16 ثم شغل البرنامج.
(gdb) r Starting program: /root/sum
Enter the first number: 1 
Enter the second number: 2 

Breakpoint 1, main ( ) at sum.c:16 
16		printf("The sum is %d\n\n", z); 
(gdb) set z=4 
(gdb) c 
Continuing. 
The sum is 4
الآن a = 1 و b = 2 و النتيجة يجب أن تكون z = 3 . ولكن قمنا بتغيير النتيجة النهائية إلى z = 4 في الدالة main. بهذه الطريقة يمكن أن تكون عملية التنقيح أسهل باستخدام gdb.

##تفعيل وإلغاء نقاط التنقيح للحصول على قائمة بنقاط التنقيح اكتب info breakpoints

(gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005c2 in main at sum.c:11
يظهر هنا نقطة تنقيح واحدة، لإلغاء نقاط التنقيح فقط اكتب رقمها بعد أمر disable ولتفعيلها لاحقا استخدم أمر enable.
(gdb) disable 1 (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep n 0x00000000004005c2 in main at sum.c:11
يمكنك أيضا أن تحذف نقاط التنقيح باستخدام أمر delete.

##تنقيح البرامج التي تعمل بالفعل هناك الكثير من البرامج التي تشتغل في الخلفية على نظام جنو/لينكس. لتنقيح أي عملية تشتغل في الخلفية، فنحن أولا بحاجة إلى رقم العملية، إن أمر pidof يعطيك رقم العملية pid :

$ pidof
نحن الآن بحاجة إلى إلحاق هذا الرقم إلى المنقح gdb. هناك طريقتان: 1- بأن تحدد رقم العلمية مع أمر gdb هكذا:
$ gdb -p
2- استخدام أمر attach من داخل gdb هكذا:
(gdb) attach
هذا كل ما لدينا الآن، وهذه الأوامر هي فقط أساسيات استخدام gdb لتعطيك بداية جيدة في تنقيح الشفرة المصدرية، ولكن هناك المزيد والمزيد من الأشياء التي لم نغطيها في هذا الدرس. فمثلا يمكننا التنقيح باستخدام معلومات stack و متغيرات النظام والكثير. حاول أن تقرأ في [دليل استخدام gdb](https://www.gnu.org/software/gdb/documentation/) وتجربة هذه الاشياء.

هذه المقالة مترجمة من الانجليزية، المصدر هنا.