- gdbserver делује као удаљени агент GDB-а за контролу процеса на другој машини путем TCP-а или серијског порта.
- За даљинско отклањање грешака, кључно је компајлирати са симболаКористите одговарајућу gdb базу података и правилно конфигуришите путање симбола и фонтова.
- gdbserver нуди једнопроцесни и вишепроцесни режим, такође се интегришући са WinDbg и QEMU за дебаговање језгра.
- Опције као што су --debug, sysroot и ограничења величине вредности помажу у дијагностиковању проблема и стабилизацији сесија.
Ако програмирате у C или C++ језику линук и никада ниси дотакао gdbserverПропуштате један од најкориснијих алата за даљинско отклањање грешака у процесима, било на серверу, уграђеном систему или чак унутар виртуелне машине или WSL-а. Далеко од тога да је нешто „магично“ или резервисано за стручњаке, gdbserver је једноставно мали програм који комуницира са gdb-ом и контролише извршавање циљног процеса.
Кључна идеја је веома једноставна.на машини на којој се покреће бинарна датотека коју желите да отклоните грешке ( мета) покрећете gdbserver; на вашем радном рачунару ( домаћинПокрећете gdb или чак WinDbg са подршком за gdb протокол. Оба се повезују преко TCP или серијског порта, и одатле можете поставити тачке прекида, прегледати променљиве, прегледати стек или пратити извршавање корак по корак као да се програм извршава на вашој машини.
Шта је gdbserver и када га је смислено користити?

gdbserver је даљински „агент“ за отклањање грешака за GNU gdbЊегова функција је веома специфична: покреће се на машини на којој се извршава програм који се анализира, контролише тај процес (или процесе) и комуницира са gdb клијентом који се налази на другој машини (или на истој) путем удаљене везе.
У свакодневној употреби, gdbserver се користи у два типична сценаријаСофтвер за дебаговање који ради у уграђеним окружењима (рутери, плоче са огољеним Линуксом, уређаји) ИОТитд.) и процесе дебаговања на удаљеним Линукс машинама, где није згодно или једноставно није могуће имати „дебелу“ gdb базу са свим библиотекама и симболима.
На практичном нивоу, gdbserver обавља задатке као што су Читање и писање регистра процеса и меморије, контрола извршавања (наставак, пауза, пролазак кроз кораке), управљање тачкама прекида и слање свих ових података у gdb користећи GDB удаљени протокол. Ова филозофија је веома слична оној код алата попут OpenOCD-а, који делују као мост између gdb-а и хардвер екстерни, с том разликом што gdbserver ради на истом систему на којем се покреће бинарна датотека.
Ако долазите из средина виндовс Такође је занимљиво знати Дебагери попут WinDbg-а могу да комуницирају са gdb сервером на Linux-у, тако да можете да дебагујете корисничке процесе на Linux-у из WinDbg-а користећи подршку за даљинско дебаговање путем gdb протокола који је Microsoft уградио у новије верзије.
Основни захтеви за дебаговање помоћу gdb и gdbserver

Пре него што почнете са даљинским отклањањем грешака, потребно је да разумете однос хост/циљ.. мета То је машина на којој се покреће програм који треба дебаговати и где ће се извршити gdbserver; домаћин Ово је машина са које ћете покренути gdb (или WinDbg) и где ћете имати изворни код и, пожељно, симболе за отклањање грешака.
Суштинска почетна тачка је компајлирање бинарног фајла са симболимаУ GCC-у или g++-у ово се постиже заставицом -gи обично је препоручљиво да се онемогуће и оптимизације (на пример са -O0Ово омогућава програму за отклањање грешака да прецизније приказује променљиве, макрое и структуру кода. За одређене макрое можете користити више нивое отклањања грешака, као што су -g3.
На страни хоста ће вам бити потребна компатибилна верзија gdb-а са циљном архитектуром. Да бисте отклонили грешке у MIPS, ARM или другом уграђеном систему архитектуре, морате користити gdb одговарајућег крос-ланца алата (на пример) arm-none-eabi-gdb o gdb-multiarch) и, ако је потребно, конфигуришите архитектуру и ендијански редослед са команде као set arch y set endian.
Што се тиче везе, gdbserver подржава два главна типаСеријска веза (веома честа у уграђеном хардверу, преко UART-а) и TCP/IP, што је најпогодније када је циљ на истој мрежи или је Linux машина доступна преко мреже. У оба случаја, команда се користи из gdb-а. target remote да се повеже са крајњом тачком коју је открио gdbserver.
Начини покретања gdbservera: једнопроцесни и вишепроцесни режим

