Moved from: bobsql.com
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.
Published Feb 05, 2022
Version 1.0BobDorr
Microsoft
Joined January 13, 2022
SQL Server Blog
Follow this blog board to get notified when there's new activity