How can you use CaptureStackBackTrace to capture the exception stack, not the calling stack? - c++

I marked up the following code:
#include "stdafx.h"
#include <process.h>
#include <iostream>
#include <Windows.h>
#include <dbghelp.h>
using namespace std;
#define TRACE_MAX_STACK_FRAMES 1024
#define TRACE_MAX_FUNCTION_NAME_LENGTH 1024
int printStackTrace()
{
void *stack[TRACE_MAX_STACK_FRAMES];
HANDLE process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
WORD numberOfFrames = CaptureStackBackTrace(0, TRACE_MAX_STACK_FRAMES, stack, NULL);
char buf[sizeof(SYMBOL_INFO)+(TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR)];
SYMBOL_INFO* symbol = (SYMBOL_INFO*)buf;
symbol->MaxNameLen = TRACE_MAX_FUNCTION_NAME_LENGTH;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
DWORD displacement;
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
for (int i = 0; i < numberOfFrames; i++)
{
DWORD64 address = (DWORD64)(stack[i]);
SymFromAddr(process, address, NULL, symbol);
if (SymGetLineFromAddr64(process, address, &displacement, &line))
{
printf("\tat %s in %s: line: %lu: address: 0x%0X\n", symbol->Name, line.FileName, line.LineNumber, symbol->Address);
}
else
{
printf("\tSymGetLineFromAddr64 returned error code %lu.\n", GetLastError());
printf("\tat %s, address 0x%0X.\n", symbol->Name, symbol->Address);
}
}
return 0;
}
void function2()
{
int a = 0;
int b = 0;
throw new exception;
}
void function1()
{
int a = 0;
function2();
}
void function0()
{
function1();
}
static void threadFunction(void *param)
{
try
{
function0();
}
catch (...)
{
printStackTrace();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
_beginthread(threadFunction, 0, NULL);
printf("Press any key to exit.\n");
cin.get();
return 0;
}
What it does is, it logs a stack trace, but the problem is that the stack trace it logs does not give me the line numbers that I want. I want it to log the line numbers of the places that threw the exception, on and up the call stack, kind of like in C#. But what it actually does right now, is it outputs the following:
at printStackTrace in c:\users\<yourusername>\documents\visual studio 2013\pr
ojects\stacktracing\stacktracing\stacktracing.cpp: line: 17: address: 0x10485C0
at threadFunction in c:\users\<yourusername>\documents\visual studio 2013\pro
jects\stacktracing\stacktracing\stacktracing.cpp: line: 68: address: 0x10457C0
SymGetLineFromAddr64 returned error code 487.
at beginthread, address 0xF9431E0.
SymGetLineFromAddr64 returned error code 487.
at endthread, address 0xF9433E0.
SymGetLineFromAddr64 returned error code 487.
at BaseThreadInitThunk, address 0x7590494F.
SymGetLineFromAddr64 returned error code 487.
at RtlInitializeExceptionChain, address 0x7713986A.
SymGetLineFromAddr64 returned error code 487.
at RtlInitializeExceptionChain, address 0x7713986A.
The problem I am facing, once again, is that line: 68 in this trace corresponds to the line that calls the method printStackTrace();, while I would like it to give me line number 45, which corresponds to the line which throws the exception: throw new exception; and then continue further up the stack.
How can I achieve this sort of behavior and break into this thread exactly when it throws this exception in order to get a proper stack trace?
PS The code above was run for a console application using MSVC++ with unicode enabled on Windows 8.1 x64 machine, with the application being run as a Win32 application in Debug mode.

On Windows, unhandled C++ exception automatically generates SEH exception. SEH __except block allows to attach a filter that accepts _EXCEPTION_POINTERS structure as a parameter, which contains the pointer to the processor's context record in the moment exception was thrown. Passing this pointer to StackWalk64 function gives the stack trace in the moment of exception. So, this problem can be solved by using SEH-style exception handling instead of C++ style.
Example code:
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#include <tchar.h>
#include <process.h>
#include <iostream>
#include <Windows.h>
#include "dbghelp.h"
using namespace std;
const int MaxNameLen = 256;
#pragma comment(lib,"Dbghelp.lib")
void printStack( CONTEXT* ctx ) //Prints stack trace based on context record
{
BOOL result;
HANDLE process;
HANDLE thread;
HMODULE hModule;
STACKFRAME64 stack;
ULONG frame;
DWORD64 displacement;
DWORD disp;
IMAGEHLP_LINE64 *line;
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
char name[MaxNameLen];
char module[MaxNameLen];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
// On x64, StackWalk64 modifies the context record, that could
// cause crashes, so we create a copy to prevent it
CONTEXT ctxCopy;
memcpy(&ctxCopy, ctx, sizeof(CONTEXT));
memset( &stack, 0, sizeof( STACKFRAME64 ) );
process = GetCurrentProcess();
thread = GetCurrentThread();
displacement = 0;
#if !defined(_M_AMD64)
stack.AddrPC.Offset = (*ctx).Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = (*ctx).Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = (*ctx).Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
#endif
SymInitialize( process, NULL, TRUE ); //load symbols
for( frame = 0; ; frame++ )
{
//get next call from stack
result = StackWalk64
(
#if defined(_M_AMD64)
IMAGE_FILE_MACHINE_AMD64
#else
IMAGE_FILE_MACHINE_I386
#endif
,
process,
thread,
&stack,
&ctxCopy,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL
);
if( !result ) break;
//get symbol name for address
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
SymFromAddr(process, ( ULONG64 )stack.AddrPC.Offset, &displacement, pSymbol);
line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));
line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
//try to get line
if (SymGetLineFromAddr64(process, stack.AddrPC.Offset, &disp, line))
{
printf("\tat %s in %s: line: %lu: address: 0x%0X\n", pSymbol->Name, line->FileName, line->LineNumber, pSymbol->Address);
}
else
{
//failed to get line
printf("\tat %s, address 0x%0X.\n", pSymbol->Name, pSymbol->Address);
hModule = NULL;
lstrcpyA(module,"");
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)(stack.AddrPC.Offset), &hModule);
//at least print module name
if(hModule != NULL)GetModuleFileNameA(hModule,module,MaxNameLen);
printf ("in %s\n",module);
}
free(line);
line = NULL;
}
}
//******************************************************************************
void function2()
{
int a = 0;
int b = 0;
throw exception();
}
void function1()
{
int a = 0;
function2();
}
void function0()
{
function1();
}
int seh_filter(_EXCEPTION_POINTERS* ex)
{
printf("*** Exception 0x%x occured ***\n\n",ex->ExceptionRecord->ExceptionCode);
printStack(ex->ContextRecord);
return EXCEPTION_EXECUTE_HANDLER;
}
static void threadFunction(void *param)
{
__try
{
function0();
}
__except(seh_filter(GetExceptionInformation()))
{
printf("Exception \n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
_beginthread(threadFunction, 0, NULL);
printf("Press any key to exit.\n");
cin.get();
return 0;
}
Example output (first two entries are noise, but the rest correctly reflects functions that caused exception):
*** Exception 0xe06d7363 occured ***
at RaiseException, address 0xFD3F9E20.
in C:\Windows\system32\KERNELBASE.dll
at CxxThrowException, address 0xDBB5A520.
in C:\Windows\system32\MSVCR110D.dll
at function2 in c:\work\projects\test\test.cpp: line: 146: address: 0x3F9C6C00
at function1 in c:\work\projects\test\test.cpp: line: 153: address: 0x3F9C6CB0
at function0 in c:\work\projects\test\test.cpp: line: 158: address: 0x3F9C6CE0
at threadFunction in c:\work\projects\test\test.cpp: line: 174: address: 0x3F9C6D70
at beginthread, address 0xDBA66C60.
in C:\Windows\system32\MSVCR110D.dll
at endthread, address 0xDBA66E90.
in C:\Windows\system32\MSVCR110D.dll
at BaseThreadInitThunk, address 0x773C6520.
in C:\Windows\system32\kernel32.dll
at RtlUserThreadStart, address 0x775FC520.
in C:\Windows\SYSTEM32\ntdll.dll
Another option is to create custom exception class that captures context in constructor and use it (or derived classes) to throw exceptions:
class MyException{
public:
CONTEXT Context;
MyException(){
RtlCaptureContext(&Context);
}
};
void function2()
{
throw MyException();
}
//...
try
{
function0();
}
catch (MyException& e)
{
printf("Exception \n");
printStack(&e.Context);
}

If you wanted to capture the stack backtrace of the point where the code threw an exception, you must capture the stack backtrace in the ctor of the exception object and store it within the exception object. Hence the part calling CaptureStackBackTrace() should be moved to the constructor of the exception object, which should also provide methods to fetch it either as a vector of addresses or as a vector of symbols. This is exactly how Throwable in Java and Exception in C# operate.
Finally, please do not write:
throw new exception;
in C++, as you would in C# or Java. This is an excellent way to both produce memory leaks and to fail to catch the exceptions by type (as you are throwing pointers to these types). Rather use:
throw exception();
I'm aware that this is an old question but people (including myself) are still finding it.

do you miss the call to below?
SymInitialize(process, NULL, TRUE);
SymSetOptions(SYMOPT_LOAD_LINES);

Related

What's the actual size of PSAPI_WORKING_SET_INFORMATION buffer used in QueryWorkingSet function of PSAPI.h

I'd like to use the function QueryWorkingSet available in PSAPI, but I'm having trouble to actually define the size of the buffer pv. Here is the code :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi, wsi2;
GetSystemInfo(&si);
QueryWorkingSet(thisProcess, &wsi, sizeof(wsi));
DWORD wsi2_buffer_size = (wsi.NumberOfEntries) * sizeof(PSAPI_WORKING_SET_BLOCK);
if (!QueryWorkingSet(thisProcess, &wsi2, wsi2_buffer_size))
{
std::cout << "ERROR CODE : " << GetLastError() << std::endl;
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
I keep ending up with abort() being called and either an error code 24 or 998 during the first call to testQueryWorkingSet(). that I interpret respectively as : wsi2_buffer_size is too low and wsi2_buffer_size is too big.
Now I have no idea of the value this variable should take, I tried :
counting everything including the NumberOfEntries field, that is DWORD wsi2_buffer_size = sizeof(wsi.NumberOfEntries) + wsi.NumberOfEntries * sizeof(PSAPI_WORKING_SET_BLOCK); => error 998;
counting only the number of entries, that is the code given above => error 998;
the size of the variable wsi2, that is DWORD wsi2_buffer_size = sizeof(wsi2); => error 24;
There has to be something I do not understand in the way we're supposed to use this function but I can't find what. I tried to adapt the code given there, that is :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi_1, * wsi;
DWORD wsi_size;
GetSystemInfo(&si);
wsi_1.NumberOfEntries = 0;
QueryWorkingSet(thisProcess, (LPVOID)&wsi_1, sizeof(wsi));
#if !defined(_WIN64)
wsi_1.NumberOfEntries--;
#endif
wsi_size = sizeof(PSAPI_WORKING_SET_INFORMATION)
+ sizeof(PSAPI_WORKING_SET_BLOCK) * wsi_1.NumberOfEntries;
wsi = (PSAPI_WORKING_SET_INFORMATION*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, wsi_size);
if (!QueryWorkingSet(thisProcess, (LPVOID)wsi, wsi_size)) {
printf("# Second QueryWorkingSet failed: %lu\n"
, GetLastError());
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
This code is working for only 1 call to testQueryWorkingSet(), the second one is aborting with error code 24. Here are the questions in brief :
How would you use QueryWorkingSet in a function that you could call multiple times successively?
What is representing the value of the parameter cb of the documentation given a PSAPI_WORKING_SET_INFORMATION?
Both examples are completely ignoring the return value and error code of the 1st call of QueryWorkingSet(). You are doing error handling only on the 2nd call.
Your 1st example fails because you are not taking into account the entire size of the PSAPI_WORKING_SET_INFORMATION when calculating wsi2_buffer_size for the 2nd call of QueryWorkingSet(). Even if the 1st call were successful, you are not allocating any additional memory for the 2nd call to fill in, if the NumberOfEntries returned is > 1.
Your 2nd example is passing in the wrong buffer size value to the cb parameter of the 1st call of QueryWorkingSet(). You are passing in just the size of a single pointer, not the size of the entire PSAPI_WORKING_SET_INFORMATION. Error 24 is ERROR_BAD_LENGTH. You need to use sizeof(wsi_1) instead of sizeof(wsi).
I would suggest calling QueryWorkingSet() in a loop, in case the working set actually changes in between the call to query its size and the call to get its data.
Also, be sure you free the memory you allocate when you are done using it.
With that said, try something more life this:
void testQueryWorkingSet()
{
HANDLE thisProcess = GetCurrentProcess();
PSAPI_WORKING_SET_INFORMATION *wsi, *wsi_new;
DWORD wsi_size;
ULONG_PTR count = 1; // or whatever initial size you want...
do
{
wsi_size = offsetof(PSAPI_WORKING_SET_INFORMATION, WorkingSetInfo[count]);
wsi = (PSAPI_WORKING_SET_INFORMATION*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, wsi_size);
if (!wsi)
{
printf("HeapAlloc failed: %lu\n", GetLastError());
abort();
}
if (QueryWorkingSet(thisProcess, wsi, wsi_size))
break;
if (GetLastError() != ERROR_BAD_LENGTH)
{
printf("QueryWorkingSet failed: %lu\n", GetLastError());
HeapFree(GetProcessHeap(), 0, wsi);
abort();
}
count = wsi->NumberOfEntries;
HeapFree(GetProcessHeap(), 0, wsi);
}
while (true);
// use wsi as needed...
HeapFree(GetProcessHeap(), 0, wsi);
}

How to register custom exception in Intel SGX?

I'm having difficulty to get my custom exception handler to work.
This is the Enclave code:
#include "Enclave_DivideZero_t.h"
#include "sgx_trts_exception.h"
#include "sgx_trts.h"
#include <string>
static char buf[200] = "Handler not called";
int divide_by_zero_handler(sgx_exception_info_t* info) {
buf[0] = '1';
return EXCEPTION_CONTINUE_EXECUTION;
}
void Enclave_DivideByZero() {
Ocall_printf(buf);
if (sgx_register_exception_handler(1, divide_by_zero_handler) == NULL) {
Ocall_printf("register failed");
} else {
Ocall_printf("register success");
}
int a(1);
int b(3/(a-a));
(void) a;
(void) b;
Ocall_printf(buf);
}
We used buf as an indication of whether the handler has been actually executed. However, the output is this:
Enclave created!
[Ocall printf] - Handler not called
[Ocall printf] - register success
[Ocall printf] - Handler not called <-- should be: "1andler not called" ("1andler" instead of "Handler")
Also, here is the App code (i.e. the untrusted code)
#include "stdafx.h"
#include "sgx_urts.h"
#include "Enclave_DivideZero_u.h"
#define ENCLAVE_FILE _T("Enclave_DivideZero.signed.dll")
sgx_status_t createEnclave(sgx_enclave_id_t *eid) {
sgx_status_t ret = SGX_SUCCESS;
sgx_launch_token_t token = {0};
int updated = 0;
ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &token, &updated, eid, NULL);
return ret;
}
void Ocall_printf( char* str) {
printf("[Ocall printf] - %s\n", str);
}
int _tmain(int argc, _TCHAR* argv[]) {
sgx_enclave_id_t eid;
sgx_status_t res = createEnclave(&eid);
if (res != SGX_SUCCESS) {
printf("App: error-, failed to create enclave.\n");
return -1;
} else {
printf("Enclave created!\n");
}
Enclave_DivideByZero(eid);
return 0;
}
The Problem: As you can see from the output indicates that the handler is registered successfully, but is not executed.
1- Why the registration doesn't work?
2- I tried to put the registeration with the App code, and for this I had to add the handler in the edl, the problem for this is passing the sgx_exception_info_t *info param, which is not clear which flags it needs (i.e. [in, .. <'flags'>]). So, is it correct to define it inside the Enclave?
p.s. I ran the code with Prerelease Mode.
[EDIT] I documented the project + code that I conducted on SGX here
So the question is a bit old now, but I got stuck at the same place, so maybe someone can still use my insight.
In trts_veh.cpp, where it is checked whether the exception was handled, it says in a comment that the "instruction triggering the exception will be executed again". This leads to the exception handling loop, as you noticed yourself.
However, you can increase the rip yourself, as it is stored in the pointer to the sgx_exception_info_t, by using "info->cpu_context.rip += 2;". Adding this inside your exception handler should do the trick.

How can I print stack trace for caught exceptions in C++ & code injection in C++

I want to have stack trace not for my exceptions only but also for any descendants of std::exception
As I understand, stack trace is completely lost when exception is caught because of stack unwinding (unrolling).
So the only way I see to grab it is injection of code saving context info (stack trace) at the place of std::exception constructor call. Am I right?
If it is the case, please tell me how code injection can be done (if it can) in C++. Your method may be not completely safe because I need it for Debug version of my app only. May be I need to use assembler?
I'm interested only in solution for GCC. It can use c++0x features
Since you mentioned that you're happy with something that is GCC specific I've put together an example of a way you might do this. It's pure evil though, interposing on internals of the C++ support library. I'm not sure I'd want to use this in production code. Anyway:
#include <iostream>
#include <dlfcn.h>
#include <execinfo.h>
#include <typeinfo>
#include <string>
#include <memory>
#include <cxxabi.h>
#include <cstdlib>
namespace {
void * last_frames[20];
size_t last_size;
std::string exception_name;
std::string demangle(const char *name) {
int status;
std::unique_ptr<char,void(*)(void*)> realname(abi::__cxa_demangle(name, 0, 0, &status), &std::free);
return status ? "failed" : &*realname;
}
}
extern "C" {
void __cxa_throw(void *ex, void *info, void (*dest)(void *)) {
exception_name = demangle(reinterpret_cast<const std::type_info*>(info)->name());
last_size = backtrace(last_frames, sizeof last_frames/sizeof(void*));
static void (*const rethrow)(void*,void*,void(*)(void*)) __attribute__ ((noreturn)) = (void (*)(void*,void*,void(*)(void*)))dlsym(RTLD_NEXT, "__cxa_throw");
rethrow(ex,info,dest);
}
}
void foo() {
throw 0;
}
int main() {
try {
foo();
}
catch (...) {
std::cerr << "Caught a: " << exception_name << std::endl;
// print to stderr
backtrace_symbols_fd(last_frames, last_size, 2);
}
}
We basically steal calls to the internal implementation function that GCC uses for dispatching thrown exceptions. At that point we take a stack trace and save it in a global variable. Then when we come across that exception later on in our try/catch we can work with the stacktrace to print/save or whatever it is you want to do. We use dlsym() to find the real version of __cxa_throw.
My example throws an int to prove that you can do this with literally any type, not just your own user defined exceptions.
It uses the type_info to get the name of the type that was thrown and then demangles it.
You could encapsulate the global variables that store the stacktrace a bit better if you wanted to.
I compiled and tested this with:
g++ -Wall -Wextra test.cc -g -O0 -rdynamic -ldl
Which gave the following when run:
./a.out
Caught a: int
./a.out(__cxa_throw+0x74)[0x80499be]
./a.out(main+0x0)[0x8049a61]
./a.out(main+0x10)[0x8049a71]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb75c2ca6]
./a.out[0x80497e1]
Please don't take this as an example of good advice though - it's an example of what you can do with a little bit of trickery and poking around at the internals!
On Linux this can be implemented by adding a call to backtrace() in the exception constructor to capture the stack trace into an exception's member variable. Unfortunately, it won't work for standard exceptions, only for the ones you define.
Some years ago I wrote this: Unchaining chained exceptions in C++
Basically some macros log the place where the stack unwind happens when an exception is thrown.
An updated version of the framework can be found in the library Imebra (http://imebra.com).
I would reimplement some parts of it (like storing the stack trace on a thread local storage).
The solution from Flexo is very nice and works well. It also has the benefit that translation from backtrace addresses to procedure names is only performed in the catch part, so its up to the receiver of an exception if they care about the backtrace or not.
However there are also cases where a solution based on libunwind can be prefered, i.e. because libunwind can in some scenarios gather procedure names where the backtrace functions fail to do so.
Here I present an idea based on Flexo's answer, but with several extensions. It uses libunwind to generate the backtrace at the time of the throw, and directly prints to stderr. It uses libDL to identify the shared object file name. It uses DWARF debugging information from elfutils to gather the source code file name and line number. It uses the C++ API to demangle C++ exceptions. Users can set the mExceptionStackTrace variable to temporarily enable/disable the stack traces.
An important point about all solutions that intercept __cxa_throw is that they add potentially an overhead for walking the stack. This is especially true for my solution that adds significant overhead for accessing the debugger symbols to gather the source file name. This may be acceptable in i.e. automatic testing where you expect your code not to throw, and you want to have a powerful stack trace for (failed) tests that do throw.
// Our stack unwinding is a GNU C extension:
#if defined(__GNUC__)
// include elfutils to parse debugger information:
#include <elfutils/libdwfl.h>
// include libunwind to gather the stack trace:
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <dlfcn.h>
#include <cxxabi.h>
#include <typeinfo>
#include <stdio.h>
#include <stdlib.h>
#define LIBUNWIND_MAX_PROCNAME_LENGTH 4096
static bool mExceptionStackTrace = false;
// We would like to print a stacktrace for every throw (even in
// sub-libraries and independent of the object thrown). This works
// only for gcc and only with a bit of trickery
extern "C" {
void print_exception_info(const std::type_info* aExceptionInfo) {
int vDemangleStatus;
char* vDemangledExceptionName;
if (aExceptionInfo != NULL) {
// Demangle the name of the exception using the GNU C++ ABI:
vDemangledExceptionName = abi::__cxa_demangle(aExceptionInfo->name(), NULL, NULL, &vDemangleStatus);
if (vDemangledExceptionName != NULL) {
fprintf(stderr, "\n");
fprintf(stderr, "Caught exception %s:\n", vDemangledExceptionName);
// Free the memory from __cxa_demangle():
free(vDemangledExceptionName);
} else {
// NOTE: if the demangle fails, we do nothing, so the
// non-demangled name will be printed. Thats ok.
fprintf(stderr, "\n");
fprintf(stderr, "Caught exception %s:\n", aExceptionInfo->name());
}
} else {
fprintf(stderr, "\n");
fprintf(stderr, "Caught exception:\n");
}
}
void libunwind_print_backtrace(const int aFramesToIgnore) {
unw_cursor_t vUnwindCursor;
unw_context_t vUnwindContext;
unw_word_t ip, sp, off;
unw_proc_info_t pip;
int vUnwindStatus, vDemangleStatus, i, n = 0;
char vProcedureName[LIBUNWIND_MAX_PROCNAME_LENGTH];
char* vDemangledProcedureName;
const char* vDynObjectFileName;
const char* vSourceFileName;
int vSourceFileLineNumber;
// This is from libDL used for identification of the object file names:
Dl_info dlinfo;
// This is from DWARF for accessing the debugger information:
Dwarf_Addr addr;
char* debuginfo_path = NULL;
Dwfl_Callbacks callbacks = {};
Dwfl_Line* vDWARFObjLine;
// initialize the DWARF handling:
callbacks.find_elf = dwfl_linux_proc_find_elf;
callbacks.find_debuginfo = dwfl_standard_find_debuginfo;
callbacks.debuginfo_path = &debuginfo_path;
Dwfl* dwfl = dwfl_begin(&callbacks);
if (dwfl == NULL) {
fprintf(stderr, "libunwind_print_backtrace(): Error initializing DWARF.\n");
}
if ((dwfl != NULL) && (dwfl_linux_proc_report(dwfl, getpid()) != 0)) {
fprintf(stderr, "libunwind_print_backtrace(): Error initializing DWARF.\n");
dwfl = NULL;
}
if ((dwfl != NULL) && (dwfl_report_end(dwfl, NULL, NULL) != 0)) {
fprintf(stderr, "libunwind_print_backtrace(): Error initializing DWARF.\n");
dwfl = NULL;
}
// Begin stack unwinding with libunwnd:
vUnwindStatus = unw_getcontext(&vUnwindContext);
if (vUnwindStatus) {
fprintf(stderr, "libunwind_print_backtrace(): Error in unw_getcontext: %d\n", vUnwindStatus);
return;
}
vUnwindStatus = unw_init_local(&vUnwindCursor, &vUnwindContext);
if (vUnwindStatus) {
fprintf(stderr, "libunwind_print_backtrace(): Error in unw_init_local: %d\n", vUnwindStatus);
return;
}
vUnwindStatus = unw_step(&vUnwindCursor);
for (i = 0; ((i < aFramesToIgnore) && (vUnwindStatus > 0)); ++i) {
// We ignore the first aFramesToIgnore stack frames:
vUnwindStatus = unw_step(&vUnwindCursor);
}
while (vUnwindStatus > 0) {
pip.unwind_info = NULL;
vUnwindStatus = unw_get_proc_info(&vUnwindCursor, &pip);
if (vUnwindStatus) {
fprintf(stderr, "libunwind_print_backtrace(): Error in unw_get_proc_info: %d\n", vUnwindStatus);
break;
}
// Resolve the address of the stack frame using libunwind:
unw_get_reg(&vUnwindCursor, UNW_REG_IP, &ip);
unw_get_reg(&vUnwindCursor, UNW_REG_SP, &sp);
// Resolve the name of the procedure using libunwind:
// unw_get_proc_name() returns 0 on success, and returns UNW_ENOMEM
// if the procedure name is too long to fit in the buffer provided and
// a truncated version of the name has been returned:
vUnwindStatus = unw_get_proc_name(&vUnwindCursor, vProcedureName, LIBUNWIND_MAX_PROCNAME_LENGTH, &off);
if (vUnwindStatus == 0) {
// Demangle the name of the procedure using the GNU C++ ABI:
vDemangledProcedureName = abi::__cxa_demangle(vProcedureName, NULL, NULL, &vDemangleStatus);
if (vDemangledProcedureName != NULL) {
strncpy(vProcedureName, vDemangledProcedureName, LIBUNWIND_MAX_PROCNAME_LENGTH);
// Free the memory from __cxa_demangle():
free(vDemangledProcedureName);
} else {
// NOTE: if the demangle fails, we do nothing, so the
// non-demangled name will be printed. Thats ok.
}
} else if (vUnwindStatus == UNW_ENOMEM) {
// NOTE: libunwind could resolve the name, but could not store
// it in a buffer of only LIBUNWIND_MAX_PROCNAME_LENGTH characters.
// So we have a truncated procedure name that can not be demangled.
// We ignore the problem and the truncated non-demangled name will
// be printed.
} else {
vProcedureName[0] = '?';
vProcedureName[1] = '?';
vProcedureName[2] = '?';
vProcedureName[3] = 0;
}
// Resolve the object file name using dladdr:
if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname && *dlinfo.dli_fname) {
vDynObjectFileName = dlinfo.dli_fname;
} else {
vDynObjectFileName = "???";
}
// Resolve the source file name using DWARF:
if (dwfl != NULL) {
addr = (uintptr_t)(ip - 4);
Dwfl_Module* module = dwfl_addrmodule(dwfl, addr);
// Here we could also ask for the procedure name:
//const char* vProcedureName = dwfl_module_addrname(module, addr);
// Here we could also ask for the object file name:
//vDynObjectFileName = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
vDWARFObjLine = dwfl_getsrc(dwfl, addr);
if (vDWARFObjLine != NULL) {
vSourceFileName = dwfl_lineinfo(vDWARFObjLine, &addr, &vSourceFileLineNumber, NULL, NULL, NULL);
//fprintf(stderr, " %s:%d", strrchr(vSourceFileName, '/')+1, vSourceFileLineNumber);
}
}
if (dwfl == NULL || vDWARFObjLine == NULL || vSourceFileName == NULL) {
vSourceFileName = "???";
vSourceFileLineNumber = 0;
}
// Print the stack frame number:
fprintf(stderr, "#%2d:", ++n);
// Print the stack addresses:
fprintf(stderr, " 0x%016" PRIxPTR " sp=0x%016" PRIxPTR, static_cast<uintptr_t>(ip), static_cast<uintptr_t>(sp));
// Print the source file name:
fprintf(stderr, " %s:%d", vSourceFileName, vSourceFileLineNumber);
// Print the dynamic object file name (that is the library name).
// This is typically not interesting if we have the source file name.
//fprintf(stderr, " %s", vDynObjectFileName);
// Print the procedure name:
fprintf(stderr, " %s", vProcedureName);
// Print the procedure offset:
//fprintf(stderr, " + 0x%" PRIxPTR, static_cast<uintptr_t>(off));
// Print a newline to terminate the output:
fprintf(stderr, "\n");
// Stop the stack trace at the main method (there are some
// uninteresting higher level functions on the stack):
if (strcmp(vProcedureName, "main") == 0) {
break;
}
vUnwindStatus = unw_step(&vUnwindCursor);
if (vUnwindStatus < 0) {
fprintf(stderr, "libunwind_print_backtrace(): Error in unw_step: %d\n", vUnwindStatus);
}
}
}
void __cxa_throw(void *thrown_exception, std::type_info *info, void (*dest)(void *)) {
// print the stack trace to stderr:
if (mExceptionStackTrace) {
print_exception_info(info);
libunwind_print_backtrace(1);
}
// call the real __cxa_throw():
static void (*const rethrow)(void*,void*,void(*)(void*)) __attribute__ ((noreturn)) = (void (*)(void*,void*,void(*)(void*)))dlsym(RTLD_NEXT, "__cxa_throw");
rethrow(thrown_exception,info,dest);
}
}
#endif
Check out backward at backward-cpp it does a good job and is well maintained
Example code
In trace.hxx
#define BACKWARD_HAS_DW 1 // or #define BACKWARD_HAS_BFD 1 check docs
#include <backward.hpp>
class recoverable_err final: std::runtime_error
{
backward::StackTrace stacktrace_;
public:
explicit recoverable_err(std::string msg) noexcept;
auto
print_stacktrace(std::ostream &stream)const noexcept -> void;
[[nodiscard]] auto
what() const noexcept -> const char * final;
};
In trace.cxx
#include "trace.hxx"
recoverable_err::recoverable_err(std::string msg) noexcept
: std::runtime_error{ msg }
, stacktrace_{ backward::StackTrace() }
{
stacktrace_.load_here();
}
auto
recoverable_err::print_stacktrace(std::ostream &stream)const noexcept -> void
{
using namespace backward;
Printer p;
p.object = true;
p.color_mode = ColorMode::always;
p.address = true;
p.print(stacktrace_, stream);
}
auto
recoverable_err::what() const noexcept -> const char *
{
return std::runtime_error::what();
}
Usage in main
auto
main() -> int
{
try
{
throw recoverable_err("Recover from nasty error");
}
catch (recoverable_err const &ex)
{
std::cerr << ex.what();
ex.print_stacktrace(std::cerr);
}
catch (std::exception const &ex)
{
std::cerr << "Using default class\n";
std::cerr << ex.what();
}
}

Detect stack overflow with old GLIBC version

We suspect that we are encountering a stack overflow in our multithreaded program. However, as it is an embedded application, we have been unable to get valgrind etc working for it. Also, we are constrained to using GCC version v4.0.0 and GLIBC v2.3.2, which do not support the flag -fstack-protector-all.
How could we go about detecting whether the segmentation faults we are seeing are the result of a stack overflow in this instance? We have doubled the stack size of all our threads, and this fixes the problem, but we would like to be sure that this is a genuine fix.
You can figure this out for yourself with a bit of care. If you set up your program to use a stack you allocated you can add a "guard page" to catch reads and writes to the first page past the end of the given stack. You can then install a signal handler to catch the signal and tell you if the segfault was caused by an access within that guard page.
This is the smallest example I could make that shows how to do this:
#include <stdio.h>
#include <ucontext.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <malloc.h>
#include <signal.h>
static char *guard = NULL;
static const int pagesize = getpagesize();
static void handler(int sig, siginfo_t *info, void *ctx) {
if ((char*)info->si_addr >= guard && (char*)info->si_addr - guard <= pagesize) {
write(2, "stack overflow\n", 15);
}
write(2, "sigsegv caught\n", 15);
_exit(-1);
}
static void install_handler() {
// register sigsegv handler:
static struct sigaction act;
act.sa_sigaction = handler;
sigemptyset(&act.sa_mask);
act.sa_flags=SA_SIGINFO|SA_ONSTACK;
// give the signal handler an alternative stack
static char stack[4096];
stack_t ss;
ss.ss_size = sizeof(stack);
ss.ss_sp = stack;
if (sigaltstack(&ss, 0)) {
perror("sigaltstack");
fprintf(stderr,"failed to set sigstack\n");
exit(-1);
}
if (sigaction(SIGSEGV, &act, NULL)) {
perror("sigaction");
fprintf(stderr,"failed to set handler\n");
exit(-1);
}
}
static int overflow() {
return overflow() + 1;
}
static void test()
{
install_handler();
puts("start test");
// real code that might overflow
// test non-overflow segv
//*(char*)0 = 0;
// test overflow
overflow();
puts("finish test");
}
int main()
{
// create a stack and guard page:
const int pagesize = getpagesize();
char *st1=(char*)memalign(pagesize,1+(pagesize*4));
guard = st1+(pagesize*4);
if (mprotect(guard, pagesize, PROT_NONE)) {
perror("mprotect");
fprintf(stderr,"failed to protect guard page: %p \n", guard);
return -1;
}
ucontext_t ctx[2];
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = 4*pagesize;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], test, 0);
swapcontext(&ctx[0], &ctx[1]);
return 0;
}
As well as using your own stack for your code to run in you have to supply another stack for the signal to be delivered using, otherwise the signal delivery itself will fail because of the guard page.
Do you get a corefile? You should be able to examine a stack trace (either by running the code in GDB or from a corefile) and see if there's a very deep call stack at the time of the crash

