nm command in linux

Giới thiệu về Lệnh nm trong Linux: Khám phá Bí mật Bên trong File Nhị Phân

Bạn đã bao giờ tò mò về cấu trúc bên trong của một file thực thi (executable) trên Linux chưa? Làm thế nào mà hệ điều hành có thể hiểu và chạy một chương trình phức tạp như vậy? Câu trả lời nằm ở những công cụ mạnh mẽ cho phép chúng ta "mổ xẻ" file nhị phân, và một trong số đó là lệnh nm.

Trong bài viết này, chúng ta sẽ cùng nhau khám phá lệnh nm một cách chi tiết, từ cơ bản đến nâng cao. Chúng ta sẽ tìm hiểu cách sử dụng nm để xem danh sách các symbol (biểu tượng) trong một file object, file thực thi, hoặc thư viện. Không chỉ vậy, chúng ta còn đi sâu vào ý nghĩa của từng loại symbol và cách chúng ảnh hưởng đến quá trình liên kết và thực thi chương trình. Hãy cùng bắt đầu hành trình khám phá thế giới "bí mật" bên trong file nhị phân nhé!

nm command là gì?

Lệnh nm là một công cụ dòng lệnh trong hệ điều hành Linux và Unix-like, được sử dụng để hiển thị danh sách các symbol (biểu tượng) từ một file object, file thực thi (executable), hoặc thư viện. Các symbol này có thể là tên của các hàm, biến, hoặc các đoạn mã khác được định nghĩa hoặc tham chiếu trong file.

Nói một cách dễ hiểu, nm cho phép bạn "nhìn trộm" vào bên trong một file nhị phân và xem những "thành phần" nào đang tồn tại ở đó. Điều này rất hữu ích trong việc debug, phân tích code, và hiểu rõ hơn về cách các chương trình hoạt động.

Cú pháp cơ bản của lệnh nm

Cú pháp cơ bản của lệnh nm rất đơn giản:

nm [options] [file]...

Trong đó:

  • nm: Lệnh gọi chương trình nm.
  • [options]: Các tùy chọn để điều chỉnh cách nm hoạt động (ví dụ: sắp xếp, lọc thông tin).
  • [file]...: Một hoặc nhiều file mà bạn muốn nm phân tích. Nếu không chỉ định file, nm sẽ mặc định đọc file a.out (file thực thi mặc định sau khi biên dịch).

Các tùy chọn phổ biến của lệnh nm

Lệnh nm cung cấp rất nhiều tùy chọn để bạn có thể tùy chỉnh kết quả hiển thị. Dưới đây là một số tùy chọn phổ biến nhất:

  • -a hoặc --debug-syms: Hiển thị tất cả các symbol, kể cả các symbol debug. Thông thường, nm sẽ bỏ qua các symbol được sử dụng cho mục đích debug.
  • -g hoặc --extern-only: Chỉ hiển thị các symbol external (được định nghĩa bên ngoài file).
  • -u hoặc --undefined-only: Chỉ hiển thị các symbol undefined (chưa được định nghĩa).
  • -n hoặc --numeric-sort: Sắp xếp các symbol theo địa chỉ số.
  • -s hoặc --print-armap: Hiển thị armap section (nếu có).
  • -C hoặc --demangle: Giải mã các symbol C++ (chuyển đổi tên hàm phức tạp thành dạng dễ đọc hơn).
  • -l hoặc --line-numbers: Với mỗi symbol, hiển thị tên file và số dòng nơi symbol đó được định nghĩa.
  • -v hoặc --reverse-sort: Sắp xếp kết quả theo thứ tự ngược lại.

Ví dụ sử dụng lệnh nm

Để hiểu rõ hơn về cách sử dụng lệnh nm, chúng ta sẽ cùng xem xét một vài ví dụ cụ thể.

Ví dụ 1: Hiển thị tất cả các symbol trong một file object

Giả sử chúng ta có một file object tên là hello.o. Để hiển thị tất cả các symbol trong file này, chúng ta sử dụng lệnh:

nm hello.o

Kết quả sẽ hiển thị danh sách các symbol, cùng với địa chỉ và loại của chúng.

Ví dụ 2: Hiển thị các symbol external trong một file thực thi

Để hiển thị chỉ các symbol external trong file thực thi myprogram, chúng ta sử dụng lệnh:

nm -g myprogram

Kết quả sẽ chỉ hiển thị các symbol được định nghĩa bên ngoài file myprogram và được tham chiếu trong myprogram.

Ví dụ 3: Sắp xếp các symbol theo địa chỉ số

Để sắp xếp các symbol theo địa chỉ số trong file library.so, chúng ta sử dụng lệnh:

nm -n library.so

Kết quả sẽ hiển thị danh sách các symbol, được sắp xếp theo thứ tự tăng dần của địa chỉ.

Ví dụ 4: Giải mã các symbol C++

Nếu bạn đang làm việc với code C++, các symbol có thể rất khó đọc do quá trình "name mangling". Để giải mã các symbol này, bạn có thể sử dụng tùy chọn -C:

nm -C mycppprogram

Kết quả sẽ hiển thị các symbol C++ đã được giải mã, giúp bạn dễ dàng hiểu ý nghĩa của chúng hơn.

Ý nghĩa của các loại symbol

