The Issue
One day, I was wondering how dynamic function call works.
I thought I’d start with a simple puts
call like in this C snippet.
#include <stdio.h>
int main(void) { puts("Hello\n"); }
To see it going through the Procedure Linkage Table (PLT)
in the context of lazy binding on x86_64 Linux LIVE, naturally, LLDB came to my mind.
To my dismay, instead of something relevant to puts
there were only these ugly and unidentifiable ___lldb_unnamed_symbol36
in the disaseembly on LLDB 13.0.0 š« :
In comparison, this is GDB 11.1:
Let’s see how an older version of LLDB is doing.
Here’s LLDB version 12.0.1 š«„:
Apparently, something went wrong between the creation of LLVM version 12 and 13 release branch.
It turned out that it was
a patch landing in July 2021 that changed the behavior.
Someone also filed a GitHub issue just a few days before I found this.
I then commented my findings on the code review page of the seemingly problematic patch.
Finding the culprit
Thankfully, LLDB has a nice “batch mode”, so it’s pretty easy to lauch it in a debugger as shown below. Otherwise I have no idea how to debug an REPL program.
lldb -- ~/llvm-project/build-lldb/bin/lldb -b -o 'image lookup -a 0x401030' a.out
After some debugging of the debugger, I finally knew where the problem was. The aforementioned patch was innocent!
Here’s the whole function added by the patch (comments removed for brevity) that’s seemingly causing the problem:
void Symbol::SynthesizeNameIfNeeded() const {
if (m_is_synthetic && !m_mangled) {
llvm::SmallString<256> name;
llvm::raw_svector_ostream os(name);
os << GetSyntheticSymbolPrefix() << GetID();
m_mangled.SetDemangledName(ConstString(os.str()));
}
}
Let’s focus on the condition of the if statement, m_mangled
is of type Mangled
, so !m_mangled
calls the broken Mangled::operator!
,
which according to git blame, dates back to Apple’s initial open-sourcing LLDB in 2010, untouched, unused, and untested for over a decade.
To my surprise, the implementation of Mangled::operator!
and Mangled::operator void*
differed from the intended behavior documented by comments in the header file.
I then replaced them with one single explicit operator bool
which implements Mangled
’s documented bool semantics.
Now, the disassmbly correctly shows: bringing balance to the Force.
Finally, as per a reviewer’s request, I added unit tests for my new bool conversion operator, which was also my first time using GoogleTest. What a fun ride! The GitHub commit can be found at: https://github.com/llvm/llvm-project/commit/633b002944b9