Tổng quan về GDB, GDB Server, KGDB

,

1. GDB

1.1 Giới thiệu GDB

GDB – GNU Debugger là một trong những chương trình đầu tiên được phát triển bởi Free Software Foundation. Ban đầu, GDB được tạo ra với mục đích gỡ những lỗi đơn giản trong hệ thống Unix, nhưng sau đó vì tính hữu dụng, dễ sử dụng, tiện lợi, GDB đã được ứng dụng nhiều trong các hệ thống nhúng khác nhau. GDB được phát triển, mở rộng, hỗ trợ debug từ vài nghìn đến hàng trăm nghìn dòng code C.

1.2 Kiến trúc của GDB

Nhìn tổng quan Kiến trúc GDB gồm 2 thành phần lớn nhất đó là Symbol Side và Target Side

gdb-image
Kiến trúc của GDB
Symbol Side

Symbol side là nơi chứa thông tin về các ký hiệu (symbol) của chương trình được sử dụng để debug. Thông tin này bao gồm: tên, kiểu của hàm và biến; số dòng; thông tin về thanh ghi, v.v. (thường là các phần như .bss, .data, .text,… trong tệp thực thi của chương trình). Symbol side sẽ trích xuất các thông tin này, sau đó thực hiện phân tích biểu thức, tìm địa chỉ bộ nhớ của các dòng nhất định và liệt kê mã nguồn.

Quá trình đọc trong symbol side bắt đầu với BFD. BFD là một thư viện dùng để xử lý các tệp nhị phân và tệp đối tượng, có thể hoạt động trên bất kỳ server nào. Nó có khả năng đọc và ghi các định dạng tệp như a.out, COFF (sử dụng trên System V Unix và MS Windows), ELF (trên Unix hiện đại, GNU/Linux và hầu hết các hệ thống nhúng) và một số định dạng khác. Sau khi xử lý các tệp nhị phân, dữ liệu sẽ được đưa vào bộ nhớ của GDB. GDB sau đó sử dụng các hàm đọc đã được phân cấp sẵn để đọc các ký hiệu.

Có hai cấp độ của hàm đọc ký hiệu: cơ bản và chi tiết. Ở cấp độ cơ bản, hàm đọc sẽ lấy các chuỗi ký hiệu từ địa chỉ. Cấp độ chi tiết được dùng để xử lý các tệp có định dạng phức tạp, ví dụ như định dạng DWARF,… Cuối cùng, từ những thông tin đã được xử lý, GDB sẽ xây dựng thành symbol tables.

Target Side

Target side liên quan đến việc thao tác với hệ thống mục tiêu. Nó bao gồm các chức năng để bắt đầu và dừng chương trình, đọc và chỉnh sửa bộ nhớ và thanh ghi,… Trong hầu hết các hệ thống kiểu Unix, có một system call tên là ptrace, cho phép một tiến trình đọc và ghi trạng thái của một tiến trình khác. Do đó, target của GDB chủ yếu là thực hiện các lệnh gọi ptrace và đưa ra kết quả. Tuy nhiên, trong trường hợp cross-debugging trên hệ thống nhúng, target side sẽ tạo ra các gói tin để gửi qua mạng (wire) và chờ nhận phản hồi.

Quá trình GDB thực thi trong target side: Ban đầu, target side được xây dựng từ một số tệp đặc thù của nền tảng, dùng để xử lý các chi tiết của các thao tác gọi ptrace, khởi động các tệp thực thi,… Tuy nhiên, phương pháp này không đủ linh hoạt cho nhiều tình huống như gỡ lỗi từ xa (remote debugging), xử lý core dump,… Vì vậy, vào năm 1990, John Gilmore đã thiết kế lại target side để gửi tất cả các thao tác đặc thù của hệ thống mục tiêu thông qua target vector. Về cơ bản, target vector là một lớp đối tượng, trong đó mỗi lớp định nghĩa các đặc điểm cụ thể của mục tiêu.

Ngoài ra, còn có target stack – nơi các target vector cho các tiến trình đang chạy được đẩy lên trên cùng của target vector của tệp thực thi khi tiến trình bắt đầu chạy và được lấy ra khi nó kết thúc. Target vector cho phép GDB dễ dàng chuyển đổi giữa các chế độ gỡ lỗi khác nhau và xử lý các tình huống phức tạp như gỡ lỗi từ xa, xử lý core dump, v.v. Điều này cung cấp một cấu trúc linh hoạt để hỗ trợ nhiều loại hệ thống và tình huống khác nhau, giúp GDB hoạt động hiệu quả hơn trong nhiều tình huống.

2. GDBServer

2.1 Giới thiệu về GDB Server

GDBserver là một chương trình chạy trên hệ thống mục tiêu (target) và được sử dụng để gỡ lỗi từ xa từ máy chủ (host). GDBserver nhận các gói tin chứa lệnh gỡ lỗi từ GDB trên máy host và trả về kết quả tương ứng. Điều này cho phép GDB trên máy host điều khiển và gỡ lỗi chương trình đang chạy trên hệ thống target từ xa. GDBserver có kích thước nhỏ hơn rất nhiều so với GDB và không cần quản lý symbol tables. Điều này làm cho GDBserver trở nên rất tiện lợi và hiệu quả, đặc biệt trong các ứng dụng nhúng hoặc các hệ thống có tài nguyên hạn chế.

2.2 Kiến trúc của hệ thống GDB Server

gdb-server image

Kiến trúc của hệ thống GDBServer
GDB

GDB là công cụ gỡ lỗi chạy trên máy chủ (host) như đã tìm hiểu ở trên. Nó cung cấp giao diện người dùng để điều khiển quá trình gỡ lỗi và gửi lệnh đến GDB Server.

