mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2025-01-25 10:51:36 +00:00
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:
parent
7a43e1720c
commit
1f0b5c5c86
5 changed files with 69 additions and 32 deletions
3
CHANGES
3
CHANGES
|
@ -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
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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 '
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue