I am not able to get much information about dynamic loading of DLL files from C++ . I know it does use some functions like LoadLibrary and FreeLibrary with GetProcAddress . But how it works actually internally in the OS perspective like where it actually looks for the DLL file and where it loads like Memory ? can someone help me on that with some diagrams ?
For Win32, loader details are on MSDN. See here.
From your C++ code, you're right (for Windows), you load with ::LoadLibrary and resolve function pointers with ::GetProcAddress. Typically you'll cast the result of GetProcAddress into the type that you know the entry point function to be, and then use it in your program.
For example, if you have a plug-in architecture like a browser, you'd decide what your plug-in directory is, get the filename list for that directory, and call ::LoadLibrary for each DLL (filtering filenames would be up to you). For each, you'd resolve the required entry points with GetProcAddress, store them in a structure for that library, and put them in some plug-in list. Later, you'd call through those function pointers to let the plug-in do its work.
If you specify a relative path (e.g. "foo.dll" rather than "c:\foo.dll"), the OS library search path kicks in. Details at MSDN.
Also, DLLs get loaded into your process's address space. Typically you don't care about where, but in the past, you could get faster load times by "rebasing" your DLLs. I don't think there are any guarantees about how the OS loader places libraries in memory, but you can always get the base address in your process's address space.
Your DLL's entry point (dllmain) can also respond to various messages -- thread attach, process attach -- to do initialization in a sensible way.
DLL search order is described on the MSDN, and there's an article on DLL loading, and two-part article describing PE format (part two here) (they're slightly old, but I don't think they're outdated). Look through MSDN Magazine and MSJ archives and you'll probably find more.
There's two ways to use a DLL. You can load it dynamically at run-time or statically link against it at link-time.
If you load dynamically it using LoadLibrary
, the OS has some mechanism to determine where to look for DLLs. It then attempts to load them. Then you can try to get function pointers to the functions you name (by string or ordinary) and call these functions.
If you link statically, basically the linker adds a reference to the DLL and some jump table with an entry for each of the DLL's functions. When the OS loads your application, it finds references to those DLLs, attempts to load these, and patches the loaded DLL's function's addresses into the jump table. Only then is your application considered loaded and will start.
Note that in reality this is a bit more complicated. For example, DLLs can in turn reference other DLLs. So when the loader loads a DLL, before the DLL can be considered loaded, it will need to (possibly recursively) load other DLLs as well.