2

I'm in a bit of an exceptional situation: I have an application that compiles, links and launches when compiling with MSVC. I'm now in progress of recompiling it clang-cl, which causes it to compile, link and crash.

Thanks to Dependency Walker, I've found that unexpected DLLs are being loaded. In my case to find a symbol for std::allocator<char>::allocator(allocator const &).

With this, I currently have the following information:

  • The DLL requiring this symbol
  • The DLL exposing the symbol
  • The symbol that is giving issues

In order to log a bug, I should be able to reduce the code to an acceptable size. Uploading the whole proprietary code base ain't an option, uploading a 20 line .cpp file is.

To reduce, I need to find the .cpp/.obj-file which requires this symbol. From there, reducing it becomes the easy work.

With this, I'm searching for a way to detect if an .obj file searches for a symbol in a different DLL.

I've already found:

  • dumpbin /SYMBOLS: Tells me where a symbol gets exported
  • dumpbin /DEPENDENTS: Tells me the DLL a DLL depends on

dumpbin /DEPENDENTS states:

Does not dump the names of the imported functions.

How do I dump the names of the imported functions, based on an .obj file?

JVApen
  • 11,008
  • 5
  • 31
  • 67
  • By definition, obj files don't have any "linking" information. That's the linker job to glue all this. From an .obj file, you can only see the names of the symbols the .obj requires. So, you want to focus on why your linker doesn't do what you expect. Have you checked clang-cl arguments for verbose and diag info. – Simon Mourier Dec 26 '18 at 09:48
  • @SimonMourier I'm not sure how to put it differently in words. How do you otherwise call functions you call with having it's implementation? – JVApen Dec 26 '18 at 19:17
  • At object (.obj) level, you only have symbols. Symbols are just names (possibly complex/decorated names, but just names). At linker start time, nothing knows where is the implementation of symbols listed as UNDEF and External (when using `dumpbin /SYMBOLS`). These symbols are just names. The Linker will try to bind these names with the whole pool of obj/dll code it has. BTW, the typical "unresolved symbol' error happens when the linker doesn't find any match between a name and the pool of obj/dll. You're trying to emulate the linker job, that's why I suggest you add diagnostics to the linker. – Simon Mourier Dec 26 '18 at 23:25

2 Answers2

2

dumpbin /symbols is indeed the correct tool for the job as it also lists undefined symbols.

For example, when using dumpbin /symbols to print the symbols in the object file generated from a source file containing

void foo();

void bar() {
    foo();
}

we get

File Type: COFF OBJECT

COFF SYMBOL TABLE
[...]
008 00000000 UNDEF  notype ()    External     | ?foo@@YAXXZ (void __cdecl foo(void))
009 00000000 SECT3  notype ()    External     | ?bar@@YAXXZ (void __cdecl bar(void))
[...]

As you can see, it contains both the symbol for the defined function bar and the symbol for the function foo that is merely declared. The difference is that for bar it says that the symbol can be found in SECT3 wheras for foo it prints UNDEF.

So in order to find all symbols that are imported from somewhere else (e.g. a DLL) you just need to search for UNDEF in the output of dumpbin /symbols.

Corristo
  • 4,911
  • 1
  • 20
  • 36
1

If you use for example

dumpbin /symbols Source.obj >dump.txt

It will dump out the COFF OBJECT and everywhere where it says External and UNDEF the linked needs to find these external symbols.

I created a small example that depends

void foo();
int main()
{
    foo();
}

and can see this in the dump file

01B 00000000 UNDEF  notype ()    External     | ?foo@@YAXXZ (void __cdecl foo(void))

UNDEF and External means that this into will be used by the linker to search for the undefined symbol.

The COFF format is described here

Damian
  • 4,395
  • 4
  • 39
  • 67