问题
Following on from a question about detecting bad linkage to globals across dll boudaries, it turns out that I need to modify a .DEF file generator tool used by the PostgreSQL project so that it correctly emits DATA
tags for .DEF entries for global variables.
Problem
I can't seem to find a way, using Microsoft's tools, to get a symbol table listing that differentiates between global variables and functions, and that includes globals that aren't initialized at their definition site.
Ideas?
Broken current approach
The tool loops over dumpbin /symbols
output to generate the .DEF file. Unlike nm
, which I'm used to, dumpbin /symbols
does not appear to emit an entry for each symbol to indicate the symbol type - function, initialized variable, uninitialized variable. It only shows whether the symbol is locally defined or not.
With each dumpbin
output line followed by the corresponding definition in the .c
file, we have first an initialized global:
00B 00000000 SECT3 notype External | _DefaultXactIsoLevel
int DefaultXactIsoLevel = XACT_READ_COMMITTED;
vs a function with non-static linkage:
022 00000030 SECT5 notype () External | _IsAbortedTransactionBlockState
bool IsAbortedTransactionBlockState(void) {...}
... and for bonus fun, un-initialized globals appear to be shown as UNDEF
, just like references to symbols from other compilation units, e.g:
007 00000004 UNDEF notype External | _XactIsoLevel
int XactIsoLevel;
even though this is pre-declared in the header during compilation (with project specific macro hand expanded for readability) as:
extern __declspec(dllexport) int XactIsoLevel;
So... it looks like dumpbin
output doesn't contain enough information to generate a correct .DEF
file.
Right now gendefs.pl
is merrily spitting out a .DEF
file that omits globals that aren't initialized, and declares everything else as code (by failing to specify CONSTANT
or DATA
in the .DEF). For something so broken, it's worked remarkably well.
Fixing it
To produce correct .DEF files, I need a way to determine which symbols are variables.
I looked at using cl.exe
's /Fm
option, but it's just a passthrough to the linker's /MAP
option, and does nothing when you're just generating an object file, not linking it.
I could use a symbol dump tool that produces more useful information like gcc's nm.exe
, but that adds extra tool dependencies and seems fragile.
At this point I am not able to simply annotate every exported function with PGDLLIMPORT
(the __declspec(dllimport)
/ __declspec(dllexport)
macro used by the project) and stop using a DEF file.
Even if I could I need to find an approach that will cause clear linker errors when PGDLLIMPORT
is omitted on an exposed variable.
So. Windows linker/compiler experts. Any ideas?
回答1:
Well, I must say I was wrong saying that microsoft tools doesn't use symbol type field at all.
1). cl
doesn't use it to differentiate actual type info, but it stores information that you need:
0x20
means function0x00
means not a function
PE/COFF specification, p. 46-47.
You may search for presence/abscence of ()
after symbol type (notype
in your case) in dumpbin
's output to find whether it is code
or data
.
2). Also, cl
generates in obj
files special section for linker which include export
switch for every __declspec(dllexport)
symbol in the form /export:symbol[,type]
.
3). And last, you can specify 'C++' external linkage and get symbols' types because of mangling.
回答2:
I just add to the other post.dumpbin
has a specific option, namely /headers
, that clearly points out the Type as code or data, together with a list of other attributes.
来源:https://stackoverflow.com/questions/21593281/generating-correct-def-files-to-export-non-static-functions-and-globals