1. Debug symbols (nm), Debug info (objdump) là gì ?
Khi biên dịch C++ chương trình, compiler tạo ra symbol table (bảng ánh xạ địa chỉ → tên hàm/biến).
#include <iostream>
using namespace std;
void foo()
{
printf("Hello World\n");
}
int main() {
foo();
return 0;
}Debug symbols : tên hàm, tên biến, địa chỉ, symbol table, loại symbol (T, U, D, B)
// "nm test" chỉ biết tên hàm (mangled) và địa chỉ.
0000000000001139 T _Z3foov
0000000000001155 T main
Debug info : thông tin mở rộng: file, line number, type info, DWARF.
// "objdump --dwarf=info test" để biết tên hàm, file, dòng, metadata đầy đủ.
<1><0x2f>: Abbrev Number: 3 (DW_TAG_subprogram)
DW_AT_name : foo
DW_AT_decl_file : test.cpp
DW_AT_decl_line : 5
Mặc định object file không bị strip, chúng ta có thể strip binary bằng option “-s” hoặc “strip test” để xóa symbol table và debug info khi đưa vào production để giảm kích thước, giảm lộ thông tin nội bộ, tăng bảo mật, lúc này stacktrace chỉ hiện địa chỉ hex, không có tên hàm.
#[root@GIGABYTEU4 test]# g++ test.cpp -o test
[root@GIGABYTEU4 test]# ls -ltr
-rwxrwxrwx 1 binh binh 138 Aug 23 01:27 test.cpp
-rwxrwxrwx 1 binh binh 17816 Aug 23 15:34 test
[root@GIGABYTEU4 test]# file test
test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a577531bd99306d16796ce6ae78639e99b2a38fc, for GNU/Linux 3.2.0, not stripped
[root@GIGABYTEU4 test]# nm test
000000000040037c r __abi_tag
000000000040403c B __bss_start
000000000040403c b completed.0
U __cxa_atexit@GLIBC_2.2.5
0000000000404038 D __data_start
0000000000404038 W data_start
00000000004010b0 t deregister_tm_clones
00000000004010a0 T _dl_relocate_static_pie
0000000000401120 t __do_global_dtors_aux
0000000000403dd8 d __do_global_dtors_aux_fini_array_entry
0000000000402008 R __dso_handle
0000000000403de0 d _DYNAMIC
000000000040403c D _edata
0000000000404040 B _end
00000000004011cc T _fini
0000000000401150 t frame_dummy
0000000000403dc8 d __frame_dummy_init_array_entry
0000000000402148 r __FRAME_END__
0000000000404000 d _GLOBAL_OFFSET_TABLE_
00000000004011b5 t _GLOBAL__sub_I__Z3foov
w __gmon_start__
000000000040201c r __GNU_EH_FRAME_HDR
0000000000401000 T _init
0000000000402000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U __libc_start_main@GLIBC_2.34
0000000000401167 T main
U puts@GLIBC_2.2.5
00000000004010e0 t register_tm_clones
0000000000401070 T _start
0000000000404040 D __TMC_END__
0000000000401156 T _Z3foov
0000000000401177 t _Z41__static_initialization_and_destruction_0ii
U _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4
U _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4
000000000040403d b _ZStL8__ioinit
[root@GIGABYTEU4 test]# objdump --dwarf=info test
test: file format elf64-x86-64
[root@GIGABYTEU4 test]#[root@GIGABYTEU4 test]# g++ test.cpp -o test -s
[root@GIGABYTEU4 test]# ls -ltr
-rwxrwxrwx 1 binh binh 138 Aug 23 01:27 test.cpp
-rwxrwxrwx 1 binh binh 15264 Aug 23 02:09 test
[root@GIGABYTEU4 test]# file test
test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=60c122084a98df3d7aa09be4343e26891264e89e, for GNU/Linux 3.2.0, stripped
[root@GIGABYTEU4 test]# nm test
nm: test: no symbols
[root@GIGABYTEU4 test]# objdump --dwarf=info test
test: file format elf64-x86-64
[root@GIGABYTEU4 test]#2. Enable debug info bằng option “-g”
object file không bị strip theo mặc định, nhưng điều đó không đồng nghĩa với việc không cần “-g“. Hai thứ này hoàn toàn khác nhau và phục vụ mục đích khác nhau. Dùng “-g” để enable debug info
[root@GIGABYTEU4 test]# g++ test.cpp -o test
[root@GIGABYTEU4 test]# ls -ltr
-rwxrwxrwx 1 binh binh 138 Aug 23 01:27 test.cpp
-rwxrwxrwx 1 binh binh 17816 Aug 23 01:56 test
[root@GIGABYTEU4 test]# file test
test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a577531bd99306d16796ce6ae78639e99b2a38fc, for GNU/Linux 3.2.0, not stripped
[root@GIGABYTEU4 test]# nm test
000000000040037c r __abi_tag
000000000040403c B __bss_start
000000000040403c b completed.0
U __cxa_atexit@GLIBC_2.2.5
0000000000404038 D __data_start
0000000000404038 W data_start
00000000004010b0 t deregister_tm_clones
00000000004010a0 T _dl_relocate_static_pie
0000000000401120 t __do_global_dtors_aux
0000000000403dd8 d __do_global_dtors_aux_fini_array_entry
0000000000402008 R __dso_handle
0000000000403de0 d _DYNAMIC
000000000040403c D _edata
0000000000404040 B _end
00000000004011cc T _fini
0000000000401150 t frame_dummy
0000000000403dc8 d __frame_dummy_init_array_entry
0000000000402148 r __FRAME_END__
0000000000404000 d _GLOBAL_OFFSET_TABLE_
00000000004011b5 t _GLOBAL__sub_I__Z3foov
w __gmon_start__
000000000040201c r __GNU_EH_FRAME_HDR
0000000000401000 T _init
0000000000402000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U __libc_start_main@GLIBC_2.34
0000000000401167 T main
U puts@GLIBC_2.2.5
00000000004010e0 t register_tm_clones
0000000000401070 T _start
0000000000404040 D __TMC_END__
0000000000401156 T _Z3foov
0000000000401177 t _Z41__static_initialization_and_destruction_0ii
U _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4
U _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4
000000000040403d b _ZStL8__ioinit
[root@GIGABYTEU4 test]# objdump --dwarf=info test
test: file format elf64-x86-64
[root@GIGABYTEU4 test]#[root@GIGABYTEU4 test]# g++ -g test.cpp -o test
[root@GIGABYTEU4 test]# ls -ltr
-rwxrwxrwx 1 binh binh 138 Aug 23 01:27 test.cpp
-rwxrwxrwx 1 binh binh 32584 Aug 23 02:05 test
[root@GIGABYTEU4 test]# file test
test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4fca7fb6a1be6be83560cc43549dc6124cd6c0fb, for GNU/Linux 3.2.0, with debug_info, not stripped
[root@GIGABYTEU4 test]# nm test
000000000040037c r __abi_tag
000000000040403c B __bss_start
000000000040403c b completed.0
U __cxa_atexit@GLIBC_2.2.5
0000000000404038 D __data_start
0000000000404038 W data_start
00000000004010b0 t deregister_tm_clones
00000000004010a0 T _dl_relocate_static_pie
0000000000401120 t __do_global_dtors_aux
0000000000403dd8 d __do_global_dtors_aux_fini_array_entry
0000000000402008 R __dso_handle
0000000000403de0 d _DYNAMIC
000000000040403c D _edata
0000000000404040 B _end
00000000004011cc T _fini
0000000000401150 t frame_dummy
0000000000403dc8 d __frame_dummy_init_array_entry
0000000000402148 r __FRAME_END__
0000000000404000 d _GLOBAL_OFFSET_TABLE_
00000000004011b5 t _GLOBAL__sub_I__Z3foov
w __gmon_start__
000000000040201c r __GNU_EH_FRAME_HDR
0000000000401000 T _init
0000000000402000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U __libc_start_main@GLIBC_2.34
0000000000401167 T main
U puts@GLIBC_2.2.5
00000000004010e0 t register_tm_clones
0000000000401070 T _start
0000000000404040 D __TMC_END__
0000000000401156 T _Z3foov
0000000000401177 t _Z41__static_initialization_and_destruction_0ii
U _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4
U _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4
000000000040403d b _ZStL8__ioinit
[root@GIGABYTEU4 test]# objdump --dwarf=info test
test: file format elf64-x86-64
Contents of the .debug_info section:
Compilation Unit @ offset 0x0:
Length: 0x2075 (32-bit)
Version: 5
Unit Type: DW_UT_compile (1)
Abbrev Offset: 0x0
Pointer Size: 8
<0><c>: Abbrev Number: 39 (DW_TAG_compile_unit)
<d> DW_AT_producer : (indirect string, offset: 0x443): GNU C++17 11.5.0 20240719 (Red Hat 11.5.0-5.0.1) -mtune=generic -march=x86-64-v2 -g
<11> DW_AT_language : 33 (C++14)
<12> DW_AT_name : (indirect line string, offset: 0x0): test.cpp
<16> DW_AT_comp_dir : (indirect line string, offset: 0x9): /mnt/d/Programming/Linux/prog/test
<1a> DW_AT_low_pc : 0x401156
<22> DW_AT_high_pc : 0x74
<2a> DW_AT_stmt_list : 0x0
...
...
<1><205a>: Abbrev Number: 75 (DW_TAG_subprogram)
<205b> DW_AT_external : 1
<205b> DW_AT_name : foo
<205f> DW_AT_decl_file : 1
<2060> DW_AT_decl_line : 4
<2061> DW_AT_decl_column : 6
<2062> DW_AT_linkage_name: (indirect string, offset: 0x5ee): _Z3foov
<2066> DW_AT_low_pc : 0x401156
<206e> DW_AT_high_pc : 0x11
<2076> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
<2078> DW_AT_call_all_tail_calls: 1
<1><2078>: Abbrev Number: 0
[root@GIGABYTEU4 test]#