Подобрете качеството на кода и предотвратите неочаквани резултати, като научите как да използвате GNU Debugger, за да разкривате нежелани грешки във вашия код.

Отстраняването на грешки е незаменимо умение за програмисти и изследователи по сигурността. Силното разбиране на отстраняването на грешки ви позволява да разберете изпълним файл на по-ниско ниво и да уловите всички дебнещи грешки.

GNU дебъгерът или GDB е вечен инструмент за отстраняване на грешки, на който програмистите разчитат от години. Ето как да използвате GDB на Linux.

Подготовка на примерни програми

За да изследвате функциите на GDB, ще ви трябва изпълним файл, с който да експериментирате. За демонстрация ще стартирате GDB на програма за проверка на ключове веднъж с налични изходен код и символи за отстраняване на грешки, веднъж без изходен код и на проста многонишкова програма, която отпечатва съобщения на екрана, както написани на C, така и компилирани с GCC (GNU C Компилатор).

Можеш използвайте всеки друг C компилатор но се уверете, че не премахвате двоичния файл.

instagram viewer

Най-вероятно ще изпълнявате GDB на вашите собствени програми. Така че не забравяйте да ги компилирате с -g флаг с gcc за активиране на символи за отстраняване на грешки.

Без наличните символи за отстраняване на грешки и със силно оголен двоичен файл ще трябва да отстраните грешки при разглобяването на програмата. Това ще изисква от вас да владеете добре асемблерния език и как работи разпределението на паметта на Linux за разбиране на данните в стека и регистрите.

Изпълнение на програма в GDB

Изпълнявате програма в GDB по няколко начина. Въведете или gdb и след като се зареди, въведете тичам. Или стартирайте gdb и след това използвайте файл команда, заредете двоичния файл в gdb и след това го изпълнете с тичам команда.

Ако вашата програма изисква аргументи от командния ред, за да функционира правилно, не забравяйте да добавите аргументите след името на програмата. Ето синтаксиса за зареждане на програмата в GDB и изпълнението й с аргументи:

gdb 
run

Или:

gdb
file
run

Задаване на точки на прекъсване с GDB

Точките на прекъсване при отстраняване на грешки са ръчно зададени твърди спирания в кода, които спират потока на изпълнение, когато програмата достигне точка на прекъсване. Задаването на точки на прекъсване ви позволява да преминете през кода и да проверите как всеки етап от изпълнението засяга данните и променливите.

В GDB, когато дебъгвате програма със символи за отстраняване на грешки, можете или да зададете точка на прекъсване по името на функцията, или да зададете точка на прекъсване въз основа на номера на реда. Ето синтаксиса:

break main
break 47

За да видите всички точки на прекъсване в текущата сесия за отстраняване на грешки, въведете:

info breakpoints

За да изтриете определена точка на прекъсване или няколко точки на прекъсване, въведете:

delete 2
delete 3-5

GDB също ви позволява да задавате условни точки на прекъсване, което означава, че програмата ще спре само ако дадено условие е изпълнено по време на изпълнение. Може да е промяната в стойността на променлива или неуспешно извикване на функция или каквото искате. Ето синтаксиса за задаване на условни точки на прекъсване:

break  if n == 2

Ако искате да продължите изпълнението на програмата след достигане на точка на прекъсване, въведете продължи команда:

continue

Преминаване през код

Преминаването през кода е от решаващо значение за разбирането как програмата обработва данните. Като преминавате през различни функции във вашата програма и изследвате състоянието на данните, можете да разберете по-добре как програмата прилага логиката, която сте написали в кода.

