Starting with SQL Server 2019, SQL Server is built with the COMDAT, ICF linker option enabled, reducing size/space usage. For example: binn\sqllang.dll is ~12MB smaller when COMDAT is enabled.
Use ICF[=iterations] to perform identical COMDAT folding. /OPT:ICF can merge identical data or functions, it can change the function names that appear in stack traces.
I was looking at a strange stack trace, the caller was not coded to invoke the displayed destination function. Here is an example:
class C1
{
public:
GetValue()
{
return m_value;
}
private:
ULONGLONG m_timeStamp;
ULONGLONG m_value;
};
class C2
{
public:
GetId()
{
return m_Id;
}
private:
char m_name[8];
ULONGLONG m_Id;
};
main()
{
C1 localVar;
printf("%lld\n", c1.GetValue());
}
You expect the stack to look like the following when calling C1::GetValue.
C1::GetValue
main
The stack was instead:
C2::GetId()
main
My first thought was there must be an override involved
My second thought was, is there a memory corruption to a vtable
Neither of these issues are the case. The C1::GetValue and the C2:GetId result in the same assembly.
mov rax, [rcx+8];
The linker correctly identified the functions as identical and kept a single copy (C2::GetId) making it look like the call to C1::GetValue was a call to C2:GetId.
The assembly tells the full story as both functions are reading 8 bytes from the base offset of the class and returning 8 bytes. It does not matter that the first 8 bytes of C1 are from the ULONGLONG and the first 8 bytes of C2 are from an array of 8 characters. The memory layout from the base pointer of the object (this, stored in rcx) to the m_value or m_id is identical, allowing the linker to eliminate the duplicate function in the final binary.
Caution: When symbolizing SQL server stack traces keep COMDAT elimination in mind when evaluating the validity of the stack.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.