This Time Self-Hosted
dark mode light mode Search

C libraries galore

Seems like it’s that time of the year again when the new glibc is released that will break a bunch of packages (or rather make them fail, given that half of those are actually broken from the start). So this makes it the perfect time to explain what’s going on and why, even though Drepper already explained the changes in glibc 2.10 (and I got to say that while they don’t look tremendously cool, it’s quite interesting to me).

There are quite a few interesting changes for which glibc 2.10 is quite desired, for instance the new (more scalable) malloc implementation, or the new faster string functions for x86-64 (amd64), or for ELF geeks like me the STT_GNU_IFUNC symbol type (that I have yet to understand fully, for now Ruby-Elf is recognizing it but not acting on it). But all this is something that you can read directly on Ulrich’s blog so I won’t write extensively about it.

Instead, as usual, I’m going to write what the problematic changes are that can cause software from not building properly; this time there are mainly two changes that cause a problem, but there are a few more exotic and rare ones: the new POSIX functions, and the extended C++ compliance (given that this implements something that has been specified in the C++ 1998 standard, it should really give a hint on how much well supported C++ is: 11 years to implement a proper disambiguation!).

Many of the new XPG7/POSIX 2008 functions are actually “backports” of GNU extensions; being GNU extensions there is nothing new to the C library, but they are now declared for the C compiler to know about even when the _GNU_SOURCE feature macro is not defined. Since some of these have pretty generic names, when a project define its own version of the function, especially with a different interface, the build is going to error out. I would say that the most common function that is now visible that wasn’t is getline() (which is pretty neat actually to finally have available in POSIX). Since the name is pretty generic, lots of software has implemented one way or another a getline() function, which almost never does the same as the GNU/POSIX function (which reminds me that symbol collisions are bad and that I really should go back at that work one day).

To solve the problem with naming collisions (which, contrary to symbol collisions, are caught by the C compiler and cause the compiler to stop) the solution is to rename the functions themselves; one has to mind, though, that adding an underscore prefix is bad because those are reserved for system symbols and should thus not be used!

The second problem, the one with C++, is actually an error in the code (given that this is actually mandated by the C++ language in 1998), that now gets finally caught by the compiler; while in C casting away the const-ness of a variable only issues a warning by default, in C++ it’s a real mistake. Unfortunately to be useful the C string functions (like strchr() or strstr() accept pointers to constants as parameters and return pointers to variables, because you cannot easily disambiguate between the two. On the other hand, you can disambiguate the two functions in C++, so that they return the same type of pointer than they are given in input, and this is what the new glibc does: returning constants to constants and variables to variables.

Unfortunately there is code out there in the wild, actually pretty common too, that used pointers to variables to collect the returns of string functions called with pointers to constant . This does not technically mean that the code is entirely broken – often times, like in the case of mediatomb, it’s just a matter of not using the proper const modifier on the variable declaration – but sometimes, the brokenness does not cause crashes for I don’t know which reason, since data that is in the read-only memory of the process is tentatively modified.

Up to this point, the problems are mostly trivial and easy to fix; unfortunately it doesn’t stop here; at least in the case of libmp4v2 the problem was an incompatible declaration of the strcasestr() function (which changed prototype for the above-described C++ changes). Turned out the headers always declared strcasestr() to have it visible (if the C library isn’t providing it, they provide their own copy), and obviously that declaration is incompatible with the new ones used by glibc 2.10. Autotools mojo fixed the issue.

So hopefully this post will keep the mind fresh for those who are looking into fixing build failures with glibc-2.10. Have fun!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.