Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SymGetSymFromAddr returns incorrect symbol name

834 views
Skip to first unread message

Steve Richter

unread,
Jul 15, 2004, 3:02:18 PM7/15/04
to
I am using SymGetSymFromAddr and StackWalk to retrieve the call stack
of a thread in another process. When I ran my code on a thread in the
current process the function names in the call stack were correct.
When I ran the same code on a thread in another process, names were
returned, but they were incorrect.

The cause turned out to be the symbol search path I was passing to
::SymInitialize( ). I was always specifying the current directory of
the process running my StackWalk code instead of the current directory
of the process whose call stack was being walked. ( the hProcess
passed to SymInitialize( ))

Why was SymGetSymFromAddr so easily confused? If it does not return
an error code in such an situation how can I ever be sure the
information is correct?

thanks,

-Steve

Oleg Starodumov

unread,
Jul 16, 2004, 4:58:31 AM7/16/04
to

> Why was SymGetSymFromAddr so easily confused? If it does not return
> an error code in such an situation how can I ever be sure the
> information is correct?
>

You can analyze what kind of symbols is loaded for the modules in question,
and base your decision on the presence of "good" symbols ("good" means
"good enough for the task you are trying to accomplish").
Or you can show the information about loaded symbols to the user and let him
decide whether he trusts the call stack with the available quality of symbols.

See SymGetModuleInfo64 function and IMAGEHLP_MODULE64 structure.

Also, SYMOPT_DEBUG option can provide additional insight into the process
of loading symbols (both for you and for your users).

Regards,
Oleg


shilpig

unread,
Jul 20, 2004, 2:33:34 AM7/20/04
to
I have a query related to SymGetSymFromAddr.

The SymGetSymFromAddr functions works fine on Win 2000 but returns FALSE
on Win Xp. Why?

pls mail me at shilpig at momentum-tech dot com

Thanx in advance

Oleg Starodumov

unread,
Jul 20, 2004, 4:57:29 AM7/20/04
to

> The SymGetSymFromAddr functions works fine on Win 2000 but returns FALSE
> on Win Xp. Why?
>

1) What error code is returned by GetLastError ?

2) Check which version of DbgHelp.dll is used on both systems.

DbgHelp.dll is redistributable, so you can always have the latest version
with your application. The latest version is included with Debugging Tools
for Windows package:
http://www.microsoft.com/whdc/ddk/debugging/default.mspx

3) Check what kind of symbols is loaded for the module. Check if loaded symbols
differ in Win2000 and XP.

Enable SYMOPT_DEBUG option and see what DbgHelp thinks about symbol
load process (by default, it will use debug output; you can also provide a callback
function using SymRegisterCallback64).

You can also use SymGetModuleInfo64 to obtain information about symbols
loaded for the module.

4) If you write a new code (but do not maintain something old), consider using
newer function SymFromAddr instead of SymGetSymFromAddr.

Regards,
Oleg


Saurabh Agarwal

unread,
Jul 21, 2004, 6:55:32 AM7/21/04
to
"Oleg Starodumov" <oleg_...@hotmail.com> wrote in message news:<#gxF3ejb...@TK2MSFTNGP12.phx.gbl>...

> > The SymGetSymFromAddr functions works fine on Win 2000 but returns FALSE
> > on Win Xp. Why?
> >
>
> 1) What error code is returned by GetLastError ?

It returns - #126 ( The specified module could not be found.
ERROR_MOD_NOT_FOUND)


> 2) Check which version of DbgHelp.dll is used on both systems.
>
> DbgHelp.dll is redistributable, so you can always have the latest version
> with your application. The latest version is included with Debugging Tools
> for Windows package:
> http://www.microsoft.com/whdc/ddk/debugging/default.mspx

I have downloaded the latest version of dbghelp.dll (6.3.17.0) and
copied this file in the system directory on both the OS. Still the
result is - My program is working on Win2K but it fails (126) on
Winxp.

> 3) Check what kind of symbols is loaded for the module. Check if loaded symbols
> differ in Win2000 and XP.
>
> Enable SYMOPT_DEBUG option and see what DbgHelp thinks about symbol
> load process (by default, it will use debug output; you can also provide a callback
> function using SymRegisterCallback64).
>
> You can also use SymGetModuleInfo64 to obtain information about symbols
> loaded for the module.

How will I do this?

> 4) If you write a new code (but do not maintain something old), consider using
> newer function SymFromAddr instead of SymGetSymFromAddr.

SymFromAddr doesnt work.

> Regards,
> Oleg

My Code is :

#include <stdio.h>
#include <stdlib.h>
#include "windows.h"
#include <process.h>
#include <imagehlp.h>

