Discussion:
dbgHelp stackwalk needs rebase
(too old to reply)
Gabriel
2004-09-16 14:01:36 UTC
Permalink
Hi!

I am implementing a StackWalker with the aid of dbgHelp.dll. A typical
process in our system depends on around 15 dlls (excluding MS and 3rd
party dlls). All dlls have the same preferred base address which means
they will be relocated by the OS.

I have two problems that I really can't solve nor understand:

1. Using StackWalk64 I don't get a complete callstack but only the
first two functions are resolved. It appears that the module lookup in
the callback fails for the other functions. But if I rebase all dlls
(ie distributing their load addresses) the complete call stacks
suddenly shows. I can't really understand why. An older version of
dbgHelp didn't have this problem.

My implementation is more or less a copy of the MFC dito, DbgHelp is
just a wrapper class for the dbgHelp.dll api

DWORD64 CALLBACK DbgHelp::getModuleBase(HANDLE process, DWORD64
address)
{
IMAGEHLP_MODULE64 moduleInfo;
moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
DWORD64 rc = 0;

// Check if present already
if(DbgHelp::instance()->SymGetModuleInfo64(address, &moduleInfo))
{
rc = moduleInfo.BaseOfImage;
}
else
{
// Find out the name of the module at requested address
MEMORY_BASIC_INFORMATION memoryBasicInfo;

if(::VirtualQueryEx(process, reinterpret_cast<void*>(address),
&memoryBasicInfo, sizeof(MEMORY_BASIC_INFORMATION)))
{
char file[MAX_PATH] = { 0 };
const DWORD cch = ::GetModuleFileNameA(
static_cast<HINSTANCE>(memoryBasicInfo.AllocationBase),
file, MAX_PATH);

// Load the module
DbgHelp::instance()->SymLoadModule64(0, cch ? file : 0, 0, 0, 0);
rc = reinterpret_cast<DWORD64>(memoryBasicInfo.AllocationBase);
}
}

return rc;
}

2. Since our app log the call stack quite frequently I would like to
just collect the stack addresses and do the symbol lookup at a later
stage. I would like to skip is the SymLoadModule64() in the code above
and move it to another part of the code. But doing this severly
cripples the stack as well, is StackWalk dependendant on the modules
being loaded in order to untangle the rest of the stack?

System:
Windows 2000 SP 4
Visual C++ 6.0 SP 5
DbgHelp.dll version 6.3.17.0 (latest)
Oleg Starodumov
2004-09-16 15:10:23 UTC
Permalink
Post by Gabriel
// Load the module
DbgHelp::instance()->SymLoadModule64(0, cch ? file : 0, 0, 0, 0);
}
Try to pass the module's base address in the fourth parameter
(the value of memoryBasicInfo.AllocationBase).
Post by Gabriel
2. Since our app log the call stack quite frequently I would like to
just collect the stack addresses and do the symbol lookup at a later
stage. I would like to skip is the SymLoadModule64() in the code above
and move it to another part of the code. But doing this severly
cripples the stack as well, is StackWalk dependendant on the modules
being loaded in order to untangle the rest of the stack?
Yes, if the last address returned by StackWalk is in a function optimized with FPO,
symbols for the module should be loaded to read FPO data of the function
and be able to walk the stack further.

Regards,
Oleg
Gabriel
2004-09-17 07:55:39 UTC
Permalink
Post by Oleg Starodumov
Post by Gabriel
// Load the module
DbgHelp::instance()->SymLoadModule64(0, cch ? file : 0, 0, 0, 0);
}
Try to pass the module's base address in the fourth parameter
(the value of memoryBasicInfo.AllocationBase).
That didn't seem to do any harm at least, haven't been able to do a
full test yet though...
Post by Oleg Starodumov
Post by Gabriel
2. Since our app log the call stack quite frequently I would like to
just collect the stack addresses and do the symbol lookup at a later
stage. I would like to skip is the SymLoadModule64() in the code above
and move it to another part of the code. But doing this severly
cripples the stack as well, is StackWalk dependendant on the modules
being loaded in order to untangle the rest of the stack?
Yes, if the last address returned by StackWalk is in a function optimized with FPO,
symbols for the module should be loaded to read FPO data of the function
and be able to walk the stack further.
Ok, that explains it, we have FPO in our release builds so I guess
we're forced to load the module here then...

