/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #if !defined WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #include #include #include #define OPTIONAL #include #include #include #include namespace { template T clampToULONG(T n) { auto const maxUlong = std::numeric_limits::max(); return n > maxUlong ? static_cast(maxUlong) : n; } } OUString osl::detail::backtraceAsString(sal_uInt32 maxDepth) { std::unique_ptr backtrace = sal::backtrace_get( maxDepth ); return sal::backtrace_to_string( backtrace.get()); } std::unique_ptr sal::backtrace_get(sal_uInt32 maxDepth) { assert(maxDepth != 0); maxDepth = clampToULONG(maxDepth); auto pStack = new void *[maxDepth]; // https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633.aspx // "CaptureStackBackTrace function" claims that you "can capture up to // MAXUSHORT frames", and on Windows Server 2003 and Windows XP it even // "must be less than 63", but assume that a too large input value is // clamped internally, instead of resulting in an error: int nFrames = CaptureStackBackTrace( 0, static_cast(maxDepth), pStack, nullptr ); return std::unique_ptr(new BacktraceState{ pStack, nFrames }); } OUString sal::backtrace_to_string(BacktraceState* backtraceState) { HANDLE hProcess = GetCurrentProcess(); // https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-syminitialize // says to not initialize more than once. [[maybe_unused]] static bool bInitialized = SymInitialize(hProcess, nullptr, false); SymRefreshModuleList(hProcess); SYMBOL_INFO * pSymbol; pSymbol = static_cast(calloc( sizeof( SYMBOL_INFO ) + 1024 * sizeof( char ), 1 )); assert(pSymbol); pSymbol->MaxNameLen = 1024 - 1; pSymbol->SizeOfStruct = sizeof( SYMBOL_INFO ); auto nFrames = backtraceState->nDepth; OUStringBuffer aBuf; for( int i = 0; i < nFrames; i++ ) { SymFromAddr( hProcess, reinterpret_cast(backtraceState->buffer[ i ]), nullptr, pSymbol ); aBuf.append( static_cast(nFrames - i - 1) ); aBuf.append( ": " ); aBuf.appendAscii( pSymbol->Name ); aBuf.append( " - 0x" ); aBuf.append( static_cast(pSymbol->Address), 16 ); aBuf.append( "\n" ); } free( pSymbol ); return aBuf.makeStringAndClear(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */