I was making a small change to a function: adding to it a couple UINTN auto variables, a new auto EFI_GUID variable, and a handful of changed lines.
Suddenly, the project would no longer compile. I got this error message from the Microsoft linker:
TSEHooks.obj : error LNK2019: unresolved external symbol __chkstk referenced in function Foo
Build\TSE.dll : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: 'C:\WinDDK\7600.16385.1\bin\x86\amd64\LINK.EXE' : return code '0x460'
This surprised me—why is the linker complaining? “unresolved external symbol”—I didn’t add a new function call, and neither did I add an extern reference. Are my linker paths messed up somehow? After burning lots of time trying various wild goose chases I started searching more for this “__chkstk”—what is that?
I started searching Google for help, and found a forum posting with the following comment:
The "chkstk" unresolved external is caused by the compiler checking to see if you've occupied more than (I think 4K on an x86 system) stack space for local variables…Could I have pushed the function over the maximum stack space? As I mentioned, I only added two UNITNs (8B each) and an EFI_GUID (16B) for 32B total.
Looking further I noticed that one of the already existing auto variables in this function was a SETUP_DATA structure variable—the variable type that holds all the BIOS Setup program settings information. This was the problem—there are over 1200 variables contained in this one structure!
After further investigation, I found the following from Microsoft:
My solution was going to be to move the SETUP_DATA variable to file scope with internal linkage, but to my surprise I found someone had already done that! So, there was a file-scope SETUP_DATA variable, and then someone created another automatic SETUP_DATA variable within the scope of one of the functions. Messy! Anyway, it made my job easier—I simply removed the auto copy of SETUP_DATA and the linker error went away.
Called by the compiler when you have more than one page of local variables in your function.
__chkstk Routine is a helper routine for the C compiler. For x86 compilers, __chkstk Routine is called when the local variables exceed 4K bytes; for x64 compilers it is 8K.
1) Microsoft, couldn’t there by a better message for communicating that the function has violated its stack space? Something like:
Stackoverflow in function Foo: Requested X bytes, maximum limit is 8192 bytes
LNK2019: unresolved external symbol __chkstk referenced in function Foo
2) Developers, be on the lookout for usages of the BIOS Setup data structure. I’m guessing it’s probably the largest of all the UEFI variables, and by a good margin.