When developing software under a Linux system, the output executable file can be large or small. If the running environment is on a server, the resources may be sufficient, but if it is in an embedded environment, storage resources must be competed for every inch. Therefore, there will be a need to slim down the executable file, such as using the strip command.
Regarding the operation of strip, some people jokingly call it “taking off clothes”. My description here will not be so naked and will be changed to “slimming down”.
In the man manual, the description of strip is:
discard symbols from object files
This means that the symbol information in the file is removed, so that the file size is reduced without affecting the execution of the executable file. In addition, removing some information from the executable file helps prevent reverse engineering.
The strip command format is as follows:
strip [options] filename …
Below I use a few examples to illustrate how to use this command:
It’s hard to make a meal without rice, so you need to prepare an executable file test first. The source file test.cpp to generate the executable file is as follows:
#include<stdio.h> class test{ }; int main(void) { printf("sizeof(class test)=%d\\ ", (int)sizeof(test)); return 0; }
Remove all symbol information
Let’s first take a look at the internal symbol information of the executable file, read it through the command readelf
$ readelf -s test Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 6: 0000000000000000 0 FUNC WEAK DEFAULT __cxa_finalize@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 63 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000238 0 SECTION LOCAL DEFAULT 1 2: 0000000000000254 0 SECTION LOCAL DEFAULT 2 3: 0000000000000274 0 SECTION LOCAL DEFAULT 3 4: 0000000000000298 0 SECTION LOCAL DEFAULT 4 5: 00000000000002b8 0 SECTION LOCAL DEFAULT 5 6: 0000000000000360 0 SECTION LOCAL DEFAULT 6 7: 00000000000003e4 0 SECTION LOCAL DEFAULT 7 8: 00000000000003f8 0 SECTION LOCAL DEFAULT 8 9: 0000000000000418 0 SECTION LOCAL DEFAULT 9 10: 00000000000004d8 0 SECTION LOCAL DEFAULT 10 11: 00000000000004f0 0 SECTION LOCAL DEFAULT 11 12: 0000000000000510 0 SECTION LOCAL DEFAULT 12 13: 0000000000000530 0 SECTION LOCAL DEFAULT 13 14: 0000000000000540 0 SECTION LOCAL DEFAULT 14 15: 00000000000006e4 0 SECTION LOCAL DEFAULT 15 16: 00000000000006f0 0 SECTION LOCAL DEFAULT 16 17: 000000000000070c 0 SECTION LOCAL DEFAULT 17 18: 0000000000000748 0 SECTION LOCAL DEFAULT 18 19: 0000000000200db8 0 SECTION LOCAL DEFAULT 19 20: 0000000000200dc0 0 SECTION LOCAL DEFAULT 20 21: 0000000000200dc8 0 SECTION LOCAL DEFAULT 21 22: 0000000000200fb8 0 SECTION LOCAL DEFAULT 22 23: 0000000000201000 0 SECTION LOCAL DEFAULT 23 24: 0000000000201010 0 SECTION LOCAL DEFAULT 24 25: 0000000000000000 0 SECTION LOCAL DEFAULT 25 26: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 27: 0000000000000570 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones 28: 00000000000005b0 0 FUNC LOCAL DEFAULT 14 register_tm_clones 29: 0000000000000600 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux 30: 0000000000201010 1 OBJECT LOCAL DEFAULT 24 completed.7698 31: 0000000000200dc0 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fin 32: 0000000000000640 0 FUNC LOCAL DEFAULT 14 frame_dummy 33: 0000000000200db8 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_ 34: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.cpp 35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 36: 000000000000084c 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__ 37: 0000000000000000 0 FILE LOCAL DEFAULT ABS 38: 0000000000200dc0 0 NOTYPE LOCAL DEFAULT 19 __init_array_end 39: 0000000000200dc8 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC 40: 0000000000200db8 0 NOTYPE LOCAL DEFAULT 19 __init_array_start 41: 000000000000070c 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR 42: 0000000000200fb8 0 OBJECT LOCAL DEFAULT 22 _GLOBAL_OFFSET_TABLE_ 43: 00000000000006e0 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini 44: 0000000000000000 0 NOTYPE WEAK DEFAULT _ITM_deregisterTMCloneTab 45: 0000000000201000 0 NOTYPE WEAK DEFAULT 23 data_start 46: 0000000000201010 0 NOTYPE GLOBAL DEFAULT 23 _edata 47: 00000000000006e4 0 FUNC GLOBAL DEFAULT 15 _fini 48: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.2.5 49: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 50: 0000000000201000 0 NOTYPE GLOBAL DEFAULT 23 __data_start 51: 0000000000000000 0 NOTYPE WEAK DEFAULT __gmon_start__ 52: 0000000000201008 0 OBJECT GLOBAL HIDDEN 23 __dso_handle 53: 00000000000006f0 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used 54: 0000000000000670 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init 55: 0000000000201018 0 NOTYPE GLOBAL DEFAULT 24 _end 56: 0000000000000540 43 FUNC GLOBAL DEFAULT 14 _start 57: 0000000000201010 0 NOTYPE GLOBAL DEFAULT 24 __bss_start 58: 000000000000064a 33 FUNC GLOBAL DEFAULT 14 main 59: 0000000000201010 0 OBJECT GLOBAL HIDDEN 23 __TMC_END__ 60: 0000000000000000 0 NOTYPE WEAK DEFAULT _ITM_registerTMCloneTable 61: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.2 62: 00000000000004f0 0 FUNC GLOBAL DEFAULT 11 _init
Use strip plus -s to remove all symbol information, and then read the file information again to see
$ strip -s test $ readelf -s test Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT _ITM_registerTMCloneTable 6: 0000000000000000 0 FUNC WEAK DEFAULT __cxa_finalize@GLIBC_2.2.5 (2)
From the output above, you can see that the symbol information within the file has been removed. However, the .dynsym and .dynstr table information still exists. These two table information are used for dynamic link library linking, so executing strip -s will not affect the use of the dynamic link library.
Remove debugging information
If you only need to remove debugging information, you can use the option –strip-debug
strip --strip-debug test
Then compare the read symbol information and find that the following content is missing from the file information after slimming down.
... 26: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c ... 34: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.cpp 35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c ...
Remove specific field information
In some cases, we need to remove specific field header information, then we can use the option -R
First, let’s read the field header information of the unslimmed executable file.
$ readelf -S test There are 29 section headers, starting at offset 0x18b8: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [1] .interp PROGBITS 0000000000000238 00000238 000000000000001c 0000000000000000 A 0 0 1 [2] .note.ABI-tag NOTE 0000000000000254 00000254 0000000000000020 0000000000000000 A 0 0 4 [3] .note.gnu.build-i NOTE 0000000000000274 00000274 0000000000000024 0000000000000000 A 0 0 4 [4] .gnu.hash GNU_HASH 0000000000000298 00000298 000000000000001c 0000000000000000 A 5 0 8 [5] .dynsym DYNSYM 00000000000002b8 000002b8 00000000000000a8 0000000000000018 A 6 1 8 [6] .dynstr STRTAB 0000000000000360 00000360 0000000000000084 0000000000000000 A 0 0 1 [7] .gnu.versionVERSYM 00000000000003e4 000003e4 000000000000000e 0000000000000002 A 5 0 2 [8] .gnu.version_r VERNEED 00000000000003f8 000003f8 0000000000000020 0000000000000000 A 6 1 8 [9] .rela.dyn RELA 0000000000000418 00000418 00000000000000c0 0000000000000018 A 5 0 8 [10] .rela.plt RELA 00000000000004d8 000004d8 0000000000000018 0000000000000018 AI 5 22 8 [11] .init PROGBITS 00000000000004f0 000004f0 0000000000000017 0000000000000000 AX 0 0 4 [12] .plt PROGBITS 0000000000000510 00000510 0000000000000020 0000000000000010 AX 0 0 16 [13] .plt.got PROGBITS 0000000000000530 00000530 0000000000000008 0000000000000008 AX 0 0 8 [14] .text PROGBITS 0000000000000540 00000540 00000000000001a2 0000000000000000 AX 0 0 16 [15] .fini PROGBITS 00000000000006e4 000006e4 0000000000000009 0000000000000000 AX 0 0 4 [16] .rodata PROGBITS 00000000000006f0 000006f0 000000000000001b 0000000000000000 A 0 0 4 [17] .eh_frame_hdr PROGBITS 000000000000070c 0000070c 000000000000003c 0000000000000000 A 0 0 4 [18] .eh_frame PROGBITS 0000000000000748 00000748 0000000000000108 0000000000000000 A 0 0 8 [19] .init_array INIT_ARRAY 0000000000200db8 00000db8 0000000000000008 0000000000000008 WA 0 0 8 [20] .fini_array FINI_ARRAY 0000000000200dc0 00000dc0 0000000000000008 0000000000000008 WA 0 0 8 [21] .dynamic DYNAMIC 0000000000200dc8 00000dc8 00000000000001f0 0000000000000010 WA 6 0 8 [22] .got PROGBITS 0000000000200fb8 00000fb8 0000000000000048 0000000000000008 WA 0 0 8 [23] .data PROGBITS 0000000000201000 00001000 0000000000000010 0000000000000000 WA 0 0 8 [24] .bss NOBITS 0000000000201010 00001010 0000000000000008 0000000000000000 WA 0 0 1 [25] .comment PROGBITS 0000000000000000 00001010 0000000000000029 0000000000000001 MS 0 0 1 [26] .symtab SYMTAB 0000000000000000 00001040 0000000000000588 0000000000000018 27 39 8 [27] .strtab STRTAB 0000000000000000 000015c8 00000000000001f2 0000000000000000 0 0 1 [28] .shstrtab STRTAB 0000000000000000 000017ba 00000000000000fe 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific)
If you need to remove the field header .gnu.version information, then execute
$ strip -R .gnu.version test
Use readelf -S again to read file information and you will find that the specified information has been removed.
Remove unnecessary symbol information for relocation
If you need to remove symbol information that is not needed for relocation, you can use the option –strip-unneeded
$ strip --strip-unneeded test
For example, when you need to slim down the static link library file, this option does not affect the link use of the static library.
Keep some symbol information when slimming
In some cases, slimming down executable files is not a one-size-fits-all approach. You may also need to leave out some symbol information. You can use the option -K
$ strip -s -Kframe_dummy test $ readelf -s test Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT _ITM_registerTMCloneTable 6: 0000000000000000 0 FUNC WEAK DEFAULT __cxa_finalize@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 27 entries: Num: Value Size Type Bind Vis Ndx Name ... 1: 0000000000000640 0 FUNC LOCAL DEFAULT 14 frame_dummy ...
It can be seen that the symbols specified after the -K option are retained and are not removed together.
In addition, the -K option can be used multiple times at the same time in the same strip command.
Remove specific symbol information
If you only need to remove specific symbol information and keep other symbol information, you can use option -N
Assume that the executable file has not been slimmed down, and then execute the following instructions
$ strip -Nframe_dummy test
After executing the above command, use readelf -s to read the symbol information. You can find that the symbols following the -N option have been removed.
Save file as
After removing the relevant information, if you want to keep the internal information of the original executable file unchanged and save the slimmed-down file as a new file, you can use the option -o
$ strip -s -otest_striped test
After outputting the slimming file, use readelf -s to read the files test_striped and test respectively. By comparison, it can be seen that the symbol information of the file test has not changed, while the symbol information of the file test_striped has been removed.
Keep original access and modification times
When you need to retain the original access and modification time information, you can use the option -p
Assuming that the executable file has never been slimmed down, use stat to see the detailed status of the file.
$ stat test File: test Size: 8304 Blocks: 24 IO Block: 4096 regular file Device: 801h/2049d Inode: 803646 Links: 1 Access: (0775/-rwxrwxr-x) Uid: ( 1000/ if) Gid: ( 1000/ if) Access: 2023-06-26 21:02:49.274028914 + 0800 Modify: 2023-06-26 21:02:49.274028914 + 0800 Change: 2023-06-26 21:02:49.274028914 + 0800 Birth: -
Then execute the strip command and try to retain the original access and modification time information
$ strip -s -p test
Take a look at the detailed status of the file
$ stat test File: test Size: 6120 Blocks: 16 IO Block: 4096 regular file Device: 801h/2049d Inode: 803647 Links: 1 Access: (0775/-rwxrwxr-x) Uid: ( 1000/ if) Gid: ( 1000/ if) Access: 2023-06-26 21:02:49.000000000 + 0800 Modify: 2023-06-26 21:02:49.000000000 + 0800 Change: 2023-06-26 21:10:53.991892402 + 0800 Birth: -
It can be seen that the original access and modification time information is retained, down to the unit of seconds.
Read option content from file
During the operation and maintenance process, in order to facilitate flexible switching of different configurations, parameter configurations are often stored in files. Different requirements require different configuration files.
The strip command also supports reading configuration options from files, in the format:
$ strip @filename
The file filename contains parameter options in text form, etc. for example
$ echo "-s test" > options.txt $ strip @options.txt
The effect is equivalent to
$ strip -s test
Output detailed process
Detailed information can be output at the same time during the execution of the strip command, use the option -v
$ strip -v -s test copy from `test' [elf64-x86-64] to `stPp23jj' [elf64-x86-64]
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. CS entry skill treeLinux introductionFirst introduction to Linux 38067 people are learning the system