[DbgHelp] SymEnumSymbolsW schlägt fehl, ERROR_SUCCESS

Cromon

Erfahrenes Mitglied
Hallo zusammen!

Um bei meinem Programmen erweiterte Fehlermeldungen anzeigen zu können liefere ich mit ihnen auch die PDB mit und verwende die Funktionen der DbHelp-API um mit der PDB einfacher arbeiten zu können.

Nun finde ich mich aber in einem Problem mit SymEnumSymbolsW wieder. In meinem ersten Entwurf habe ich frühe Bindung (denke nicht, dass das terminologisch korrekt ist :p) über die .lib, die standardmässig bei Visual Studio dabei ist (dbhelp.lib) verwendet und die normale dbghelp.dll daran gebunden, die bei Windows dabei war. Dabei hat mein Code eigentlich wunderbar funktioniert, ausser dass ich bei SymGetTypeInfo mit TI_GET_NAME LocalFree im Buffer nicht verwenden konnte, obwohl die Dokumentation sagte, dies müsse so getan werden:
Code:
case SymTagPointerType:
	{
		LPVOID value = *(LPVOID*)(frame.AddrFrame.Offset + inf->Address);
		DWORD subType = 0;
		SymGetTypeInfo(GetCurrentProcess(), inf->ModBase, inf->TypeIndex, TI_GET_TYPE, &subType);
		SymGetTypeInfo(GetCurrentProcess(), inf->ModBase, subType, TI_GET_SYMTAG, &tag);
		switch(tag)
		{
		case SymTagUDT:
			{
				LPWSTR symName = NULL;
				BOOL ret = SymGetTypeInfo(GetCurrentProcess(), inf->ModBase, subType, TI_GET_SYMNAME, &symName);
				if(symName == NULL || !ret)
				{
					msg << _T("unkPtr* ") << inf->Name << _T(" = ") << value;
					break;
				}
#ifdef UNICODE
				msg << symName << _T("* ") << inf->Name << _T(" = ") << value;
#else
				int len = wcslen(symName) + 1;
				char* symTmp = new char[len];
				WideCharToMultiByte(CP_ACP, 0, symName, len, symTmp, len, NULL, NULL);
				msg << symTmp << _T("* ") << inf->Name << _T(" = ") << value;
				delete [] symTmp;
#endif
				LocalFree(symName);
			}
			break;
		}
	}
	break;

Bei LocalFree tratt eine Zugriffsverletzung ein. Da ich viel gelesen habe, dass die neusten Versionen der dbhelp.dll verwendet werden sollen und nicht die, die normal bei Windows dabei sind habe ich mir die von Microsoft heruntergeladen und zu meiner Applikation gepackt. Ein Blick in den Debugger ergab, dass dann auch wirklich diese geladen wurde. Nun, das war unschön, denn nun hat SymEnumSymbolsW nicht mehr funktioniert:
Code:
IMAGEHLP_STACK_FRAME curFrame;
curFrame.InstructionOffset = pSymbol->Address;

if(SymSetContext(GetCurrentProcess(), &curFrame, NULL))
{
	MethodInfo inf = { strm, i };
	BOOL ret = SymEnumSymbolsW(GetCurrentProcess(), 0, NULL, GetFunction(), &inf);
	DWORD dwCode = GetLastError();
}

ret -> FALSE
dwCode -> ERROR_SUCCESS

