8
votes

This is my 2nd post on this site in my effort to understand the compilation/linking process with gcc. When I try to make an executable, symbols need to be resolved at link time, but when I try to make a shared library, symbols are not resolved at link time of this library. They will perhaps be resolved when I am trying to make an executable using this shared library. Hands-on:

bash$ cat printhello.c
#include <stdio.h>
//#include "look.h"

void PrintHello()
{
look();
printf("Hello World\n");
}

bash$ cat printbye.c
#include <stdio.h>
//#include "look.h"

void PrintBye()
{
look();
printf("Bye bye\n");
}

bash$  cat look.h
void look();

bash$ cat look.c
#include <stdio.h>

void look()
{
printf("Looking\n");
}

bash$ gcc printhello.c printbye.c
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
/tmp/cck21S0u.o: In function `PrintHello':
printhello.c:(.text+0x7): undefined reference to `look'
/tmp/ccNWbCnd.o: In function `PrintBye':
printbye.c:(.text+0x7): undefined reference to `look'
collect2: ld returned 1 exit status

bash$ gcc -Wall -shared -o libgreet printhello.c printbye.c
printhello.c: In function 'PrintHello':
printhello.c:6: warning: implicit declaration of function 'look'
printbye.c: In function 'PrintBye':
printbye.c:5: warning: implicit declaration of function 'look'

So my question is why are symbols not resolved when I am linking a shared library. This work(Resolving symbols of its downstream) will need to be done when I will use this library to make an executable, but that means we need to know what this library depends on when using this library, but isn't it not undesirable?

Thanks, Jagrati

6

6 Answers

9
votes

Does adding -z defs when building the library do what you want? If not, check the ld man pages, there are quite a few options on the handling of undefined symbols.

5
votes

Since you didn't give the -c (compile only) option, you requested gcc to compile the two source files and link them with the standard library (libc) and the c run-time startup (crt0, typically) to produce a running program. crt0 tries to enter your program by calling main(), which is the undefined symbol the linker can't find. It can't find it because you don't have a main() in either of your .c files, right?

So, on to your actual question, "Why symbols of a shared library are not resolved at link time?" The answer is, what do you mean by "link time?" By defintion, a dynamically linked program isn't "linked" until it starts (or maybe not even then, depending on your system.)

On a Linux system, you can see which dynamic libraries a program depends on with the ldd command (on Mac OS use 'otool -L'). The output of ldd will tell you which dynamic libraries a program depends on, which where found in the library search path, and which ones cannot be found (if any).

When you dynamic program starts, the dynamic linker that was linked into it locates and loads the dynamic libraries the program depends on, and "fixes" the references to the external symbols. If any of these fail, your program will fail to start. One all of the formerly unresolved symbols have been resolved, the dynamic linker returns and the C runtime will call your main() function. (It's somewhat different on Mac OS, but similar in effect, the linking happens after your program is started.)

2
votes

I think the linker option -Bsymbolic is what you're looking for.

0
votes

The linked has no way of knowing, in ELF at least, where the symbols are (i.e. in which libraries). In OS X, on the other hand, you need to link libraries the way you described. In the end, it is a question of design. One is more flexible, the other, more rigorous.

0
votes

Even when you build a shared library it must resolve all the dependencies.

Thus when a shared library is loaded at compile time it knows what other shared libraries to load at runtime so that it can resolve other dependencies.

1) Build a shared (look.<sharedLib>) library with look()
2) Build a shared (hg.<sharedLib>) library with hello() bye() link against look.<sharedLib>
3) Build Application with main() that links against hg.<sharedlib>

At runtime the application will then load hg.<sharedlib> which will intern load the shared library look.<sharedlib>

0
votes

A executable requires a entry point. But a shared library can be built without the entry point and later the executable can be compiled with this shared library.