How It Works: SQL Server Stack Trace – COMDAT Elimination

How It Works:​​ SQL Server Stack Trace – COMDAT​​ Elimination

 

 

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.

  • Bob Dorr