applied patch: stack-backtrace support on linux; use new DebugHelp API on win32

git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@89 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
spog 2006-07-09 14:27:06 +00:00
parent 7a43e1720c
commit 1f0b5c5c86
5 changed files with 69 additions and 32 deletions

View file

@ -4,6 +4,9 @@ that we distribute with the binaries. (see changelog)
09/07/2006 09/07/2006
Shaderman Shaderman
- Updated win32 libxml2 package to 2.6.24. - Updated win32 libxml2 package to 2.6.24.
namespace
- Ported win32 stack-backtrace to use new DebugHelp API.
- Added stack-backtrace functionality for Linux/OSX.
11/06/2006 11/06/2006
SPoG SPoG

View file

@ -559,6 +559,7 @@ radiant_src = [
'renderer.cpp', 'renderer.cpp',
'renderstate.cpp', 'renderstate.cpp',
'scenegraph.cpp', 'scenegraph.cpp',
'stacktrace.cpp',
'select.cpp', 'select.cpp',
'selection.cpp', 'selection.cpp',
'server.cpp', 'server.cpp',

View file

@ -169,8 +169,8 @@ CCFLAGS = '-DPOSIX -DXWINDOWS ' + warningFlags
CXXFLAGS = '-pipe -DPOSIX -DXWINDOWS ' + warningFlags + warningFlagsCXX CXXFLAGS = '-pipe -DPOSIX -DXWINDOWS ' + warningFlags + warningFlagsCXX
CPPPATH = [] CPPPATH = []
if (BUILD == 'debug'): if (BUILD == 'debug'):
CXXFLAGS += '-g -D_DEBUG ' CXXFLAGS += '-g3 -D_DEBUG '
CCFLAGS += '-g -D_DEBUG ' CCFLAGS += '-g3 -D_DEBUG '
elif (BUILD == 'release' or BUILD == 'final'): elif (BUILD == 'release' or BUILD == 'final'):
CXXFLAGS += '-O2 ' CXXFLAGS += '-O2 '
CCFLAGS += '-O2 ' CCFLAGS += '-O2 '

View file

@ -24,6 +24,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "environment.h" #include "environment.h"
#ifdef __linux__
#include <execinfo.h>
void write_stack_trace(TextOutputStream& outputStream)
{
const unsigned int MAX_SYMBOLS = 256;
void* symbols[MAX_SYMBOLS];
// get return addresses
int symbol_count = backtrace(symbols, MAX_SYMBOLS);
if(!symbol_count)
return;
// resolve and print names
char** symbol_names = backtrace_symbols(symbols, symbol_count);
if(symbol_names)
{
for(int i = 0; (i < symbol_count); ++i)
outputStream << symbol_names[i] << "\n";
// not a memleak, see www.gnu.org/software/libc/manual (Debugging Support, Backtraces)
free(symbol_names);
}
}
#endif
#if defined (WIN32) && defined (_MSC_VER) #if defined (WIN32) && defined (_MSC_VER)
#include "windows.h" #include "windows.h"
@ -80,19 +107,20 @@ inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const
struct EnumerateSymbolsContext struct EnumerateSymbolsContext
{ {
STACKFRAME& sf; STACKFRAME64& sf;
TextOutputStream& outputStream; TextOutputStream& outputStream;
std::size_t count; std::size_t count;
EnumerateSymbolsContext(STACKFRAME& sf, TextOutputStream& outputStream) : sf(sf), outputStream(outputStream), count(0) EnumerateSymbolsContext(STACKFRAME64& sf, TextOutputStream& outputStream) : sf(sf), outputStream(outputStream), count(0)
{ {
} }
}; };
void write_symbol(PSYMBOL_INFO pSym, STACKFRAME& sf, TextOutputStream& outputStream, std::size_t& count) void write_symbol(PSYMBOL_INFO pSym, STACKFRAME64& sf, TextOutputStream& outputStream, std::size_t& count)
{ {
if ( pSym->Flags & SYMFLAG_PARAMETER )
{
#if 0 #if 0
if ( pSym->Flags & SYMFLAG_PARAMETER )
{
DWORD basicType; DWORD basicType;
if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex, if ( SymGetTypeInfo( GetCurrentProcess(), pSym->ModBase, pSym->TypeIndex,
TI_GET_BASETYPE, &basicType ) ) TI_GET_BASETYPE, &basicType ) )
@ -139,7 +167,6 @@ void write_symbol(PSYMBOL_INFO pSym, STACKFRAME& sf, TextOutputStream& outputStr
int bleh = 0; int bleh = 0;
} }
} }
#endif
if(count != 0) if(count != 0)
{ {
outputStream << ", "; outputStream << ", ";
@ -147,6 +174,7 @@ void write_symbol(PSYMBOL_INFO pSym, STACKFRAME& sf, TextOutputStream& outputStr
outputStream << pSym->Name; outputStream << pSym->Name;
++count; ++count;
} }
#endif
} }
BOOL CALLBACK BOOL CALLBACK
@ -174,33 +202,44 @@ void write_stack_trace(PCONTEXT pContext, TextOutputStream& outputStream)
return; return;
} }
STACKFRAME sf; STACKFRAME64 sf;
memset( &sf, 0, sizeof(sf) ); memset( &sf, 0, sizeof(sf) );
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Mode = AddrModeFlat;
#ifdef _M_IX86 #ifdef _M_IX86
// Initialize the STACKFRAME structure for the first call. This is only // Initialize the STACKFRAME structure for the first call. This is only
// necessary for Intel CPUs, and isn't mentioned in the documentation. // necessary for Intel CPUs, and isn't mentioned in the documentation.
sf.AddrPC.Offset = context.Eip; sf.AddrPC.Offset = context.Eip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Offset = context.Esp; sf.AddrStack.Offset = context.Esp;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Offset = context.Ebp; sf.AddrFrame.Offset = context.Ebp;
sf.AddrFrame.Mode = AddrModeFlat;
dwMachineType = IMAGE_FILE_MACHINE_I386; dwMachineType = IMAGE_FILE_MACHINE_I386;
#elif _M_X64
sf.AddrPC.Offset = context.Rip;
sf.AddrStack.Offset = context.Rsp;
// MSDN: x64: The frame pointer is RBP or RDI. This value is not always used.
// very funny, we'll try Rdi for now
sf.AddrFrame.Offset = context.Rdi;
dwMachineType = IMAGE_FILE_MACHINE_AMD64;
#endif #endif
const unsigned int max_sym_name = 1024;// should be enough
while ( 1 ) while ( 1 )
{ {
// Get the next stack frame // Get the next stack frame
if ( ! StackWalk( dwMachineType, if ( ! StackWalk64( dwMachineType,
m_hProcess, m_hProcess,
GetCurrentThread(), GetCurrentThread(),
&sf, &sf,
&context, &context,
0, 0,
SymFunctionTableAccess, SymFunctionTableAccess64,
SymGetModuleBase, SymGetModuleBase64,
0 ) ) 0 ) )
break; break;
@ -208,23 +247,23 @@ void write_stack_trace(PCONTEXT pContext, TextOutputStream& outputStream)
break; // the frame is OK. Bail if not. break; // the frame is OK. Bail if not.
// Get the name of the function for this stack frame entry // Get the name of the function for this stack frame entry
BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + MAX_SYM_NAME ]; BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + max_sym_name ];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME; pSymbol->MaxNameLen = max_sym_name;
DWORD64 symDisplacement = 0; // Displacement of the input address, DWORD64 symDisplacement = 0; // Displacement of the input address,
// relative to the start of the symbol // relative to the start of the symbol
IMAGEHLP_MODULE module = { sizeof(IMAGEHLP_MODULE) }; IMAGEHLP_MODULE64 module = { sizeof(IMAGEHLP_MODULE64) };
if(SymGetModuleInfo(m_hProcess, sf.AddrPC.Offset, &module)) if(SymGetModuleInfo64(m_hProcess, sf.AddrPC.Offset, &module))
{ {
outputStream << module.ModuleName << "!"; outputStream << module.ModuleName << "!";
if ( SymFromAddr(m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol)) if ( SymFromAddr(m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol))
{ {
char undecoratedName[MAX_SYM_NAME]; char undecoratedName[max_sym_name];
UnDecorateSymbolName(pSymbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE); UnDecorateSymbolName(pSymbol->Name, undecoratedName, max_sym_name, UNDNAME_COMPLETE);
outputStream << undecoratedName; outputStream << undecoratedName;
@ -242,9 +281,9 @@ void write_stack_trace(PCONTEXT pContext, TextOutputStream& outputStream)
outputStream << " + " << Offset(reinterpret_cast<void*>(symDisplacement)); outputStream << " + " << Offset(reinterpret_cast<void*>(symDisplacement));
// Get the source line for this stack frame entry // Get the source line for this stack frame entry
IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) }; IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
DWORD dwLineDisplacement; DWORD dwLineDisplacement;
if ( SymGetLineFromAddr( m_hProcess, sf.AddrPC.Offset, if ( SymGetLineFromAddr64( m_hProcess, sf.AddrPC.Offset,
&dwLineDisplacement, &lineInfo ) ) &dwLineDisplacement, &lineInfo ) )
{ {
outputStream << " " << lineInfo.FileName << " line " << Unsigned(lineInfo.LineNumber); outputStream << " " << lineInfo.FileName << " line " << Unsigned(lineInfo.LineNumber);

View file

@ -23,12 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define INCLUDED_STACKTRACE_H #define INCLUDED_STACKTRACE_H
class TextOutputStream; class TextOutputStream;
void write_stack_trace(TextOutputStream& outputStream) void write_stack_trace(TextOutputStream& outputStream);
#if defined(WIN32)
;
#else
{
}
#endif
#endif #endif