A last-minute patch for 0.51 and a conference this Sunday

Hello there, some people reported our current 0.51 build experiences issue on newer Linux distributions. An easy way to patch your downloaded game is provided right below. There is also a conference this Sunday that will be viewable online.

Conference this Sunday for Debian

We are participating in the current MiniDebConf Online Gaming Edition hosted by Debian.

MDCO Gaming edition logo

So, on Sunday November 22th (tomorrow) at 19:30 UTC there will be a 45 minutes conference entitled:

Building a community as a service: how to stop suffering from “that code is meant to be forked”

Here is the fourth cover:

Earlier id Tech engines were well known to have seen their source code opened when they were replaced and thus unprofitable. While this was a huge benefit for mankind, game developers still suffer today from design choices and mindset induced by the fact such code base was meant to die. 20 years later we will focus on id Tech 3 heritage, how both the market, open source communities and development practices evolved, and embark in the journey of the required transition from dead code dump to an ecosystem as a service.

I’ll be the speaker, the live stream is there.

If you miss the appointment, don’t worry! The video will be available online after the broadcast, and a full transcript will be published.

How to patch your game if you have trouble running it on recent Linux distribution

Issue was confirmed on Fedora, Arch Linux, Debian testing (Debian stable not having the problem) and derivatives. As distributions are shipping updates, more are likely to break.

The symptom is easy to notice: the game segfaults immediately at startup before being able to do anything. Yes that’s pretty bad.

TL,DR: if you experience the bug, here is an easy way to download a patcher:

wget http://dl.unvanquished.net/hotfix/unvanquished_0.51.1_patch
chmod +x unvanquished_0.51.1_patch

Then you can run the game with the patcher this way:

./unvanquished_0.51.1_patch daemon

This will work out of the box if you’ve downloaded and installed the game using our game updater with default options. If you’ve used the universal zip, the easier for you is to store the patcher right to the daemon binary and run it from that directory. granger

The patcher is a launcher that patches a copy of the binary then runs it (and leaves the broken one unmodified). So until 0.52 is out, use this simple launcher.

You can also pass daemonded as parameter to patch and run the server, you can pass all the usual game command line options after that.

It’s also possible to rebuild the binaries, but that involves more work and on our side we are focusing on the upcoming 0.52 release.

People just wanting to fix definitely their binaries can do this (better make a backup before!):

printf '\x8b\x74\x24\x20\x48\x31\xc0\x85\xf6\x0f\x94\xc0\xeb\x3f' \
    | dd of=daemon bs=1 seek=2186551 count=14 conv=notrunc
printf '\x8b\x74\x24\x20\x48\x31\xc0\x85\xf6\x0f\x94\xc0\xeb\x3f' \
    | dd of=daemonded bs=1 seek=738855 count=14 conv=notrunc

More details about the problem, if you like to dive deep into the matrix


Daemon patch wizardry uncovered, reading the matrix without decoder.
Daemon patch wizardry uncovered, reading the matrix without decoder.

Yes, this is true witchcraft. For geeky geeks, here are some explanations from our master wizard slipher:

The crash is caused by a mistake or shortcoming in the implementation of the “Dual ABI” concept in libstdc++. For this bug, the relevant dual-ABI class is std::error_category (which has the dual ABI because it has a member function returning an std::string). Following this commit, stdlibc++ defines two versions of error_category. For new builds, the headers point to the new version which is defined in an inline namespace _V2. The inline namespace changes the mangled name of symbols in compiled code, while there is no change to source code which uses error_category.

The 0.51 release was apparently built with GCC 4.9, which predates the introduction of the dual ABI. This means it gets linked to the backwards-compatibility symbols when using new solibs. A build using GCC 5+ should have the headers pointing at the new ABI, and thereby avoid the problem (it links to std::_V2::system_category() and avoids constructing any backwards-compatibility objects). So nothing need be done to avoid the problem in new releases (although I’ll remove the call to default_error_condition in any case, since it does not make sense to use it).

I reproduced the crash using libstdc++.so.6.0.28; I believe libstdc++.so.6.0.21 should be the first version that contains the dual ABI changes and therefore risks hitting the bug.

And here he gave more explanations again:

I doubt there is anything to be done on the libstdc++ side. It is probably impossible to make a build that can work with both of the error_category ABIs, and the new one has been out for a long time now.

The conjecture from my previous comment that it depends on the random value in the RDX register at the time of the call to error_category::equivalent (which was supposed to be a call to error_category::default_error_condition) was correct. On Mageia, RDX happened to contain a readable address, while on Debian Buster it contained 4.

Now error_category::default_error_condition is supposed to return an error_condition struct consisting of an integer code and a pointer to an error_category. The ABI dictates that the integer code goes in RAX and the pointer in RDX. error_category::equivalent returns a boolean which goes in RAX. It returns false, having compared against random junk. And it so happens that in this solib build, the last thing that gets put in RDX by error_category::equivalent is the address of std::system_category(), an instance of error_category. So by pure luck, a valid and correct error_condition is returned and the train is back on the rails.

I could make a binary patch for the 0.51 daemon to bypass the problem by replacing a few instructions in CreateCrashDumpPath, if it would be helpful.

This is really helpful of indeed, so he wrote that dd spell and you can do it yourself or use the patcher.

And you can still play Unvanquished while waiting for 0.52! battlesuit

One thought on “A last-minute patch for 0.51 and a conference this Sunday”

Comments are closed.