During my last project I had to work with some libraries pre-loaded on systems, they didn't work as I wanted, but I couldn't change the system version. What to do? Live patch your libraries!
- LD_PRELOAD
- This is widely used by softwares that just want to run unmodified programs with unmodified libraries, but using different functions than libraries provides. As an example, ALSA does that by intercepting
open()
, read()
and friends from LibC with a new version that check if filename is some OSS device and then route these through ALSA. This method is pretty simple and the base for others: just create a new library with functions to override and put it in higher precedence in linker or export environment variable LD_PRELOAD pointing to these library before running the application (this have the highest precendence). If you still want to use the previous (overrided) function then you must use dlopen()
and load the original library and then dlsym()
to get the original symbol. - Have the functions in your application
- If you have your function in your own application, it will have higher precedence over libraries and will work just as LD_PRELOAD. Actually this is the same thing.
- When it doesn't work...
- Sometimes this just doesn't work, in my case it didn't work when I tried to override
gtk_image_set_from_file()
but use it from g_object_set()
with a property that calls that function internally. My guess on why this doesn't work is because function call and declaration were in the same object and thus compiler may have inlined or did some other optimization. In this case you have to find an alternative solution and in my case was a even bigger hack:
- Get an instance of
GtkImageClass
(use GTK_IMAGE_GET_CLASS()
)
- Declare my own
gtk_image_ser_property()
which remember the old setter (((GObjectClass*)GtkImageClass)->set_property
) and call it if property was something different than the one that call our desired function.
- Have the class to use our setter with
((GObjectClass*)GtkImageClass)->set_property = my_gtk_image_set_property;
If you have another live patching technique you want to share, just post a comment!
Yes, you read it right: GLib is a technical disaster. After some time working with it, both using, building upon and hacking its internals, you can see the mess.
One thing that really piss me off is people that, instead of solving problems, create more problems that they call a "work-around". GLib just do that: compiler-aided OO languages were badly supported in GCC? Let's fix GCC? No, let's create OO atop C, using a lot of pre-processor, make things cumbersome, error-prone, ... POSIX and its GNU/LibC implementation lacks features? Let's create a whole new string, list and hash implementation! Oh, and do not forget that missing printf()
, make it g_print()
!
I'm not a C++ enthusiast, but I do think it or ObjectiveC or any other compiler-aided Object Oriented language would help. Anyone that already implemented GObject subclasses know what I'm talking about. The very first thing you'll notice is that you have to copy and paste too much code, but still have to change little bits here and there, making the process error-prone. Then you have the pre-processor macros and if you already worked with them or read Linux kernel position on it, you know it's a mess and should be avoided. And how about a dynamic type system using C? Yes, GLib does have that, making things slower, bigger and impossible to compiler to optimize virtual-tables and dispatchers! And back to GCC, it's now good enough and improving support for OO languages, but GLib/GObject will win nothing, GCC still handle it as regular procedural code.
Insanity doesn't stop there, some Software Engineer Guru wanted to have "private" fields and yes, they also did it, even worse: they seem to incentive that! Any experienced hacker must know that this is just bullshit... and when you're dealing with barebone C, where you have direct access to memory, you just think "they're playing jokes". Let's suppose you could protect memory regions, why would you protect it? Against developers? Why? This idea must came from a non-programmer, because any programmer should know what to do and this just make debugging and testing more difficult. But let's face it: C doesn't offer any way to protect memory regions, so all you have to do is to have pointer to an area and use it... but they like the ClassNamePrivate, that just make things bigger, slower and painful to debug. If Operating System Kernels, that deals with critical data, don't do any fancy stuff to "protect" it, why GLib guys do?
Still looking how BSDs and Linux relates to GLib and GObject, you can see that the kernels have saner implementation of linked lists, trees and hash tables. They also have clever Object Oriented code (vfs and others). Weird enough, hacking Linux or BSDs kernels are much easier when you compare easy-of-use and consistency of APIs.
How about namespaces and method resolution? Why would I use a language that supports that? It's so cool to use gtk_label_set_text()
or filling your mind with Object Hierarchies! Of course it's gtk_misc_get_padding()
if I'm dealing with a GtkLabel
. When using these functions you may also opt to use casts and make it even more error prone or to use those GTK_LABEL()
-like macros, that do function calls and some branches.
Just to make it clear: I know other languages and libraries have problems too. Qt is another good example on how-to-not-fix-the-proper-problem: stl is broken, let's re-implement it! Why use namespaces, it's just one letter! Let's require user to pre-process their code (moc). However any of these are excuse, GLib has is a technical disaster because it tries to solve the wrong problem.