views:

79

answers:

3
$ chmod +x libsomelibrary.so
$ ./libsomelibrary.so
Segmentation fault

$ gcc -O2 http://vi-server.org/vi/bin/rundll.c -ldl -o rundll
$ ./rundll ./libsomelibrary.so main
(application starts normally)

Why can't I just start libsomelibrary.so if it has usable entry point?

rundll.c is trivial:

void* d = dlopen(argv[1], RTLD_LAZY);
void* m = dlsym(d, argv[2]);
return ((int(*)(int,char**,char**))m)(argc-2, argv+2, envp);

Why is it not used internally when attempting to load a binary?

+3  A: 

Shared libraries are not designed to be directly runnable. They are designed to be linked into another codebase. It may have a usable entry point, but being executable entails more than merely having a usable entry point. The rundll utility is proof of this. Your second test shows that the shared library is indeed executable, but only after rundll does some work. If you are curious as to what all has to be done before the library code can be executed, take a look at the source code for rundll.

bta
"rundll" is a program I've just written. But it is a trivial thing. System easily can do it (if we are trying to execute the library, dlopen it, dlsym "main" and execute it).
Vi
Why does "being executable" entail "more than merely having a usable entry point"? Please provide some additional explanation.
wj32
It is trivial. I have seen a number of applications whose main executable is a small wrapper like this that `dlopen`s the main library and jumps to a pre-defined function. The system doesn't do this automatically because in the general case, it doesn't know where the entry point is (or which entry point to use, in the case of multiple entry points) or what kind of setup needs to be done before jumping to that entry point.
bta
@bta, "which entry point to use" -> "main". "what kind of setup" -> the same as "rundll" does (the same as if we have compiled it without "-shared" option).
Vi
@nos, And what prevents it to be done automatically? Why application is that more than just a library which has "main" symbol?
Vi
@nos: I can only speak from a Windows background, but the NT kernel maps ntdll.dll into each new process, and ntdll contains the basic support functions needed by every program including the loader code. Also, on modern OSes which support base address randomization all modules (EXEs and DLLs) can be relocated, making your second point irrelevant.
wj32
@wj32 But much of that isn't done automagically by the system, it's initiated by glue code that's part of your exe that runs before your main().
nos
@nos: Not on Windows. I don't know about GNU/Linux.
wj32
@Vi- *You* know that "main" is the correct entry point, but the OS doesn't know that. You can have multiple entry points (and may not have an entry point named "main") so the OS doesn't assume anything. As caf notes in his answer, an executable's header tells the OS what entry point to use. Your library doesn't have such a header, so the OS doesn't know how to execute it as-is.
bta
+1  A: 

You can start shared libraries in Linux.

For example, if you start /lib/libc.so.6, it will print out its version number:

$ /lib/libc.so.6
GNU C Library stable release version 2.12, by Roland McGrath et al.
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.5.0 20100520 (prerelease).
Compiled on a Linux 2.6.34 system on 2010-05-29.
Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html&gt;.

There must be something missing from your library.

Jörg W Mittag
+3  A: 

main is not the entry point recognised by the kernel or the dynamic linker - it is called by the startup code linked into your executable when you compile it (such startup code isn't linked into shared libraries by default).

The ELF header contains the start address.

caf