3.9 דיבוג עם GDB פתרון
דבגו מה שלא דיבגתם¶
תרגיל זה הוא תרגול חופשי - אין פתרון יחיד. הנה דוגמה לתהליך דיבוג שמכסה את מה שנדרש:
דוגמה לדיבוג קוד C קיים¶
נניח שיש לכם את הקוד הבא שכתבתם בעבר:
#include <stdio.h>
int sum_array(int arr[], int size) {
int total = 0;
for (int i = 0; i < size; i++) {
total += arr[i];
}
return total;
}
int main() {
int numbers[] = {10, 20, 30, 40, 50};
int result = sum_array(numbers, 5);
printf("sum = %d\n", result);
return 0;
}
שלב 1: קומפילציה עם debug symbols¶
שלב 2: הרצה בתוך GDB עם pwndbg¶
שלב 3: שימוש בפקודות שלמדנו¶
(gdb) break main
(gdb) run
(gdb) next
(gdb) next
(gdb) print numbers
(gdb) x/5dw &numbers # הצגת 5 ערכים עשרוניים מהמערך
(gdb) step # נכנסים לתוך sum_array
(gdb) info locals # רואים את total ו-i
(gdb) next
(gdb) next
(gdb) print total # רואים ערך ביניים
(gdb) info registers # רואים את כל האוגרים
(gdb) x/20xb $rbp # מסתכלים על ה-stack frame
(gdb) disass sum_array # רואים את האסמבלי
(gdb) finish # יוצאים מהפונקציה
(gdb) print result # רואים את התוצאה
(gdb) continue
הרעיון הוא לתרגל את כל הפקודות: break, run, next, step, finish, continue, print, x, info locals, info registers, disass, ולהבין את הקשר בין קוד ה-C לקוד האסמבלי שנוצר.
מצאו ת'באג¶
הקוד:
// bug_simple.c
int main() {
int numbers[5] = {1, 2, 3, 4, 5};
int index = 10;
numbers[index] = 42;
return 0;
}
תהליך הדיבוג:¶
(gdb) break main
(gdb) run
(gdb) next # int numbers[5] = {1, 2, 3, 4, 5};
(gdb) next # int index = 10;
(gdb) print index
$1 = 10
(gdb) next # numbers[index] = 42; -> כאן הקריסה
אם התוכנית קרסה:
(gdb) backtrace # רואים איפה קרסה
(gdb) print index # רואים שהוא 10
(gdb) x/5dw &numbers # רואים שהמערך הוא רק 5 איברים
הבאג:¶
המערך numbers מוגדר עם 5 איברים (אינדקסים 0 עד 4), אבל הקוד ניגש לאינדקס 10 - שנמצא מחוץ לגבולות המערך. זו גישה לזיכרון שלא שייך למערך, מה שגורם לכתיבה למקום לא מורשה בזיכרון (דריסה של ערכים אחרים על ה-stack או קריסה).
התיקון - להשתמש באינדקס שנמצא בטווח התקין (0 עד 4):
מצאו ת'באג 2¶
הקוד:
// logic_bug.c
int main() {
int numbers[5] = {1, 2, 3, 4, 5};
int sum = 0;
for (int i = 0; i <= 5; i++) {
sum = sum + numbers[i];
}
return 0;
}
תהליך הדיבוג:¶
(gdb) break main
(gdb) run
(gdb) display i
(gdb) display sum
(gdb) next # עוברים על הגדרות המשתנים
(gdb) next
(gdb) next # נכנסים ללולאה
(gdb) next # i = 0, sum = 1
(gdb) next # i = 1, sum = 3
(gdb) next # i = 2, sum = 6
(gdb) next # i = 3, sum = 10
(gdb) next # i = 4, sum = 15
(gdb) next # i = 5, sum = ??? ערך זבל!
(gdb) print numbers[5] # ערך לא מוגדר - מחוץ למערך
הבאג:¶
התנאי בלולאה הוא i <= 5 במקום i < 5. המערך מכיל 5 איברים (אינדקסים 0 עד 4), אבל הלולאה רצה גם עם i = 5 - מה שגורם לגישה ל-numbers[5] שנמצא מחוץ לגבולות המערך. זוהי שגיאת off-by-one קלאסית.
הערך ש-numbers[5] מחזיר הוא ערך זבל - מה שנמצא בזיכרון אחרי המערך (סביר שזה חלק מה-stack frame, אולי הערך של sum עצמו או i או כתובת חזרה).
התיקון: