summaryrefslogtreecommitdiff
path: root/md/writeup/making_c_executables_smaller.md
blob: 1fb5341eb11b676dc8d3835c60108ee135b945bd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
title: Making C executables smaller
keywords:C,linux,elf,optimizations

# Making C executables smaller
There are some simple things that can be done to make C executables as small as possible.
Here is some example code we will work with:

```c
#include <SDL/SDL.h>
 
char quit = 0;
 
int main()
{
    SDL_Surface *screen,surface;
    SDL_Event e;
    SDL_Init( SDL_INIT_VIDEO );
    screen = SDL_SetVideoMode( 400, 400, 32, SDL_SWSURFACE );
    while(!quit)
        while(SDL_PollEvent(&e)>0)
        {
            if(e.type==SDL_MOUSEBUTTONDOWN) quit=1;
            if(e.type==SDL_KEYDOWN) quit=1;
        }
    SDL_Quit();
}
```

Compile:
```
gcc main.c -o main -lSDL
```

Size before: 5326 bytes
Execute command:
```
strip main
```

strip is included in most unix systems. It deletes some info
symbols from executables

Size after: 3532 bytes


You can also try sstrip which is advanced version of strip.
You can download it from 
ELF kickers[2] webpage.


Execute command:

```
sstrip main
```

Size after: 1960 bytes


There are some others way to decrease size of program.
GC Masher[3] Allows to
brute force gcc options for smaller executable size.
I where using this options for gcsmaher

```
-O  -O0  -O1  -O2  -O3  -Os
-ffast-math
-fomit-frame-pointer
-fauto-inc-dec
-mpush-args
-mno-red-zone
-mstackrealign 
```

After running with this options executable size is 5175 bytes and best compiling options are all possible combination. 
Combining with sstrip gives 1960 bytes. And there size where not reduced but some time there can be saved some bytes.Now we will change main function with

```c
void _start()
```

and return change to
```c
asm ( \
      "movl $1,%eax\n" \
      "xor %ebx,%ebx\n" \
      "int $128\n" \
    );
```

One other thing is to archive your executable and cat it with unpack shell script.

```bash
a=/tmp/I;tail -n+2 $0|zcat>$a;chmod +x $a;$a;rm $a;exit
```

Best options and smallest size now is 563 byte. Nope this is not smallest size try to rename executable name to one symbol and you will get 4 extra bytes.

```
gcc -Os -ffast-math -fomit-frame-pointer 
-fauto-inc-dec -mpush-args -mno-red-zone -c small.c;
ld -dynamic-linker /lib/ld-linux.so.2 small.o /usr/lib/libSDL.so -o small;
strip -s -R .comment -R .gnu.version small;sstrip small;
7z a -tGZip -mx=9 small.gz small > /dev/null;
cat unpack.header small.gz > small;
chmod a+x small;rm small.gz small.o
```




Link to other resources source of example code[1].


Author in link has 634 bytes. With his options I have 622 bytes and
using gcmasher i have 606 bytes. I have used his source in this compare.


## Links
http://users.utu.fi/tmwire/linux4k.html  
http://www.muppetlabs.com/%7Ebreadbox/software/elfkickers.html  
http://pouet.net/prod.php?which=18479  

## Downloads
small_sdl_elf.zip -
2KiB - http://archive.main.lv/files/writeup/list_elf_section_names/elf_section_list.zip