Lệnh objdump trong linux với các ví dụ dễ hiểu

Lệnh objdump trong Linux là một công cụ mạnh mẽ để phân tích các tệp đối tượng, tệp thực thi và thư viện. Nó cho phép bạn xem nội dung của các tệp này, bao gồm mã máy, dữ liệu và thông tin gỡ lỗi. Với lệnh objdump trong linux, bạn có thể hiểu rõ hơn về cách chương trình hoạt động và tìm ra các vấn đề tiềm ẩn. Công cụ này rất hữu ích cho các nhà phát triển và kỹ sư hệ thống.

Lệnh objdump trong linux là gì?

Lệnh objdump trong Linux là một công cụ mạnh mẽ giúp bạn "mổ xẻ" các file object, file thực thi và thư viện, cho phép xem xét cấu trúc bên trong của chúng. Command objdump in linux cho phép bạn xem mã assembly, thông tin header, bảng biểu tượng và nhiều thông tin gỡ lỗi khác. Nó rất hữu ích cho việc phân tích mã, tìm hiểu cách chương trình hoạt động và gỡ lỗi các vấn đề phức tạp. Sử dụng objdump, bạn có thể hiểu rõ hơn về cách chương trình được biên dịch và liên kết, từ đó cải thiện kỹ năng lập trình của mình. Hãy thử khám phá sức mạnh của objdump để làm chủ thế giới Linux nhé!

Tìm hiểu Mục đích của Lệnh objdump

Trong bước này, bạn sẽ tìm hiểu về mục đích của lệnh objdump trong Linux. Lệnh objdump là một công cụ mạnh mẽ để phân tích nội dung của object file.

Object file là các file nhị phân chứa machine code và các thông tin khác liên quan đến chương trình. Lệnh objdump có thể dịch ngược machine code thành định dạng dễ đọc.

Việc dịch ngược này hữu ích cho việc hiểu cách chương trình hoạt động, gỡ lỗi hoặc thậm chí là reverse-engineering phần mềm. Hãy bắt đầu bằng cách tạo một chương trình C đơn giản.

Sau đó, chúng ta sẽ sử dụng objdump để phân tích nội dung của chương trình đó. Đầu tiên, tạo một file mới tên là hello.c trong thư mục ~/project với nội dung sau:

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

Tiếp theo, biên dịch chương trình bằng trình biên dịch gcc với các tham số phù hợp:

cd ~/project
gcc -o hello hello.c

Bây giờ, hãy sử dụng lệnh objdump để phân tích nội dung của file thực thi hello vừa tạo:

objdump -d hello

Ví dụ về kết quả đầu ra:

hello:     file format elf64-x86-64

Disassembly of section .init:

0000000000001000 <_init>:
    1000:   f3 0f 1e fa             endbr64
    1004:   48 83 ec 08             sub    $0x8,%rsp
    1008:   48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        ## 3fe8 <__gmon_start__>
    100f:   48 85 c0                test   %rax,%rax
    1012:   74 02                   je     1016 <_init+0x16>
    1014:   ff d0                   callq  *%rax
    1016:   48 83 c4 08             add    $0x8,%rsp
    101a:   c3                      retq

Lệnh objdump dịch ngược machine code trong file hello, hiển thị các instruction cấp thấp. Các instruction này sẽ được bộ xử lý thực thi khi chương trình chạy.

Điều này rất hữu ích để hiểu cách chương trình hoạt động và để gỡ lỗi các vấn đề phát sinh. Trong bước tiếp theo, bạn sẽ khám phá cú pháp và các tùy chọn cơ bản của lệnh objdump.

Khám phá cú pháp và tùy chọn cơ bản của objdump

Trong bước này, bạn sẽ khám phá cú pháp và tùy chọn cơ bản của lệnh objdump. Lệnh objdump có nhiều tùy chọn để tùy chỉnh đầu ra và trích xuất thông tin cụ thể từ file object.

Hãy bắt đầu bằng cách xem lại cú pháp cơ bản của lệnh objdump:

objdump [options] file