Той също така ви помага да откриете корена на сривовете и да проучите поведението на програмата с хирургическа прецизност, тъй като можете да преминавате през всеки ред код, както желаете. Можете да преминете през кода по три основни начина в GDB:

  1. стъпка: Тази команда казва на GDB да премине към следващия ред на изходния файл. Това ви позволява по същество да обхождате дължината на изходния код ред по ред.
  2. следващия: Тази команда изпълнява следващия ред от изходния код в текущата функция и след това спира. следващия третира функцията като единичен ред, така че ако използвате next преди извикване на функция, тя ще я третира като единичен ред и ще премине през него, за разлика от стъпка команда.
  3. завършек: Командата за завършване изпълнява всички останали редове в текущата функция и след това спира.

Изследване на променливи

Докато преминавате през кода, бихте искали да изследвате стойността на променливите, за да видите как логиката на програмата ги променя. Ето синтаксиса за преглед на стойността на променливите в GDB:

print 

В случай, че искате да отпечатате промените в стойността на дадена променлива всеки път, когато тя се актуализира, трябва да използвате командата display. Това е особено полезно, когато искате да проследите и отпечатате стойността на променлива в цикъл:

display 

Задаване на точки за наблюдение

Точките за наблюдение и условните точки на прекъсване са тясно свързани, тъй като и двете отговарят на промените в програмата. Точките за наблюдение се използват за проследяване на промените в данните в кода. Например, може да искате програмата да прекъсва всеки път, когато стойността на променлива се промени. Ето как да го направите с GDB:

watch 

Отстраняване на грешки, специфични за нишки с GDB

GDB ви позволява да извършвате специфично за нишката отстраняване на грешки, когато работите с многонишкови програми. За демонстрация ще работим с проста C програма, която използва четири нишки за отпечатване на съобщения с всяка нишка.

За да видите текущо създадените нишки във вашата програма, използвайте инфо команда:

info threads

За да работите с конкретна нишка, можете да я изберете от списъка, като използвате нейния индексен номер. Например:

thread 2

След като изберете нишката, можете да преминете през нейния поток на изпълнение, като използвате стъпка, следващия, и завършек команди, както е показано по-горе.

Отдалечено отстраняване на грешки с GDB

Можете също така дистанционно да отстранявате грешки в програми, разположени на различна система. За да направите това, трябва да настроите gdbserver на целевата машина. Можете лесно да го инсталирате, като използвате мениджъра на пакети по подразбиране на вашата дистрибуция или други мениджъри на пакети, които сте инсталирали на вашата система.

Например, за да инсталирате gdbserver на вашите базирани на Ubuntu или Debian системи, използвайте APT:

sudo apt install gdbserver

Веднъж инсталиран, преместете се в папката на двоичния файл и изпълнете тази команда, за да стартирате gdbserver:

gdbserver :

gdbserver трябва да върне изхода, че работи и слуша на порта, който сте дефинирали. Сега на клиентската машина стартирайте GDB и след това се свържете с отдалечения сървър, като използвате мишена команда:

target remote :

Писане на GDB скриптове за автоматизиране на отстраняването на грешки

GDB позволява на програмистите да пишат GDB скриптове, които автоматично ще изпълняват GDB команди. Това помага изключително много, когато се опитвате да дебъгвате една и съща част от код няколко пъти. Вместо да се налага да задавате точката на прекъсване, преминавате през кода и отпечатвате стойности на променливи всеки път, когато зареждате двоичния файл, можете да използвате GDB скрипт, за да автоматизирате целия процес.

Ето един пример:

set logging enabled on
set logging file sample.out
break main
command 1
backtrace
print N
continue
end
quit

В скрипта по-горе вие ​​казвате на GDB да активира регистрирането и да запише журнала във файл, наречен sample.out, след което задайте точка на прекъсване на основен функция.

За точка на прекъсване номер 1, в този случай точката на прекъсване в основната функция, изпълнете следните команди: обратно проследяване, печат, продължи. По принцип GDB първо ще изпълни обратно проследяване, след това ще отпечата стойността на променливата "N", ще продължи изпълнението и накрая ще излезе.

За да изпълните този скрипт, използвайте:

gdb -x