Question

This code consistently fails to build in ubuntu 12.04, 12.10, linux mint 13 and 14, but it compiles correctly on ubuntu maverick 10.10

#include <stdio.h>
#include <signal.h>
#include <stdio.h>
#include <signal.h>
#include <execinfo.h>
#include <stdlib.h>
#include <string.h>

//#define __USE_GNU
//#include <sys/ucontext.h>

#include <ucontext.h>
#ifndef __USE_GNU
#error "__USE_GNU HAS been undefined"
#endif
#include <cxxabi.h>
#include <iostream>


#ifndef _SYS_UCONTEXT_H
#error "sys/context HAS NOT BEEN INCLUDED"
#endif

void print_trace(const char * file, int line) //(FILE *out, const char *file, int line)
{
    const size_t max_depth = 100;
    size_t stack_depth;
    void *stack_addrs[max_depth];
    char **stack_strings;

    stack_depth = backtrace(stack_addrs, max_depth);
    stack_strings = backtrace_symbols(stack_addrs, stack_depth);

    //fprintf(out, "Call stack from %s:%d:\n", file, line);
// demangle output: http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
    // spec: http://www.ib.cnea.gov.ar/~oop/biblio/libstdc++/namespaceabi.html

    //string binary;
    // Usually e.start=1: we skip the first frame (traced_exception constructor)
    for( size_t i=1; i<stack_depth; ++i ){
        char *line = stack_strings[i];
        char *lb = strchr(line, '(');
        char *plus = 0;
        char *rb = 0;
        char *demangled = 0;
        if( lb != 0 ){
            /* Print out the path to the binary? Seems pointless.
            if( binary != string( line, lb-line ) ){
                binary = string( line, lb-line );
                stream << "in " << binary << ":\n";
            }
            */
            *lb = '\0';
            plus = strchr(lb+1,'+');
            if( plus != 0 ){
                *plus = '\0';
                int status;
                demangled = abi::__cxa_demangle(lb+1, 0, 0, &status);
                /*if( status != 0 ){
                    cerr << "status: "<<status<<"\tstring:"<<lb+1<<endl;
                }*/
                rb = strchr(plus+1, ')');
            }else{
                rb = strchr(lb+1, ')');
            }
            if( rb != 0 ){
                *rb = '\0';
            }
        }
        if( lb == 0 ){
            std::cout << line;
        }else{
            if( plus != 0 ){
                std::cout << "+" << (plus+1);
            }
            if( demangled != 0 ){
                std::cout << '\t' << demangled;
                free(demangled);
            }else if( lb != 0 && rb > lb ){
                std::cout << '\t' << (lb+1) << "()";
            }
        }
        std::cout << '\n';
    }
    free(stack_strings); // malloc()ed by backtrace_symbols
}


void bt_sighandler(int sig, siginfo_t *info,
                   void *secret) {

  printf("<<< SIGNAL HANDLER >>>\n");
  print_trace("none" , 0);
  void *trace[16];
  char **messages = (char **)NULL;
  int i, trace_size = 0;
  ucontext_t *uc = (ucontext_t *)secret;

  /* Do something useful with siginfo_t */
  if (sig == SIGSEGV)
    printf("Got signal %d, faulty address is %p, "
           "from %p\n", sig, info->si_addr, 
           uc->uc_mcontext.gregs[REG_EIP]);
  else
    printf("Got signal %d#92;\n", sig);

  trace_size = backtrace(trace, 16);
  /* overwrite sigaction with caller's address */
  trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];

  messages = backtrace_symbols(trace, trace_size);
  /* skip first stack frame (points here) */
  printf("[bt] Execution path:#92;\n");
  for (i=1; i<trace_size; ++i)
  {
    printf("[bt] %s :", messages[i]);
    char syscom[256];
    sprintf(syscom,"addr2line %p -e %s", trace[i] , "executableName" ); //last parameter is the name of this app
    system(syscom);
    printf("\n");
  }
  exit(0);
}



inline void initialise_signal_handlers()
{
    /* Install our signal handler */
    printf(" initialising signal handlers... \n ");
    struct sigaction sa;

    sa.sa_sigaction = bt_sighandler;
    sigemptyset (&sa.sa_mask);
    sa.sa_flags = SA_RESTART | SA_SIGINFO;


    sigaction(SIGSEGV, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGABRT, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGBUS, &sa, NULL);
    sigaction(SIGSTKFLT, &sa, NULL);
    sigaction(SIGSYS, &sa, NULL);

    printf(" signal handlers initialised successfully \n ");
}

I try to build this with

g++ -c SignalHandlers.cpp 
SignalHandlers.cpp: In function ‘void bt_sighandler(int, siginfo_t*, void*)’:
SignalHandlers.cpp:146:34: error: ‘REG_EIP’ was not declared in this scope
SignalHandlers.cpp:152:45: error: ‘REG_EIP’ was not declared in this scope

