Date: | July 24, 2006 / year-entry #246 |
Tags: | other |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20060724-00/?p=30403 |
Comments: | 9 |
Summary: | If a function is declared with the dllimport declaration specifier, this instructs the Visual Studio C/C++ compiler that the function in question is an imported function rather than a normal function with external linkage. With this additional information, the compiler generates slightly different code when it needs to reference an imported function, since the compiler... |
If a function is declared with the
First, there is no need for the stub function any more,
because the compiler can generate the special
mov ebx, [__imp__FunctionName] push 1 call ebx ; FunctionName(1) push 2 call ebx ; FunctionName(2)
(Note to crazy people:
This optimization means that you can run into problems
if you patch a module's import table once it has started
running, because the function pointer may have been
optimized into a register before you patched the import.
Consider, in the above example. that you patched the
Similarly, if your program tries to take the address of an imported
function that has been declared with the As a result of this extra knowledge imparted to the compiler, the stub function is no longer needed; the compiler knows to go straight to the imported function address table. Note that there are still occasional circumstances wherein you can induce the stub function to be created. We'll take a look at them (and related dangers) next time. |
Comments (9)
Comments are closed. |
Is there a reason these ‘imp‘ functions don’t show up in ‘dumpbin /exports’, or am I just looking at the wrong dlls?
I ask because I’m generating some .coff files myself, and functions are linking fine but pointers to structs aren’t resolving properly. I thought dumpbin.exe output would be definitive, and everything looks good there, but it looks like I might need to look at the raw data.
@Grant: the imp function dont show up in the dumpbin, because they dont exist in the Dll. They exist only in the .lib
Hmmm.. so it turns "a = &b;" into "a = *_imp_b;"? I can be pretty sure people have lost a lot of hair trying to debug his programs and realizing the compiler was changing the code behind their backs… nice trick anyhow ^^
Antonio: I’d expect the register optimisation Raymond describes is only done for Release builds, not Debug.
Uh – oh. Finally it makes sense what Jeffery Richter wrote in his book ("Advanced Windows Programming"), when elaborating about thread injection and getting an address of the function stub. Thank you, Raymond.
When you ask C to do things it can’t.
The patching would still be safe if it was done from inside the function at the original address and was idempotent.
(In other words: if calling the old function through the cached address in the register simply resulted in it being patched again and then the new function being called)
Ooops – checked again, and it was there in all it’s glory:
#if !defined(USER32)
#define WINUSERAPI DECLSPEC_IMPORT
#else
#define WINUSERAPI
#endif
Last time I checked I noticed onl the empty definition branch. There aredefinitely advantages to those who can read :-)
Seems like the typical define you make for building vs. consuming a DLL.