How to register custom exception in Intel SGX? - c++

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.

Related

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

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);

'SDL_main' : must return a value

I am trying to retreive content of websice in c++ usind SDL but it is giving me this error:
'SDL_main' : must return a value
my code is:
#include <iostream>
#include "SDL.h"
#include "SDL_net.h"
#include <cstring>
int main(int argc,char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDLNet_Init();
IPaddress ip;
SDLNet_ResolveHost(&ip,"www.linux.org",80);
const char* http="GET / HTTP/1.1\nHost: www.linux.org\n\n";
TCPsocket client=SDLNet_TCP_Open(&ip);
SDLNet_TCP_Send(client,http,strlen(http)+1);
char text[10000];
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
SDLNet_TCP_Close(client);
SDLNet_Quit();
SDL_Quit();
}
When I put return 0; at the end, it built project but it finished immediately after that
(I am using vs2012)
UPDATE
cout<<"Some message";
doesn't print anything, is it possible that I have configured my imports wrong? are those additional dependencies right?
SDL.lib;SDL_net.lib;SDLmain.lib
I don't know what else could be wrong ...
It's because SDL defines a macro like this:
#define main SDL_main
So the function you've written is actually called SDL_main and like any other function that is not the actual main function, if it doesn't return void, you have to give it a return statement.
because your code doesn't loop forever it just returns 0 after first pass, you need to make a loop like:
while(1){
sdl_events event;
switch(event){
//handle events, drawings and so on
...
...
...
case SDL_QUIT:
exit (0);
break;
}
}
http://sdl.beuc.net/sdl.wiki/OpenGL_Full_Example
UPDATE
you may also have some problem connecting to host so you could check if connection succeed like this:
#define MAXLEN 1024
int result;
char msg[MAXLEN];
result = SDLNet_TCP_Recv(sock,msg,MAXLEN-1);
if(result <= 0) {
// TCP Connection is broken. (because of error or closure)
SDLNet_TCP_Close(sock);
exit(1);
}
else {
msg[result] = 0;
printf("Received: \"%s\"\n",msg);
}
UPDATE 2
change this:
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
to this:
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
UPDATE 3
try this, put your receive part in this if statement
if(SDLNet_SocketReady(client) == 1)
{
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
}
if this still doesn't work I suggest to use QT sockets or Boost asio, both async and more intuitive

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

Increases physical memory continuously Visual C++ CryptMsgClose and CryptReleaseContext

I am using C++ and Visual Studio 2005.
I have a project that memory Increases in a very abnormal. When debug the code I Realized That there are Several parts That Contribute to it. Like this for example:
// has to add crypt32.lib to link
#include <windows.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void memoryUP( const unsigned char *pData, int cData )
{
HCRYPTMSG msg = NULL;
HCRYPTPROV hProv = NULL;
CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,0);
msg = CryptMsgOpenToDecode(MY_ENCODING_TYPE,0,0,hProv,NULL,NULL);
if(!(CryptMsgUpdate( msg, pData, cData, TRUE)))
{
if(msg != NULL)
{
CryptMsgClose(msg);
msg = NULL;
}
}
if (hProv != NULL)
CryptReleaseContext(hProv,0);
if (msg != NULL)
{
CryptMsgClose(msg);
msg = NULL;
}
}
int main(int argc, char** argv)
{
MyFile myfile = myReadFile("c:\\file.p7s");
{
for(int i=0; i<100000; ++i)
{
memoryUP( myfile._data, myfile._length );
}
}
delete myfile;
return 0;
}
When I run this code, the memory goes up continuously "when call CryptMsgUpdate". Am I deallocating wrong?
I tried to use Memory Leak Detection Enabling method to detect memory leak but nothing appears:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
and
_CrtDumpMemoryLeaks();
Thanks in Advance
You have to release resources in reverse order of their acquisition:
CryptAcquireContext();
if (success)
{
CryptMsgOpenToDecode();
if (success)
{
CryptMsgClose();
}
// else: nothing to close, opening failed
CryptReleaseContext();
}
// else: nothing to release, acquisition failed
The deeper nested constructions depend on the outer ones and may lock up resources, so you can only release the prerequisite resources after you've released the dependent ones.
Since you tagged this C++, I would be remiss to mention that those sort of things should be handled with RIAA, and you should make a class that takes responsibility for the resource. As you can see even in this simple example, writing the correct error checking paths very quickly become onerous, so it'd be much better and more modular to have a class that cleans up after itself, which automatically happens in the correct order.
I think you should call CryptMsgClose before CryptReleaseContext.