Ở phần trước, chúng ta đã tìm hiểu về kiến trúc của GDBServer. Trong phần này, chúng ta sẽ cùng nhau thực hiện một vài demo ứng dụng thực tiễn của hệ thống GDB server, bao gồm việc thực hiện remote debugging trên hai máy ảo (cùng kiến trúc) và trên board BeagleBone Black (khác kiến trúc). Bên cạnh đó, chúng ta cũng sẽ tìm hiểu cách sử dụng VSCode IDE để hỗ trợ quá trình gỡ lỗi. Những ví dụ này sẽ minh họa tính linh hoạt và khả năng của GDB server trong việc gỡ lỗi các ứng dụng trên các hệ thống khác nhau.
1. Remote debugging trên máy ảo
1.1 Thiết lập môi trường, cài những package cần thiết
Chúng ta sẽ cần cài những package support cho GDBserver trên cả máy host và máy target
1 2 3 |
sudo apt update sudo apt install gdb gdbserver gdb-multiarch sudo apt intsall openssh-server |
1.2 Thực hiện debug
Mình sẽ demo bằng 2 máy ảo VMWare WorkStation 17 player chạy cùng hệ điều hành Ubuntu 22.04 LTS
Đầu tiên, Vì để dễ thực hiện command line và dễ nhìn hơn nên mình sẽ thực hiện SSH từ VSCode đến máy host
Bước 2. Tạo file demo.c để thực hiện debug
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include <stdio.h> // Function to calculate sum of array int sum_array(int arr[], int size) { int sum = 0; for (int i = 0; i < size; i++) { sum += arr[i]; } return sum; } // Function to find max element in array int find_max(int arr[], int size) { int max = arr[0]; for (int i = 1; i < size; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } // Function to print array void print_array(int arr[], int size) { printf("Mảng: "); for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } // Main function int main() { int numbers[] = {3, 5, 7, 2, 8, -1, 4, 10, 12}; // 9 elements int size = sizeof(numbers) / sizeof(numbers[0]); print_array(numbers, size); int total = sum_array(numbers, size); printf("Sum: %d\n", total); int maximum = find_max(numbers, size); printf("Max: %d\n", maximum); return 0; } |
Bước 3. Chạy dòng lệnh gcc -g -o demo demo.c để biên dịch file demo.c với tùy chọn debug
Bước 4. Khời động gdb server bên máy target bằng dòng lệnh gdbserver :1234 demo – khởi động gdb server ở port 1234
![gdb-server](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-4.png)
Khởi động gdb server thành công trên máy target ở port 1234
Bước 5. Bên máy host, copy file demo đã biên dịch từ máy target qua để load symbol bằng lệnh chạy trên máy target: scp demo host@192.168.146.140:/home/host/gdb. Trong đó 192.168.146.140 là địa chỉ ip máy host có thể kiểm tra bằng ifconfig
Bước 6. Khi bên máy host đã có file demo. Để kết nối đến gdb server, đầu tiên chạy gdb -tui
– một tùy chọn của GDB để khởi chạy GDB với giao diện người dùng dạng text (TUI – Text User Interface) để có cái nhìn tổng quan hơn về code. Ngoài ra khi đâ sử dụng quen, chúng ta có thể chỉ cần chạy gdb demo
![gdb -tui](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-5.png)
Giao diện của tùy chọn -tui
Bước 7. Chạy lệnh target remote 192.168.146.139:1234 để kết nối đến gdbserver với 192.168.146.139 là ip máy target và 1234 là port được bật ở câu lệnh trên
![connect success](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-7.png)
Kết nối thành công
Bước 8 Sau khi kết nối thành công, thêm symbol file vào gdb bằng lệnh: add-symbol-file /home/host/gdb/demo
![add-symbol-file](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-8.png)
Add symbol thành công
Bước 9. Sau khi gdb load symbol từ file demo thành công, chúng ta cùng thực hiện debug bằng cách đặt các breakpoint. ở đây, mình sẽ đặt tại các hàm print_array, find_max, sum_array bằng lệnh b print_array, b find_max, b sum_array
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-9.png)
Đặt break point thành công, sau đó in ra thông tin các breakpoint bằng lệnh info b
Bước 10. Chạy lệnh c (continue) để tiếp tục thực thi chương trình, chương trình sẽ dừng ở breakpoint đầu tiên. Giao diện gdb -tui cũng sẽ hiển thị code của file demo
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-10.png)
Chương trình dừng tại breakpoint đầu tiên
Bước 11. Sử dụng các lệnh cơ bản như next, print để kiểm tra.
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-11.png)
Sử dụng lênh next để thực thi từng dòng, và print ra giá trị cần kiểm tra
Bước 12. Khi đã kiểm tra xong những vấn đề liên quan đến breakpoint đầu tiên, chạy lệnh c để đến breakpoint thứ 2.
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-12.png)
Khi đến breakpoint thứ 2, các lệnh đã thực thi trước đó cũng sẽ được thực thi bên gdb server của máy target
Bước 13. Thực hiện các lệnh tương tự cho đến khi kết thúc chương trình.
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-13.png)
Chương trình kết thúc, gdb server sẽ đóng lại
2. Sử dụng VSCode IDE để thực hiện Remote Debugging
VSCode là IDE có giao diện thân thiện với người dùng, ngoài ra trên đó còn có những package hỗ trợ gdb khiến việc thao tác debug trực quan, dễ dàng hơn. Để thực hiện debug trên Vscode, chúng ta thực hiện các bước sau:
Đầu tiên. Cài đặt extension trong VSCode
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-14.png)
Extension Native Debug trên VScode
Bước 2. Mở file demo.c trên VSCode sau đó, trong phần Run and Debug của VSCode chọn create a launch.json file
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-15.png)
Giao diện Run and Debug được tích hợp trong VSCode
Bước 3. Lựa chọn C++ debuger (GDB/LLDB)
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-16.png)
Các lựa chọn debugger
Bước 4. Cấu hình file Json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{ "version": "0.2.0", "configurations": [ { "name": "C Launch", "type": "cppdbg", "request": "launch", "program": "/home/host/gdb/demo", "cwd": "/home/host/gdb", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "192.168.146.139:1234", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ] } ] } |
Trong đó:
- name: Tên của cấu hình gỡ lỗi.
- type: Loại cấu hình gỡ lỗi (ví dụ: cppdbg cho C/C++).
- request: Loại yêu cầu gỡ lỗi (launch để khởi chạy chương trình, attach để kết nối vào một tiến trình đang chạy).
- program: Đường dẫn đến chương trình sẽ được gỡ lỗi.
- cwd: Thư mục làm việc hiện tại khi chương trình chạy.
- MIMode: Chế độ GDB Machine Interface (gdb hoặc lldb).
- miDebuggerPath: Đường dẫn đến GDB hoặc LLDB debugger.
- miDebuggerServerAddress: Địa chỉ máy chủ gỡ lỗi từ xa (IP và cổng).
- setupCommands: Các lệnh được thực thi khi phiên gỡ lỗi bắt đầu (như bật “pretty-printing”).
- args: Tham số dòng lệnh cho chương trình.
- environment: Các biến môi trường cho chương trình.
- stopAtEntry: Dừng tại điểm vào chương trình (true hoặc false).
Bước 5. Sau khi save, mở file demo.c và đặt breakpoint
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-17.png)
Các điểm đỏ được đặt là các breakpoint
Bước 6. Qua máy target, bật gdbserver như ở phần trên và chọn launch ở VSCode
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-18.png)
Kết nối thành công đến gdbserver trên target
Bước 7. Sau khi kết nối thành công, sử dụng thanh công cụ của được hỗ trợ để thực hiện debug
![](https://vinalinux.com.vn/wp-content/uploads/2024/09/image-19.png)
Thanh công cụ được hỗ trợ
Bước 8. VSCode sẽ hiển thị những phần như Giá trị biến, thanh ghi, segs, FPU, SSE, AVX, Call Stack cho người dùng cái nhìn chi tiết về các thành phần, tài nguyên được sử dụng khi chạy chương trình.