AdBlock Detection Block

Sure, ad-blocking software does a great job at
blocking ads, but it also blocks some useful and important features of our
website. For the best possible site experience please take a moment to
disable your AdBlocker.

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

نشره Fahad في السبت, 2016/02/20 - 4:48م

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 <http://gnu.org/licenses/gpl.html> 
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: 
<http://www.gnu.org/software/gdb/bugs/>. 
Find the GDB manual and other documentation resources online at: 
<http://www.gnu.org/software/gdb/documentation/>. 
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 <stdio.h> 

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 <stdio.h>   
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 <process_name>

نحن الآن بحاجة إلى إلحاق هذا الرقم إلى المنقح gdb. هناك طريقتان: 1- بأن تحدد رقم العلمية مع أمر gdb هكذا:

$ gdb -p <pid>

2- استخدام أمر attach من داخل gdb هكذا:

(gdb) attach <pid>

هذا كل ما لدينا الآن، وهذه الأوامر هي فقط أساسيات استخدام gdb لتعطيك بداية جيدة في تنقيح الشفرة المصدرية، ولكن هناك المزيد والمزيد من الأشياء التي لم نغطيها في هذا الدرس. فمثلا يمكننا التنقيح باستخدام معلومات stack و متغيرات النظام والكثير. حاول أن تقرأ في دليل استخدام gdb وتجربة هذه الاشياء.

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

مستكشف مانع الإعلانات

نحن نعرف أن الإعلانات مزعجة!

لكن نحن في وادي التقنية لا نستخدم الإعلانات المزعجة ولا نستخدم إعلانات جوجل. نستخدم مربعا صغيرا على يمين الموقع من شركة حسوب العربية ونحن متأكدون من أنه لن يسبب لك أي إزعاج. من فضلك قم بتعطيل مانع الإعلانات لموقعنا وادعمنا.