- gdbserver działa jako zdalny agent GDB, kontrolując procesy na innej maszynie poprzez TCP lub port szeregowy.
- Aby debugować zdalnie, kluczowe jest skompilowanie z symboleUżyj odpowiedniego gdb i poprawnie skonfiguruj ścieżki symboli i czcionek.
- gdbserver oferuje tryb pojedynczego procesu i tryb wieloprocesowy, a także integrację z WinDbg i QEMU w celu debugowania jądra.
- Opcje takie jak --debug, sysroot i limity wielkości wartości pomagają diagnozować problemy i stabilizować sesje.
Jeśli programujesz w C lub C++ Linux i nigdy nie dotykałeś gdbserveraTracisz jedno z najprzydatniejszych narzędzi do zdalnego debugowania procesów, czy to na serwerze, w systemie wbudowanym, czy nawet w maszynie wirtualnej lub WSL. gdbserver to nie coś „magicznego” ani zarezerwowanego dla ekspertów, lecz po prostu mały program, który komunikuje się z gdb i kontroluje wykonywanie procesu docelowego.
Kluczowa idea jest bardzo prosta.: na komputerze, na którym uruchomiony jest plik binarny, który chcesz debugować ( cel) uruchamiasz gdbserver na swoim komputerze służbowym ( gospodarzUruchamiasz gdb, a nawet WinDbg, z obsługą protokołu gdb. Oba łączą się przez TCP lub port szeregowy, a stamtąd możesz ustawiać punkty przerwania, inspekcję zmiennych, przeglądać stos lub śledzić wykonywanie krok po kroku, tak jakby program działał na Twoim komputerze.
Czym jest gdbserver i kiedy ma sens jego użycie?

gdbserver to zdalny „agent” debugowania dla GNU gdbJego funkcja jest bardzo specyficzna: działa na maszynie, na której uruchomiony jest program podlegający analizie, steruje tym procesem (lub procesami) i komunikuje się z klientem gdb znajdującym się na innej maszynie (lub na tej samej) za pomocą połączenia zdalnego.
W codziennym użytkowaniu gdbserver jest używany w dwóch typowych scenariuszachOprogramowanie do debugowania działające w środowiskach wbudowanych (routery, płyty z uproszczoną wersją systemu Linux, urządzenia) IoTitd.) oraz procesy debugowania na zdalnych maszynach z systemem Linux, gdzie nie jest wygodne lub po prostu niemożliwe posiadanie „bogatej” bazy danych gdb ze wszystkimi bibliotekami i symbolami.
W praktyce gdbserver obsługuje takie zadania, jak: Odczytuj i zapisuj rejestry procesów i pamięć, kontroluj wykonywanie (kontynuuj, wstrzymaj, przechodź krok po kroku), zarządzaj punktami przerwania i wysyłaj wszystkie te dane do gdb za pomocą zdalnego protokołu GDB. Ta filozofia jest bardzo podobna do filozofii narzędzi takich jak OpenOCD, które działają jako pomost między gdb a… sprzęt komputerowy zewnętrzny, z tą różnicą, że gdbserver działa w tym samym systemie, w którym działa plik binarny.
Jeśli pochodzisz ze środowisk Windows Ciekawie jest też wiedzieć Debugery takie jak WinDbg mogą komunikować się z gdbserverem w systemie Linux, dzięki czemu można debugować procesy użytkownika w systemie Linux z poziomu WinDbg, korzystając z obsługi debugowania zdalnego za pośrednictwem protokołu gdb, który firma Microsoft włączyła w ostatnich wersjach.
Podstawowe wymagania dotyczące debugowania z gdb i gdbserver