Access violation reading location 0xc3618000

I am working on a project about IR Tracking and I am using FreeTrack (www.free-track.net) software for it. FreeTrack offers a sdk folder with their download with C, Matlab and delphi code which can be used to interface the data from FreeTrack to your own writing program in one of these languages.
I started off with Matlab, but when matlab gave a problem, I went on to C++ in Mvisual. This also gives a problem, which seems like the same in Matlab.
Here is the thing:
When i want to read data from a DLL of the freetrack client, I use:
//declare imported function pointers
importGetData getData;
getData = (importGetData)GetProcAddress(hinstLib, "FTGetData");
if (getData(pData))
printf("Yaw: %f\n", data.yaw);
First time it works, but the data is 0. Second time it does it, Mvisual gives the error:
Unhandled exception at 0xc3618000 in FreeTrack.exe: 0xC0000005: Access violation
reading location 0xc3618000.
getData has the adres 0xc3618000.
This only happens when FreeTrack is running. When it isnt, No data is returned from getData.
Any idea's what this can be?
Original code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
typedef struct
{
float yaw;
float pitch;
float roll;
float x;
float y;
float z;
int dataID;
}FreeTrackData;
// DLL function signatures
// These match those given in FTTypes.pas
// WINAPI is macro for __stdcall defined somewhere in the depths of windows.h
typedef bool (WINAPI *importGetData)(FreeTrackData * data);
typedef char *(WINAPI *importGetDllVersion)(void);
typedef void (WINAPI *importReportID)(int name);
typedef char *(WINAPI *importProvider)(void);
int main(int argc, char **argv)
{
/*while(1){
printf("hello");
}*/
//declare imported function pointers
importGetData getData;
importGetDllVersion getDllVersion;
importReportID reportID;
importProvider provider;
// create variables for exchanging data with the dll
FreeTrackData data;
FreeTrackData *pData;
pData = &data;
char *pDllVersion;
int name = 453;
char *pProvider;
//while(1){};
// Load DLL file
HINSTANCE hinstLib = LoadLibrary("FreeTrackClient.dll");
if (hinstLib == NULL) {
printf("ERROR: unable to load DLL\n");
//return 1;
while(1){};
}
else
{
printf("dll loaded\n");
}
//while(1){};
// Get function pointers
getData = (importGetData)GetProcAddress(hinstLib, "FTGetData");
getDllVersion = (importGetDllVersion)GetProcAddress(hinstLib, "FTGetDllVersion");
//reportID = (importReportID)GetProcAddress(hinstLib, "FTReportID");
reportID = (importReportID)GetProcAddress(hinstLib, "FTReportName");
provider = (importProvider)GetProcAddress(hinstLib, "FTProvider");
// Check they are valid
if (getData == NULL) {
printf("ERROR: unable to find 'FTGetData' function\n");
FreeLibrary(hinstLib);
//return 1;
}
if (getDllVersion == NULL){
printf("ERROR: unable to find 'FTGetDllVersion' function\n");
FreeLibrary(hinstLib);
//return 1;
}
if (reportID == NULL){
printf("ERROR: unable to find 'FTReportID' function\n");
FreeLibrary(hinstLib);
//return 1;
}
if (reportID == NULL){
printf("ERROR: unable to find 'FTProvider' function\n");
FreeLibrary(hinstLib);
//return 1;
}
// Print the address of each function
printf("FTGetData is at address: 0x%x\n",getData);
printf("FTGetDllVersion is at address: 0x%x\n",getDllVersion);
printf("FTReportID is at address: 0x%x\n",reportID);
printf("FTProvider is at address: 0x%x\n",provider);
// Call each function and display result
pDllVersion = getDllVersion();
printf("Dll Version: %s\n", pDllVersion);
pProvider = provider();
printf("Provider: %s\n", pProvider);
reportID(name); //not sure what this does - I guess it tells the dll that I am using it.
system("pause"); //wait till keyboard is pressed before entering main loop
while( kbhit() != 1)
{
//system("cls"); //clear screen
if (getData(pData))
{
printf("Provider: %s\n", pProvider);
printf("Record ID: %d\n" , data.dataID);
printf("Yaw: %5.2f\n" , data.yaw );
printf("Pitch: %5.2f\n" , data.pitch );
printf("Roll: %5.2f\n" , data.roll );
printf("X: %5.2f\n" , data.x );
printf("Y: %5.2f\n" , data.y );
printf("Z: %5.2f\n" , data.z );
}
else
{
printf("Nothing returned from getData\n");
break;
}
}
// Unload DLL file
FreeLibrary(hinstLib);
return 0;
}
You told printf that yaw was a C-style string, but it's a float!
I think this might be caused by the structure definition of FreeTrackData.
I found an updated one from this post, and hope that would help.