3

In writing some code to print backtraces in C++, I came across this answer, which includes copying the definition of a type:

/* This structure mirrors the one found in /usr/include/asm/ucontext.h */
typedef struct _sig_ucontext {
 unsigned long     uc_flags;
 struct ucontext   *uc_link;
 stack_t           uc_stack;
 struct sigcontext uc_mcontext;
 sigset_t          uc_sigmask;
} sig_ucontext_t;

I can't just include <asm/ucontext.h> since there it is defined as simply ucontext which collides with a similarly named type from <sys/ucontext.h> (which is included from the necessary <signal.h>):

/* Userlevel context.  */
typedef struct ucontext
  {
    unsigned long int uc_flags;
    struct ucontext *uc_link;
    stack_t uc_stack;
    mcontext_t uc_mcontext;
    __sigset_t uc_sigmask;
    struct _libc_fpstate __fpregs_mem;
  } ucontext_t;

All I need here is the struct sigcontext uc_mcontext member from the asm version. Is there a better way to retrieve that value than just copying out this struct? That seems incredibly hackish and error-prone to me.

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977

1 Answers1

1

One potential workaround is to make asm/ucontext.h the first include in your source file and abuse preprocessor to rename conflicting definition:

#define ucontext asm_ucontext
#include <asm/ucontext.h>
#undef asm_ucontext

You can then use asm_ucontext to refer to alternative definition of ucontext.

A bit less hacky approach is to employ sed to automatically extract necessary definitions from system file:

$ echo '#include <asm/ucontext.h>' | gcc -x c - -E -o- | sed -n '/^struct ucontext/,/^};/{ s/ucontext/asm_ucontext/; p}' | tee asm_ucontext.h
struct asm_ucontext {
  unsigned long uc_flags;
  struct asm_ucontext *uc_link;
  stack_t uc_stack;
  struct sigcontext uc_mcontext;
  sigset_t uc_sigmask;
};
yugr
  • 19,769
  • 3
  • 51
  • 96