An argument for symbol versioning

Sat, 03 Oct 2009 15:19:02 +0200
stuff-to-remember

A little example for why it is nice to have symbol versioning in libraries. Safe the following as test.sh. Call without arguments: segfault; call with argument "half": segfault; call with argument "both": works.

#!/bin/sh
cat >s1.h <<EOF
extern void test(int *);
#define DO(x) test(x)
EOF
cat >libs1.c <<EOF
#include <stdio.h>
#include "s1.h"

void test(int *a) {
	printf("%d\n", *a);
}
EOF
cat >libs1.map <<EOF
S_1 {
 global:
  test;
};
EOF
cat >s2.h <<EOF
extern void test(int);
#define DO(x) test(*x)
EOF
cat >libs2.c <<EOF
#include <stdio.h>
#include "s2.h"

void test(int a) {
	printf("%d\n", a);
}
EOF
cat >libs2.map <<EOF
S_2 {
 global:
  test;
};
EOF
cat >a.h <<EOF
void a(void);
EOF
cat >liba.c <<EOF
#include "s.h"
#include "a.h"

void a(void) {
	int b = 4;
	DO(&b);
}
EOF
cat > test.c <<EOF
#include "a.h"
#include "s.h"

int main() {
	int b = 3;
	DO(&b);
	a();
	return 0;
}
EOF
rm -f liba.so libs.so* test s.h
if test $# -le 0 || test "x$1" != "xboth" ; then
gcc -Wall -O2 -shared -o libs.so.1 -Wl,-soname,libs.so.1 libs1.c
else
gcc -Wall -O2 -shared -o libs.so.1 -Wl,-soname,libs.so.1 -Wl,-version-script libs1.map libs1.c
fi
if test $# -le 0 ; then
gcc -Wall -O2 -shared -o libs.so.2 -Wl,-soname,libs.so.2 libs2.c
else
gcc -Wall -O2 -shared -o libs.so.2 -Wl,-soname,libs.so.2 -Wl,-version-script libs2.map libs2.c
fi
ln -s libs.so.1 libs.so
ln -s s1.h s.h
gcc -Wall -O2 -shared -o liba.so -Wl,-soname,liba.so liba.c -L. -ls
gcc -Wall -O2 test.c -L. -ls -la -o test
rm libs.so s.h
ln -s libs.so.2 libs.so
ln -s s2.h s.h
gcc -Wall -O2 -shared -o liba.so -Wl,-soname,liba.so liba.c -L. -ls
LD_LIBRARY_PATH=. ./test