Linking

References

Overview

Example C Program

Linking

Linking
Linking

Why Linkers?

Why Linkers?

What Do Linkers Do?

Symbols in Example C Program

What Do Linkers Do?

Three Kinds of Object Files (Modules)

Executable and Linkable Format (ELF)

ELF Object File Format

ELF
ELF

ELF Object File Format

ELF Object File Format (Continued)

Linker Symbols

Symbol Identification

Local Symbols

How the Linker Resolves Duplicate Symbol Definitions

Linker Symbol Rules

Global Variables

Type Mismatch Error

Use of extern Example

Use of extern Example (Continued)

Relocation Entries

Relocation Entries

Libraries: Packaging a Set of Functions

One Solution: Static Libraries

Creating Static Libraries

Commonly Used Libraries

Using Static Libraries

Using Static Libraries

linux> gcc -static -o prog -L. -lstuff main.o 
main.o: In function `main':
main.c:(.text+0x19): undefined reference to `thing'
collect2: error: ld returned 1 exit status

Another Solution: Shared Libraries

Shared Libraries

What Dynamic Libraries Require?

Dynamic Linking at Load Time

Shared Libraries
Shared Libraries

Dynamic Linking at Run Time

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];

int main(int argc, char** argv)
{
    void *handle;
    void (*addvec)(int *, int *, int *, int);
    char *error;

    /* Dynamically load the shared library that contains addvec() */
    handle = dlopen("./libvector.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        exit(1);
    }
    ...

Dynamic Linking at Run Time (Continued)

    ...

    /* Get a pointer to the addvec() function we just loaded */
    addvec = dlsym(handle, "addvec");
    if ((error = dlerror()) != NULL) {
        fprintf(stderr, "%s\n", error);
        exit(1);
    }

    /* Now we can call addvec() just like any other function */
    addvec(x, y, z, 2);
    printf("z = [%d %d]\n", z[0], z[1]);

    /* Unload the shared library */
    if (dlclose(handle) < 0) {
        fprintf(stderr, "%s\n", dlerror());
        exit(1);
    }
    return 0;
}

Linking Summary

Case Study: Library Interpositioning

Some Interpositioning Applications

Example Program

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
  int i;
  for (i = 1; i < argc; i++) {
    void *p =
          malloc(atoi(argv[i]));
    free(p);
  }
  return(0);
}

Example Program

Compile Time Interpositioning

Compile Time Interpositioning

#ifdef LINKTIME
#include <stdio.h>

void *__real_malloc(size_t size);
void __real_free(void *ptr);

/* malloc wrapper function */
void *__wrap_malloc(size_t size)
{
    void *ptr = __real_malloc(size); /* Call libc malloc */
    printf("malloc(%d) = %p\n", (int)size, ptr);
    return ptr;
}

/* free wrapper function */
void __wrap_free(void *ptr)
{
    __real_free(ptr); /* Call libc free */
    printf("free(%p)\n", ptr);
}
#endif

Load/Run Time Interpositioning

#ifdef RUNTIME
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

/* malloc wrapper function */
void *malloc(size_t size)
{
    void *(*mallocp)(size_t size);
    char *error;

    mallocp = dlsym(RTLD_NEXT, "malloc"); /* Get addr of libc malloc */
    if ((error = dlerror()) != NULL) {
        fputs(error, stderr);
        exit(1);
    }
    char *ptr = mallocp(size); /* Call libc malloc */
    printf("malloc(%d) = %p\n", (int)size, ptr);
    return ptr;
}

Load/Run Time Interpositioning

/* free wrapper function */
void free(void *ptr)
{
    void (*freep)(void *) = NULL;
    char *error;

    if (!ptr)
        return;

    freep = dlsym(RTLD_NEXT, "free"); /* Get address of libc free */
    if ((error = dlerror()) != NULL) {
        fputs(error, stderr);
        exit(1);
    }
    freep(ptr); /* Call libc free */
    printf("free(%p)\n", ptr);
}
#endif

Load/Run Time Interpositioning

Interpositioning Recap

Linking Recap