So, I recently had need to patch a binary. Due to some poor recording, I couldn’t rebuild the binary from source as I didn’t know what version of the source it was, and this was quite important. It looked like the source had been patched with one or more cherrypicked updates, and recompiled.
So, I was left with a quandary. I needed to change one instance of strcmp to strcasecmp, without breaking everything else and losing the exact patch(es) that had already been applied.
In the end I decided to use LD_PRELOAD and write a replacement for strcmp. It was only going to need to change on one specific search term, and so I could easily test the values passed in (using strcmp ironically) and replace strcmp with strcasecmp in this one specific instance.
However, after writing it, and LD_PRELOADing it, it just didn’t work. The function was there, because I could see debug coming out of it when other shared objects accessed strcmp, but the main executable itself, it just wasn’t having it.
A bit of checking, and some ltrace to prove it, and I found that when you use gcc with optimisation turned on, it inlines strcmp.
Now I know that strcmp is in a library so technically can’t be inlined, but gcc turns out to have its own version of various simple library functions, and substitutes them for the libc versions.
-fno-builtin as a gcc option stops this happening. But without that, you can’t use LD_PRELOAD to affect strcmp. Or several other functions.