gdbserver може да ради на два главна начина Када говоримо о дебаговању у корисничком режиму: директно повезано са једним процесом или као „сервер процеса“ који омогућава навођење и повезивање са различитим системским процесима.
У режиму једног процеса Покрећете gdbserver, наводећи host:port и програм који треба покренути. У једноставном примеру на Linux десктоп машини, могли бисте да урадите нешто овако:
Команда: gdbserver localhost:3333 foo
Са том командом, gdbserver покреће бинарну датотеку. foo и он остаје да слуша на порту 3333Док се удаљени gdb не повеже, програм остаје заустављен; када се gdb повеже са target remote localhost:3333, процес почиње да контролише дескрушер.
У вишепроцесном режиму (процесни сервер) опција се користи --multiУ овом случају, gdbserver не покреће директно ниједан програм, већ једноставно слуша долазне везе и дозвољава клијенту (gdb или WinDbg) да управља којим процесом да се креира или коме се прикључи:
Команда: gdbserver --multi localhost:1234
Приликом рада са WinDbg-ом на Linux-у, овај вишемод је посебно занимљив.Зато што из самог WinDbg-а можете да наведете процесе на удаљеном систему, видите PID, корисника и командну линију и да се придружите оном који вас занима, на сличан начин као што се то ради са процесним сервером. dbgsrv.exe на Виндовс-у.
Даљинско дебаговање помоћу gdbserver-а и gdb-а корак по корак
Хајде да ово спустимо на земљу једним веома типичним примером.Отклоните грешке у једноставној апликацији на истој машини (хост и циљ се подударају) користећи gdbserver за симулацију удаљеног сценарија.
Прво напишете и компајлирате мали програмНа пример, глупа петља која исписује бројач:
Команда: gcc -g foo.c -o foo
Кључна ствар овде је застава -gОво додаје неопходне информације за отклањање грешака бинарној датотеци тако да gdb може да прикаже линије кода, имена променљивих, типове итд. У „стварном“ окружењу за крос-компилацију, ову компилацију бисте урадили помоћу крос-алатка, а затим копирали и бинарну датотеку и њене зависности на циљ.
Следећи корак је покретање gdbserver-а на циљуАко су хост и циљ иста машина, онда:
Команда: gdbserver localhost:3333 foo
Видећете поруку сличну „Процес foo је креиран; pid = XXXX; Ослушкује се порт 3333“. Ово указује да је gdbserver креирао процес и чека да се gdb повеже. Ако сте на систему где су потребне додатне привилегије (на пример, за повезивање са системским процесима), можда ћете морати да покренете команду са sudoАли увек је мудро бити опрезан приликом давања дозволе. корен до десулфуризатора.
На хосту покрећете gdb наводећи локалну извршну датотеку (исти онај који се покреће на циљу или идентична копија са симболима):
Команда: gdb foo
Када се једном уђе у gdb, успоставља се удаљена веза са:
Команда: target remote localhost:3333
У том тренутку, gdb учитава симболе из локалне бинарне датотеке.Синхронизује се са gdbserver-ом и преузима контролу над процесом који се заправо извршава под gdbserver-ом. Одатле је ток уобичајен: команде попут break да постави преломне тачке, continue, step, next, print да се испитају променљиве, backtrace да видим батерију итд.
Повезивање са покренутим процесима помоћу gdbserver-а
Не желите увек да покрећете програм од нуле.Често сте заинтересовани да се придружите процесу који је већ у току (на пример, httpd по рутерсистемски демон или производни сервис).
Типичан образац је коришћење опције --attach са gdbserveraпрослеђивањем порта на којем ће слушати и PID-а циљног процеса. На пример, на рутеру где сте копирали gdbserver компајлиран за његову архитектуру, могли бисте да урадите:
Команда: gdbserver localhost:3333 --attach <pid_de_httpd>
На страни хоста, користићете верзију gdb-а која подржава архитектуру рутера., на пример gdb-multiarchпретходно конфигурисање архитектуре и ендијанског редоследа:
Команда: set arch mips
set endian big
Затим наводите локалну датотеку која садржи симболе. удаљеног бинарног програма (на пример file httpd) и, ако је потребно, обавештавате gdb где се бинарна датотека заправо извршава на циљу помоћу set remote exec-file /usr/bin/httpdКоначно, баш као и раније, повезујете се са:
Команда: target remote 192.168.0.1:3333
Једном причвршћеноМожете поставити тачке прекида на одређене функције (на пример break checkFirmware), наставити извршавање и дозволити нормалном току програма (на пример, отпремање фирмвера са веб интерфејса) да покрене тачку прекида.
Коришћење gdbservera са WinDbg-ом на Linux-у
Последњих година, Мајкрософт је додао подршку за дебаговање Линукс процеса у Виндбг-у. Коришћење gdbserver-а као бекенда. Ова функционалност је намењена сценаријима у којима радите у Windows-у, али се код покреће на Linux-у (укључујући WSL).
За дебаговање одређеног Линукс процеса помоћу Виндбг-а користећи гдбсерверТок би био отприлике овакав: прво лоцирате циљни процес на Линук машини помоћу команде као што је ps -A (на пример а python3 који се покреће), затим покрећете gdbserver на циљу:
Команда: gdbserver localhost:1234 python3
Ако окружење то захтева, можда ћете морати да користите sudo gdbserver ...уз исте безбедносне мере као и увек. Када gdbserver покаже да „Слуша порт 1234“, у WinDbg-у идите на „Датотека / Повежи се са удаљеним дебагером“ и наведите стринг за повезивање следећег типа:
Команда: gdb:server=localhost,port=1234
WinDbg користи мали „драјвер“ за gdb протокол за комуникацију са gdb сервером и, када се веза успостави, остаје заустављена на тачки боот процеса. Одатле можете користити његове прозоре стека, модуле, меморију, тачке прекида, као и команде попут k да видите батерију или lm да наведете модуле (имајући у виду да неке команде очекују PE формат, а не ELF, тако да у одређеним случајевима могу приказивати чудне податке).
gdbserver и WinDbg процесни сервер
Поред случаја са једним процесом, WinDbg се може повезати са gdbserver-ом који делује као процесни сервер да би радио сличније начину на који функционише са удаљеним Windows процесима. У овом режиму, gdbserver се покреће са --multi и без повезаног процеса:
Команда: sudo gdbserver --multi localhost:1234
Из WinDbg-а, изаберите „Датотека / Повежи се са процесним сервером“ и поново користите стринг за повезивање gdb:server=localhost,port=1234Када је веза активна, можете навести доступне Linux процесе и прикључити се на онај који желите или чак покренути нови процес.
Треба имати на уму један суптилни детаљ.WinDbg разликује „процесни сервер“ и „јединствени циљ“ у зависности од тога да ли је gdbserver већ повезан са процесом када се повеже. Ако сте оставили gdbserver повезан са процесом, затворили WinDbg, а затим покушали да се поново повежете, можда неће бити детектован као процесни сервер и можда ћете морати поново да покренете gdbserver.
Да бисте завршили сесију процесног сервераОбично је довољно једноставно притиснути CTRL+D у конзоли где је покренут gdbserver и зауставити дебаговање из WinDbg-а. У неким екстремним случајевима, ако постоје проблеми са синхронизацијом, може бити потребно потпуно затворити дебагер и поново покренути gdbserver од нуле.
Управљање симболима и изворним кодом у даљинском отклањању грешака
Један од кључева за олакшавање даљинског отклањања грешака јесте добро разјашњење симбола и фонтова.Без симбола, навигација кроз стек или постављање тачака прекида на одређеним функцијама постаје мучење.
У класичним сценаријима gdb + gdbserver, идеално је чувати копију извршне датотеке са симболима на хосту. (неогрануто) и изворно стабло. gdb не захтева да удаљени бинарни фајл садржи симболе; довољно је да локална датотека коју учитавате са file подудара се са удаљеним извршним фајлом на нивоу офсета.
У свету дебаговања у WinDbg-у и Linux-у, појавили су се и сервиси попут DebugInfoD-а.који приказују симболе и фонтове преко HTTP-а. WinDbg може да користи посебне путање типа DebugInfoD*https://debuginfod.elfutils.org обоје .sympath ас ин .srcpath да бисте преузели DWARF симболе на захтев и изворни код бинарних датотека за Linux ELF.
У конкретном примеру са WSL-ом, где се кориснички код налази испод C:\Users\Bob\Могли бисте рећи WinDbg-у:
Команда: .sympath C:\Users\Bob\
.srcpath C:\Users\Bob\
А ако желите да користите и DebugInfoD за системске бинарне датотеке:
Команда: .sympath+ DebugInfoD*https://debuginfod.elfutils.org
.srcpath+ DebugInfoD*https://debuginfod.elfutils.org
Са овом конфигурацијом, када прегледате стек или унесете libc функцијеВиндобг може покушати да преузме одговарајуће ДВАРФ симболе и, ако сервер такође изложи код, прикаже изворни код са значајним детаљима, иако интерно, Виндоус алати не обрађују ЕЛФ и ДВАРФ тако „изворно“ као ПЕ и ПДБ.
Практични пример: дебаговање C++ програма помоћу gdbserver-а и WinDbg-а
Илустративан пример је мала C++ апликација која исписује поздрав на екран., компајлирано у WSL-у са симболима за дебаговање. Замислите програм који резервише std::array<wchar_t, 50> и копира дужу поруку у њу, што доводи до скраћивања текста и појављивања карактера ???? на крају
Након компајлирања са нечим попут:
Команда: g++ DisplayGreeting.cpp -g -o DisplayGreeting
Покрећете gdbserver против тог бинарног фајла.:
Команда: gdbserver localhost:1234 DisplayGreeting
У WinDbg-у се повезујете са стрингом gdb:server=localhost,port=1234 И, када се сесија успостави и путање симбола и фонтова буду конфигурисане, постављате тачку прекида у DisplayGreeting!mainможете користити dx greeting да прегледате локални низ и видите његову величину (50 позиција), и визуелно проверите у картици меморије или у приказу променљивих како је поздрав одсечен.
Лепота овог примера је у томе што показује да, чак и без пуне подршке за све ELF/DWARF формате у WinDbg-уМожете прегледати стекове, прегледати типове, постављати тачке прекида по имену функције и релативно удобно се кретати кроз C++ код користећи gdbserver као удаљени бекенд.
Отклањање грешака у Линукс кернелу помоћу qemu и gdb
gdbserver се не користи само у корисничком режиму; постоје и веома моћни сценарији у режиму језгра.посебно када комбинујете QEMU са подршком за дебаговање. Иако овде улогу „gdbservera“ испуњава QEMU-ова сопствена опција, приступ је идентичан: један крај покреће систем који треба дебаговати и отвара gdb порт; други крај је или gdb или дебагер који говори удаљеним протоколом.
Да бисте отклонили грешке у кернелу, потребно га је компајлирати са одређеним опцијама за отклањање грешака.: активирајте генерисање информација за отклањање грешака (CONFIG_DEBUG_INFO), скрипте GDB језгра (CONFIG_GDB_SCRIPTS) и сопствени режим за отклањање грешака језгра (CONFIG_DEBUG_KERNELТакође је важно онемогућити опције које уклањају симболе током повезивања, као што је „Уклони симболе генерисане асемблером током повезивања“.
Након компајлирања добићете бинарну датотеку vmlinux „није огољено“што је онај који ћете користити из gdb-а. Такође вам је потребан основни initramfs, који можете генерисати командом попут:
Команда: mkinitramfs -o ramdisk.img
Затим покрећете QEMU са параметрима за дебаговањеТипичан пример укључује опцију -gdb tcp::1234 да отворите gdb-компатибилну удаљену крајњу тачку и -S тако да виртуелна машина почне паузирана од почетка. Такође наводите језгро са -kernel vmlinux, -initrd ramdisk.img, меморија са -m 512 и обично преусмеравате конзолу на ttyS0 да управља свиме од терминал.
Са QEMU притвореним чекајући gdbСа хост машине, покрећете gdb показујући на vmlinux и повезујете се са target remote localhost:1234Одатле можете поставити ране тачке прекида, на пример hb start_kernelи контролишите извршавање помоћу команди као што су c (настави) и CTRL+C за поновну паузу.
Недавне измене и нијансе у gdb и gdbserver
У модерним дистрибуцијама попут Red Hat Enterprise Linux-а 8, постоји низ промена у gdb-у и gdbserver-у које вреди имати на уму.посебно ако долазите са претходних верзија или имате скрипте које анализирају излаз дебагера.
С једне стране, gdbserver сада покреће „ниже“ процесе користећи љускуБаш као и gdb, ово омогућава проширење и замене променљивих у командној линији. Ако из било ког разлога треба да онемогућите ово понашање, постоје посебна подешавања документована у RHEL 8 за враћање на претходни режим.
Неколико ствари је такође уклоњено или промењено: подршка за отклањање грешака за Јава програме компајлиране са gcj, HP-UX XDB режим компатибилности, команде као што су set remotebaud (замењено са set serial baud) или компатибилност са одређеним старијим форматом stabsШтавише, нумерација навоја више није глобална, већ по „нижим“ навојима, и појављује се као inferior_num.thread_num, са новим практичним променљивим као што су $_gthread да се односи на глобални идентификатор.
Још једна релевантна нова карактеристика је подешавање max-value-sizeОво ограничава количину меморије коју gdb може да додели за приказ садржаја вредности. Подразумевана вредност је 64 KiB, тако да покушаји штампања огромних низова или масивних структура могу резултирати упозорењем „вредност је превелика“ уместо приказивања целе расположиве меморије.
Такође је прилагођен начин на који gdb обрађује sysrootПодразумевана вредност је сада target:То значи да ће за удаљене процесе прво покушати да пронађе библиотеке и симболе на циљном систему. Ако желите да да приоритет локалним симболима, требало би да покренете set sysroot са рутом која вас занима пре него што кренете target remote.
Што се тиче историје команди, променљива окружења која се сада користи је GDBHISTSIZE уместо HISTSIZEОво вам омогућава да прецизно подесите колико дуго желите да задржите команде које сте унели у сесијама отклањања грешака, а да притом не ометате понашање других апликација које користе библиотеку за читање линија.
Савети за радни ток и решавање проблема са gdbserver-ом
Да би се постигао удобан радни процес, постоје неки обрасци који обично веома добро функционишу. Приликом развоја за уграђене системе или удаљене сервере, први корак је аутоматизација компилације симбола и бинарног распоређивања на циљ колико год је то могуће. На овај начин, увек знате која верзија извршне датотеке се покреће и имате копију симбола лако доступну на хосту.
У окружењима са много језгара које изазивају пад система, вреди научити како да користите gdb у пакетном режиму., са заставама као што су --batch, --ex y -x да аутоматски покреће команде на листи језгара и обрађује њихове повратне трагове из скрипти (на пример у ПитонОво вам омогућава да брзо филтрирате понављајуће проблеме, групишете грешке по трагу стека итд.
Када нешто крене наопако са удаљеном везом, опција --debug гдбсервер је твој најбољи пријатељАко покренете, на пример, процесни сервер са:
Команда: gdbserver --debug --multi localhost:1234
Конзола gdbserver-а ће приказати детаљне трагове онога што се дешава На нивоу удаљеног протокола, ово укључује долазне пакете, грешке у форматирању, проблеме са прекидом везе итд. Ово је веома корисно када ваш gdb сервер изненада прекине везу, процес се сруши чим се постави тачка прекида или ваш графички кориснички интерфејс за дебаговање пошаље нешто што gdbserver не разуме.
У контекстима као што је TP-Link рутер где повезујете gdbserver са критичним процесом као што је httpdРелативно је уобичајено да одређене тачке прекида стварају услове трке или watchdog-ове који заустављају процес када он остане „заглављен“ предуго у дебагеру. У тим ситуацијама, може бити потребно подесити који су сигнали блокирани, које нити се контролишу и, ако је потребно, изменити саму конфигурацију система (времена чекања, хардверске watchdog-ове) како би се омогућиле дуже сесије дебаговања.
Добро коришћење gdbserver-а подразумева комбиновање неколико деловаКомпајлирајте са одговарајућим симболима, изаберите исправну gdb базу за архитектуру, конфигуришите путање симбола и изворног кода, разумејте два главна режима gdbservera (једнопроцесни и вишепроцесни) и не бојте се да преузимате из режима --debug када се веза не понаша како се очекује. Са том основом, дебаговање апликација које се покрећу на удаљеном Линукс систему, рутеру или виртуелној машини са прилагођеним кернелом са вашег рачунара постаје прилично рутинско и, пре свега, невероватно корисно.
Страствени писац о свету бајтова и технологије уопште. Волим да делим своје знање кроз писање, и то је оно што ћу радити на овом блогу, показивати вам све најзанимљивије ствари о гаџетима, софтверу, хардверу, технолошким трендовима и још много тога. Мој циљ је да вам помогнем да се крећете у дигиталном свету на једноставан и забаван начин.