I've been using dumpbin
recently to see symbols in some static libraries using dumpbin foo.lib /symbols
. I wanted to see how it could be used for executables and DLLs.
My first observation is that dumpbin foo.{exe|dll} /symbols
returns nothing.
For DLLs, I observed that the exports option was necessary to get symbol data:
dumpbin foo.dll /exports
. Why is this option necessary in this case? If the corresponding *.iobj file is available, I can use dumpbin foo.iobj /symbols
dumps ALL symbols whereas /exports on the DLL I assume only shows the symbols that are exposed by the DLL.
For executables, dumpbin bar.exe /symbols
produces nothing, where as dumpbin bar.exe /exports
seems to dump some symbols.
Can anyone explain what's going on under the hood here?
The arguments you're using to dumpbin tell it which sections of the file to dump out.
The reason you need to use different arguments is that you're looking at pieces of data that happen to resemble each other really closely, but (from a PE file point of view) are entirely different pieces of data that are stored in different sections of the file.
So, when you create an object file, it defines some symbols, and those go in to the symbols section of the PE file. When you link those to create a DLL/exe file, any symbols it exports create records in the exports section of the file. From our viewpoint, those look similar (in fact, an exported name will usually be the name of some symbol that was in the symbols section of some object file), but it's still stored in a different section.
When the compiler does its thing, it writes data into the symbols section, but (at least usually) doesn't create an imports or exports section at all. Then the linker does its thing, mostly reading from the symbols section, and writing to the imports and exports sections. Then the loader does its thing, mostly reading from the imports and exports sections, and ignoring the symbols section.