- Ο gdbserver λειτουργεί ως απομακρυσμένος πράκτορας του GDB για τον έλεγχο διεργασιών σε άλλο μηχάνημα μέσω TCP ή σειριακής σύνδεσης.
- Για την απομακρυσμένη αποσφαλμάτωση, είναι σημαντικό να μεταγλωττίσετε με σύμβολαΧρησιμοποιήστε την κατάλληλη gdb και ρυθμίστε σωστά τις διαδρομές συμβόλων και γραμματοσειρών.
- Το gdbserver προσφέρει λειτουργία μίας και πολλαπλών διεργασιών, ενώ ενσωματώνεται επίσης με WinDbg και QEMU για εντοπισμό σφαλμάτων στον πυρήνα.
- Επιλογές όπως --debug, sysroot και όρια μεγέθους τιμών βοηθούν στη διάγνωση προβλημάτων και στη σταθεροποίηση των περιόδων λειτουργίας.
Αν προγραμματίζετε σε C ή C++ Linux και δεν έχεις αγγίξει ποτέ τον gdbserverΧάνετε ένα από τα πιο χρήσιμα εργαλεία για τον απομακρυσμένο εντοπισμό σφαλμάτων σε διεργασίες, είτε σε διακομιστή, είτε σε ενσωματωμένο σύστημα, είτε ακόμα και μέσα σε εικονική μηχανή ή WSL. Το gdbserver δεν είναι κάτι «μαγικό» ή προορισμένο για ειδικούς, αλλά είναι απλώς ένα μικρό πρόγραμμα που επικοινωνεί με το gdb και ελέγχει την εκτέλεση της διεργασίας-στόχου.
Η κεντρική ιδέα είναι πολύ απλή.: στον υπολογιστή όπου εκτελείται το δυαδικό αρχείο που θέλετε να εντοπίσετε σφάλματα (το στόχος) ξεκινάτε το gdbserver; στον υπολογιστή της εργασίας σας (το οικοδεσπότηςΞεκινάτε το gdb ή ακόμα και το WinDbg με υποστήριξη για το πρωτόκολλο gdb. Και τα δύο συνδέονται μέσω TCP ή σειριακής θύρας και από εκεί μπορείτε να ορίσετε σημεία διακοπής, να ελέγξετε μεταβλητές, να δείτε τη στοίβα ή να ακολουθήσετε την εκτέλεση βήμα προς βήμα σαν να εκτελείται το πρόγραμμα στον δικό σας υπολογιστή.
Τι είναι το gdbserver και πότε έχει νόημα να το χρησιμοποιώ;

Το gdbserver είναι ένας απομακρυσμένος "παράγοντας" εντοπισμού σφαλμάτων για το GNU gdbΗ λειτουργία του είναι πολύ συγκεκριμένη: εκτελείται στον υπολογιστή όπου εκτελείται το πρόγραμμα που πρόκειται να αναλυθεί, ελέγχει αυτήν τη διεργασία (ή διεργασίες) και επικοινωνεί με έναν πελάτη gdb που βρίσκεται σε έναν άλλο υπολογιστή (ή στον ίδιο υπολογιστή) μέσω μιας απομακρυσμένης σύνδεσης.
Στην καθημερινή χρήση, το gdbserver χρησιμοποιείται σε δύο τυπικά σενάριαΛογισμικό εντοπισμού σφαλμάτων που εκτελείται σε ενσωματωμένα περιβάλλοντα (δρομολογητές, πλακέτες με απλοποιημένο Linux, συσκευές) IoTκ.λπ.) και διεργασίες εντοπισμού σφαλμάτων σε απομακρυσμένα μηχανήματα Linux, όπου δεν είναι βολικό ή απλώς δεν είναι δυνατό να έχετε μια "παχιά" gdb με όλες τις βιβλιοθήκες και τα σύμβολα.
Σε πρακτικό επίπεδο, ο gdbserver χειρίζεται εργασίες όπως Ανάγνωση και εγγραφή καταχωρητών διεργασιών και μνήμης, έλεγχος εκτέλεσης (συνέχεια, παύση, μετάβαση), διαχείριση σημείων διακοπής και αποστολή όλων αυτών των δεδομένων στο gdb χρησιμοποιώντας το απομακρυσμένο πρωτόκολλο GDB. Αυτή η φιλοσοφία είναι πολύ παρόμοια με αυτή εργαλείων όπως το OpenOCD, τα οποία λειτουργούν ως γέφυρα μεταξύ του gdb και ενός υλικού εξωτερικό, με τη διαφορά ότι το gdbserver εκτελείται στο ίδιο σύστημα όπου εκτελείται το δυαδικό αρχείο.
Αν προέρχεστε από περιβάλλοντα Windows Είναι επίσης ενδιαφέρον να γνωρίζουμε Τα προγράμματα εντοπισμού σφαλμάτων όπως το WinDbg μπορούν να επικοινωνήσουν με έναν gdbserver σε 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) και, εάν είναι απαραίτητο, διαμορφώστε την αρχιτεκτονική και την endianness με εντολές ως set arch y set endian.
Όσον αφορά τη σύνδεση, ο gdbserver υποστηρίζει δύο κύριους τύπουςΜια σειριακή σύνδεση (πολύ συνηθισμένη σε ενσωματωμένο υλικό, μέσω UART) και TCP/IP, η οποία είναι πιο βολική όταν ο στόχος βρίσκεται στο ίδιο δίκτυο ή είναι ένα μηχάνημα Linux προσβάσιμο μέσω του δικτύου. Και στις δύο περιπτώσεις, η εντολή χρησιμοποιείται από το gdb. target remote για να συνδεθείτε στο τελικό σημείο που εκτίθεται από το gdbserver.
Τρόποι εκκίνησης του gdbserver: λειτουργία μίας διεργασίας και λειτουργία πολλαπλών διεργασιών

