```c #include <stdio.h> #include <stdbool.h> #define STRUCT_INIT 0 static void func_a(void); static void func_b(void); typedef struct test_s { void (*const func_a)(void); void (*const func_b)(void); } test_t; #if STRUCT_INIT == 1 test_t test = { .func_a = func_a, .func_b = func_b, }; #endif static void func_a(void) { printf("%s", __func__); } static void func_b(void) { printf("%s", __func__); } int main(void) { #if STRUCT_INIT == 1 #else test_t test = {.func_a = func_a}; #endif test.func_a(); return 0; } ``` 反組譯 ```bash $ gcc -fdata-sections -ffunction-sections foo.c -o foo -Wl,--gc-sections $ objdump -d foo > foo.txt #$ objdump -d foo > foo_no_init.txt ``` 初始化結構(STRUCT_INIT == 1), 函數會加入物件, 有 func_b ```asm foo: 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 Disassembly of section .plt: 0000000000001020 <.plt>: 1020: ff 35 9a 2f 00 00 pushq 0x2f9a(%rip) # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x8> 1026: f2 ff 25 9b 2f 00 00 bnd jmpq *0x2f9b(%rip) # 3fc8 <_GLOBAL_OFFSET_TABLE_+0x10> 102d: 0f 1f 00 nopl (%rax) 1030: f3 0f 1e fa endbr64 1034: 68 00 00 00 00 pushq $0x0 1039: f2 e9 e1 ff ff ff bnd jmpq 1020 <.plt> 103f: 90 nop Disassembly of section .plt.got: 0000000000001040 <__cxa_finalize@plt>: 1040: f3 0f 1e fa endbr64 1044: f2 ff 25 ad 2f 00 00 bnd jmpq *0x2fad(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 104b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) Disassembly of section .plt.sec: 0000000000001050 <printf@plt>: 1050: f3 0f 1e fa endbr64 1054: f2 ff 25 75 2f 00 00 bnd jmpq *0x2f75(%rip) # 3fd0 <printf@GLIBC_2.2.5> 105b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) Disassembly of section .text: 0000000000001060 <_start>: 1060: f3 0f 1e fa endbr64 1064: 31 ed xor %ebp,%ebp 1066: 49 89 d1 mov %rdx,%r9 1069: 5e pop %rsi 106a: 48 89 e2 mov %rsp,%rdx 106d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 1071: 50 push %rax 1072: 54 push %rsp 1073: 4c 8d 05 a6 01 00 00 lea 0x1a6(%rip),%r8 # 1220 <__libc_csu_fini> 107a: 48 8d 0d 2f 01 00 00 lea 0x12f(%rip),%rcx # 11b0 <__libc_csu_init> 1081: 48 8d 3d 07 01 00 00 lea 0x107(%rip),%rdi # 118f <main> 1088: ff 15 52 2f 00 00 callq *0x2f52(%rip) # 3fe0 <__libc_start_main@GLIBC_2.2.5> 108e: f4 hlt 108f: 90 nop 0000000000001090 <deregister_tm_clones>: 1090: 48 8d 3d 89 2f 00 00 lea 0x2f89(%rip),%rdi # 4020 <__TMC_END__> 1097: 48 8d 05 82 2f 00 00 lea 0x2f82(%rip),%rax # 4020 <__TMC_END__> 109e: 48 39 f8 cmp %rdi,%rax 10a1: 74 15 je 10b8 <deregister_tm_clones+0x28> 10a3: 48 8b 05 2e 2f 00 00 mov 0x2f2e(%rip),%rax # 3fd8 <_ITM_deregisterTMCloneTable> 10aa: 48 85 c0 test %rax,%rax 10ad: 74 09 je 10b8 <deregister_tm_clones+0x28> 10af: ff e0 jmpq *%rax 10b1: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 10b8: c3 retq 10b9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 00000000000010c0 <register_tm_clones>: 10c0: 48 8d 3d 59 2f 00 00 lea 0x2f59(%rip),%rdi # 4020 <__TMC_END__> 10c7: 48 8d 35 52 2f 00 00 lea 0x2f52(%rip),%rsi # 4020 <__TMC_END__> 10ce: 48 29 fe sub %rdi,%rsi 10d1: 48 89 f0 mov %rsi,%rax 10d4: 48 c1 ee 3f shr $0x3f,%rsi 10d8: 48 c1 f8 03 sar $0x3,%rax 10dc: 48 01 c6 add %rax,%rsi 10df: 48 d1 fe sar %rsi 10e2: 74 14 je 10f8 <register_tm_clones+0x38> 10e4: 48 8b 05 05 2f 00 00 mov 0x2f05(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable> 10eb: 48 85 c0 test %rax,%rax 10ee: 74 08 je 10f8 <register_tm_clones+0x38> 10f0: ff e0 jmpq *%rax 10f2: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 10f8: c3 retq 10f9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001100 <__do_global_dtors_aux>: 1100: f3 0f 1e fa endbr64 1104: 80 3d 15 2f 00 00 00 cmpb $0x0,0x2f15(%rip) # 4020 <__TMC_END__> 110b: 75 2b jne 1138 <__do_global_dtors_aux+0x38> 110d: 55 push %rbp 110e: 48 83 3d e2 2e 00 00 cmpq $0x0,0x2ee2(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 1115: 00 1116: 48 89 e5 mov %rsp,%rbp 1119: 74 0c je 1127 <__do_global_dtors_aux+0x27> 111b: 48 8b 3d de 2e 00 00 mov 0x2ede(%rip),%rdi # 4000 <__dso_handle> 1122: e8 19 ff ff ff callq 1040 <__cxa_finalize@plt> 1127: e8 64 ff ff ff callq 1090 <deregister_tm_clones> 112c: c6 05 ed 2e 00 00 01 movb $0x1,0x2eed(%rip) # 4020 <__TMC_END__> 1133: 5d pop %rbp 1134: c3 retq 1135: 0f 1f 00 nopl (%rax) 1138: c3 retq 1139: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001140 <frame_dummy>: 1140: f3 0f 1e fa endbr64 1144: e9 77 ff ff ff jmpq 10c0 <register_tm_clones> 0000000000001149 <func_a>: 1149: f3 0f 1e fa endbr64 114d: 55 push %rbp 114e: 48 89 e5 mov %rsp,%rbp 1151: 48 8d 35 ab 0e 00 00 lea 0xeab(%rip),%rsi # 2003 <__func__.2327> 1158: 48 8d 3d a1 0e 00 00 lea 0xea1(%rip),%rdi # 2000 <_fini+0xdd8> 115f: b8 00 00 00 00 mov $0x0,%eax 1164: e8 e7 fe ff ff callq 1050 <printf@plt> 1169: 90 nop 116a: 5d pop %rbp 116b: c3 retq 000000000000116c <func_b>: 116c: f3 0f 1e fa endbr64 1170: 55 push %rbp 1171: 48 89 e5 mov %rsp,%rbp 1174: 48 8d 35 8f 0e 00 00 lea 0xe8f(%rip),%rsi # 200a <__func__.2331> 117b: 48 8d 3d 7e 0e 00 00 lea 0xe7e(%rip),%rdi # 2000 <_fini+0xdd8> 1182: b8 00 00 00 00 mov $0x0,%eax 1187: e8 c4 fe ff ff callq 1050 <printf@plt> 118c: 90 nop 118d: 5d pop %rbp 118e: c3 retq 000000000000118f <main>: 118f: f3 0f 1e fa endbr64 1193: 55 push %rbp 1194: 48 89 e5 mov %rsp,%rbp 1197: 48 8b 05 72 2e 00 00 mov 0x2e72(%rip),%rax # 4010 <test> 119e: ff d0 callq *%rax 11a0: b8 00 00 00 00 mov $0x0,%eax 11a5: 5d pop %rbp 11a6: c3 retq 11a7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 11ae: 00 00 00000000000011b0 <__libc_csu_init>: 11b0: f3 0f 1e fa endbr64 11b4: 41 57 push %r15 11b6: 4c 8d 3d fb 2b 00 00 lea 0x2bfb(%rip),%r15 # 3db8 <__frame_dummy_init_array_entry> 11bd: 41 56 push %r14 11bf: 49 89 d6 mov %rdx,%r14 11c2: 41 55 push %r13 11c4: 49 89 f5 mov %rsi,%r13 11c7: 41 54 push %r12 11c9: 41 89 fc mov %edi,%r12d 11cc: 55 push %rbp 11cd: 48 8d 2d ec 2b 00 00 lea 0x2bec(%rip),%rbp # 3dc0 <__do_global_dtors_aux_fini_array_entry> 11d4: 53 push %rbx 11d5: 4c 29 fd sub %r15,%rbp 11d8: 48 83 ec 08 sub $0x8,%rsp 11dc: e8 1f fe ff ff callq 1000 <_init> 11e1: 48 c1 fd 03 sar $0x3,%rbp 11e5: 74 1f je 1206 <__libc_csu_init+0x56> 11e7: 31 db xor %ebx,%ebx 11e9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 11f0: 4c 89 f2 mov %r14,%rdx 11f3: 4c 89 ee mov %r13,%rsi 11f6: 44 89 e7 mov %r12d,%edi 11f9: 41 ff 14 df callq *(%r15,%rbx,8) 11fd: 48 83 c3 01 add $0x1,%rbx 1201: 48 39 dd cmp %rbx,%rbp 1204: 75 ea jne 11f0 <__libc_csu_init+0x40> 1206: 48 83 c4 08 add $0x8,%rsp 120a: 5b pop %rbx 120b: 5d pop %rbp 120c: 41 5c pop %r12 120e: 41 5d pop %r13 1210: 41 5e pop %r14 1212: 41 5f pop %r15 1214: c3 retq 1215: 66 66 2e 0f 1f 84 00 data16 nopw %cs:0x0(%rax,%rax,1) 121c: 00 00 00 00 0000000000001220 <__libc_csu_fini>: 1220: f3 0f 1e fa endbr64 1224: c3 retq Disassembly of section .fini: 0000000000001228 <_fini>: 1228: f3 0f 1e fa endbr64 122c: 48 83 ec 08 sub $0x8,%rsp 1230: 48 83 c4 08 add $0x8,%rsp 1234: c3 retq ``` 初始化結構(STRUCT_INIT == 0), 函數不會加入物件, 無 func_b ```asm foo: 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 Disassembly of section .plt: 0000000000001020 <.plt>: 1020: ff 35 9a 2f 00 00 pushq 0x2f9a(%rip) # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x8> 1026: f2 ff 25 9b 2f 00 00 bnd jmpq *0x2f9b(%rip) # 3fc8 <_GLOBAL_OFFSET_TABLE_+0x10> 102d: 0f 1f 00 nopl (%rax) 1030: f3 0f 1e fa endbr64 1034: 68 00 00 00 00 pushq $0x0 1039: f2 e9 e1 ff ff ff bnd jmpq 1020 <.plt> 103f: 90 nop Disassembly of section .plt.got: 0000000000001040 <__cxa_finalize@plt>: 1040: f3 0f 1e fa endbr64 1044: f2 ff 25 ad 2f 00 00 bnd jmpq *0x2fad(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 104b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) Disassembly of section .plt.sec: 0000000000001050 <printf@plt>: 1050: f3 0f 1e fa endbr64 1054: f2 ff 25 75 2f 00 00 bnd jmpq *0x2f75(%rip) # 3fd0 <printf@GLIBC_2.2.5> 105b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) Disassembly of section .text: 0000000000001060 <_start>: 1060: f3 0f 1e fa endbr64 1064: 31 ed xor %ebp,%ebp 1066: 49 89 d1 mov %rdx,%r9 1069: 5e pop %rsi 106a: 48 89 e2 mov %rsp,%rdx 106d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 1071: 50 push %rax 1072: 54 push %rsp 1073: 4c 8d 05 96 01 00 00 lea 0x196(%rip),%r8 # 1210 <__libc_csu_fini> 107a: 48 8d 0d 1f 01 00 00 lea 0x11f(%rip),%rcx # 11a0 <__libc_csu_init> 1081: 48 8d 3d e4 00 00 00 lea 0xe4(%rip),%rdi # 116c <main> 1088: ff 15 52 2f 00 00 callq *0x2f52(%rip) # 3fe0 <__libc_start_main@GLIBC_2.2.5> 108e: f4 hlt 108f: 90 nop 0000000000001090 <deregister_tm_clones>: 1090: 48 8d 3d 71 2f 00 00 lea 0x2f71(%rip),%rdi # 4008 <__TMC_END__> 1097: 48 8d 05 6a 2f 00 00 lea 0x2f6a(%rip),%rax # 4008 <__TMC_END__> 109e: 48 39 f8 cmp %rdi,%rax 10a1: 74 15 je 10b8 <deregister_tm_clones+0x28> 10a3: 48 8b 05 2e 2f 00 00 mov 0x2f2e(%rip),%rax # 3fd8 <_ITM_deregisterTMCloneTable> 10aa: 48 85 c0 test %rax,%rax 10ad: 74 09 je 10b8 <deregister_tm_clones+0x28> 10af: ff e0 jmpq *%rax 10b1: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 10b8: c3 retq 10b9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 00000000000010c0 <register_tm_clones>: 10c0: 48 8d 3d 41 2f 00 00 lea 0x2f41(%rip),%rdi # 4008 <__TMC_END__> 10c7: 48 8d 35 3a 2f 00 00 lea 0x2f3a(%rip),%rsi # 4008 <__TMC_END__> 10ce: 48 29 fe sub %rdi,%rsi 10d1: 48 89 f0 mov %rsi,%rax 10d4: 48 c1 ee 3f shr $0x3f,%rsi 10d8: 48 c1 f8 03 sar $0x3,%rax 10dc: 48 01 c6 add %rax,%rsi 10df: 48 d1 fe sar %rsi 10e2: 74 14 je 10f8 <register_tm_clones+0x38> 10e4: 48 8b 05 05 2f 00 00 mov 0x2f05(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable> 10eb: 48 85 c0 test %rax,%rax 10ee: 74 08 je 10f8 <register_tm_clones+0x38> 10f0: ff e0 jmpq *%rax 10f2: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 10f8: c3 retq 10f9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001100 <__do_global_dtors_aux>: 1100: f3 0f 1e fa endbr64 1104: 80 3d fd 2e 00 00 00 cmpb $0x0,0x2efd(%rip) # 4008 <__TMC_END__> 110b: 75 2b jne 1138 <__do_global_dtors_aux+0x38> 110d: 55 push %rbp 110e: 48 83 3d e2 2e 00 00 cmpq $0x0,0x2ee2(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 1115: 00 1116: 48 89 e5 mov %rsp,%rbp 1119: 74 0c je 1127 <__do_global_dtors_aux+0x27> 111b: 48 8b 3d de 2e 00 00 mov 0x2ede(%rip),%rdi # 4000 <__dso_handle> 1122: e8 19 ff ff ff callq 1040 <__cxa_finalize@plt> 1127: e8 64 ff ff ff callq 1090 <deregister_tm_clones> 112c: c6 05 d5 2e 00 00 01 movb $0x1,0x2ed5(%rip) # 4008 <__TMC_END__> 1133: 5d pop %rbp 1134: c3 retq 1135: 0f 1f 00 nopl (%rax) 1138: c3 retq 1139: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001140 <frame_dummy>: 1140: f3 0f 1e fa endbr64 1144: e9 77 ff ff ff jmpq 10c0 <register_tm_clones> 0000000000001149 <func_a>: 1149: f3 0f 1e fa endbr64 114d: 55 push %rbp 114e: 48 89 e5 mov %rsp,%rbp 1151: 48 8d 35 ab 0e 00 00 lea 0xeab(%rip),%rsi # 2003 <__func__.2326> 1158: 48 8d 3d a1 0e 00 00 lea 0xea1(%rip),%rdi # 2000 <_fini+0xde8> 115f: b8 00 00 00 00 mov $0x0,%eax 1164: e8 e7 fe ff ff callq 1050 <printf@plt> 1169: 90 nop 116a: 5d pop %rbp 116b: c3 retq 000000000000116c <main>: 116c: f3 0f 1e fa endbr64 1170: 55 push %rbp 1171: 48 89 e5 mov %rsp,%rbp 1174: 48 83 ec 10 sub $0x10,%rsp 1178: 48 c7 45 f0 00 00 00 movq $0x0,-0x10(%rbp) 117f: 00 1180: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp) 1187: 00 1188: 48 8d 05 ba ff ff ff lea -0x46(%rip),%rax # 1149 <func_a> 118f: 48 89 45 f0 mov %rax,-0x10(%rbp) 1193: 48 8b 45 f0 mov -0x10(%rbp),%rax 1197: ff d0 callq *%rax 1199: b8 00 00 00 00 mov $0x0,%eax 119e: c9 leaveq 119f: c3 retq 00000000000011a0 <__libc_csu_init>: 11a0: f3 0f 1e fa endbr64 11a4: 41 57 push %r15 11a6: 4c 8d 3d 0b 2c 00 00 lea 0x2c0b(%rip),%r15 # 3db8 <__frame_dummy_init_array_entry> 11ad: 41 56 push %r14 11af: 49 89 d6 mov %rdx,%r14 11b2: 41 55 push %r13 11b4: 49 89 f5 mov %rsi,%r13 11b7: 41 54 push %r12 11b9: 41 89 fc mov %edi,%r12d 11bc: 55 push %rbp 11bd: 48 8d 2d fc 2b 00 00 lea 0x2bfc(%rip),%rbp # 3dc0 <__do_global_dtors_aux_fini_array_entry> 11c4: 53 push %rbx 11c5: 4c 29 fd sub %r15,%rbp 11c8: 48 83 ec 08 sub $0x8,%rsp 11cc: e8 2f fe ff ff callq 1000 <_init> 11d1: 48 c1 fd 03 sar $0x3,%rbp 11d5: 74 1f je 11f6 <__libc_csu_init+0x56> 11d7: 31 db xor %ebx,%ebx 11d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 11e0: 4c 89 f2 mov %r14,%rdx 11e3: 4c 89 ee mov %r13,%rsi 11e6: 44 89 e7 mov %r12d,%edi 11e9: 41 ff 14 df callq *(%r15,%rbx,8) 11ed: 48 83 c3 01 add $0x1,%rbx 11f1: 48 39 dd cmp %rbx,%rbp 11f4: 75 ea jne 11e0 <__libc_csu_init+0x40> 11f6: 48 83 c4 08 add $0x8,%rsp 11fa: 5b pop %rbx 11fb: 5d pop %rbp 11fc: 41 5c pop %r12 11fe: 41 5d pop %r13 1200: 41 5e pop %r14 1202: 41 5f pop %r15 1204: c3 retq 1205: 66 66 2e 0f 1f 84 00 data16 nopw %cs:0x0(%rax,%rax,1) 120c: 00 00 00 00 0000000000001210 <__libc_csu_fini>: 1210: f3 0f 1e fa endbr64 1214: c3 retq Disassembly of section .fini: 0000000000001218 <_fini>: 1218: f3 0f 1e fa endbr64 121c: 48 83 ec 08 sub $0x8,%rsp 1220: 48 83 c4 08 add $0x8,%rsp 1224: c3 retq ```