Zanim zaczniesz debugować zdalnie, musisz zrozumieć relację host-cel.. cel Jest to maszyna, na której uruchamiany jest program przeznaczony do debugowania i na której zostanie uruchomiony serwer gdbserver; gospodarz To jest maszyna, na której uruchomisz gdb (lub WinDbg) i gdzie będziesz miał kod źródłowy oraz, najlepiej, symbole debugowania.
Podstawowym punktem wyjścia jest kompilacja pliku binarnego za pomocą symboliW GCC lub g++ można to osiągnąć za pomocą flagi -gi zazwyczaj zaleca się również wyłączenie optymalizacji (np. z -O0Dzięki temu debugger może dokładniej wyświetlać zmienne, makra i strukturę kodu. W przypadku określonych makr można użyć wyższych poziomów debugowania, takich jak: -g3.
Po stronie hosta potrzebna będzie kompatybilna wersja gdb z architekturą docelową. Aby debugować system wbudowany MIPS, ARM lub inną architekturę, należy użyć gdb odpowiedniego łańcucha narzędzi (na przykład) arm-none-eabi-gdb o gdb-multiarch) i w razie potrzeby skonfiguruj architekturę i kolejność bajtów za pomocą polecenia jako set arch y set endian.
Jeśli chodzi o połączenie, gdbserver obsługuje dwa główne typyŁącze szeregowe (bardzo powszechne w sprzęcie wbudowanym, przez UART) i TCP/IP, co jest najwygodniejsze, gdy cel znajduje się w tej samej sieci lub jest to komputer z systemem Linux dostępny przez sieć. W obu przypadkach polecenie jest wydawane z poziomu gdb. target remote aby połączyć się z punktem końcowym udostępnionym przez gdbserver.
Sposoby uruchamiania gdbserver: tryb pojedynczego procesu i tryb wieloprocesowy