Ο 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 σε Windows.
Απομακρυσμένος εντοπισμός σφαλμάτων με gdbserver και gdb βήμα προς βήμα
Ας το φέρουμε αυτό στη γη με ένα πολύ χαρακτηριστικό παράδειγμα.: Εντοπισμός σφαλμάτων σε μια απλή εφαρμογή στον ίδιο υπολογιστή (ταιριάζουν ο κεντρικός υπολογιστής και ο στόχος) χρησιμοποιώντας το gdbserver για την προσομοίωση του απομακρυσμένου σεναρίου.
Αρχικά γράφετε και μεταγλωττίζετε ένα μικρό πρόγραμμαΓια παράδειγμα, ένας ανόητος βρόχος που εκτυπώνει έναν μετρητή:
Εντολή: gcc -g foo.c -o foo
Το κλειδί εδώ είναι η σημαία -gΑυτό προσθέτει τις απαραίτητες πληροφορίες εντοπισμού σφαλμάτων στο δυαδικό αρχείο, έτσι ώστε το gdb να μπορεί να εμφανίζει γραμμές κώδικα, ονόματα μεταβλητών, τύπους κ.λπ. Σε ένα "πραγματικό" περιβάλλον cross-compiling, θα κάνατε αυτήν τη μεταγλώττιση με το cross-toolchain και στη συνέχεια θα αντιγράφατε τόσο το δυαδικό αρχείο όσο και τις εξαρτήσεις του στον προορισμό.
Το επόμενο βήμα είναι να ξεκινήσετε το 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 ένα routerένας δαίμονας συστήματος ή μια υπηρεσία παραγωγής).
Το τυπικό μοτίβο είναι να χρησιμοποιήσετε την επιλογή --attach από τον gdbserverμεταβιβάζοντας τη θύρα όπου θα κάνει ακρόαση και το PID της διεργασίας-στόχου. Για παράδειγμα, σε έναν δρομολογητή όπου έχετε αντιγράψει έναν gdbserver που έχει μεταγλωττιστεί για την αρχιτεκτονική του, θα μπορούσατε να κάνετε τα εξής:
Εντολή: gdbserver localhost:3333 --attach <pid_de_httpd>
Από την πλευρά του κεντρικού υπολογιστή, θα χρησιμοποιήσετε μια έκδοση του gdb που υποστηρίζει την αρχιτεκτονική του δρομολογητή., για παράδειγμα gdb-multiarchδιαμόρφωση της αρχιτεκτονικής και της endianness εκ των προτέρων:
Εντολή: 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), συνεχίστε την εκτέλεση και αφήστε την κανονική ροή του προγράμματος (για παράδειγμα, μεταφόρτωση υλικολογισμικού από τη διεπαφή ιστού) να ενεργοποιήσει το σημείο διακοπής.
Χρήση του gdbserver με WinDbg σε Linux
Τα τελευταία χρόνια, η Microsoft έχει προσθέσει υποστήριξη για την αποσφαλμάτωση διεργασιών Linux στο WinDbg. Χρήση του gdbserver ως backend. Αυτή η λειτουργικότητα προορίζεται για σενάρια όπου εργάζεστε σε Windows αλλά ο κώδικας εκτελείται σε Linux (συμπεριλαμβανομένου του WSL).
Για να εντοπίσετε σφάλματα σε μια συγκεκριμένη διεργασία Linux με WinDbg χρησιμοποιώντας gdbserverΗ ροή θα ήταν κάπως έτσι: πρώτα εντοπίζετε τη διεργασία-στόχο στο μηχάνημα Linux με μια εντολή όπως ps -A (για παράδειγμα ένα python3 που εκτελείται), τότε εκκινείτε το gdbserver στον προορισμό:
Εντολή: gdbserver localhost:1234 python3
Εάν το απαιτεί το περιβάλλον, ίσως χρειαστεί να χρησιμοποιήσετε sudo gdbserver ...με τις ίδιες προφυλάξεις ασφαλείας όπως πάντα. Μόλις ο gdbserver υποδείξει ότι είναι "Ακούγοντας στη θύρα 1234", στο WinDbg μεταβείτε στο "Αρχείο / Σύνδεση με απομακρυσμένο πρόγραμμα εντοπισμού σφαλμάτων" και καθορίστε μια συμβολοσειρά σύνδεσης του ακόλουθου τύπου:
Εντολή: gdb:server=localhost,port=1234
Το WinDbg χρησιμοποιεί ένα μικρό "driver" πρωτοκόλλου gdb για επικοινωνία με τον gdbserver. και, μόλις δημιουργηθεί η σύνδεση, παραμένει σταματημένη στο σημείο εκκίνηση της διεργασίας. Από εκεί μπορείτε να χρησιμοποιήσετε τα παράθυρα στοίβας, τις ενότητες, τη μνήμη, τα σημεία διακοπής, καθώς και εντολές όπως 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Το WinDbg ενδέχεται να επιχειρήσει να κατεβάσει τα αντίστοιχα σύμβολα DWARF και, εάν ο διακομιστής εκθέσει επίσης τον κώδικα, να εμφανίσει τον πηγαίο κώδικα με σημαντικές λεπτομέρειες, αν και εσωτερικά η αλυσίδα εργαλείων των Windows δεν χειρίζεται τα ELF και DWARF τόσο "εγγενώς" όσο τα PE και PDB.
Πρακτικό παράδειγμα: εντοπισμός σφαλμάτων σε ένα πρόγραμμα 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 ως απομακρυσμένο backend.
Αποσφαλμάτωση του πυρήνα του Linux με qemu και gdb
Το gdbserver δεν χρησιμοποιείται μόνο σε λειτουργία χρήστη. Υπάρχουν επίσης πολύ ισχυρά σενάρια σε λειτουργία πυρήνα.ειδικά όταν συνδυάζετε το QEMU με υποστήριξη εντοπισμού σφαλμάτων. Αν και εδώ ο ρόλος του "gdbserver" εκπληρώνεται από την επιλογή του QEMU, η προσέγγιση είναι πανομοιότυπη: το ένα άκρο εκτελεί το σύστημα που πρόκειται να εντοπιστεί σφάλματα και ανοίγει μια θύρα gdb. το άλλο άκρο είναι είτε το gdb είτε ένα πρόγραμμα εντοπισμού σφαλμάτων που εκφωνεί το απομακρυσμένο πρωτόκολλο.
Για να εντοπίσετε σφάλματα στον πυρήνα, πρέπει να τον μεταγλωττίσετε με συγκεκριμένες επιλογές εντοπισμού σφαλμάτων.: ενεργοποίηση της δημιουργίας πληροφοριών εντοπισμού σφαλμάτων (CONFIG_DEBUG_INFO), τα σενάρια πυρήνα GDB (CONFIG_GDB_SCRIPTS) και η λειτουργία εντοπισμού σφαλμάτων του πυρήνα (CONFIG_DEBUG_KERNELΕίναι επίσης σημαντικό να απενεργοποιήσετε τις επιλογές που αφαιρούν σύμβολα κατά τη σύνδεση, όπως η "Αφαίρεση συμβόλων που δημιουργούνται από τον assembler κατά τη σύνδεση".
Μετά τη μεταγλώττιση θα λάβετε ένα δυαδικό αρχείο 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 για να επιστρέψετε στην προηγούμενη λειτουργία.
Αρκετά πράγματα έχουν επίσης αφαιρεθεί ή τροποποιηθεί: υποστήριξη εντοπισμού σφαλμάτων για προγράμματα Java που έχουν μεταγλωττιστεί με 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 για την αυτόματη εκκίνηση εντολών σε μια λίστα πυρήνων και την επεξεργασία των backtraces τους από σενάρια (για παράδειγμα σε PythonΑυτό σας επιτρέπει να φιλτράρετε γρήγορα επαναλαμβανόμενα προβλήματα, να ομαδοποιείτε αποτυχίες με βάση την ιχνηλάτηση στοίβας κ.λπ.
Όταν κάτι πάει στραβά με την απομακρυσμένη σύνδεση, η επιλογή --debug Ο gdbserver είναι ο καλύτερός σου φίλοςΑν ξεκινήσετε, για παράδειγμα, έναν διακομιστή διεργασιών με:
Εντολή: gdbserver --debug --multi localhost:1234
Η κονσόλα gdbserver θα εμφανίσει λεπτομερή ίχνη για το τι συμβαίνει Σε επίπεδο απομακρυσμένου πρωτοκόλλου, αυτό περιλαμβάνει εισερχόμενα πακέτα, σφάλματα μορφοποίησης, προβλήματα αποσύνδεσης κ.λπ. Αυτό είναι πολύ χρήσιμο όταν ο διακομιστής gdb αποσυνδέεται ξαφνικά, μια διεργασία καταρρέει μόλις οριστεί ένα σημείο διακοπής ή το γραφικό περιβάλλον χρήστη εντοπισμού σφαλμάτων στέλνει κάτι που ο gdbserver δεν καταλαβαίνει.
Σε περιπτώσεις όπως ένας δρομολογητής TP-Link όπου συνδέετε τον gdbserver σε μια κρίσιμη διεργασία όπως httpdΕίναι σχετικά συνηθισμένο ορισμένα σημεία διακοπής να δημιουργούν συνθήκες κούρσας ή watchdogs που τερματίζουν τη διεργασία όταν παραμένει "κολλημένη" για πολύ καιρό στο πρόγραμμα εντοπισμού σφαλμάτων. Σε αυτές τις περιπτώσεις, μπορεί να είναι απαραίτητο να ρυθμίσετε ποια σήματα μπλοκάρονται, ποια νήματα ελέγχονται και, εάν είναι απαραίτητο, να τροποποιήσετε την ίδια τη διαμόρφωση του συστήματος (χρόνοι χρονικού ορίου, watchdogs υλικού) για να επιτρέψετε μεγαλύτερες περιόδους λειτουργίας εντοπισμού σφαλμάτων.
Η καλή χρήση του gdbserver περιλαμβάνει τον συνδυασμό πολλών κομματιώνΜεταγλωττίστε με τα κατάλληλα σύμβολα, επιλέξτε το σωστό gdb για την αρχιτεκτονική, διαμορφώστε τις διαδρομές συμβόλων και πηγαίου κώδικα, κατανοήστε τις δύο κύριες λειτουργίες του gdbserver (μονοεπεξεργασία και πολλαπλή επεξεργασία) και μην φοβάστε να κάνετε λήψη από τη λειτουργία. --debug όταν η σύνδεση δεν συμπεριφέρεται όπως αναμένεται. Με αυτή τη βάση, η διόρθωση σφαλμάτων σε εφαρμογές που εκτελούνται σε ένα απομακρυσμένο σύστημα Linux, έναν δρομολογητή ή μια εικονική μηχανή με έναν προσαρμοσμένο πυρήνα από τον υπολογιστή σας γίνεται αρκετά συνηθισμένη και, πάνω απ 'όλα, εξαιρετικά χρήσιμη.
Παθιασμένος συγγραφέας για τον κόσμο των byte και της τεχνολογίας γενικότερα. Μου αρέσει να μοιράζομαι τις γνώσεις μου μέσω της γραφής, και αυτό θα κάνω σε αυτό το blog, θα σας δείξω όλα τα πιο ενδιαφέροντα πράγματα σχετικά με τα gadget, το λογισμικό, το υλικό, τις τεχνολογικές τάσεις και πολλά άλλα. Στόχος μου είναι να σας βοηθήσω να περιηγηθείτε στον ψηφιακό κόσμο με απλό και διασκεδαστικό τρόπο.