GDB Server

GDB Server chạy trên máy khách (target), GDB Server thực hiện nhiệm vụ trung gian giữa GDB và ứng dụng đang được gỡ lỗi (BuggyApp). GDB Server chịu trách nhiệm khởi động, dừng và kiểm soát quá trình của BuggyApp, sử dụng các hệ thống gọi của Linux như ptrace.

Remote Protocol

Remote Protocol của hệ thống thường sử dụng là TCP/IP, ngoài ra còn có thể sử dụng UART

Khi nhận được lệnh từ GDB, GDB Server sử dụng ptrace để điều khiển và theo dõi BuggyApp .Các thao tác chính bao gồm:

  • ATTACH: GDB Server sử dụng ptrace(PTRACE_ATTACH, pid) để đính kèm vào BuggyApp.
  • KILL: Dừng tiến trình khi cần thiết.
  • READ/WRITE: Đọc và ghi vào bộ nhớ của BuggyApp để thực hiện gỡ lỗi

2.3 Cách sử dụng GDB Server

Chúng ta hãy cùng tìm hiểu các ứng dụng của GDB Server trong việc gỡ lỗi từ xa (Remote Debugging). Cách thiết lập môi trường và sử dụng VSCode để thực hiện gỡ lỗi trên hai hệ thống cùng kiến trúc hoặc hai hệ thống khác kiến trúc cụ thể là Remote Debugging trên board Beaglebone Black thông qua bài viết: Sử dụng GDB Server để thực hiện remote debugging

3. KGDB – Kernel GDB

3.1 Giới thiệu KGDB

GDB là một công cụ mạnh mẽ và linh hoạt cho việc gỡ lỗi các chương trình C và C++, bao gồm cả nhân Linux. Tuy nhiên, việc gỡ lỗi ở nhân kernel phức tạp hơn nhiều so với gỡ lỗi các ứng dụng ở không gian người dùng (user space) do bản chất cấp thấp của nhân và sự tương tác trực tiếp của nó với phần cứng.

Một cách để giải quyết vấn đề này là sử dụng phần cứng chuyên dụng để debug kernel như JTAG. Tuy nhiên, điều này yêu cầu phải có giao diện JTAG trên hệ thống mục tiêu (target), một bộ chuyển đổi JTAG và phần mềm như OpenOCD. Mặc dù JTAG có thể cần thiết cho các nhiệm vụ như khởi động board (gỡ lỗi bootloader hoặc quá trình khởi tạo kernel), nhưng nó thường đi kèm với cấu hình phức tạp và trong nhiều tình huống, không thực sự cần thiết.

Trong Linux, kernel đã tích hợp sẵn hỗ trợ debug kernel bằng GDB thông qua kiến trúc client/server được gọi là KGDB. KGDB giúp người dùng thuận tiện hơn trong việc debug kernel mà không cần đến JTAG hoặc các phần cứng hỗ trợ debug khác.

3.2 Kiến trúc KGDB

kgdb-image
Kiến trúc hệ thống debug sử dụng KGDB

Kiến trúc của hệ thống debug sử dụng KGDB gồm 3 thành phần chính. Đó là: KGDB core (trên máy target), KGDB I/O layer(tầng giao tiếp), GDB (trên máy host).

KGDB Core

KGDB core được tích hợp vào Linux Kernel. Nó thực hiện các chức năng quan trọng như:

  • Nhận lệnh từ GDB, chẳng hạn như lệnh để dừng, tiếp tục thực thi, kiểm tra các giá trị thanh ghi, bộ nhớ và các hàm trong kernel.
  • Quản lý việc tạm dừng và tiếp tục các tiến trình đang chạy trong kernel.
  • Kiểm soát việc đặt các breakpointwatchpoint trong mã kernel.
  • Tương tác với scheduler của kernel để tạm dừng hoặc tiếp tục các tiến trình cần debug.

KGDB core chịu trách nhiệm chính trong việc dịch và thực thi các lệnh mà GDB gửi đến. Đây là trái tim của hệ thống KGDB, đóng vai trò quản lý quá trình debug của kernel.

KGDB I/O layer (Tầng giao tiếp KGDB)

KGDB I/O layer là tầng giao tiếp giữa KGDB coreGDB trên hệ thống host. Tầng này chịu trách nhiệm truyền tải thông tin debug qua các giao thức giao tiếp như Serial (UART), Ethernet.

GDB trên host

GDB chạy trên máy chủ phát triển, nơi lập trình viên điều khiển quá trình gỡ lỗi từ xa. GDB được cấu hình để kết nối với KGDB trên hệ thống mục tiêu thông qua các giao thức mạng hoặc cổng serial.

Trên máy host, GDB sẽ tương tác với kernel image có thông tin biểu tượng gỡ lỗi vmlinux bằng cách nạp hình ảnh này vào bộ nhớ để phân tích. GDB sử dụng thông tin từ symbol table để xác định vị trí của các hàm và biến, cho phép lập trình viên thiết lập breakpoints, kiểm tra giá trị của thanh ghi và bộ nhớ, cũng như thực hiện các lệnh gỡ lỗi như tiếp tục hoặc bước qua từng dòng lệnh. Qua đó, GDB giúp theo dõi call stack và phân tích trạng thái của kernel, hỗ trợ quá trình gỡ lỗi hiệu quả hơn.

3.3 Cách sử dụng KGDB

Chúng ta hãy cùng tìm hiểu các ứng dụng của KGDB Server trong việc gỡ lỗi Linux Kernel. Cách thiết lập môi trường và sử dụng VSCode để thực hiện gỡ lỗi các module .ko thông qua bài viết Sử dung KGDB để thực hiện debug Linux Kernel .

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top