question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Compiling on macOS fails

See original GitHub issue

On macOS make yeilds:

/usr/include/ucontext.h:43:2: error: The deprecated ucontext routines require _XOPEN_SOURCE to be defined
#error The deprecated ucontext routines require _XOPEN_SOURCE to be defined
 ^
...

Using

cc -D_XOPEN_SOURCE -c injector.c -o injector.o -Wall

or

diff --git a/injector.c b/injector.c
index 75848b5..280ae4e 100644
--- a/injector.c
+++ b/injector.c
@@ -13,7 +13,7 @@
 #include <time.h>
 #include <execinfo.h>
 #include <limits.h>
-#include <ucontext.h>
+#include <sys/ucontext.h>
 #include <sys/types.h>
 #include <stdint.h>
 #include <stdbool.h>

fixes the first issue. But, it looks like there is still an issue with the portability of ucontext structures:

cc  -c injector.c -o injector.o -Wall
injector.c:321:93: warning: excess elements in array initializer
        .start={.bytes={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, .len=0},
                                                                                                   ^~~~
injector.c:322:91: warning: excess elements in array initializer
        .end={.bytes={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, .len=0},
                                                                                                 ^~~~
injector.c:853:31: error: member reference type 'struct __darwin_mcontext64 *' is a pointer; did you mean to use '->'?
        ((ucontext_t*)p)->uc_mcontext.gregs[IP]+=UD2_SIZE;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
                                     ->
injector.c:853:32: error: no member named 'gregs' in 'struct __darwin_mcontext64'
        ((ucontext_t*)p)->uc_mcontext.gregs[IP]+=UD2_SIZE;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
injector.c:853:38: error: use of undeclared identifier 'REG_RIP'
        ((ucontext_t*)p)->uc_mcontext.gregs[IP]+=UD2_SIZE;
                                            ^
injector.c:81:13: note: expanded from macro 'IP'
        #define IP REG_RIP
                   ^
injector.c:866:29: error: member reference type 'struct __darwin_mcontext64 *' is a pointer; did you mean to use '->'?
                (uintptr_t)uc->uc_mcontext.gregs[IP]-(uintptr_t)packet-preamble_length;
                           ~~~~~~~~~~~~~~~^
                                          ->
injector.c:866:30: error: no member named 'gregs' in 'struct __darwin_mcontext64'
                (uintptr_t)uc->uc_mcontext.gregs[IP]-(uintptr_t)packet-preamble_length;
                           ~~~~~~~~~~~~~~~ ^
injector.c:866:36: error: use of undeclared identifier 'REG_RIP'
                (uintptr_t)uc->uc_mcontext.gregs[IP]-(uintptr_t)packet-preamble_length;
                                                 ^
injector.c:81:13: note: expanded from macro 'IP'
        #define IP REG_RIP
                   ^
injector.c:883:24: error: member reference type 'struct __darwin_mcontext64 *' is a pointer; did you mean to use '->'?
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
               ~~~~~~~~~~~~~~~^
                              ->
/usr/include/secure/_string.h:65:27: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                          ^~~~
injector.c:883:25: error: no member named 'gregs' in 'struct __darwin_mcontext64'
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
               ~~~~~~~~~~~~~~~ ^
/usr/include/secure/_string.h:65:27: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                          ^~~~
injector.c:883:45: error: member reference type 'mcontext_t' (aka 'struct __darwin_mcontext64 *') is a pointer; did you mean to use
      '->'?
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
                                      ~~~~~~~~~~~~~^
                                                   ->
/usr/include/secure/_string.h:65:33: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                                ^~~
injector.c:883:46: error: no member named 'gregs' in 'struct __darwin_mcontext64'
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
                                      ~~~~~~~~~~~~~ ^
/usr/include/secure/_string.h:65:33: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                                ^~~
injector.c:883:73: error: member reference type 'mcontext_t' (aka 'struct __darwin_mcontext64 *') is a pointer; did you mean to use
      '->'?
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
                                                                  ~~~~~~~~~~~~~^
                                                                               ->
/usr/include/secure/_string.h:65:38: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                                     ^~~
injector.c:883:74: error: no member named 'gregs' in 'struct __darwin_mcontext64'
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
                                                                  ~~~~~~~~~~~~~ ^
/usr/include/secure/_string.h:65:38: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                                     ^~~
injector.c:883:24: error: member reference type 'struct __darwin_mcontext64 *' is a pointer; did you mean to use '->'?
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
               ~~~~~~~~~~~~~~~^
                              ->
/usr/include/secure/_string.h:65:59: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                                                          ^~~~
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
                                                      ^~~~~~
injector.c:883:25: error: no member named 'gregs' in 'struct __darwin_mcontext64'
        memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
               ~~~~~~~~~~~~~~~ ^
/usr/include/secure/_string.h:65:59: note: expanded from macro 'memcpy'
  __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
                                                          ^~~~
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0'
#define __darwin_obsz0(object) __builtin_object_size (object, 0)
                                                      ^~~~~~
injector.c:884:17: error: member reference type 'struct __darwin_mcontext64 *' is a pointer; did you mean to use '->'?
        uc->uc_mcontext.gregs[IP]=(uintptr_t)&resume;
        ~~~~~~~~~~~~~~~^
                       ->
injector.c:884:18: error: no member named 'gregs' in 'struct __darwin_mcontext64'
        uc->uc_mcontext.gregs[IP]=(uintptr_t)&resume;
        ~~~~~~~~~~~~~~~ ^
injector.c:884:24: error: use of undeclared identifier 'REG_RIP'
        uc->uc_mcontext.gregs[IP]=(uintptr_t)&resume;
                              ^
injector.c:81:13: note: expanded from macro 'IP'
        #define IP REG_RIP
                   ^
injector.c:885:17: error: member reference type 'struct __darwin_mcontext64 *' is a pointer; did you mean to use '->'?
        uc->uc_mcontext.gregs[REG_EFL]&=~TF;
        ~~~~~~~~~~~~~~~^
                       ->
injector.c:885:18: error: no member named 'gregs' in 'struct __darwin_mcontext64'
        uc->uc_mcontext.gregs[REG_EFL]&=~TF;
        ~~~~~~~~~~~~~~~ ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
2 warnings and 20 errors generated.
make: *** [injector.o] Error 1

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:13
  • Comments:15

github_iconTop GitHub Comments

3reactions
floatingatollcommented, Jul 28, 2017
-       ((ucontext_t*)p)->uc_mcontext.gregs[IP]+=UD2_SIZE;
+       ((ucontext_t*)p)->uc_mcontext->__ss.__rip+=UD2_SIZE;

Variations of this seem to, at the very least, remove more warnings. Still doesn’t compile and I’d be surprised if a straight swap out here worked.

1reaction
jaketeslercommented, Feb 5, 2019

I got this to compile, but I’m not sure if the executable still works as intended. This is ONLY for 64-bit – I didn’t take the time to convert these changes for 32-bit, but I imagine it wouldn’t be too difficult.


Change 1: Dummy Struct

Modify the following snippet: https://github.com/xoreaxeaxeax/sandsifter/blob/8375e6123d093629e3e4437d7903839fd0742c2a/injector.c#L174-L177 Delete the entire dummy_stack definition. Then, copy the following (to anywhere before the inject_state typedef struct definition on line 90!):

typedef struct {
	uint64_t dummy_stack_hi[256];
	uint64_t dummy_stack_lo[256];
} dumb_stack;
static dumb_stack dummy_stack __attribute__ ((aligned(PAGE_SIZE)));

Then, in the __x86_64__ inject_state definition, modify the struct:

...
	uint64_t rsp;
	dumb_stack dumb;
} state_t;
...

and the inject_state definition:

...
	.rsp=0,
	.dumb.dummy_stack_lo=0,
	.dumb.dummy_stack_hi=0
};
...

