1

I'm trying to create a minimal sized executable for a demoscene contest. I'm trying to minimize the size of the executable by linking it myself.

Here is my minimal main.c, taken from http://www.int21.de/linux4k/ It draws a white triangle on the screen:

#include "SDL/SDL.h"
#include "GL/gl.h"

void _start(){
    SDL_Event event;

    SDL_SetVideoMode(640,480,0,SDL_OPENGL|SDL_FULLSCREEN);

    SDL_ShowCursor(SDL_DISABLE);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.33,1.33,-1,1,1.5,100);
    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);

    glLoadIdentity();
    glBegin(GL_TRIANGLES);
    glVertex3i(1,1,-10);
    glVertex3i(1,-1,-10);
    glVertex3i(-1,1,-10);
    glEnd();
    SDL_GL_SwapBuffers();

    do{
        SDL_PollEvent(&event);
    } while (event.type!=SDL_KEYDOWN);
    SDL_Quit();
}

I am using void _start() instead of int main(), because I don't want to use the C runtime. Here are my build commands (my machine is running Ubuntu Linux):

gcc -c main.c
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -lSDL -lGL main.o -o main

The program crashes on SDL_SetVideoMode. gdb reports:

Program received signal SIGSEGV, Segmentation fault.
_dl_map_object_from_fd (name=0x7ffff77dfcec "libXrender.so.1", fd=-1, fbp=0x7fffffffd908, 
    realname=0x601de0 "/usr/lib/x86_64-linux-gnu/libXrender.so.1", loader=<optimized out>, l_type=<optimized out>, 
    mode=-1879048190, stack_endp=0x7fffffffdc68, nsid=0) at dl-load.c:1574

What is wrong? If I change void _start() to int main(), and compile the whole thing with gcc main.c -o main -lSDL -lGL, it works just fine. This working version and the self-linked broken version have exactly the same list of linked libraries when I inspect the executables with ldd.

jnalanko
  • 147
  • 4

1 Answers1

1

TL;DR: Patient: "Doctor, it hurts when I do ${THAT}" – Doctor: "Then don't do ${THAT}".

If you don't want to have the C runtime in there you must make sure that you don't use any code that relies on the C runtime being available and more importantly being initialized. SDL strongly depends on the facilities of libc (which is why you probably added that -lc so that SDL can be properly linked), so when you link it, you need all that libc stuff. However for libc to properly work it must be initialized, which is what _start() does.

If you want to get your executable size down, which yes also involved getting rid of the (bloated GNU) libc, you'll have to do a lot of things yourself and/or patch libraries you use not to rely on the things you want to remove.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Thanks. I'm just wondering why this tutorial makes it seem so easy: http://www.int21.de/linux4k/ – jnalanko Mar 15 '15 at 19:31
  • @jnalanko: One possible reason is, that the shared object version of libSDL is used; and depending on how its built has been configured it may do all its libc initialization in it's constructor segment. Note that in the case of 4k intros using SDL would probably disqualify you, since SDL is not a standard library found on vanilla systems (the requirement for 4k intros usually is that they must work on systems with just the essentials and the drivers installed and nothing more). However creating an X11 window with just Xlib is not *that* hard. – datenwolf Mar 15 '15 at 20:59