Dưới đây là một số tùy chọn phổ biến nhất cho lệnh objdump:

  • -d hoặc --disassemble: Phân tích mã thực thi (disassemble executable code).
  • -S hoặc --source: Trộn mã nguồn với phần đã phân tích (intermix source code with disassembly).
  • -t hoặc --syms: Hiển thị nội dung của bảng ký hiệu (display the contents of the symbol table).
  • -x hoặc --all-headers: Hiển thị tất cả thông tin header có sẵn (display all available header information).
  • -h hoặc --section-headers: Hiển thị nội dung của các header section (display the contents of the section headers).

Hãy thử một vài tùy chọn này với file thực thi hello mà chúng ta đã tạo ở bước trước:

## Display the disassembly with source code
objdump -dS hello

## Display the symbol table
objdump -t hello

## Display all available header information
objdump -x hello

Ví dụ về đầu ra:

hello:     file format elf64-x86-64

Disassembly of section .text:

0000000000001000 <_init>:
    1000:   f3 0f 1e fa             endbr64
    1004:   48 83 ec 08             sub    $0x8,%rsp
    1008:   48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        ## 3fe8 <__gmon_start__>
    100f:   48 85 c0                test   %rax,%rax
    1012:   74 02                   je     1016 <_init+0x16>
    1014:   ff d0                   callq  *%rax
    1016:   48 83 c4 08             add    $0x8,%rsp
    101a:   c3                      retq

0000000000001020 <__libc_csu_init>:
    1020:   f3 0f 1e fa             endbr64
    1024:   41 57                   push   %r15
    1026:   4c 8d 3d 93 2c 00 00    lea    0x2c93(%rip),%r15        ## 3cc0 <__frame_dummy_init_array_entry>
    102d:   41 56                   push   %r14
    102f:   49 89 e6                mov    %rsp,%r14
    1032:   41 55                   push   %r13
    1034:   41 54                   push   %r12
    1036:   4c 8d 25 83 2c 00 00    lea    0x2c83(%rip),%r12        ## 3cc0 <__frame_dummy_init_array_entry>
    103d:   55                      push   %rbp
    103e:   48 8d 2d 83 2c 00 00    lea    0x2c83(%rip),%rbp        ## 3cc8 <__do_global_dtors_aux_fini_array_entry>
    1045:   53                      push   %rbx
    1046:   4c 29 e5                sub    %r12,%rbp
    1049:   48 83 ec 08             sub    $0x8,%rsp
    104d:   e8 ae fe ff ff          callq  f00 <_init>
    1052:   48 c1 fd 03             sar    $0x3,%rbp
    1056:   74 1f                   je     1077 <__libc_csu_init+0x57>
    1058:   31 db                   xor    %ebx,%ebx
    105a:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    105f:   4c 89 f2                mov    %r14,%rdx
    1062:   4c 89 ee                mov    %r13,%rsi
    1065:   44 89 e7                mov    %r12d,%edi
    1068:   41 ff 14 df             callq  *(%r15,%rbx,8)
    106c:   48 83 c3 01             add    $0x1,%rbx
    1070:   48 39 dd                cmp    %rbx,%rbp
    1073:   75 ea                   jne    105f <__libc_csu_init+0x3f>
    1075:   48 83 c4 08             add    $0x8,%rsp
    1079:   5b                      pop    %rbx
    107a:   5d                      pop    %rbp
    107b:   41 5c                   pop    %r12
    107d:   41 5d                   pop    %r13
    107f:   41 5e                   pop    %r14
    1081:   41 5f                   pop    %r15
    1083:   c3                      retq

0000000000001084 <__libc_csu_fini>:
    1084:   f3 0f 1e fa             endbr64
    1088:   c3                      retq

