In my previous post I explained what an ELF is here.
An ELF is literally an executable and linkable file.
When inspecting a file in linux we usually check the metadata of the file with the file command.
I noticed something odd, when running the file command on ls, cat, grep or any of the everyday commands we use in linux.
First let’s check ls.

You can see it’s a stripped binary.
Second, what about cat?

Hmm, strange. It’s also a stripped binary.
How about grep?

grep’s also a stripped binary.
By running the file command on 3 of the most frequently used gnu-coreutils.
You can make a plausible guess that all GNU programs are stripped binaries.
But what exactly are stripped binaries?
According to stackoverflow stripped binaries are ELF files that don’t contain debugging symbols.
Let’s compile some super simple C code.
BTW, it’s the exact same code as from here.
#include <stdio.h>
int main(){
printf("hello hwkim301\n");
}
Compile the C code without using any optimization flags or whatsoever.
gcc hello.c -o hello
Here’s the result of running file(command).
By default gcc creates ELF files which aren’t stripped.

I wondered why are GNU-coreutils all stripped binaries?
There weren’t many answers to this online, except this one.
According to the answer, non-stripped binaries contain debugging info called DWARF which take up more space in the files.
Distributing non-stripped ELF files also make it a bit easier for ctfers or hackers to reverse-engineer the binary, since they can get some hints from the variable names or source-code in the DWARF info.
That’s why linux distros like Ubuntu, Debian make their binaries stripped.
Now that we know that gcc doesn’t strip ELF files by default, and then stripped ELFs don’t have debugging info.
Let’s try to create a stripped ELF ourselves.
There are two ways of creating a stripped binary as far as I know.
The first method is by passing the gcc -s flag.
gcc hello.c -s -o hello2

The second way would be to compile the C code without any flags and then use the strip command.
gcc hello.c -o hello
strip hello

The document specifies that gcc -s is the same as the strip command.
An answer from stackoverflow adds on saying that gcc -s and strip is the same but the strip command allows finer grained control over what gets removed.
Is it really true that stripped binaries are smaller in size?
Let’s check it out.

The stripped binary is slightly smaller in size.
You can check the DWARF info by running objdump -w or readelf -w.
readelf -w hello2
Contents of the .eh_frame section:
00000000 0000000000000014 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_nop
DW_CFA_nop
00000018 0000000000000014 0000001c FDE cie=00000000 pc=0000000000001060..0000000000001086
DW_CFA_advance_loc: 4 to 0000000000001064
DW_CFA_undefined: r16 (rip)
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000030 0000000000000024 00000034 FDE cie=00000000 pc=0000000000001020..0000000000001040
DW_CFA_def_cfa_offset: 16
DW_CFA_advance_loc: 6 to 0000000000001026
DW_CFA_def_cfa_offset: 24
DW_CFA_advance_loc: 10 to 0000000000001030
DW_CFA_def_cfa_expression (DW_OP_breg7 (rsp): 8; DW_OP_breg16 (rip): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit9; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus)
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000058 0000000000000014 0000005c FDE cie=00000000 pc=0000000000001040..0000000000001050
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000070 0000000000000014 00000074 FDE cie=00000000 pc=0000000000001050..0000000000001060
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000088 000000000000001c 0000008c FDE cie=00000000 pc=0000000000001149..0000000000001167
DW_CFA_advance_loc: 5 to 000000000000114e
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to 0000000000001151
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_advance_loc: 21 to 0000000000001166
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
000000a8 ZERO terminator
I purposely ran objdump -W on a non-stripped file to see the differences between the DWARF info, but since I don’t have any background knowledge on DWARF info it’s a bit cryptic to me.
objdump -W hello
hello: file format elf64-x86-64
Contents of the .eh_frame section:
00000000 0000000000000014 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_nop
DW_CFA_nop
00000018 0000000000000014 0000001c FDE cie=00000000 pc=0000000000001060..0000000000001086
DW_CFA_advance_loc: 4 to 0000000000001064
DW_CFA_undefined: r16 (rip)
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000030 0000000000000024 00000034 FDE cie=00000000 pc=0000000000001020..0000000000001040
DW_CFA_def_cfa_offset: 16
DW_CFA_advance_loc: 6 to 0000000000001026
DW_CFA_def_cfa_offset: 24
DW_CFA_advance_loc: 10 to 0000000000001030
DW_CFA_def_cfa_expression (DW_OP_breg7 (rsp): 8; DW_OP_breg16 (rip): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit9; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus)
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000058 0000000000000014 0000005c FDE cie=00000000 pc=0000000000001040..0000000000001050
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000070 0000000000000014 00000074 FDE cie=00000000 pc=0000000000001050..0000000000001060
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000088 000000000000001c 0000008c FDE cie=00000000 pc=0000000000001149..0000000000001167
DW_CFA_advance_loc: 5 to 000000000000114e
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to 0000000000001151
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_advance_loc: 21 to 0000000000001166
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
000000a8 ZERO terminator
Have a look at the DWARF’s website and the wikipedia page if you’re interested.
I found some lectures to get a better understanding on ELF files and what symbols are from cppCon.
1. Greg Law’s cppcon talk
2. Serge Guelton’s cppcon talk
3. Anders Schau Knatten’s cpponsea talk