How It Works: SQL Server Stack Trace – COMDAT Elimination
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:
You expect the stack to look like the following when calling C1::GetValue.
The stack was instead:
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.