glibc 2.7, HLDS, and CentOS 5»

We have a number of CentOS 5 (specfically, CentOS 5.9) machines at work. There’s nothing terribly wrong with them, they were just installed before CentOS 6 was offically released. End of life for CentOS 5 isn’t until 2014, so we haven’t felt significant pressure to upgrade (and there’s not a whole lot of benefit to us for doing so).

Today, Valve released an update for Counter-Strike. Among all the changes, they switched to GCC 4.6, which brings with it a dependency on glibc 2.7. This is somewhat of a problem for us, as CentOS 5 is only shipping with glibc 2.5.

This means when I tried to start the updated server, I saw the following error:


Error:/lib/libc.so.6: version `GLIBC_2.7' not found (required by ./engine_i486.so)

We had a couple options here:

So, the first step here is to figure out how to compile and run two versions of glibc on a machine. Compiling is no problem, it’s a pretty standard configure; make; make install. The only tricky bit here is CentOS 5 ships with a very old version of GCC and binutils. So, I had to install gcc44 and compile a newer version of binutils. After that, it was just a matter of:

CFLAGS='-march=i686 -O2' CC=gcc44 CXX=gcc44-c++ ../configure --prefix=/home/glibc215 \
 --with-binutils=/home/newbinutils/bin/ && make -j 4 && make install

If it’s not obvious there, I’m using glibc 2.15 instead of 2.17. 2.16 and 2.17 require kernel headers from a kernel newer then what we’re using. I could have grabbed a newer kernel and just used it for the headers, but I didn’t need to be running the latest version of glibc.

So, now I’ve got a fresh version of glibc sitting in /home/glibc215 and i just need a way to convince the server to run it. Most of the suggestions I found were to edit the binary and make it use the newer version. That’s not really great for us, as we’d have to edit the binary again after every update. Rather then do this, I decided to just call ld-linux.so.2 directly for the new exe. To maintain compatibility with the default launcher script (hlds_run), I created a simple wrapper script:

#!/bin/bash
/home/glibc215/lib/ld-linux.so.2 --library-path /home/glibc215/lib/:. ./hlds_linux $*

Then, I made hlds_run use this wrapper instead of the server (via the -binary command line argument). I was pretty happy when the server started up perfectly! This was pretty important to solve, as the other Half Life 1 games are going to be upgraded in this manner in the next couple months.