i mean, if i use some function that is in some dll, and i use it like dll-at-load-time, how the hell then compiler knows at what address this function is. i mean, if i use dll like test.dll and this dll is already in memory, and then run my application, how does my application knows at what address this function is? i mean, it must be like 'jmp to_some_function' but when we compile we dont know at what address this will be...help
For every function you want to call, you have to use the GetProcAddress API to find the location of the procedure.
That is if we use dll like at run time, but if we use dll at load time we dont use GetProcAddress...we just use the name of function, no GetProcAddress at all, so this doesnt answer my question:)
The linker builds an "import table" as part of the EXE. When Windows loads the EXE, it puts the actual address of the procedure in the import table. You can see these entries in the link map. If procedure XYZ expects 3 DWORDS (12 bytes) of operands on the stack, the import table entry will be __imp__XYZ@12 :)
Using the Import Section in the PE file, the linker generates stubs (relocations) in the exe file for the Windows loader to patch at runtime. The loader does this by looking at the HintName and FirstThunk arrays, which are arranged in parallel: function_name <-> RVA. The HintName array stays unchanged, but the loader overwrites the FirstThunk array. Basically, every reference to a dll function in your code points to a thunk entry (i.e., an RVA in the exe file that will be patched); each RVA is associated with the name of a function in the HintName array. The loader gets the actual address of the function from the dll once the dll has been loaded into memory (and mapped to the process address space of your program) and patches in the address. This is nifty -- it means you could have 100 references to dll_funcXXX in your code, but only one patch would be required to handle all of them (as usual with late binding, the price is an extra level of indirection). An obvious consequence of this is: the exe you list and print out from a HEX editor is not yet fit to run; it still has to be loaded into memory and patched by the loader. See the book by Matt Pietrek, Windows 95 System Programming Secrets. This is the best source for the PE file format, and he discusses the HintName and FirstThunk mechanism. This topic also came up a month or two ago in this forum, you can check previous postings (replies by Xmas, Alan Mason) for more information. (Putting the cross-referenced contents of this forum into a chm help file would be nice and is planned.)URL's detailing the coff obj and lib formats were also given; this information is optional but useful in understanding what the compiler and linker do in detail.
The compiler and linker don't know the address. Only the loader knows. The .LIB file associated with the DLL has a DWORD for each DLL function, and the DWORDs will be included into the EXE file if they are referenced. The loader fills in these DWORDs when it loads the DLL. It uses the DLL's export table to calculate the values (function addresses) to store in these DWORDs. Your program invokes the DLL function by either doing a JMP DWORD PTR or a CALL DWORD PTR , where xxxx is the address of the DWORD filled in by the loader. xxxx is known to the linker (via the LIB file) in the form "__imp__xxxx@dd". ===== If CALL/INVOKE xxxx assembles as CALL __imp__xxxx@dd, your program uses the indirect call (CALL DWORD PTR ). If CALL/INVOKE assembles as CALL _xxxx@dd, the linker loads a subroutine _xxxx@dd (from the LIB file) that contains one instruction, an indirect jump (JMP DWORD PTR ).
If you don't have access to Pietrek's book (or even if you do), go to Iczelion's Win32 Tutorial page and read the PE tutorials. Tutorial 6: Import Table will explain this process to you in full detail.