union SYMBUFFER
{
IMAGEHLP_SYMBOL sym;
BYTE buffer [ sizeof (IMAGEHLP_SYMBOL) + 512 ];
};

unsigned int level = 0;
CONTEXT context;
STACKFRAME frame;
union SYMBUFFER symbol;
IMAGEHLP_MODULE module;
char modulename [512];
DWORD section;
DWORD offset;
HANDLE handle;

#pragma comment( lib, "imagehlp.lib" )

int main()
{
if (! SymInitialize (GetCurrentProcess (), NULL, TRUE))
{
printf("failed to dump stack trace: cannot get symbolic
information\n");
return -1;
}

// FIXME: XP 64-bit adds: RtlCaptureContext (&context);
// This is documented to *not* work, but apparently it does.
context.ContextFlags = CONTEXT_FULL;
if (! GetThreadContext (GetCurrentThread (), &context))
return -1;

memset (&module, 0, sizeof (module));
memset (&frame, 0, sizeof (frame));

module.SizeOfStruct = sizeof (module);

frame.AddrPC.Offset = context.Eip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Esp;
frame.AddrStack.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;

if (! StackWalk (IMAGE_FILE_MACHINE_I386,
GetCurrentProcess (),
GetCurrentThread (),
&frame,
&context,
NULL,
SymFunctionTableAccess,
SymGetModuleBase,
NULL)
|| frame.AddrFrame.Offset == 0)
{
printf("StackWalk fail\n");
return -1;
}

// Print stack frame too? If we know how many arguments there
// are (from demangling function name -- see below, could count
// commas), args are: *((ULONG *)frame.AddrFrame.Offset+2+ARG).
printf ("(%2u) 0x%08lx 0x%08lx\n", level, frame.AddrPC.Offset,
frame.AddrFrame.Offset);

memset (&symbol, 0, sizeof (symbol));
symbol.sym.SizeOfStruct = sizeof (symbol);
symbol.sym.MaxNameLength = sizeof (symbol) - sizeof (symbol.sym);

offset = 0;
handle = GetCurrentProcess ();
if (! SymGetSymFromAddr (handle, frame.AddrPC.Offset, &offset,
&symbol.sym))
{
printf("SymGetSymFromAddr fail\n");
return -1;
}

printf("%s", symbol.sym.Name);
printf (" + %lx", offset);

return 0;
}

Oleg Starodumov

unread,
Jul 21, 2004, 7:14:29 AM7/21/04
to

> I have downloaded the latest version of dbghelp.dll (6.3.17.0) and
> copied this file in the system directory on both the OS.

Dbghelp.dll is protected by Windows File Protection,
so you cannot replace it in the system directory - it will be
replaced by an older version almost immediately (see Event Log
to verify it).

You should store Dbghelp.dll in the same directory with your application -
then your application will be able to use the latest version.
(That's why SymFromAddr does not work, too).

I will take a look at the code later today.

Regards,
Oleg


Oleg Starodumov

unread,
Jul 21, 2004, 8:49:15 AM7/21/04
to

> It returns - #126 ( The specified module could not be found.
> ERROR_MOD_NOT_FOUND)
>

Now it seems to be clear. The application calls GetThreadContext to obtain
the context for StackWalk, and since it is a system call, the first (and only) frame
returned by StackWalk will have its EIP point to the system call stub
which does not belong to any module. Therefore SymGetSymFromAddr
responds with the given error.

This behaviour is different in Windows 2000 and XP, because of the new
way to call system services in XP. (In Win2000, the first frame returned
by StackWalk will usually belong to NTDLL.DLL, and SymGetSymFromAddr
is usually able to find the symbol)

If this application would continue calling StackWalk after the first call,
it would probably encounter good symbols for subsequent frames.


> > You can also use SymGetModuleInfo64 to obtain information about symbols
> > loaded for the module.
>
> How will I do this?
>

Call the function to obtain module information into IMAGEHLP_MODULE64 structure.

The latest documentation is also with Debugging Tools for Windows
(choose custom setup, install SDK and find the help file in sdk\help folder).

Regards,
Oleg


Saurabh Agarwal

unread,
Jul 26, 2004, 1:10:30 AM7/26/04
to
> If this application would continue calling StackWalk after the first call,
> it would probably encounter good symbols for subsequent frames.


I tried doing this. But thst too didnt gave me correct output.
My sample code is:

module.SizeOfStruct = sizeof (module);

while( TRUE )
{


if (! StackWalk (IMAGE_FILE_MACHINE_I386,
GetCurrentProcess (),
GetCurrentThread (),
&frame,
&context,
NULL,
SymFunctionTableAccess,
SymGetModuleBase,
NULL)
|| frame.AddrFrame.Offset == 0)
{
printf("StackWalk fail\n");

break;
}

// Print stack frame too? If we know how many arguments there
// are (from demangling function name -- see below, could count
// commas), args are: *((ULONG *)frame.AddrFrame.Offset+2+ARG).
printf ("(%2u) 0x%08lx 0x%08lx\n", level, frame.AddrPC.Offset,
frame.AddrFrame.Offset);

memset (&symbol, 0, sizeof (symbol));
symbol.sym.SizeOfStruct = sizeof (symbol);
symbol.sym.MaxNameLength = sizeof (symbol) - sizeof (symbol.sym);

offset = 0;
handle = GetCurrentProcess ();
if (! SymGetSymFromAddr (handle, frame.AddrPC.Offset, &offset,
&symbol.sym))
{
printf("SymGetSymFromAddr fail\n");
}

else
{


printf("%s", symbol.sym.Name);
printf (" + %lx", offset);
}
}

getch();
return 0;
}


