summaryrefslogtreecommitdiff
path: root/extra/msvc_dbg.c
diff options
context:
space:
mode:
authorivmai <ivmai>2011-03-13 19:53:03 +0000
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 21:06:56 +0400
commit015db4806b7299592a94e3099b0fe50cca2b1e58 (patch)
tree6f1afe15759e6b993b2802ceea8fd8a49e66ee49 /extra/msvc_dbg.c
parent618a4c49d9c8c50e95f075e11e826aded68518cd (diff)
downloadbdwgc-015db4806b7299592a94e3099b0fe50cca2b1e58.tar.gz
2011-03-13 Ivan Maidanski <ivmai@mail.ru>
* extra/msvc_dbg.c: Test _MSC_VER macro; include "gc.h" (for GC_word); reformat the code; expand all tabs to spaces. * extra/msvc_dbg.c (ULONG_PTR): Replace with GC_ULONG_PTR; define as word.
Diffstat (limited to 'extra/msvc_dbg.c')
-rw-r--r--extra/msvc_dbg.c504
1 files changed, 266 insertions, 238 deletions
diff --git a/extra/msvc_dbg.c b/extra/msvc_dbg.c
index 2420a44b..5bc216a1 100644
--- a/extra/msvc_dbg.c
+++ b/extra/msvc_dbg.c
@@ -19,12 +19,15 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-#ifndef _M_AMD64
-/* X86_64 is ccurrently missing some meachine-dependent code below. */
+#if !defined(_M_AMD64) && defined(_MSC_VER)
+
+/* X86_64 is currently missing some meachine-dependent code below. */
#include "private/msvc_dbg.h"
+#include "gc.h"
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -35,319 +38,344 @@
#pragma comment(lib, "dbghelp.lib")
#pragma optimize("gy", off)
+typedef GC_word word;
+#define GC_ULONG_PTR word
+
#ifdef _WIN64
- typedef ULONG_PTR ULONG_ADDR;
+ typedef GC_ULONG_PTR ULONG_ADDR;
#else
- typedef ULONG ULONG_ADDR;
+ typedef ULONG ULONG_ADDR;
#endif
static HANDLE GetSymHandle()
{
- static HANDLE symHandle = NULL;
- if (!symHandle) {
- BOOL bRet = SymInitialize(symHandle = GetCurrentProcess(), NULL, FALSE);
- if (bRet) {
- DWORD dwOptions = SymGetOptions();
- dwOptions &= ~SYMOPT_UNDNAME;
- dwOptions |= SYMOPT_LOAD_LINES;
- SymSetOptions(dwOptions);
- }
- }
- return symHandle;
+ static HANDLE symHandle = NULL;
+ if (!symHandle) {
+ BOOL bRet = SymInitialize(symHandle = GetCurrentProcess(), NULL, FALSE);
+ if (bRet) {
+ DWORD dwOptions = SymGetOptions();
+ dwOptions &= ~SYMOPT_UNDNAME;
+ dwOptions |= SYMOPT_LOAD_LINES;
+ SymSetOptions(dwOptions);
+ }
+ }
+ return symHandle;
}
-static void* CALLBACK FunctionTableAccess(HANDLE hProcess, ULONG_ADDR dwAddrBase)
+static void* CALLBACK FunctionTableAccess(HANDLE hProcess,
+ ULONG_ADDR dwAddrBase)
{
- return SymFunctionTableAccess(hProcess, dwAddrBase);
+ return SymFunctionTableAccess(hProcess, dwAddrBase);
}
static ULONG_ADDR CALLBACK GetModuleBase(HANDLE hProcess, ULONG_ADDR dwAddress)
{
- MEMORY_BASIC_INFORMATION memoryInfo;
- ULONG_ADDR dwAddrBase = SymGetModuleBase(hProcess, dwAddress);
- if (dwAddrBase) {
- return dwAddrBase;
- }
- if (VirtualQueryEx(hProcess, (void*)(ULONG_PTR)dwAddress, &memoryInfo, sizeof(memoryInfo))) {
- char filePath[_MAX_PATH];
- char curDir[_MAX_PATH];
- char exePath[_MAX_PATH];
- DWORD size = GetModuleFileNameA((HINSTANCE)memoryInfo.AllocationBase, filePath, sizeof(filePath));
-
- // Save and restore current directory around SymLoadModule, see KB article Q189780
- GetCurrentDirectoryA(sizeof(curDir), curDir);
- GetModuleFileNameA(NULL, exePath, sizeof(exePath));
+ MEMORY_BASIC_INFORMATION memoryInfo;
+ ULONG_ADDR dwAddrBase = SymGetModuleBase(hProcess, dwAddress);
+ if (dwAddrBase) {
+ return dwAddrBase;
+ }
+ if (VirtualQueryEx(hProcess, (void*)(GC_ULONG_PTR)dwAddress, &memoryInfo,
+ sizeof(memoryInfo))) {
+ char filePath[_MAX_PATH];
+ char curDir[_MAX_PATH];
+ char exePath[_MAX_PATH];
+ DWORD size = GetModuleFileNameA((HINSTANCE)memoryInfo.AllocationBase,
+ filePath, sizeof(filePath));
+
+ /* Save and restore current directory around SymLoadModule, see KB */
+ /* article Q189780. */
+ GetCurrentDirectoryA(sizeof(curDir), curDir);
+ GetModuleFileNameA(NULL, exePath, sizeof(exePath));
#if defined(_MSC_VER) && _MSC_VER == 1200
- /* use strcat for VC6 */
- strcat(exePath, "\\..");
+ /* use strcat for VC6 */
+ strcat(exePath, "\\..");
#else
- strcat_s(exePath, sizeof(exePath), "\\..");
+ strcat_s(exePath, sizeof(exePath), "\\..");
#endif /* _MSC_VER >= 1200 */
- SetCurrentDirectoryA(exePath);
+ SetCurrentDirectoryA(exePath);
#ifdef _DEBUG
- GetCurrentDirectoryA(sizeof(exePath), exePath);
+ GetCurrentDirectoryA(sizeof(exePath), exePath);
#endif
- SymLoadModule(hProcess, NULL, size ? filePath : NULL, NULL, (ULONG_ADDR)(ULONG_PTR)memoryInfo.AllocationBase, 0);
- SetCurrentDirectoryA(curDir);
- }
- return (ULONG_ADDR)(ULONG_PTR)memoryInfo.AllocationBase;
+ SymLoadModule(hProcess, NULL, size ? filePath : NULL, NULL,
+ (ULONG_ADDR)(GC_ULONG_PTR)memoryInfo.AllocationBase, 0);
+ SetCurrentDirectoryA(curDir);
+ }
+ return (ULONG_ADDR)(GC_ULONG_PTR)memoryInfo.AllocationBase;
}
static ULONG_ADDR CheckAddress(void* address)
{
- ULONG_ADDR dwAddress = (ULONG_ADDR)(ULONG_PTR)address;
- GetModuleBase(GetSymHandle(), dwAddress);
- return dwAddress;
+ ULONG_ADDR dwAddress = (ULONG_ADDR)(GC_ULONG_PTR)address;
+ GetModuleBase(GetSymHandle(), dwAddress);
+ return dwAddress;
}
size_t GetStackFrames(size_t skip, void* frames[], size_t maxFrames)
{
- HANDLE hProcess = GetSymHandle();
- HANDLE hThread = GetCurrentThread();
- CONTEXT context;
- context.ContextFlags = CONTEXT_FULL;
- if (!GetThreadContext(hThread, &context)) {
- return 0;
- }
- // GetThreadContext might return invalid context for the current thread
+ HANDLE hProcess = GetSymHandle();
+ HANDLE hThread = GetCurrentThread();
+ CONTEXT context;
+ context.ContextFlags = CONTEXT_FULL;
+ if (!GetThreadContext(hThread, &context)) {
+ return 0;
+ }
+ /* GetThreadContext might return invalid context for the current thread. */
#if defined(_M_IX86)
__asm mov context.Ebp, ebp
#endif
- return GetStackFramesFromContext(hProcess, hThread, &context, skip + 1, frames, maxFrames);
+ return GetStackFramesFromContext(hProcess, hThread, &context, skip + 1,
+ frames, maxFrames);
}
-size_t GetStackFramesFromContext(HANDLE hProcess, HANDLE hThread, CONTEXT* context, size_t skip, void* frames[], size_t maxFrames)
+size_t GetStackFramesFromContext(HANDLE hProcess, HANDLE hThread,
+ CONTEXT* context, size_t skip,
+ void* frames[], size_t maxFrames)
{
- size_t frameIndex;
- DWORD machineType;
- STACKFRAME stackFrame = { 0 };
- stackFrame.AddrPC.Mode = AddrModeFlat;
+ size_t frameIndex;
+ DWORD machineType;
+ STACKFRAME stackFrame = { 0 };
+ stackFrame.AddrPC.Mode = AddrModeFlat;
#if defined(_M_IX86)
- machineType = IMAGE_FILE_MACHINE_I386;
- stackFrame.AddrPC.Offset = context->Eip;
- stackFrame.AddrStack.Mode = AddrModeFlat;
- stackFrame.AddrStack.Offset = context->Esp;
- stackFrame.AddrFrame.Mode = AddrModeFlat;
- stackFrame.AddrFrame.Offset = context->Ebp;
+ machineType = IMAGE_FILE_MACHINE_I386;
+ stackFrame.AddrPC.Offset = context->Eip;
+ stackFrame.AddrStack.Mode = AddrModeFlat;
+ stackFrame.AddrStack.Offset = context->Esp;
+ stackFrame.AddrFrame.Mode = AddrModeFlat;
+ stackFrame.AddrFrame.Offset = context->Ebp;
#elif defined(_M_MRX000)
- machineType = IMAGE_FILE_MACHINE_R4000;
- stackFrame.AddrPC.Offset = context->Fir;
+ machineType = IMAGE_FILE_MACHINE_R4000;
+ stackFrame.AddrPC.Offset = context->Fir;
#elif defined(_M_ALPHA)
- machineType = IMAGE_FILE_MACHINE_ALPHA;
- stackFrame.AddrPC.Offset = (unsigned long)context->Fir;
+ machineType = IMAGE_FILE_MACHINE_ALPHA;
+ stackFrame.AddrPC.Offset = (unsigned long)context->Fir;
#elif defined(_M_PPC)
- machineType = IMAGE_FILE_MACHINE_POWERPC;
- stackFrame.AddrPC.Offset = context->Iar;
+ machineType = IMAGE_FILE_MACHINE_POWERPC;
+ stackFrame.AddrPC.Offset = context->Iar;
#elif defined(_M_IA64)
- machineType = IMAGE_FILE_MACHINE_IA64;
- stackFrame.AddrPC.Offset = context->StIIP;
+ machineType = IMAGE_FILE_MACHINE_IA64;
+ stackFrame.AddrPC.Offset = context->StIIP;
#elif defined(_M_ALPHA64)
- machineType = IMAGE_FILE_MACHINE_ALPHA64;
- stackFrame.AddrPC.Offset = context->Fir;
+ machineType = IMAGE_FILE_MACHINE_ALPHA64;
+ stackFrame.AddrPC.Offset = context->Fir;
#else
#error Unknown CPU
#endif
- for (frameIndex = 0; frameIndex < maxFrames; ) {
- BOOL bRet = StackWalk(machineType, hProcess, hThread, &stackFrame, &context, NULL, FunctionTableAccess, GetModuleBase, NULL);
- if (!bRet) {
- break;
- }
- if (skip) {
- skip--;
- } else {
- frames[frameIndex++] = (void*)(ULONG_PTR)stackFrame.AddrPC.Offset;
- }
- }
- return frameIndex;
+ for (frameIndex = 0; frameIndex < maxFrames; ) {
+ BOOL bRet = StackWalk(machineType, hProcess, hThread, &stackFrame,
+ &context, NULL, FunctionTableAccess, GetModuleBase, NULL);
+ if (!bRet) {
+ break;
+ }
+ if (skip) {
+ skip--;
+ } else {
+ frames[frameIndex++] = (void*)(GC_ULONG_PTR)stackFrame.AddrPC.Offset;
+ }
+ }
+ return frameIndex;
}
size_t GetModuleNameFromAddress(void* address, char* moduleName, size_t size)
{
- if (size) *moduleName = 0;
- {
- const char* sourceName;
- IMAGEHLP_MODULE moduleInfo = { sizeof (moduleInfo) };
- if (!SymGetModuleInfo(GetSymHandle(), CheckAddress(address), &moduleInfo)) {
- return 0;
- }
- sourceName = strrchr(moduleInfo.ImageName, '\\');
- if (sourceName) {
- sourceName++;
- } else {
- sourceName = moduleInfo.ImageName;
- }
- if (size) {
- strncpy(moduleName, sourceName, size)[size - 1] = 0;
- }
- return strlen(sourceName);
- }
+ if (size) *moduleName = 0;
+ {
+ const char* sourceName;
+ IMAGEHLP_MODULE moduleInfo = { sizeof (moduleInfo) };
+ if (!SymGetModuleInfo(GetSymHandle(), CheckAddress(address),
+ &moduleInfo)) {
+ return 0;
+ }
+ sourceName = strrchr(moduleInfo.ImageName, '\\');
+ if (sourceName) {
+ sourceName++;
+ } else {
+ sourceName = moduleInfo.ImageName;
+ }
+ if (size) {
+ strncpy(moduleName, sourceName, size)[size - 1] = 0;
+ }
+ return strlen(sourceName);
+ }
}
size_t GetModuleNameFromStack(size_t skip, char* moduleName, size_t size)
{
- void* address = NULL;
- GetStackFrames(skip + 1, &address, 1);
- if (address) {
- return GetModuleNameFromAddress(address, moduleName, size);
- }
- return 0;
+ void* address = NULL;
+ GetStackFrames(skip + 1, &address, 1);
+ if (address) {
+ return GetModuleNameFromAddress(address, moduleName, size);
+ }
+ return 0;
}
-size_t GetSymbolNameFromAddress(void* address, char* symbolName, size_t size, size_t* offsetBytes)
+size_t GetSymbolNameFromAddress(void* address, char* symbolName, size_t size,
+ size_t* offsetBytes)
{
- if (size) *symbolName = 0;
- if (offsetBytes) *offsetBytes = 0;
- __try {
- ULONG_ADDR dwOffset = 0;
- union {
- IMAGEHLP_SYMBOL sym;
- char symNameBuffer[sizeof(IMAGEHLP_SYMBOL) + MAX_SYM_NAME];
- } u;
- u.sym.SizeOfStruct = sizeof(u.sym);
- u.sym.MaxNameLength = sizeof(u.symNameBuffer) - sizeof(u.sym);
-
- if (!SymGetSymFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset, &u.sym)) {
- return 0;
- } else {
- const char* sourceName = u.sym.Name;
- char undName[1024];
- if (UnDecorateSymbolName(u.sym.Name, undName, sizeof(undName), UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)) {
- sourceName = undName;
- } else if (SymUnDName(&u.sym, undName, sizeof(undName))) {
- sourceName = undName;
- }
- if (offsetBytes) {
- *offsetBytes = dwOffset;
- }
- if (size) {
- strncpy(symbolName, sourceName, size)[size - 1] = 0;
- }
- return strlen(sourceName);
- }
- } __except (EXCEPTION_EXECUTE_HANDLER) {
- SetLastError(GetExceptionCode());
- }
- return 0;
+ if (size) *symbolName = 0;
+ if (offsetBytes) *offsetBytes = 0;
+ __try {
+ ULONG_ADDR dwOffset = 0;
+ union {
+ IMAGEHLP_SYMBOL sym;
+ char symNameBuffer[sizeof(IMAGEHLP_SYMBOL) + MAX_SYM_NAME];
+ } u;
+ u.sym.SizeOfStruct = sizeof(u.sym);
+ u.sym.MaxNameLength = sizeof(u.symNameBuffer) - sizeof(u.sym);
+
+ if (!SymGetSymFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset,
+ &u.sym)) {
+ return 0;
+ } else {
+ const char* sourceName = u.sym.Name;
+ char undName[1024];
+ if (UnDecorateSymbolName(u.sym.Name, undName, sizeof(undName),
+ UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)) {
+ sourceName = undName;
+ } else if (SymUnDName(&u.sym, undName, sizeof(undName))) {
+ sourceName = undName;
+ }
+ if (offsetBytes) {
+ *offsetBytes = dwOffset;
+ }
+ if (size) {
+ strncpy(symbolName, sourceName, size)[size - 1] = 0;
+ }
+ return strlen(sourceName);
+ }
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ SetLastError(GetExceptionCode());
+ }
+ return 0;
}
-size_t GetSymbolNameFromStack(size_t skip, char* symbolName, size_t size, size_t* offsetBytes)
+size_t GetSymbolNameFromStack(size_t skip, char* symbolName, size_t size,
+ size_t* offsetBytes)
{
- void* address = NULL;
- GetStackFrames(skip + 1, &address, 1);
- if (address) {
- return GetSymbolNameFromAddress(address, symbolName, size, offsetBytes);
- }
- return 0;
+ void* address = NULL;
+ GetStackFrames(skip + 1, &address, 1);
+ if (address) {
+ return GetSymbolNameFromAddress(address, symbolName, size, offsetBytes);
+ }
+ return 0;
}
-size_t GetFileLineFromAddress(void* address, char* fileName, size_t size, size_t* lineNumber, size_t* offsetBytes)
+size_t GetFileLineFromAddress(void* address, char* fileName, size_t size,
+ size_t* lineNumber, size_t* offsetBytes)
{
- if (size) *fileName = 0;
- if (lineNumber) *lineNumber = 0;
- if (offsetBytes) *offsetBytes = 0;
- {
- char* sourceName;
- IMAGEHLP_LINE line = { sizeof (line) };
- ULONG_PTR dwOffset = 0;
- if (!SymGetLineFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset, &line)) {
- return 0;
- }
- if (lineNumber) {
- *lineNumber = line.LineNumber;
- }
- if (offsetBytes) {
- *offsetBytes = dwOffset;
- }
- sourceName = line.FileName;
- // TODO: resolve relative filenames, found in 'source directories' registered with MSVC IDE.
- if (size) {
- strncpy(fileName, sourceName, size)[size - 1] = 0;
- }
- return strlen(sourceName);
- }
+ if (size) *fileName = 0;
+ if (lineNumber) *lineNumber = 0;
+ if (offsetBytes) *offsetBytes = 0;
+ {
+ char* sourceName;
+ IMAGEHLP_LINE line = { sizeof (line) };
+ GC_ULONG_PTR dwOffset = 0;
+ if (!SymGetLineFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset,
+ &line)) {
+ return 0;
+ }
+ if (lineNumber) {
+ *lineNumber = line.LineNumber;
+ }
+ if (offsetBytes) {
+ *offsetBytes = dwOffset;
+ }
+ sourceName = line.FileName;
+ /* TODO: resolve relative filenames, found in 'source directories' */
+ /* registered with MSVC IDE. */
+ if (size) {
+ strncpy(fileName, sourceName, size)[size - 1] = 0;
+ }
+ return strlen(sourceName);
+ }
}
-size_t GetFileLineFromStack(size_t skip, char* fileName, size_t size, size_t* lineNumber, size_t* offsetBytes)
+size_t GetFileLineFromStack(size_t skip, char* fileName, size_t size,
+ size_t* lineNumber, size_t* offsetBytes)
{
- void* address = NULL;
- GetStackFrames(skip + 1, &address, 1);
- if (address) {
- return GetFileLineFromAddress(address, fileName, size, lineNumber, offsetBytes);
- }
- return 0;
+ void* address = NULL;
+ GetStackFrames(skip + 1, &address, 1);
+ if (address) {
+ return GetFileLineFromAddress(address, fileName, size, lineNumber,
+ offsetBytes);
+ }
+ return 0;
}
-size_t GetDescriptionFromAddress(void* address, const char* format, char* buffer, size_t size)
+size_t GetDescriptionFromAddress(void* address, const char* format,
+ char* buffer, size_t size)
{
- char*const begin = buffer;
- char*const end = buffer + size;
- size_t line_number = 0;
- char str[128];
-
- if (size) {
- *buffer = 0;
- }
- buffer += GetFileLineFromAddress(address, buffer, size, &line_number, NULL);
- size = end < buffer ? 0 : end - buffer;
-
- if (line_number) {
- wsprintf(str, "(%d) : ", line_number);
- if (size) {
- strncpy(buffer, str, size)[size - 1] = 0;
- }
- buffer += strlen(str);
- size = end < buffer ? 0 : end - buffer;
- }
-
- if (size) {
- strncpy(buffer, "at ", size)[size - 1] = 0;
- }
- buffer += strlen("at ");
- size = end < buffer ? 0 : end - buffer;
-
- buffer += GetSymbolNameFromAddress(address, buffer, size, NULL);
- size = end < buffer ? 0 : end - buffer;
-
- if (size) {
- strncpy(buffer, " in ", size)[size - 1] = 0;
- }
- buffer += strlen(" in ");
- size = end < buffer ? 0 : end - buffer;
-
- buffer += GetModuleNameFromAddress(address, buffer, size);
- size = end < buffer ? 0 : end - buffer;
-
- return buffer - begin;
+ char*const begin = buffer;
+ char*const end = buffer + size;
+ size_t line_number = 0;
+ char str[128];
+
+ if (size) {
+ *buffer = 0;
+ }
+ buffer += GetFileLineFromAddress(address, buffer, size, &line_number, NULL);
+ size = end < buffer ? 0 : end - buffer;
+
+ if (line_number) {
+ wsprintf(str, "(%d) : ", line_number);
+ if (size) {
+ strncpy(buffer, str, size)[size - 1] = 0;
+ }
+ buffer += strlen(str);
+ size = end < buffer ? 0 : end - buffer;
+ }
+
+ if (size) {
+ strncpy(buffer, "at ", size)[size - 1] = 0;
+ }
+ buffer += strlen("at ");
+ size = end < buffer ? 0 : end - buffer;
+
+ buffer += GetSymbolNameFromAddress(address, buffer, size, NULL);
+ size = end < buffer ? 0 : end - buffer;
+
+ if (size) {
+ strncpy(buffer, " in ", size)[size - 1] = 0;
+ }
+ buffer += strlen(" in ");
+ size = end < buffer ? 0 : end - buffer;
+
+ buffer += GetModuleNameFromAddress(address, buffer, size);
+ size = end < buffer ? 0 : end - buffer;
+
+ return buffer - begin;
}
-size_t GetDescriptionFromStack(void*const frames[], size_t count, const char* format, char* description[], size_t size)
+size_t GetDescriptionFromStack(void* const frames[], size_t count,
+ const char* format, char* description[],
+ size_t size)
{
- char*const begin = (char*)description;
- char*const end = begin + size;
- char* buffer = begin + (count + 1) * sizeof(char*);
- size_t i;
- for (i = 0; i < count; ++i) {
- if (description) description[i] = buffer;
- size = end < buffer ? 0 : end - buffer;
- buffer += 1 + GetDescriptionFromAddress(frames[i], NULL, buffer, size);
- }
- if (description) description[count] = NULL;
- return buffer - begin;
+ char*const begin = (char*)description;
+ char*const end = begin + size;
+ char* buffer = begin + (count + 1) * sizeof(char*);
+ size_t i;
+ for (i = 0; i < count; ++i) {
+ if (description) description[i] = buffer;
+ size = end < buffer ? 0 : end - buffer;
+ buffer += 1 + GetDescriptionFromAddress(frames[i], NULL, buffer, size);
+ }
+ if (description) description[count] = NULL;
+ return buffer - begin;
}
/* Compatibility with <execinfo.h> */
int backtrace(void* addresses[], int count)
{
- return GetStackFrames(1, addresses, count);
+ return GetStackFrames(1, addresses, count);
}
char** backtrace_symbols(void*const* addresses, int count)
{
- size_t size = GetDescriptionFromStack(addresses, count, NULL, NULL, 0);
- char** symbols = (char**)malloc(size);
- GetDescriptionFromStack(addresses, count, NULL, symbols, size);
- return symbols;
+ size_t size = GetDescriptionFromStack(addresses, count, NULL, NULL, 0);
+ char** symbols = (char**)malloc(size);
+ GetDescriptionFromStack(addresses, count, NULL, symbols, size);
+ return symbols;
}
#endif /* !_M_AMD64 */