gdbserver może działać na dwa główne sposoby Kiedy mówimy o debugowaniu w trybie użytkownika: bezpośrednio powiązane z pojedynczym procesem lub jako „serwer procesów”, który umożliwia wyświetlanie i dołączanie do różnych procesów systemowych.
W trybie pojedynczego procesu Uruchamiasz gdbserver, określając host:port i program do uruchomienia. W prostym przykładzie na komputerze stacjonarnym z systemem Linux możesz zrobić coś takiego:
Komenda: gdbserver localhost:3333 foo
Za pomocą tego polecenia gdbserver uruchamia plik binarny. foo i nasłuchuje na porcie 3333Dopóki zdalny gdb się nie połączy, program pozostaje zatrzymany; gdy gdb łączy się z target remote localhost:3333, proces zaczyna być kontrolowany przez rozdrabniacz.
W trybie wieloprocesowym (serwer procesów) opcja ta jest używana --multiW tym przypadku gdbserver nie uruchamia bezpośrednio żadnego programu, lecz po prostu nasłuchuje połączeń przychodzących i pozwala klientowi (gdb lub WinDbg) decydować, który proces utworzyć lub do którego się podłączyć:
Komenda: gdbserver --multi localhost:1234
Podczas pracy z WinDbg na Linuksie ten wielomodowy tryb jest szczególnie interesujący.Ponieważ z poziomu samego WinDbg można wyświetlić listę procesów w systemie zdalnym, zobaczyć PID, użytkownika i wiersz poleceń oraz dołączyć się do procesu, który nas interesuje, w podobny sposób, jak ma to miejsce w przypadku serwera procesów dbgsrv.exe w systemie Windows.
Zdalne debugowanie za pomocą gdbserver i gdb krok po kroku
Przyjrzyjmy się temu bliżej i posłużmy się typowym przykładem.:Debugowanie prostej aplikacji na tej samej maszynie (zgodność hosta i celu) przy użyciu gdbserver w celu symulacji scenariusza zdalnego.
Najpierw napisz i skompiluj mały programNa przykład głupia pętla drukująca licznik:
Komenda: gcc -g foo.c -o foo
Kluczem tutaj jest flaga -gDodaje to do pliku binarnego niezbędne informacje debugowania, dzięki czemu gdb może wyświetlać wiersze kodu, nazwy zmiennych, typy itd. W „prawdziwym” środowisku kompilacji krzyżowej, kompilację tę należy wykonać za pomocą łańcucha narzędzi krzyżowych, a następnie skopiować plik binarny i jego zależności do środowiska docelowego.
Następnym krokiem jest uruchomienie gdbserver na docelowym komputerzeJeśli host i cel to ta sama maszyna, to:
Komenda: gdbserver localhost:3333 foo
Zobaczysz komunikat podobny do „Proces foo został utworzony; pid = XXXX; Nasłuchuje na porcie 3333”. Oznacza to, że gdbserver utworzył proces i oczekuje na połączenie gdb. Jeśli korzystasz z systemu, w którym wymagane są większe uprawnienia (na przykład do dołączenia do procesów systemowych), może być konieczne uruchomienie polecenia z sudoAle zawsze warto zachować ostrożność udzielając pozwolenia. korzeń do odsiarczacza.
Na hoście uruchamiasz gdb, określając lokalny plik wykonywalny (ten sam, który działa na komputerze docelowym lub identyczna kopia z symbolami):
Komenda: gdb foo
Po wejściu do gdb nawiąż połączenie zdalne za pomocą:
Komenda: target remote localhost:3333
W tym momencie gdb ładuje symbole z lokalnego pliku binarnego.Synchronizuje się z gdbserverem i przejmuje kontrolę nad procesem, który faktycznie działa w gdbserverze. Od tego momentu przepływ jest typowy: polecenia takie jak break aby ustawić punkty krytyczne, continue, step, next, print do inspekcji zmiennych, backtrace aby zobaczyć baterię itp.
Łączenie się z działającymi procesami za pomocą gdbserver
Nie zawsze chcesz uruchamiać program od nowa.Często jesteś zainteresowany dołączeniem do procesu, który już trwa (np. httpd d Routerdemon systemowy lub usługa produkcyjna).
Typowy schemat polega na użyciu opcji --attach z gdbserverPrzekazując port, na którym będzie nasłuchiwać, oraz PID procesu docelowego. Na przykład, na routerze, na którym skopiowałeś gdbserver skompilowany dla jego architektury, możesz wykonać następujące czynności:
Komenda: gdbserver localhost:3333 --attach <pid_de_httpd>
Po stronie hosta należy użyć wersji gdb, która obsługuje architekturę routera., na przykład gdb-multiarchwcześniejsza konfiguracja architektury i kolejności bajtów:
Komenda: set arch mips
set endian big
Następnie należy określić plik lokalny zawierający symbole. zdalnego pliku binarnego (na przykład file httpd) i jeśli to konieczne, poinformuj gdb, gdzie na komputerze docelowym faktycznie działa plik binarny set remote exec-file /usr/bin/httpdNa koniec, tak jak poprzednio, łączysz się z:
Komenda: target remote 192.168.0.1:3333
Po przymocowaniuMożesz ustawić punkty przerwania dla określonych funkcji (na przykład break checkFirmware), kontynuuj wykonywanie i pozwól, aby normalny przebieg programu (na przykład przesyłanie oprogramowania sprzętowego z interfejsu internetowego) wyzwolił punkt przerwania.
Korzystanie z gdbserver z WinDbg w systemie Linux
W ostatnich latach firma Microsoft dodała obsługę debugowania procesów Linux w WinDbg Używanie gdbserver jako zaplecza. Ta funkcjonalność jest przeznaczona dla scenariuszy, w których pracujesz w systemie Windows, ale kod działa w systemie Linux (w tym WSL).
Aby debugować konkretny proces systemu Linux za pomocą WinDbg przy użyciu gdbserverPrzepływ operacji wyglądałby mniej więcej tak: najpierw należy zlokalizować proces docelowy na komputerze z systemem Linux za pomocą polecenia takiego jak ps -A (na przykład python3 który jest uruchomiony), a następnie uruchamiasz gdbserver na obiekcie docelowym:
Komenda: gdbserver localhost:1234 python3
Jeśli środowisko tego wymaga, może być konieczne użycie sudo gdbserver ...Z tymi samymi środkami bezpieczeństwa, co zawsze. Gdy gdbserver wskaże, że „nasłuchuje na porcie 1234”, w WinDbg przejdź do „Plik / Połącz ze zdalnym debugerem” i określ ciąg połączenia następującego typu:
Komenda: gdb:server=localhost,port=1234
WinDbg używa małego „sterownika” protokołu gdb do komunikacji z gdbserverem a po nawiązaniu połączenia pozostaje ono zatrzymane w punkcie boot procesu. Stamtąd możesz korzystać z okien stosu, modułów, pamięci, punktów przerwania, a także poleceń takich jak k aby zobaczyć baterię lub lm aby wyświetlić listę modułów (pamiętając, że niektóre polecenia oczekują formatu PE, a nie ELF, więc w pewnych przypadkach mogą wyświetlać dziwne dane).
gdbserver i serwer procesów WinDbg
Oprócz przypadku pojedynczego procesu WinDbg może połączyć się z gdbserverem pełniącym funkcję serwera procesów aby działać bardziej podobnie do tego, jak działa ze zdalnymi procesami systemu Windows. W tym trybie gdbserver jest uruchamiany z --multi i bez powiązanego procesu:
Komenda: sudo gdbserver --multi localhost:1234
W WinDbg wybierz „Plik / Połącz z serwerem przetwarzania” i ponownie używasz ciągu połączenia gdb:server=localhost,port=1234Gdy połączenie jest aktywne, możesz wyświetlić listę dostępnych procesów Linuxa i przyłączyć się do wybranego procesu, a nawet uruchomić nowy proces.
Należy pamiętać o jednym drobnym szczególe.WinDbg rozróżnia „serwer procesów” i „pojedynczy cel” w zależności od tego, czy gdbserver jest już połączony z procesem w momencie nawiązania połączenia. Jeśli pozostawisz gdbserver połączony z procesem, zamkniesz WinDbg, a następnie spróbujesz ponownie się połączyć, może on nie zostać wykryty jako serwer procesów i konieczne może być ponowne uruchomienie gdbserver.
Aby zakończyć sesję serwera procesówZazwyczaj wystarczy nacisnąć CTRL+D w konsoli, w której działa gdbserver i zatrzymać debugowanie z WinDbg. W skrajnych przypadkach, jeśli wystąpią problemy z synchronizacją, konieczne może być całkowite zamknięcie debugera i ponowne uruchomienie gdbservera od podstaw.
Zarządzanie symbolami i kodem źródłowym podczas zdalnego debugowania
Jednym z kluczy do wygodnego zdalnego debugowania jest dobre rozróżnienie części symboli i czcionekBez symboli nawigacja po stosie lub ustawianie punktów przerwania dla konkretnych funkcji staje się torturą.
W klasycznych scenariuszach gdb + gdbserver najlepszym rozwiązaniem jest przechowywanie kopii pliku wykonywalnego z symbolami na hoście. (nierozpakowany) i drzewo źródłowe. gdb nie wymaga, aby zdalny plik binarny zawierał symbole; wystarczy, że lokalny plik, który ładujesz, file dopasuj zdalny plik wykonywalny na poziomie przesunięcia.
W świecie debugowania WinDbg i Linuxa pojawiły się również usługi takie jak DebugInfoD.które udostępniają symbole i czcionki przez HTTP. WinDbg może używać specjalnych ścieżek typu DebugInfoD*https://debuginfod.elfutils.org obaj w .sympath jak .srcpath aby pobrać na żądanie symbole DWARF i kod źródłowy plików binarnych Linux ELF.
W konkretnym przykładzie z WSL, gdzie kod użytkownika znajduje się pod C:\Users\Bob\Możesz powiedzieć WinDbg:
Komenda: .sympath C:\Users\Bob\
.srcpath C:\Users\Bob\
A jeśli chcesz używać DebugInfoD również do plików binarnych systemu:
Komenda: .sympath+ DebugInfoD*https://debuginfod.elfutils.org
.srcpath+ DebugInfoD*https://debuginfod.elfutils.org
Dzięki tej konfiguracji podczas inspekcji stosu lub wprowadzania funkcji libcWinDbg może próbować pobrać odpowiadające im symbole DWARF i jeśli serwer również udostępni kod, wyświetlić kod źródłowy ze znacznym stopniem szczegółowości, mimo że wewnętrznie zestaw narzędzi systemu Windows nie obsługuje symboli ELF i DWARF tak „natywnie” jak PE i PDB.
Przykład praktyczny: debugowanie programu C++ za pomocą gdbserver i WinDbg
Dobrym przykładem jest mała aplikacja C++ wyświetlająca powitanie na ekranie., skompilowany w WSL z symbolami debugowania. Wyobraź sobie program, który rezerwuje std::array<wchar_t, 50> i kopiuje do niego dłuższą wiadomość, powodując obcięcie tekstu i pojawienie się znaków ???? na końcu
Po skompilowaniu przy użyciu czegoś takiego:
Komenda: g++ DisplayGreeting.cpp -g -o DisplayGreeting
Uruchamiasz gdbserver na podstawie tego pliku binarnego:
Komenda: gdbserver localhost:1234 DisplayGreeting
W WinDbg łączysz się z ciągiem gdb:server=localhost,port=1234 Po ustanowieniu sesji i skonfigurowaniu ścieżek symboli i czcionek należy ustawić punkt przerwania w DisplayGreeting!mainmożesz użyć dx greeting aby sprawdzić tablicę lokalną i zobaczyć jej rozmiar (50 pozycji) oraz wizualnie sprawdzić na karcie pamięci lub w widoku zmiennych, w jaki sposób powitanie jest odcinane.
Piękno tego przykładu polega na tym, że pokazuje on, że nawet bez pełnego wsparcia dla wszystkich formatów ELF/DWARF w WinDbgKorzystając z gdbserver jako zdalnego zaplecza, możesz wygodnie przeglądać stosy, sprawdzać typy, ustawiać punkty przerwania według nazwy funkcji i poruszać się po kodzie C++.
Debugowanie jądra Linux za pomocą qemu i gdb
gdbserver nie jest wykorzystywany wyłącznie w trybie użytkownika; istnieją również bardzo zaawansowane scenariusze w trybie jądra.Zwłaszcza w połączeniu z QEMU i obsługą debugowania. Chociaż w tym przypadku rolę „gdbservera” pełni opcja QEMU, podejście jest identyczne: z jednej strony uruchamiany jest system do debugowania i otwierany jest port gdb; z drugiej strony jest to albo gdb, albo debugger obsługujący zdalny protokół.
Aby debugować jądro, należy je skompilować z użyciem określonych opcji debugowania.:aktywuj generowanie informacji debugowania (CONFIG_DEBUG_INFO), skrypty jądra GDB (CONFIG_GDB_SCRIPTS) i własny tryb debugowania jądra (CONFIG_DEBUG_KERNELWażne jest również wyłączenie opcji, które usuwają symbole podczas łączenia, takich jak „Usuń symbole wygenerowane przez asembler podczas łączenia”.
Po skompilowaniu otrzymasz plik binarny vmlinux „nie rozebrany”To właśnie ten, którego będziesz używać z gdb. Potrzebujesz również podstawowego initramfs, który możesz wygenerować poleceniem takim jak:
Komenda: mkinitramfs -o ramdisk.img
Następnie uruchamiasz QEMU z parametrami debugowaniaTypowy przykład obejmuje opcję -gdb tcp::1234 aby otworzyć zdalny punkt końcowy zgodny z gdb i -S aby maszyna wirtualna uruchomiła się od początku w trybie pauzy. Możesz również określić jądro za pomocą -kernel vmlinux, -initrd ramdisk.img, pamięć z -m 512 i zazwyczaj przekierowujesz konsolę do ttyS0 zarządzać wszystkim z poziomu terminal.
Z zatrzymanym QEMU w oczekiwaniu na gdbZ komputera hosta należy uruchomić gdb wskazując na vmlinux i łączysz się z target remote localhost:1234Stąd możesz ustawić wczesne punkty przerwania, na przykład hb start_kerneli kontrolować wykonywanie za pomocą poleceń takich jak c (kontynuuj) i CTRL+C, aby ponownie wstrzymać.
Ostatnie zmiany i niuanse w gdb i gdbserver
W nowoczesnych dystrybucjach, takich jak Red Hat Enterprise Linux 8, wprowadzono szereg zmian w gdb i gdbserver, o których warto pamiętać.szczególnie jeśli korzystasz ze starszych wersji lub masz skrypty analizujące wyniki debugera.
Z jednej strony gdbserver uruchamia teraz „niższe” procesy za pomocą powłokiPodobnie jak gdb, umożliwia to rozszerzanie zmiennych i zamiany w wierszu poleceń. Jeśli z jakiegoś powodu musisz wyłączyć to działanie, w RHEL 8 opisano konkretne ustawienia umożliwiające powrót do poprzedniego trybu.
Usunięto lub zmieniono również kilka rzeczy:obsługa debugowania dla programów Java skompilowanych za pomocą gcj, tryb zgodności HP-UX XDB, polecenia takie jak set remotebaud (zastąpiony przez set serial baud) lub zgodności z pewnym starszym formatem stabsPonadto numeracja wątków nie jest już globalna, ale według wątku „niższego” i pojawia się jako inferior_num.thread_numz nowymi zmiennymi zapewniającymi wygodę, takimi jak $_gthread aby odwołać się do globalnego identyfikatora.
Kolejną istotną nową funkcją jest regulacja max-value-sizeOgranicza to ilość pamięci, jaką gdb może przydzielić do wyświetlenia zawartości wartości. Domyślnie jest to 64 KiB, więc próby drukowania ogromnych tablic lub struktur mogą skutkować ostrzeżeniem „wartość za duża” zamiast wyświetlenia całej dostępnej pamięci.
Dostosowano również sposób, w jaki gdb obsługuje sysrootWartość domyślna to teraz target:Oznacza to, że w przypadku procesów zdalnych najpierw spróbuje znaleźć biblioteki i symbole w systemie docelowym. Aby nadać priorytet symbolom lokalnym, należy uruchomić set sysroot z trasą, która Cię interesuje, zanim ją wykonasz target remote.
Jeśli chodzi o historię poleceń, obecnie używana zmienna środowiskowa to GDBHISTSIZE zamiast HISTSIZEDzięki temu możesz dokładnie określić, jak długo chcesz przechowywać polecenia wpisane podczas sesji debugowania, nie zakłócając działania innych aplikacji korzystających z biblioteki odczytu wierszy.
Wskazówki dotyczące przepływu pracy i rozwiązywania problemów z gdbserver
Aby zapewnić komfortowy przepływ pracy, istnieją pewne schematy, które sprawdzają się bardzo dobrze. Podczas tworzenia oprogramowania dla systemów wbudowanych lub serwerów zdalnych, pierwszym krokiem jest zautomatyzowanie kompilacji symboli i wdrażania plików binarnych na komputerze docelowym w maksymalnym możliwym zakresie. W ten sposób zawsze wiesz, która wersja pliku wykonywalnego jest uruchomiona i masz kopię symbolu dostępną na hoście.
W środowiskach z wieloma rdzeniami awaryjnymi warto nauczyć się używać gdb w trybie wsadowym., z flagami takimi jak --batch, --ex y -x aby automatycznie uruchamiać polecenia na liście rdzeni i przetwarzać ich ślady ze skryptów (na przykład w PythonUmożliwia to szybkie filtrowanie powtarzających się problemów, grupowanie awarii według śladu stosu itp.
Gdy coś pójdzie nie tak ze zdalnym połączeniem, opcja --debug gdbserver jest twoim najlepszym przyjacielemJeżeli na przykład rozpoczniesz doręczanie pism sądowych za pomocą:
Komenda: gdbserver --debug --multi localhost:1234
Konsola gdbserver pokaże szczegółowe ślady tego, co się dzieje Na poziomie protokołu zdalnego obejmuje to pakiety przychodzące, błędy formatowania, problemy z rozłączaniem itp. Jest to bardzo przydatne, gdy serwer gdb nagle się rozłączy, proces ulegnie awarii zaraz po ustawieniu punktu przerwania lub gdy interfejs graficzny debugowania wyśle coś, czego gdbserver nie rozumie.
W kontekstach takich jak router TP-Link, w którym podłączasz gdbserver do krytycznego procesu, takiego jak httpdDość często zdarza się, że niektóre punkty przerwania tworzą warunki wyścigu lub alarmy, które przerywają proces, gdy pozostaje on „zablokowany” w debugerze przez zbyt długi czas. W takich sytuacjach może być konieczne dostosowanie blokowanych sygnałów, kontrolowanych wątków oraz, w razie potrzeby, modyfikacja samej konfiguracji systemu (czasów przekroczenia limitu czasu, alarmów sprzętowych), aby umożliwić dłuższe sesje debugowania.
Dobre wykorzystanie gdbserver wymaga połączenia kilku elementówKompiluj z odpowiednimi symbolami, wybierz właściwy gdb dla architektury, skonfiguruj ścieżki symboli i źródeł, zrozum dwa główne tryby gdbserver (pojedynczy proces i wiele procesów) i nie bój się pobierać z trybu --debug gdy połączenie nie zachowuje się zgodnie z oczekiwaniami. Dzięki temu rozwiązaniu debugowanie aplikacji działających w zdalnym systemie Linux, routerze lub maszynie wirtualnej z niestandardowym kernelem z poziomu komputera staje się dość rutynowe i, przede wszystkim, niezwykle przydatne.
Pisarz z pasją zajmujący się światem bajtów i technologii w ogóle. Uwielbiam dzielić się swoją wiedzą poprzez pisanie i właśnie to będę robić na tym blogu, pokazywać Ci wszystkie najciekawsze rzeczy o gadżetach, oprogramowaniu, sprzęcie, trendach technologicznych i nie tylko. Moim celem jest pomóc Ci poruszać się po cyfrowym świecie w prosty i zabawny sposób.