0000000000001089 <main>:
    1089:   f3 0f 1e fa             endbr64
    108d:   55                      push   %rbp
    108e:   48 89 e5                mov    %rsp,%rbp
    1091:   bf 00 00 00 00          mov    $0x0,%edi
    1096:   e8 85 fe ff ff          callq  f20 <puts@plt>
    109b:   b8 00 00 00 00          mov    $0x0,%eax
    10a0:   5d                      pop    %rbp
    10a1:   c3                      retq
    10a2:   66 2e 0f 1f 84 00 00 00 00 00 nopw   %cs:0x0(%rax,%rax,1)
    10ac:   0f 1f 40 00             nopl   0x0(%rax)

Disassembly of section .fini:

00000000000010b0 <_fini>:
    10b0:   f3 0f 1e fa             endbr64
    10b4:   48 83 ec 08             sub    $0x8,%rsp
    10b8:   48 83 c4 08             add    

Phân tích đầu ra của objdump trên một chương trình C đơn giản

Trong bước cuối cùng này, bạn sẽ phân tích chi tiết đầu ra của lệnh objdump, tập trung vào chương trình hello đã tạo trước đó.

Hãy bắt đầu bằng cách xem xét kỹ hơn đầu ra disassembly (hợp ngữ):

objdump -d hello

Ví dụ về đầu ra:

hello:     file format elf64-x86-64

Disassembly of section .text:

0000000000001089 <main>:
    1089:   f3 0f 1e fa             endbr64
    108d:   55                      push   %rbp
    108e:   48 89 e5                mov    %rsp,%rbp
    1091:   bf 00 00 00 00          mov    $0x0,%edi
    1096:   e8 85 fe ff ff          callq  f20 <puts@plt>
    109b:   b8 00 00 00 00          mov    $0x0,%eax
    10a0:   5d                      pop    %rbp
    10a1:   c3                      retq

Đầu ra disassembly hiển thị các machine instruction (lệnh máy) tạo nên hàm main của chương trình hello.

Hãy chia nhỏ các instruction (lệnh) này:

  1. f3 0f 1e fa: Đây là instruction endbr64, một tính năng bảo mật để ngăn chặn một số loại tấn công.
  2. 55: Đây là instruction push %rbp, lưu base pointer register (thanh ghi con trỏ gốc) trên stack.
  3. 48 89 e5: Đây là instruction mov %rsp,%rbp, đặt base pointer (con trỏ gốc) thành stack pointer (con trỏ ngăn xếp) hiện tại.
  4. bf 00 00 00 00: Đây là instruction mov $0x0,%edi, đặt đối số đầu tiên (file descriptor) thành 0 cho lệnh gọi hàm puts.
  5. e8 85 fe ff ff: Đây là instruction callq f20 <puts@plt>, gọi hàm puts để in thông báo "Hello, World!".
  6. b8 00 00 00 00: Đây là instruction mov $0x0,%eax, đặt giá trị trả về của hàm main thành 0.
  7. 5d: Đây là instruction pop %rbp, khôi phục base pointer (con trỏ gốc) từ stack.
  8. c3: Đây là instruction retq, trả về từ hàm main.

Bằng cách hiểu đầu ra disassembly, bạn có thể hiểu sâu hơn về cách chương trình hello hoạt động ở cấp độ thấp.

Điều này đặc biệt hữu ích để gỡ lỗi sự cố hoặc reverse-engineering (kỹ nghệ đảo ngược) phần mềm.

Kết luận cho linux objdump command

Tóm lại, lệnh objdump là một công cụ vô cùng hữu ích cho việc phân tích các file object và file thực thi trên hệ thống Linux. Nó giúp chúng ta hiểu rõ hơn về cấu trúc bên trong của chương trình, từ đó gỡ lỗi và tối ưu hóa hiệu quả hơn. Với linux objdump command, bạn có thể xem mã assembly, thông tin header, bảng symbol và nhiều thông tin quan trọng khác. Hãy thử nghiệm với các tùy chọn khác nhau để khám phá hết tiềm năng của công cụ này. Việc nắm vững objdump sẽ giúp bạn trở thành một lập trình viên Linux thành thạo hơn. Đừng ngần ngại sử dụng nó để khám phá sâu hơn về thế giới phần mềm. Chúc bạn thành công trên con đường chinh phục Linux!

Last Updated : 17/10/2025