Fork me on GitHub
03 Oct 2009

Executable Shared Libraries

I figured out a way to create a shared library that is also executable. One possible use for this would be to make Cython modules that can be run by themselves or imported from Python. I found some mailing list discussions from 2003 describing a method, but it does not work on x86 Linux. The method below works, at least, on x86-64 Linux with gcc 4.3.3 on Ubuntu 9.04.

Unfortunately, I could not get gcc to do this for me - I have to run the linker myself. I tried giving -Wl,-shared, but gcc put the flag too late in the command line. If anyone figures out a way to do this, let me know!

Update: Thanks to Daniel Jacobowitz, I found out that -fPIC -fPIE -pie is sufficient. Easy! I've updated the post bleow to reflect this.

Here's some example code:

// library.c
#include <stdio.h>
#include <stdlib.h>

void foo(int x) {
    printf("foo(%d)\n", x);
}

int main(int argc, char **argv) {
    if (argc != 2) {
        fprintf(stderr, "USAGE: %s n\n", argv[0]);
        exit(1);
    }
    foo(atoi(argv[1]));
    return 0;
}

Compile -fPIC -fPIE -pie to make a position-independent executable, which can be loaded like a shared library.

$ gcc -fPIC -fPIE -pic -o library.so library.c

Now you can both execute and load your shared library.

$ ./library.so 12
foo(12)

$ python -c \
    'import ctypes; x = ctypes.cdll.LoadLibrary("./library.so"); x.foo(13)'
foo(13)

Manual Method

The rest of this post describes the stupid way I did it before, mainly for historical interest.

Run gcc '-###' to find out what command it would have run.

$ gcc '-###' -fPIC -fPIE -pie -rdynamic -o library.so library.o

Look for the collect2 line - this is the linker. Run that exact command, but insert -shared before the -pie. On my system, I ran this:

$ /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 \
    --eh-frame-hdr \
    -m elf_x86_64 \
    -shared \
    -pie \
    --export-dynamic \
    -o library.so \
    -z relro \
    /usr/lib/Scrt1.o \
    /usr/lib/crti.o \
    /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbeginS.o \
    -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 \
    -L/usr/lib \
    -L/lib \
    library.o \
    -lgcc \
    --as-needed \
    -lgcc_s \
    --no-as-needed \
    -lc \
    -lgcc \
    --as-needed \
    -lgcc_s \
    --no-as-needed \
    /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtendS.o \
    /usr/lib/crtn.o

← Previous
Next →