2  * Copyright (c) 2015 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 #include <mach/mach.h> 
  31 thread_get_register_pointer_values(thread_t thread
, uintptr_t *sp
, size_t *length
, uintptr_t *values
) 
  34                 return KERN_INVALID_ARGUMENT
; 
  36         if (*length 
> 0 && values 
== NULL
) { 
  37                 return KERN_INVALID_ARGUMENT
; 
  40         size_t in_length 
= *length
; 
  41         size_t out_length 
= 0; 
  44         i386_thread_state_t state 
= {}; 
  45         thread_state_flavor_t flavor 
= x86_THREAD_STATE32
; 
  46         mach_msg_type_number_t count 
= i386_THREAD_STATE_COUNT
; 
  47 #elif defined(__x86_64__) 
  48         x86_thread_state64_t state 
= {}; 
  49         thread_state_flavor_t flavor 
= x86_THREAD_STATE64
; 
  50         mach_msg_type_number_t count 
= x86_THREAD_STATE64_COUNT
; 
  51 #elif defined(__arm__) 
  52         arm_thread_state_t state 
= {}; 
  53         thread_state_flavor_t flavor 
= ARM_THREAD_STATE
; 
  54         mach_msg_type_number_t count 
= ARM_THREAD_STATE_COUNT
; 
  55 #elif defined(__arm64__) 
  56         arm_thread_state64_t state 
= {}; 
  57         thread_state_flavor_t flavor 
= ARM_THREAD_STATE64
; 
  58         mach_msg_type_number_t count 
= ARM_THREAD_STATE64_COUNT
; 
  60 #error thread_get_register_pointer_values not defined for this architecture 
  63         kern_return_t ret 
= thread_get_state(thread
, flavor
, (thread_state_t
)&state
, &count
); 
  64         if (ret 
!= KERN_SUCCESS
) { 
  68         // If the provided pointer value is > PAGE_SIZE, add it to the output array 
  69         // if there's available space.  (Values between 0 and PAGE_SIZE are the NULL page 
  70         // and not valid pointers.) 
  71 #define push_register_value(p) do { \ 
  72     if ((uintptr_t)p > PAGE_SIZE) { \ 
  73         if (out_length < in_length && values) \ 
  74             values[out_length] = p; \ 
  83         push_register_value(state
.__eax
); 
  84         push_register_value(state
.__ebx
); 
  85         push_register_value(state
.__ecx
); 
  86         push_register_value(state
.__edx
); 
  87         push_register_value(state
.__edi
); 
  88         push_register_value(state
.__esi
); 
  89         push_register_value(state
.__ebp
); 
  90 #elif defined(__x86_64__) 
  92                 if (state
.__rsp 
> 128) { 
  93                         *sp 
= state
.__rsp 
- 128 /* redzone */; 
  99         push_register_value(state
.__rax
); 
 100         push_register_value(state
.__rbx
); 
 101         push_register_value(state
.__rcx
); 
 102         push_register_value(state
.__rdx
); 
 103         push_register_value(state
.__rdi
); 
 104         push_register_value(state
.__rbp
); 
 105         push_register_value(state
.__r8
); 
 106         push_register_value(state
.__r9
); 
 107         push_register_value(state
.__r10
); 
 108         push_register_value(state
.__r11
); 
 109         push_register_value(state
.__r12
); 
 110         push_register_value(state
.__r13
); 
 111         push_register_value(state
.__r14
); 
 112         push_register_value(state
.__r15
); 
 113 #elif defined(__arm__) 
 118         push_register_value(state
.__lr
); 
 120         for (int i 
= 0; i 
< 13; i
++) { 
 121                 push_register_value(state
.__r
[i
]); 
 123 #elif defined(__arm64__) 
 125                 uintptr_t __sp 
= arm_thread_state64_get_sp(state
); 
 127                         *sp 
= __sp 
- 128 /* redzone */; 
 133         push_register_value(arm_thread_state64_get_lr(state
)); 
 135         for (int i 
= 0; i 
< 29; i
++) { 
 136                 push_register_value(state
.__x
[i
]); 
 139 #error thread_get_register_pointer_values not defined for this architecture 
 142         *length 
= out_length
; 
 144         if (in_length 
== 0 || out_length 
> in_length
) { 
 145                 return KERN_INSUFFICIENT_BUFFER_SIZE
;