Mỗi symbol trong danh sách mà nm hiển thị đều có một loại (type) nhất định, cho biết vai trò và tính chất của symbol đó. Dưới đây là một số loại symbol phổ biến nhất:

  • T: Symbol là một đoạn code trong text section (thường là một hàm).
  • D: Symbol là một biến đã được khởi tạo trong data section.
  • B: Symbol là một biến chưa được khởi tạo trong BSS section.
  • U: Symbol là một symbol undefined (chưa được định nghĩa). Symbol này cần được định nghĩa ở một file object hoặc thư viện khác để chương trình có thể liên kết thành công.
  • W: Symbol là một weak symbol. Tương tự như global symbol, nhưng có độ ưu tiên thấp hơn trong quá trình liên kết.
  • r: Symbol nằm trong read-only data section.

Việc hiểu ý nghĩa của các loại symbol này rất quan trọng để bạn có thể phân tích và debug chương trình một cách hiệu quả.

Ứng dụng thực tế của lệnh nm

Lệnh nm không chỉ là một công cụ để "vọc vạch" file nhị phân. Nó còn có rất nhiều ứng dụng thực tế trong quá trình phát triển phần mềm.

  • Debug chương trình: Khi chương trình gặp lỗi, bạn có thể sử dụng nm để kiểm tra xem các symbol cần thiết có tồn tại hay không, và chúng được định nghĩa ở đâu.
  • Phân tích code: nm giúp bạn hiểu rõ hơn về cấu trúc và các thành phần của một chương trình, đặc biệt là các thư viện bên ngoài.
  • Kiểm tra tính tương thích nhị phân: Bạn có thể sử dụng nm để so sánh các phiên bản khác nhau của một thư viện và xem có sự thay đổi nào về symbol hay không.
  • Tìm hiểu về cách liên kết chương trình: nm giúp bạn hiểu rõ hơn về quá trình liên kết (linking) và cách các symbol được giải quyết.

Dưới đây là một ví dụ cụ thể về việc sử dụng nm để debug chương trình:

Giả sử bạn gặp lỗi "undefined reference" khi biên dịch chương trình. Lỗi này có nghĩa là chương trình của bạn đang cố gắng sử dụng một symbol (ví dụ: một hàm) mà không tìm thấy định nghĩa của nó. Bạn có thể sử dụng nm để kiểm tra xem symbol đó có tồn tại trong các file object và thư viện mà bạn đang liên kết hay không.

Bảng so sánh lệnh nm với các công cụ tương tự

Công cụ Mô tả Ưu điểm Nhược điểm
nm Hiển thị danh sách các symbol từ file object, file thực thi, hoặc thư viện. Đơn giản, dễ sử dụng, có sẵn trên hầu hết các hệ thống Linux/Unix. Chỉ hiển thị thông tin cơ bản, không có nhiều tính năng nâng cao.
objdump Hiển thị nhiều thông tin khác nhau về file object, bao gồm cả symbol table, disassembly, header information, v.v. Cung cấp thông tin chi tiết hơn so với nm. Cú pháp phức tạp hơn, kết quả hiển thị có thể khó đọc.
readelf Hiển thị thông tin về file ELF (Executable and Linkable Format), bao gồm cả symbol table. Đặc biệt hữu ích khi làm việc với file ELF. Cú pháp phức tạp.
lief (thư viện Python) Cung cấp API để phân tích và sửa đổi các file PE, ELF, Mach-O. Mạnh mẽ, linh hoạt, có thể tự động hóa các tác vụ phân tích. Yêu cầu kiến thức về Python và thư viện lief.

Câu hỏi thường gặp (FAQ)

  1. Làm thế nào để biết một symbol được định nghĩa ở file nào?

    Bạn có thể sử dụng lệnh nm -l [file] để hiển thị tên file và số dòng nơi symbol đó được định nghĩa.

  2. Làm thế nào để tìm tất cả các symbol undefined trong một dự án lớn?

    Bạn có thể sử dụng một vòng lặp để chạy nm -u trên tất cả các file object và thư viện trong dự án.

  3. nm có thể được sử dụng để phân tích malware không?

    Có, nm có thể là một công cụ hữu ích trong việc phân tích malware, giúp bạn hiểu rõ hơn về chức năng và cấu trúc của malware.

  4. Tại sao một số symbol lại có địa chỉ là 0000000000000000?

    Điều này thường xảy ra với các symbol undefined hoặc các symbol được định nghĩa trong các file object chưa được liên kết.

  5. nm có thể được sử dụng trên Windows không?

    Không, nm là một công cụ Linux/Unix. Trên Windows, bạn có thể sử dụng các công cụ tương tự như dumpbin (đi kèm với Visual Studio).

Kết luận

Lệnh nm là một công cụ mạnh mẽ và hữu ích để khám phá thế giới bên trong file nhị phân. Mặc dù có vẻ phức tạp ban đầu, nhưng khi bạn đã nắm vững cú pháp và ý nghĩa của các loại symbol, bạn sẽ thấy nm là một trợ thủ đắc lực trong việc debug, phân tích code, và hiểu rõ hơn về cách các chương trình hoạt động.

Hy vọng bài viết này đã cung cấp cho bạn một cái nhìn tổng quan và chi tiết về lệnh nm. Hãy thử sử dụng nm trên các file nhị phân khác nhau và khám phá những điều thú vị mà nó mang lại. Chúc bạn thành công!

Last Updated : 22/08/2025