Apparently, after Maverick, /usr/include/sys/ was moved to /usr/include/x86_64-linux-gnu/sys, but the g++ compiler paths were never updated after this move. (This is why is never a good idea to update operating systems in a compulsory way, it is better to let the dust settle after an update, but it seems that the dust bunnies on this one are still caught on whirlwinds.)

In any case, including the path directly on ubuntu 12.04 doesn't work either:

$ g++ -I/usr/include/x86_64-linux-gnu/sys -c SignalHandlers.cpp 
In file included from /usr/include/x86_64-linux-gnu/sys/signal.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
..............................................
                 from SignalHandlers.cpp:4:
/usr/include/x86_64-linux-gnu/sys/signal.h:1:20: error: #include nested too deeply
In file included from /usr/include/x86_64-linux-gnu/sys/signal.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
 ..... and a lot more of those
                 from SignalHandlers.cpp:6:
/usr/include/x86_64-linux-gnu/sys/signal.h:1:20: error: #include nested too deeply
In file included from /usr/include/x86_64-linux-gnu/sys/signal.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
.... and lots and lots more of those
                 from /usr/include/x86_64-linux-gnu/sys/ucontext.h:23,
                 from SignalHandlers.cpp:14:
/usr/include/x86_64-linux-gnu/sys/signal.h:1:20: error: #include nested too deeply
In file included from /usr/include/x86_64-linux-gnu/sys/unistd.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/unistd.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/unistd.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/unistd.h:1,
.... lots and lots of that error
                 from /usr/include/c++/4.6/x86_64-linux-gnu/./bits/gthr-default.h:42,
                 from /usr/include/c++/4.6/x86_64-linux-gnu/./bits/gthr.h:170,
                 from /usr/include/c++/4.6/ext/atomicity.h:34,
                 from /usr/include/c++/4.6/bits/ios_base.h:41,
                 from /usr/include/c++/4.6/ios:43,
                 from /usr/include/c++/4.6/ostream:40,
                 from /usr/include/c++/4.6/iostream:40,
                 from SignalHandlers.cpp:19:
/usr/include/x86_64-linux-gnu/sys/unistd.h:1:20: error: #include nested too deeply
In file included from SignalHandlers.cpp:14:0:
/usr/include/x86_64-linux-gnu/sys/ucontext.h:139:5: error: ‘stack_t’ does not name a type
SignalHandlers.cpp:132:29: error: ‘siginfo_t’ has not been declared
SignalHandlers.cpp: In function ‘void bt_sighandler(int, int*, void*)’:
SignalHandlers.cpp:143:14: error: ‘SIGSEGV’ was not declared in this scope
SignalHandlers.cpp:145:36: error: request for member ‘si_addr’ in ‘* info’, which is of non-class type ‘int’
SignalHandlers.cpp:146:34: error: ‘REG_EIP’ was not declared in this scope
SignalHandlers.cpp:152:45: error: ‘REG_EIP’ was not declared in this scope
SignalHandlers.cpp: In function ‘void initialise_signal_handlers()’:
SignalHandlers.cpp:174:22: error: aggregate ‘initialise_signal_handlers()::sigaction sa’ has incomplete type and cannot be defined
SignalHandlers.cpp:177:29: error: ‘sigemptyset’ was not declared in this scope
SignalHandlers.cpp:178:19: error: ‘SA_RESTART’ was not declared in this scope
SignalHandlers.cpp:178:32: error: ‘SA_SIGINFO’ was not declared in this scope
SignalHandlers.cpp:181:15: error: ‘SIGSEGV’ was not declared in this scope
SignalHandlers.cpp:181:33: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:182:15: error: ‘SIGUSR1’ was not declared in this scope
SignalHandlers.cpp:182:33: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:183:15: error: ‘SIGABRT’ was not declared in this scope
SignalHandlers.cpp:183:33: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:184:15: error: ‘SIGINT’ was not declared in this scope
SignalHandlers.cpp:184:32: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:185:15: error: ‘SIGBUS’ was not declared in this scope
SignalHandlers.cpp:185:32: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:186:15: error: ‘SIGSTKFLT’ was not declared in this scope
SignalHandlers.cpp:186:35: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:187:15: error: ‘SIGSYS’ was not declared in this scope
SignalHandlers.cpp:187:32: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’

g++ version:

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Was it helpful?

Solution

I can reproduce your original problem when I'm not using -I ... on the command line. Let me have a rummage and see what I can come up with.

Edit: If you DON'T alter the -I for the compiler (it shouldn't be needed), then I would think that you either need to pass -m32 (to compile for 32-bit) or change your REG_EIP for REG_RIP, since you are (I think) compiling for 64-bit.

Something like this would work:

#ifdef __x86_64__
#define REG_EIP REG_RIP
#endif

OTHER TIPS

You are building for a 64-bit system, so REG_EIP doesn't exist. It's replaced with REG_RIP.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top