The output on Win 2k:
( 0) 0x77f9be6 0x0012ff80
ZwGetContextThread + b( 0) 0x00401549 0x0012ffc0
mainCRTStartup + e9( 0) 0x7c5987e7 0x0012fff0
ProcessIdToSessionId + 17dStackWalk fail

The output on Win XP:
( 0) 0x7ffe0304 0x0012ff80
SymGetSymFromAddr fail
( 0) 0x00401549 0x0012ffc0
SymGetSymFromAddr fail
( 0) 0x77e814c7 0x0012fff0
SymGetSymFromAddr fail
GetCurrentDirectoryW + 44StackWalk fail

Pls note that I have copied the latest dbghlp.dll (918k of
version-6.3.17.0) in the debug directory (path which contains my
executables).

Pls guide me. This is becoming critical.

Thanx in Advance.
Shilpi

Oleg Starodumov

unread,
Jul 26, 2004, 5:51:22 AM7/26/04
to

> #pragma comment( lib, "imagehlp.lib" )
>

Your application does not use Dbghelp.dll.

Change the pragma shown above to use dbghelp.lib,
and configure include and lib paths so that they find
the Debugging Tools SDK \inc and \lib\i386 directories
before any other directories.


> The output on Win 2k:
> ( 0) 0x77f9be6 0x0012ff80
> ZwGetContextThread + b( 0) 0x00401549 0x0012ffc0
> mainCRTStartup + e9( 0) 0x7c5987e7 0x0012fff0
> ProcessIdToSessionId + 17dStackWalk fail
>
> The output on Win XP:
> ( 0) 0x7ffe0304 0x0012ff80
> SymGetSymFromAddr fail
> ( 0) 0x00401549 0x0012ffc0
> SymGetSymFromAddr fail
> ( 0) 0x77e814c7 0x0012fff0
> SymGetSymFromAddr fail
> GetCurrentDirectoryW + 44StackWalk fail
>

I suspect that on WinXP it simply cannot find symbols for the executable.
Make sure that you copy the application's symbols (.PDB file, if you use it)
to that system along with the executable.

DbgHelp can provide an additional insight into the process
of loading symbols:

After you have linked the application to Dbghelp.dll,
include the following code _before_ the call to SymInitialize():

DWORD dwOptions = SymGetOptions();
dwOptions |= SYMOPT_DEBUG;
SymSetOptions( dwOptions );

Then run the application on Windows XP under debugger and check
messages with "DBGHELP:" prefix in Debug Output window.

If SymGetSymFromAddr still continues to fail, please post the complete
contents of Debug Output window on Windows XP (with the mentioned
"DBGHELP: xxx" messages).

Regards,
Oleg


Steve Richter

unread,
Jul 26, 2004, 8:25:48 AM7/26/04
to
saga...@momentum-tech.com (Saurabh Agarwal) wrote in message news:<19675a56.04072...@posting.google.com>...

> > If this application would continue calling StackWalk after the first call,
> > it would probably encounter good symbols for subsequent frames.
>
>
> I tried doing this. But thst too didnt gave me correct output.
> My sample code is:
> #include <stdio.h>
> #include <stdlib.h>
> #include "windows.h"
> #include <process.h>
> #include <imagehlp.h>

First thing I would do is change Imagehlp to DbgHelp. Then use the
StackWalk64 api instead of StackWalk. The documentation says that
Stackwalk64 supercedes Stackwalk.

http://msdn.microsoft.com/library/en-us/debug/base/stackwalk64.asp?frame=true

-Steve

Saurabh Agarwal

unread,
Jul 27, 2004, 5:20:08 AM7/27/04
to
Changing the pragma to use dbghelp.lib, instead of imagehlp.lib and
keeping dbghlp.dll in debug directory solved the problem on win XP.

Thanx everybody, esp Oleg

0 new messages