We also need to modify the stack reset on line 766:

inject_state.dumb.dummy_stack_lo[0]=0;

And lastly, we need to modify the inline asm here: https://github.com/xoreaxeaxeax/sandsifter/blob/8375e6123d093629e3e4437d7903839fd0742c2a/injector.c#L777-L815 The asm on line 813 should read:

[rsp]"m"(inject_state.dumb.dummy_stack_lo),

Change 2: uc_mcontext

We need to modify uc_mcontext references for macOS. Make all of the following changes:

  • Line 853:
((ucontext_t*)p)->uc_mcontext->__ss.__rip+=UD2_SIZE;
  • Line 866:
(uintptr_t)uc->uc_mcontext->__ss.__rip-(uintptr_t)packet-preamble_length;
  • Lines 883-885:
uc->uc_mcontext->__ss = fault_context->__ss;
uc->uc_mcontext->__ss.__rip =(uintptr_t)&resume;
uc->uc_mcontext->__ss.__rflags &=~TF;

Change 3: header file

Create a new file injector.h with the following contents:

extern char debug, resume, preamble_start, preamble_end;

Then modify the extern definition on line 366. https://github.com/xoreaxeaxeax/sandsifter/blob/8375e6123d093629e3e4437d7903839fd0742c2a/injector.c#L366 Change line 366 to:

