I have tried the opposite of the global list: using enumsourcefiles,
walk the compilands down to their elements, but globals do not show up
there (they are restricted to the globals list).
Shouldn't symbol->get_lexicalParent(&parSym) result in obtaining the
compiland that a global variable was culled from?
This must be something I am doing, any ideas?
Pseudocode:
loadPdbFile()
openSession()
getGlobalScope()
WalkChildrenOfGlobalEntry()
-> GetSymbolPtr()
-> PrintInfo()
I have tried the following:
get_lexicalParent, gives NULL
get_container, not available until v8.0 (vs 2005?)
get_sourceFileName, gives NULL
-d
I haven't tried it myself, but heard that IDiaSectionContrib (+IDiaEnumSectionContribs)
was used successfully to get this information. The idea is to enumerate section contributions,
determine which contribution the global variable belongs to (by rva), and get the compiland
from the corresponding IDiaSectionContrib.
Regards,
Oleg
[VC++ MVP http://www.debuginfo.com/]
I gather all the contributing sections and remember their rva and
length. I then walk the globals (SymTagData). If their RVA is within a
selected contributor, I keep it.
You know there is no way to get the size or base type of a global using
DIA? What an odd, quasi-useless interface.
One big problem Im having is that ENUMs do not get an address (of
course), so I have no way of segregating them based on sections.
Any ideas on how to tie an ENUM to a file?
I am trying to pull out ENUMS and globals (structs, vars, etc) from a
.lib. Here is a summary of strange DIA issues:
1) .LIB pdb files contain no globals. You have to create a DLL to get
them.
2) .DLL pdb files contain no way to associate an ENUM with a file
3) .DLL pdb files contain no direct way to associate a global var with
a file.
Im almost to the point where I use the PE/COFF format to pull out
globals from a .LIB, and DIA on the .LIB file for ENUMS (to restrict
enums to their .lib). Not sure what structs and arrays will look like
in the PE format, have to look into that.
What is the tag of that global?
> One big problem Im having is that ENUMs do not get an address (of
> course), so I have no way of segregating them based on sections.
>
> Any ideas on how to tie an ENUM to a file?
>
Most likely it is not possible with debug info interfaces (not possible to tie
a type symbol to the source it came from). Take a look at source browser
interface, may be it can help:
http://www.microsoft.com/downloads/details.aspx?FamilyId=621AE185-1C2A-4D6B-8146-183D66FE709D&displaylang=en
>
> I am trying to pull out ENUMS and globals (structs, vars, etc) from a
> .lib. Here is a summary of strange DIA issues:
> 1) .LIB pdb files contain no globals. You have to create a DLL to get
> them.
Right, .PDB file in this case contains only types.
> 2) .DLL pdb files contain no way to associate an ENUM with a file
> 3) .DLL pdb files contain no direct way to associate a global var with
> a file.
>
I am not sure that I correctly understand what you mean under "ENUMs, globals
(structs, vars, etc)". Could you please post a code sample and list the information
you want to get for it?
Oleg
Thanks again for a reply. I figured out my most pressing need: use
get_typeId to locate the type symbol of a global var. I had tried
get_type, get_baseType, getTypeIds etc. to no avail. Now I know that I
can use DIA for what I am trying to do.
Below is the (entire) source of a .cpp file I created a DLL around in
order to explore the DIA stuff. I am trying to gather all global
variables and enumerations that belong only to select .cpp files of a
given DLL. Ie: not the entire landscape of microsoft vars that got
linked in, but specific to the user's code.
Pretty simple task on the outset. So far the one thing that is
frustrating is the lack of tying an enum to the source file it came
from. Without that, my code ends up pulling out all enums used in and
by the DLL code. This is easy to circumvent by just parsing both the
compiler's vc70.pdb and the linker's dll.pdb file. The former would
give enums restricted to the local code, and the latter will give me
the globals (with a little jokeying) that belong to the local code. It
is inconvenient to have to parse two pdb files but it will do.
=============================
enum
{
DORKO_1 = 0x11223344,
DORKO_2 = 0x55,
} DORKO_ENUM;
enum
{
DORKO_ALONE,
};
int myGlobal1;
int myGlobal2;
char myGlobal3;
struct {
int myMember1;
char myMember2;
} myStruct;
Why not simply collect the list of variables that come from the particular compiland,
walk their types and remember all enums (and other interesting symbols) found
on the way? This should give the list of all types that also came from this compiland.
Oleg
The only area these can be found is as a member of the global symbol's
children.
If there is a way to get these from the .obj compiland that would be
fantastic. Do you know how to do that?
Here is the code I used (quick, sloppy test code) to pull out that
example code (stored in dorko.cpp). I call testDumpFiles
///////////////////////////////////////////////////////////////////////////////////////////////////
void testMain()
{
(... open pdb file, obtain enumsourcefiles ...)
testDumpFiles(fileList);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
int testDumpFiles(CComPtr<IDiaEnumSourceFiles> pFiles)
{
CComPtr<IDiaSourceFile> pFile;
CComPtr<IDiaEnumSymbols> pList;
LONG count;
pFiles->get_Count(&count);
for (int x=0;x<count;x++) {
pFile = NULL;
pFiles->Item(x, &pFile);
pList = NULL;
pFile->get_compilands(&pList);
CComBSTR name;
pFile->get_fileName(&name);
wstring fname = name;
// NOTE: restrict report list to the
sample demo file
if (fname.find(L"dorko\\") != string::npos) {
wcout << L"====== " << name.m_str << endl;
testDumpSymbols(pList, 0);
}
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
int testDumpSymbols(CComPtr<IDiaEnumSymbols> pList, int indent)
{
CComPtr<IDiaEnumSymbols> pChildren;
CComPtr<IDiaSymbol> pSym = NULL;
wstring prepend = L"";
ULONG celt = 0;
// Construct indent string
for (int x=0;x<indent;x++)
prepend += L" ";
while(pList && SUCCEEDED(pList->Next(1, &pSym, &celt)) && celt == 1)
{
DWORD tag;
CComBSTR name;
pSym->get_symTag(&tag);
pSym->get_name(&name);
if (name.Length() == 0)
name = L"?";
wcout << prepend;
printf ("%- 20ws % 2d\n", name.m_str, tag);
if (tag != SymTagFuncDebugStart && tag != SymTagFuncDebugEnd) {
pChildren = NULL;
pSym->findChildren(SymTagNull, NULL, 0, &pChildren);
if (pChildren)
testDumpSymbols(pChildren, indent+4);
}
pSym = NULL;
}
return 0;
}
-d
I am not sure that I properly explained my last idea. I mean that, after you have
determined the variables that belong to the compiland of interest (e.g. via section
contributions), you can walk the type symbols of these variables - starting with
get_type() of the symbol that represents the variable (Data).
While walking the types, you will see the type symbols (like Enum, UDT, etc.)
that originate from this compiland.
Some time ago I wrote an article about accessing type information (in terms of
DbgHelp, but can be applied to DIA too):
http://www.debuginfo.com/articles/dbghelptypeinfo.html
For example, if you have a global variable of type SomeStruct:
// SomeFile.cpp
SomeStruct g_var;
You determine the compiland it belongs to via section contributions,
and start walking its type. IDiaSymbol::get_type on the Data symbol will give
you UDT symbol, which represents SomeStruct, and so on. From this you can
decide that SomeStruct originates from this compiland. The same for other
structs, enums, etc. you find on the way.
Oleg
I understand the type thing fine, but I do not see how the enum
suggestion will work. Can you explain this a bit more? How will I
encounter a all ENUMs in this way? ENUMs do not have an address, so I
cannot tie them to a section. I also cannot assume the user declares a
variable of an enum type either. Given an ENUM's type, I was unable to
track it back to a compiland.
Using this sample code (entire .cpp shown):
enum
{
MYENUM,
};
I could not readily find a way to associate "MYENUM" with a compiland.
-d
If there is no variable of the enum type, the enum itself should not get into debug information.
If there is a variable of the enum type, you can determine the compiland the enum is from
because you can determine the compiland the variable is from.
>
> Using this sample code (entire .cpp shown):
>
> enum
> {
> MYENUM,
> };
>
This enum should not get into debug information.
Oleg
int x;
x = MYENUM;
I don't believe it will do with the standard compiler/linker/etc,
unless you prove it somehow ;)
With special tools it is possible (e.g. like public symbols for Windows DLLs
contain type information), but in that case there is probably no way to determine
the compiland.
> In fact, its common for users to do this as well:
>
> int x;
> x = MYENUM;
>
The type of this variable will be BaseType/btInt in the debug info, no sign of enum.
But as soon as you declare a variable of the enum type, it becomes possible to find
the variable and use its type information to correlate the enum with the compiland.
Oleg