Das ist natürlich merkwürdig, habe ich doch überhaupt nichts am Code geändert. Meine erste Überlegung war, dass es sein kann, dass ich ja mit einer möglicherweise inkompatiblen lib früh gebunden habe und bin umgestiegen auf späte Bindung:
Code:
	HMODULE hMod = LoadLibrary(_T(".\\dbghelp.dll"));
	pSymInitialize = (tSymInitialize)GetProcAddress(hMod, "SymInitializeW");
	pSymFromAddrW = (tSymFromAddrW)GetProcAddress(hMod, "SymFromAddrW");
	pSymFromAddr = (tSymFromAddr)GetProcAddress(hMod, "SymFromAddr");
	pSymGetLineFromAddrW64 = (tSymGetLineFromAddrW64)GetProcAddress(hMod, "SymGetLineFromAddrW64");
	pSymGetLineFromAddr = (tSymGetLineFromAddr)GetProcAddress(hMod, "SymGetLineFromAddr");
	pSymSetContext = (tSymSetContext)GetProcAddress(hMod, "SymSetContext");
	pSymEnumSymbolsW = (tSymEnumSymbolsW)GetProcAddress(hMod, "SymEnumSymbolsW");
	pSymGetTypeInfo = (tSymGetTypeInfo)GetProcAddress(hMod, "SymGetTypeInfo");
	pStackWalk = (tStackWalk)GetProcAddress(hMod, "StackWalk");
	pSymGetModuleBase = (tSymGetModuleBase)GetProcAddress(hMod, "SymGetModuleBase");
	pSymFunctionTableAccess = (tSymFunctionTableAccess)GetProcAddress(hMod, "SymFunctionTableAccess");

Ich habe ausserdem die library nicht mehr gelinkt und alle Funktionsnamen angepasst. Das laden der Exports hat soweit auch tiptop funktioniert, wie ich mit dem Debugger erkennen konnte, alle Zeiger sind gut initialisiert. Es gilt jedoch weiterhin:
ret -> FALSE
GetLastError() -> ERROR_SUCCESS
und die Callbackfunktion wird nie aufgerufen...

Ich bin mittlerweile echt ratlos!

Gruss
Cromon
 
Zuletzt bearbeitet:
Hi.

Wenn du sowieso keine Maske angibst, dann verwende doch einfach die SymEnumSymbols Funktion.

Der Fehlercode wird sonst leider durch den Aufruf einer anderen WinAPI Funktion (HeapFree) innerhalb von SymEnumSymbolsW maskiert.

Gruß
 
Es liegt nicht nur an der Maske, dass ich SymEnumSymbolsW verwenden, sondern auch am Callback. Bei SymEnumSymbols muss diese PSYMBOL_INFO als Parameter haben, bei SymEnumSymbolsW PSYMBO_INFOW. Werde aber mal schauen, ob es mit SymEnumSymbols geht und ggf. dann meinen Code so umstrukturieren, dass ich umwandle, falls nötig.
 
Ich habe es mir gerade zum Anlass genommen meine Klasse fertig für Unicode und ANSI abzuschliessen und die entsprechenden Definitionen eingefügt. Es funktioniert jetzt zwar mit ANSI und UNICODE aber die Tatsache, dass so wohl SymEnumSymbols als auch SymEnumSymbolsW beide FALSE zurückgeben ist leider noch immer vorhanden. Die Adresse scheint ja zu stimmen, denn ich erhalte den Namen der Funktion an der Adresse ohne Probleme. Also erstelle ich mit SymSetContext einen korrekten Kontext meiner Funktion. Ich muss mal schauen, ob ich mit dem Debugger noch bisschen weiter rein komme in SymEnumSymbols :)
 
Ich habe es mir gerade zum Anlass genommen meine Klasse fertig für Unicode und ANSI abzuschliessen und die entsprechenden Definitionen eingefügt. Es funktioniert jetzt zwar mit ANSI und UNICODE aber die Tatsache, dass so wohl SymEnumSymbols als auch SymEnumSymbolsW beide FALSE zurückgeben ist leider noch immer vorhanden.
Das war zu erwarten. ;)

Was sagt GetLastError() bei SymEnumSymbols?

Gruß
 
Dabei erhalte ich weiterhin 0 als letzten Fehler. Warum das so ist habe ich jetzt über den Debugger auch herausgefunden. Am Anfang der Funktion wird der Code auf 0 gesetzt und anschliessend wird SetLastError nie mehr aufgerufen. Zudem habe ich gesehen, dass auch durchwegs Symbole gefunden werden, aber aus irgendeinem Grund das Callback nie aufgerufen.
 
Zurück