char debug, resume, preamble_start, preamble_end;

Change 4: pthread modifications

This code was borrowed from https://yyshen.github.io/2015/01/18/binding_threads_to_cores_osx.html. Copy the following block underneath the top #include section.

#define SYSCTL_CORE_COUNT   "machdep.cpu.core_count"

typedef struct cpu_set {
  uint32_t    count;
} cpu_set_t;

static inline void
CPU_ZERO(cpu_set_t *cs) { cs->count = 0; }

static inline void
CPU_SET(int num, cpu_set_t *cs) { cs->count |= (1 << num); }

static inline int
CPU_ISSET(int num, cpu_set_t *cs) { return (cs->count & (1 << num)); }

int sched_getaffinity(pid_t pid, size_t cpu_size, cpu_set_t *cpu_set)
{
  int32_t core_count = 0;
  size_t  len = sizeof(core_count);
  int ret = sysctlbyname(SYSCTL_CORE_COUNT, &core_count, &len, 0, 0);
  if (ret) {
    printf("error while get core count %d\n", ret);
    return -1;
  }
  cpu_set->count = 0;
  for (int i = 0; i < core_count; i++) {
    cpu_set->count |= (1 << i);
  }

  return 0;
}

int pthread_setaffinity_np(pthread_t thread, size_t cpu_size,
                           cpu_set_t *cpu_set)
{
  thread_port_t mach_thread;
  int core = 0;

  for (core = 0; core < 8 * cpu_size; core++) {
    if (CPU_ISSET(core, cpu_set)) break;
  }
  printf("binding to core %d\n", core);
  thread_affinity_policy_data_t policy = { core };
  mach_thread = pthread_mach_thread_np(thread);
  thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY,
                    (thread_policy_t)&policy, 1);
  return 0;
}

Then, modify line 1344 to read:

if (pthread_setaffinity_np(0, sizeof(mask), &mask)) {

Lastly, append this to the #include section

#include <mach/thread_policy.h>

Change 5: Python

The sifter.py file is designed for Linux and attempts to gather CPU info via /proc/cpuinfo, which doesn’t exist on macOS. So, I made a small change to allow running on a Mac. https://github.com/xoreaxeaxeax/sandsifter/blob/8375e6123d093629e3e4437d7903839fd0742c2a/sifter.py#L681-L684 Modify the get_cpu_info() function to:

def get_cpu_info():
    p =  subprocess.Popen(['/usr/sbin/sysctl','-a'], stdout=subprocess.PIPE)
    p.wait()
    cpu = [l.strip('machdep.cpu.') for l in str(p.stdout.read()).split('\n') if 'machdep.cpu' in l]
    return cpu

Lastly, run make. If you encounter this error:

/usr/include/ucontext.h:43:2: error: The deprecated ucontext routines require _XOPEN_SOURCE to be defined

Run make with the CFLAGS variable:

CFLAGS="-D_XOPEN_SOURCE" make

Hope this helps! Also hopefully the injector binary still functions as expected. Please comment below with results or findings.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Terminal compiling problem | Apple Developer Forums
Good evening everyone, I write in this forum for an error message that the compiler from terminal MacOS returns me after sending the...
Read more >
Compiling on macOS 12.0 Monterey fails · Issue #7657 · curl/curl
I did this After discovering that the Homebrew build (on 11.0) curl was very slow when running curl --version I tried reinstalling curl...
Read more >
Compiling code with gcc on macOS Monterey 12.5.1 results in ...
I get a clang error: clang: error: invalid version number in '-mmacosx-version-min=12.5' when using gcc-12 and gfortran-12. The version number ...
Read more >
Fail to compiling ocaml-base-compiler.3.12.0 on macos
Hello all, I am trying to install an old ocaml version on my macos. `opam switch create compcert-tso ocaml-base-compiler.3.12.0` But I got ...
Read more >
M1 Mac: Cannot build packages requiring compilation - General
... that requires compilation as it fails every time with error messages ... on a Mac Studio with an M1 Max chip on...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found