Link By Hand

From Devpit
Jump to: navigation, search

Introduction

This page provides an example of generating .o files (from .c and .S files), combining them into a shared object file (.so), linking a main.o file against the shared object file, and verifying that the symbols come from the share object file.

Source Code

The topology of the example is that you have an object file main.o which was compiled from main.c. It gets the symbols function1 and function2 from an external library (a .so file). These functions come from two different object files (function1.o and function2.o which were compiled from two different source files (function1.c and function2.c). The example shows how the function object files are joined into the shared object file and how main.o is linked with the shared object file to generate the test executable.

/* main.c  */
#include <stdio.h>

extern int function1(int param);
extern int function2(int param);

const int a = 32;
const int b = 64;

int main() {
        int add;
        add = function1(a) + function2(b);
        printf("add == %d\n",add); 

        return add;
}
/* function1.c  */
int function1(int param)
{
        param += param - 17;
        return param;
}
/* function2.S */
        .file   "function2.S"
        .section        ".text"
        .align 2
        .globl function2
        .type   function2, @function
function2:
        stwu 1,-32(1)
        stw 31,28(1)
        mr 31,1
        stw 3,8(31)
        lwz 9,8(31)
        lwz 0,8(31)
        add 9,9,0
        addi 0,9,-5
        stw 0,8(31)
        lwz 0,8(31)
        mr 3,0
        lwz 11,0(1)
        lwz 31,-4(11)
        mr 1,11
        blr
        .size   function2,.-function2
        .ident  "GCC: (GNU) 4.1.3 20070803 (test toolchain)"
        .section        .note.GNU-stack,"",@progbits

Compilation

  • Invoke the compiler to make function1.o:
user@system:~/test: gcc function1.c -c
  • Manually invoke the assembler to create function2.o:
user@system:~/test: as function2.S -o function2.o
  • Compile main.c into main.o:
user@system:~/test: gcc main.c -c -o main.o

Create Shared Object File

  • Create the shared object file using function1.o and function2.o:
user@system:~/test: gcc -shared -Wl,-soname,libfunctions.so.1 -o libfunctions.so.1.0.0 function1.o function2.o -lc
  • Create the necessary version symbolic link.
user@system:~/test: ln -s libfunctions.so.1.0.0 libfunctions.so.1

Manually Link and Create Executable

  • Manually link main.o with the function shared object file and create the executable test'.
user@system:~/test: gcc main.o -o test ./libfunctions.so.1.0.0

Run and Test Example

  • Let's run our example. We need to specify the current directory in the library path in order to pick up our new shared object file.
user@system:~/test: LD_LIBRARY_PATH="$PWD:$LD_LIBRARY_PATH" ./test
add == 170
  • Lets check with LD_DEBUG to verify that the symbols are coming from the shared object file that we just created:
user@system:~/test: LD_DEBUG=symbols LD_LIBRARY_PATH="$PWD:$LD_LIBRARY_PATH" ./test 2>&1 | grep function[12]
     13134:     symbol=function1;  lookup in file=./test [0]
     13134:     symbol=function1;  lookup in file=/home/ryanarn/test/libfunctions.so.1 [0]
     13134:     symbol=function2;  lookup in file=./test [0]
     13134:     symbol=function2;  lookup in file=/home/ryanarn/test/libfunctions.so.1 [0]