I'd like to see which functions in a static library will be exported if linked into a dll. How do I do this?
int foo(int i)
{ return i + 1; }
__declspec(dllexport) int bar(int i)
{ return i + 1; }
dumpbin /symbols mylib.lib
yields the same information for both functions.
00A 00000000 SECT4 notype () External | ?foo@@YAHH@Z (int__cdecl foo(int))
00B 00000020 SECT4 notype () External | ?bar@@YAHH@Z (int __cdecl bar(int))
How can I know that bar()
will be exported but foo()
will not?
Q1)
How do you identify exported functions in a Windows static library?
That is one question, and:
Q2)
I'd like to see which functions in a static library will be exported if linked into a dll. How do I do this?
is a different question.
Q2
Taking Q2 first: You cannot tell, by any inspection of a static library, which global symbols defined in it (including DLL exports) will be linked into an arbitrary DLL if that static library is input to its linkage. To demonstrate:
foo.c
__declspec(dllexport) int foo(int i) { return i + 1; }
bar.c
__declspec(dllexport) in bar(int i) { return i + 1; }
foomain.c
#include <windows.h>
__declspec(dllexport) int foo(int i);
BOOLEAN WINAPI DllMain( IN HINSTANCE hDllHandle,
IN DWORD nReason,
IN LPVOID Reserved )
{
return foo(1) == 2;
}
barmain.c
#include <windows.h>
__declspec(dllexport) int bar(int i);
BOOLEAN WINAPI DllMain( IN HINSTANCE hDllHandle,
IN DWORD nReason,
IN LPVOID Reserved )
{
return bar(1) == 2;
}
Compile all those source files:
>cl /c foo.c bar.c foomain.c barmain.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
foo.c
bar.c
foomain.c
barmain.c
Generating Code...
Now make a static library containing foo.obj
and bar.obj
:
>lib /out:foobar.lib foo.obj bar.obj
Microsoft (R) Library Manager Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Next, link a DLL with inputs foomain.obj
and foobar.lib
:
>link /out:foo.dll /dll foomain.obj foobar.lib
Microsoft (R) Incremental Linker Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Creating library foo.lib and object foo.exp
Lastly, link another DLL with inputs barmain.obj
and, again, foobar.lib
>link /out:bar.dll /dll barmain.obj foobar.lib
Microsoft (R) Incremental Linker Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Creating library bar.lib and object bar.exp
Both of the functions, foo
and bar
, defined within foobar.lib
, are declared
dllexport
. Let's see what symbols are exported by foo.dll
:
>dumpbin /exports foo.dll
Microsoft (R) COFF/PE Dumper Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file foo.dll
File Type: DLL
Section contains the following exports for foo.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00001030 foo
Summary
2000 .data
6000 .rdata
1000 .reloc
B000 .text
Just foo
, not bar
.
And what are the exports of bar.dll
?
>dumpbin /exports bar.dll
Microsoft (R) COFF/PE Dumper Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file bar.dll
File Type: DLL
Section contains the following exports for bar.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00001030 bar
Summary
2000 .data
6000 .rdata
1000 .reloc
B000 .text
Just bar
, not foo
.
Whether foo
or bar
, or both, or neither, will be linked from foobar.lib
into
an executable or DLL depends on what object files not within static libraries are also
in the linkage.
The static library foobar.lib
is simply an archive (in Unix ar
archive format)
of object files (foo.o
, bar.o
) that you can offer to the linker from which to
select the ones it needs, if any, to carry on the linkage of an executable or DLL. The linker
extracts just those object files from the archive and inputs them to the linkage, exactly
as if you had named them individually in the linker commandline and not mentioned the static
library at all.
The object files that the linker will need to extract from a static library are those that provide definitions for unresolved references that accrue from other object files that must be linked.
So the linkage of foo.dll
proceeds like this:
foomain.obj
is linked because an object file named in the commandline is linked unconditionally.
The linkage of foomain.obj
gives rises to an unresolved reference to foo
.
So foobar.lib
is searched for an object file that defines foo
.
The archive member foobar.lib(foo.obj)
is found to provide a definition of foo
, so it is extracted and linked into foo.dll
.
The other archive member foobar.lib(bar.obj)
provides no definitions for any unresolved references, so it is not extracted or linked.
The linkage:
>link /out:foo.dll /dll foomain.obj foobar.lib
is exactly the same as:
>link /out:foo.dll /dll foomain.obj foo.obj
And likewise, the linkage:
>link /out:bar.dll /dll barmain.obj foobar.lib
is exactly the same as:
>link /out:bar.dll /dll barmain.obj bar.obj
A static library contributes nothing to a linkage except the object files that are picked out of it, and the ones that are picked out, if any, depend on the other object files in the linkage. In this light you can see that Q2 amounts to:
If I have some object files in which are are defined symbols some declared dllexport
, and some not, how can I tell which of the symbols will be exported from a DLL, given that 0 or more of those object files are linked into it?
How long is a piece of string? You need to be given the actual linkage of some actual DLL to be able to determine what its DLL exports will be.
Back to Q1
In the same light, Q1 amounts to:
How do you identify exported functions in a Windows object file?
That must be possible, because the linker does it.
We inspected the DLL exports of foo.dll
by running:
>dumpbin /exports foo.dll
and it reported foo
. dumpbin /exports FILE
is the way we'd usually interrogate
the DLL exports of a FILE
that is a DLL or program. It shows us the symbols in
the dynamic symbol table of FILE
.
dumpbin
knows that a static libary is just a bag of object files. So
>dumpbin /symbols foobar.lib
shows us the same two symbol tables as:
>dumpbin /symbols foo.obj bar.obj
i.e.
COFF SYMBOL TABLE
000 010463CB ABS notype Static | @comp.id
001 80000191 ABS notype Static | @feat.00
002 00000000 SECT1 notype Static | .drectve
Section length 3C, #relocs 0, #linenums 0, checksum 67EAC832
004 00000000 SECT2 notype Static | .debug$S
Section length 6C, #relocs 0, #linenums 0, checksum 0
006 00000000 SECT3 notype Static | .text$mn
Section length B, #relocs 0, #linenums 0, checksum B38E4E30
008 00000000 SECT3 notype () External | _bar
String Table Size = 0x0 bytes
COFF SYMBOL TABLE
000 010463CB ABS notype Static | @comp.id
001 80000191 ABS notype Static | @feat.00
002 00000000 SECT1 notype Static | .drectve
Section length 3C, #relocs 0, #linenums 0, checksum 1D7A1E73
004 00000000 SECT2 notype Static | .debug$S
Section length 6C, #relocs 0, #linenums 0, checksum 0
006 00000000 SECT3 notype Static | .text$mn
Section length B, #relocs 0, #linenums 0, checksum B38E4E30
008 00000000 SECT3 notype () External | _foo
String Table Size = 0x0 bytes
Likwise:
>dumpbin /exports foobar.lib
reports the same DLL exports - namely none - as:
>dumpbin /exports foo.obj bar.obj
And it must be none because an object file has no dynamic symbol table.
A dynamic symbol table is generated by the linker. So only files produced by the linker can possess one. That means a DLL or executable. Not an object file, which is produced by the compiler and consumed by the linker.
The linker records in the dynamic symbol table of a DLL or executable the
global symbols that are qualified dllexport
in the object files that were actually linked.
Thus, foo.dll
exports foo
because foo
is qualfied as dllexport
in the archive
member foobar.lib(foo.obj)
which was linked into foo.dll
. It does not export
bar
, although bar
is also qualified dllexport
in foobar.lib(bar.obj)
because that object file was not linked into foo.dll
So the linker detects that foo
is qualified as dllexport
in foo.obj
and
on that basis adds foo
to the dynamic symbol table of foo.dll
.
That qualification takes the simple form of a linker directive that the compiler embeds
in foo.obj
instructing the linker to export the symbol foo
for dynamic linkage.
The compiler emits that linker directive because the source code declares foo
with __declspec(dllexport)
. And the linker will obey that directive, if it links
foo.obj
, by adding foo
to the dynamic symbol table. You could build the same foo.dll
without using __declspec(dllexport)
at all in the source code and instead giving
the linker flag /export:foo
yourself in the linker commandline.
You can therefore detect the dllexport
qualification of foo
by asking dumpbin
to show
you the linker directives that the compiler has inscribed in foo.obj
:
>dumpbin /directives foo.obj
Microsoft (R) COFF/PE Dumper Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file foo.obj
File Type: COFF OBJECT
Linker Directives
-----------------
/DEFAULTLIB:LIBCMT
/DEFAULTLIB:OLDNAMES
/EXPORT:_foo <-- This
Summary
6C .debug$S
3C .drectve
B .text$mn
And similarly:
>dumpbin /directives bar.obj
Microsoft (R) COFF/PE Dumper Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file bar.obj
File Type: COFF OBJECT
Linker Directives
-----------------
/DEFAULTLIB:LIBCMT
/DEFAULTLIB:OLDNAMES
/EXPORT:_bar <-- And this
Summary
6C .debug$S
3C .drectve
B .text$mn
So:
>dumpbin /directives foobar.lib
Microsoft (R) COFF/PE Dumper Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file foobar.lib
File Type: LIBRARY
Linker Directives
-----------------
/DEFAULTLIB:LIBCMT
/DEFAULTLIB:OLDNAMES
/EXPORT:_bar
Linker Directives
-----------------
/DEFAULTLIB:LIBCMT
/DEFAULTLIB:OLDNAMES
/EXPORT:_foo
Summary
D8 .debug$S
78 .drectve
16 .text$mn
reports the same two exports as:
>dumpbin /directives foo.obj bar.obj
and that is the answer to Q1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With