Thanks!

My next problem is that stresstesting the functionality seem to
produce some odd behaviour. Getting the callstack first thing in the
main thread is no problem, trying to get the callstack first thing in
a worker thread cripples it. The thread is completely synchronized
with the main thread, ie no simultaneous calls to dbgHelp API is made.
Any ideas of where to dig?

TIA,

Gabriel
Gabriel
2004-09-20 17:46:23 UTC
Permalink
Post by Gabriel
My next problem is that stresstesting the functionality seem to
produce some odd behaviour. Getting the callstack first thing in the
main thread is no problem, trying to get the callstack first thing in
a worker thread cripples it. The thread is completely synchronized
with the main thread, ie no simultaneous calls to dbgHelp API is made.
Any ideas of where to dig?
Cockpit error! I retreived the thread context in one function and used it in
another.

// Gabriel
Gabriel
2004-09-20 17:40:31 UTC
Permalink
Post by Oleg Starodumov
Post by Gabriel
// Load the module
DbgHelp::instance()->SymLoadModule64(0, cch ? file : 0, 0, 0, 0);
}
Try to pass the module's base address in the fourth parameter
(the value of memoryBasicInfo.AllocationBase).
That didn't help, the wierd thing is that in some cases I still can resolve
symbols, but the modulenames don't show...

// Gabriel
Oleg Starodumov
2004-09-21 08:57:26 UTC
Permalink
Post by Gabriel
Post by Oleg Starodumov
Post by Gabriel
// Load the module
DbgHelp::instance()->SymLoadModule64(0, cch ? file : 0, 0, 0, 0);
}
Try to pass the module's base address in the fourth parameter
(the value of memoryBasicInfo.AllocationBase).
That didn't help, the wierd thing is that in some cases I still can resolve
symbols, but the modulenames don't show...
Try these things:

1. Check that symbols are really loaded (e.g. call SymGetModuleInfo64 after
loading symbols for a module and check IMAGEHLP_MODULE64.SymType
to see what symbols are loaded).
Also, does SymLoadModule64 return the correct base address?

2. Enable SYMOPT_DEBUG option and see the resulting output while loading symbols
and walking the call stack. Will there be something explaining the problem,
or at least something strange? Will there be a difference between the cases
with and without rebasing?

3. Check return values of all functions, and GetLastError codes in case of failure.
What exactly does fail, where and when?

Oleg
Gabriel
2004-09-20 17:40:42 UTC
Permalink
Post by Oleg Starodumov
Post by Gabriel
// Load the module
DbgHelp::instance()->SymLoadModule64(0, cch ? file : 0, 0, 0, 0);
}
Try to pass the module's base address in the fourth parameter
(the value of memoryBasicInfo.AllocationBase).
That didn't help, the wierd thing is that in some cases I still can resolve
symbols, but the modulenames don't show...

// Gabriel
Gabriel
2004-09-20 17:43:22 UTC
Permalink
Post by Oleg Starodumov
Post by Gabriel
// Load the module
DbgHelp::instance()->SymLoadModule64(0, cch ? file : 0, 0, 0, 0);
}
Try to pass the module's base address in the fourth parameter
(the value of memoryBasicInfo.AllocationBase).
That didn't help... The wierd thing is that in some cases I still can
resolve symbols, but modules doesn't show...

// Gabriel
h***@gmail.com
2013-07-29 10:08:12 UTC
Permalink
Hi, Gabriel, I encountered the same problem as you, that I can't get the complete stack. Have you solve this problem?
Loading...