Skip to content
Advertisement

How are external symbols of a shared library resolved in the main program?

I’ve been reading a lot about the semantics of load-time linking of shared libraries and one thing that I’m having trouble understanding is how can the main program make references to functions defined in shared libraries? For example, say I have this code

myShared.sh

int get(){
   return 0;
}

main.c

  extern int get();
  int main(){
    int a = get();
  }

I understand that, since shared libraries cannot make any assertions about where they will be placed, they must use the GOT and PLT to make references to their own functions and global data. But how does the actual program that uses said libraries know where the functions will be loaded so that it can make references to them? Obviously, the linker has no idea since the linking of such libraries doesn’t happen until load-time. So, there are only two ways I can think of that would make it possible to reference such external functions.

  1. The linker simply places some place holders where get (in the above example) is being called and then adds some meta-data necessary for the loader to then come and replace the place holder with the actual address of the function (like how shared libraries used Load-time relocation before PIC) But this cause notable overhead and was the very motivation (I think) for the introduction of PIC in the first place

  2. The main program also has its own GOT and PLT and the loader will have to also fill the GOT of the main program along that of the shared library’s (either all at once during loading in case of global variables, or in a lazy fashion using PLT for functions) But this sound like a major duplication of effort.

So, which one of these two, if any, is the method used to resolve shared libraries’ external symbols?

Advertisement

Answer

Symbol resolution in main program is not much different from that in shared libraries and is achieved via main program’s GOT and PLT tables. You are correct that this incurs certain amount of duplication between static (ld) and dynamic (ld.so) linkers and slows down program startup but on the other hand allows for increased flexibility at runtime (e.g. interposing symbols via LD_PRELOAD).

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement