简体   繁体   中英

Interesting GCC Linking

I was playing around with symbols and function pointers recently and noticed that though the following code runs fine:

#include <stdio.h>
int main(int argc, const char * argv[]) {
    printf("%p\n",printf); // <--this line makes it work
    int (*printfptr)(const char * restrict, ...);
    printfptr = 0x1001fe910;
    (*printfptr)("Hello world\n");
    return 0;
}

This does not:

#include <stdio.h>
int main(int argc, const char * argv[]) {
    // printf("%p\n",printf); // <-- commenting this out breaks it
    int (*printfptr)(const char * restrict, ...);
    printfptr = 0x1001fe910;
    (*printfptr)("Hello world\n");
    return 0;
}

(EXC_BAD_ACCESS)

How come dereferencing the exact same pointer causes issues when there is no reference to printf in the code? Even this works fine:

#include <stdio.h>    
int main(int argc, const char * argv[]) {
    int (*printfptr)(const char * restrict, ...);
    printfptr = 0x1001fe910;
    (*printfptr)("Hello world\n");
    return 0;
}
void *_ = printf; // <-- because of this

Why is this?

On shared objects (.so) the symbols are really resolved only at the moment of first use. By default the linker sets the option -z lazy which tells:

       When generating an executable or shared  library,  mark  it  to
       tell  the  dynamic  linker to defer function call resolution to
       the point when the function is called  (lazy  binding),  rather
       than at load time.  Lazy binding is the default.

You can change that behaviour by providing option -z now .

man ld for all gory details.

EDIT: Resolving a symbol is done with dynamic link API on POSIX systems. Functions dlsym() , dlopen() , dlclose() and dlerror() defined in <dlfcn.h> . This edition added so that you can search for these names.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM