├── Makefile ├── screenshot.png ├── src ├── core │ ├── Makefile │ ├── NSString_helper.h │ ├── ncmnp_traps.h │ ├── ncmnp_types.h │ ├── ncmnp.h │ ├── ncmnp_commons.h │ ├── ncmnp_utils.h │ ├── NSString_helper.m │ ├── mach_exc.h │ ├── ncmnp.m │ └── mach_excServer.c └── cli │ ├── Makefile │ ├── script.py │ └── main.c ├── .gitignore └── README.md /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | mkdir -p build 3 | make -C src/core 4 | make -C src/cli 5 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sumimakito/NeteaseCloudMusic-Now-Playing/HEAD/screenshot.png -------------------------------------------------------------------------------- /src/core/Makefile: -------------------------------------------------------------------------------- 1 | CC=clang 2 | 3 | FRAMEWORKS:=-fobjc-arc 4 | 5 | SOURCE=ncmnp.m NSString_helper.m mach_excServer.c 6 | 7 | OUT_DIR=../../build 8 | 9 | OUT=libncmnp.dylib 10 | 11 | all: 12 | $(CC) -dynamiclib $(SOURCE) $(FRAMEWORKS) -o $(OUT_DIR)/$(OUT) 13 | -------------------------------------------------------------------------------- /src/core/NSString_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef NSString_helper_h 2 | #define NSString_helper_h 3 | 4 | #include 5 | 6 | void convert_NSTaggedPointerStrings_to_c_str(uint64_t ns_tps, char *buffer, unsigned long buffer_size); 7 | 8 | void copy_NSString_to_c_str(void *nss_ptr, char *buffer, unsigned long buffer_size); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/cli/Makefile: -------------------------------------------------------------------------------- 1 | CC=clang 2 | 3 | LD:=-lncmnp 4 | 5 | DYLIB_DIR:=../../build 6 | 7 | DYLIB=libncmnp.dylib 8 | 9 | LDFLAGS+=-L$(DYLIB_DIR) 10 | 11 | SOURCE=main.c 12 | 13 | OUT_DIR=../../build 14 | 15 | OUT=ncmnp 16 | 17 | all: 18 | $(CC) $(LD) $(LDFLAGS) $(SOURCE) -o $(OUT_DIR)/$(OUT) 19 | install_name_tool -change $(DYLIB_DIR)/$(DYLIB) @executable_path/$(DYLIB) $(OUT_DIR)/$(OUT) 20 | -------------------------------------------------------------------------------- /src/core/ncmnp_traps.h: -------------------------------------------------------------------------------- 1 | #ifndef NCMNP_NCMNP_TRAPS_H 2 | #define NCMNP_NCMNP_TRAPS_H 3 | 4 | #include "ncmnp_types.h" 5 | 6 | const byte_t _TRAP[] = {0xcc}; 7 | 8 | #define TRAP_SONG_NAME ((trap_t) 0x95089) 9 | #define TRAP_ARTIST_NAME ((trap_t) 0x950f7) 10 | #define TRAP_ALBUM_NAME ((trap_t) 0x9510f) 11 | #define TRAP_RST ((trap_t) 0x95112) 12 | #define TRAP ((vm_offset_t) &_TRAP[0]) 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/cli/script.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def on_updated(song, artist, album): 5 | with open('now-playing.txt', 'w') as f: 6 | f.write('\n'.join([song, artist, album])) 7 | 8 | 9 | if __name__ == '__main__': 10 | if len(sys.argv) != 4: 11 | print('invalid arguments') 12 | print('usage: {} song artist album'.format(sys.argv[0])) 13 | exit(0) 14 | on_updated(sys.argv[1], sys.argv[2], sys.argv[3]) 15 | -------------------------------------------------------------------------------- /src/core/ncmnp_types.h: -------------------------------------------------------------------------------- 1 | #ifndef NCMNP_NCMNP_TYPES_H 2 | #define NCMNP_NCMNP_TYPES_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef u_char byte_t; 9 | typedef uint64_t trap_t; 10 | typedef x86_thread_state64_t th_state_t; 11 | 12 | #define TH_STATE x86_THREAD_STATE64 13 | #define TH_STATE_COUNT x86_THREAD_STATE64_COUNT 14 | #define VM_RWX ((vm_prot_t) (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)) 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | /build 3 | 4 | # Prerequisites 5 | *.d 6 | 7 | # Object files 8 | *.o 9 | *.ko 10 | *.obj 11 | *.elf 12 | 13 | # Linker output 14 | *.ilk 15 | *.map 16 | *.exp 17 | 18 | # Precompiled Headers 19 | *.gch 20 | *.pch 21 | 22 | # Libraries 23 | *.lib 24 | *.a 25 | *.la 26 | *.lo 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | 42 | # Debug files 43 | *.dSYM/ 44 | *.su 45 | *.idb 46 | *.pdb 47 | 48 | # Kernel Module Compile Results 49 | *.mod* 50 | *.cmd 51 | .tmp_versions/ 52 | modules.order 53 | Module.symvers 54 | Mkfile.old 55 | dkms.conf -------------------------------------------------------------------------------- /src/core/ncmnp.h: -------------------------------------------------------------------------------- 1 | #ifndef NCMNP_NCMNP_H 2 | #define NCMNP_NCMNP_H 3 | 4 | #include 5 | #include 6 | #include "ncmnp_types.h" 7 | #include "ncmnp_commons.h" 8 | 9 | byte_t *memory_backup_for(trap_t trap); 10 | 11 | void arbitrary_copy_NSString_to_c_str(vm_address_t address, char *buffer, unsigned long buffer_size); 12 | 13 | void target_backup_mem(trap_t trap); 14 | 15 | void target_set_trap(trap_t trap); 16 | 17 | void target_reset_trap(trap_t trap); 18 | 19 | void target_set_traps(); 20 | 21 | void print_registers(th_state_t thread_state); 22 | 23 | void handle_trap(th_state_t *thread_state); 24 | 25 | vm_address_t get_base_for_task(mach_port_name_t task); 26 | 27 | vm_address_t get_base_for_pid(pid_t pid); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/core/ncmnp_commons.h: -------------------------------------------------------------------------------- 1 | #ifndef NCMNP_NCMNP_COMMONS_H 2 | #define NCMNP_NCMNP_COMMONS_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct song_info { 8 | char song[2048]; 9 | char artist[2048]; 10 | char album[2048]; 11 | vm_address_t _song_addr; 12 | vm_address_t _artist_addr; 13 | vm_address_t _album_addr; 14 | uint _song_updated; 15 | uint _artist_updated; 16 | uint _album_updated; 17 | } song_info_t; 18 | 19 | #define FUNC_ON_UPDATE_GENERATE(name) void (*(name))(song_info_t *) 20 | #define FUNC_ON_UPDATE_TYPE void (*)(song_info_t *) 21 | 22 | void detach(pid_t target_pid, mach_port_name_t target_exception_port); 23 | 24 | void attach(pid_t target_pid, FUNC_ON_UPDATE_TYPE); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/core/ncmnp_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef NCMNP_NCMNP_UTILS_H 2 | #define NCMNP_NCMNP_UTILS_H 3 | 4 | #include 5 | 6 | #ifdef NCMNP_LOGGING_COLORFUL 7 | #define FATAL(fmt, args...) printf("\e[91mfatal: " fmt "\e[0m\n", ##args); exit(EXIT_FAILURE) 8 | #define WARN(fmt, args...) printf("\e[93mwarning: " fmt "\e[0m\n", ##args) 9 | #define INFO(fmt, args...) printf("\e[96minfo: " fmt "\e[0m\n", ##args) 10 | #else 11 | #ifdef NCMNP_LOGGING_NORMAL 12 | #define FATAL(fmt, args...) printf("fatal: " fmt "\n", ##args); exit(EXIT_FAILURE) 13 | #define WARN(fmt, args...) printf("warning: " fmt "\n", ##args) 14 | #define INFO(fmt, args...) printf("info: " fmt "\n", ##args) 15 | #else 16 | #define FATAL(fmt, args...) printf("fatal: " fmt "\n", ##args); exit(EXIT_FAILURE) 17 | #define WARN(fmt, args...) printf("warning: " fmt "\n", ##args) 18 | #define INFO(fmt, args...) 19 | #endif 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NeteaseCloudMusic-Now-Playing 2 | ====== 3 | 通过进程注入的方式来获得 macOS 网易云音乐的正在播放信息 4 | 5 | ![screenshot.png](screenshot.png) 6 | 7 | ## 应用范例 8 | 9 | 同步我的近期正在播放信息 10 | 11 | [https://mak1t0.cc/now-playing](https://mak1t0.cc/now-playing) 12 | 13 | ## 详细思路 14 | 15 | [https://keep.moe/2019/05/16/netease-now-playing-lldb/](https://keep.moe/2019/05/16/netease-now-playing-lldb/) 16 | 17 | [https://keep.moe/2019/05/16/netease-now-playing-interceptor/](https://keep.moe/2019/05/16/netease-now-playing-interceptor/) 18 | 19 | ## 构建 20 | 21 | 运行 `make` 构建成功后将生成 build 文件夹,其中 libncmnp.dylib 需要与可执行文件处于同一目录下。 22 | 23 | ## 使用 24 | 25 | 将 src/cli/script.py 复制至可执行文件所在目录,并保证 libncmnp.dylib 在同一目录下。 26 | 27 | 可以对 script.py 中的 on_updated 函数体进行修改,但不推荐修改函数签名。 28 | 29 | 另外由于脚本部分将使用 execv 调用 python,引入更多外部依赖可能会导致运行时出现未知问题,因此推荐在 script.py 中仅进行本地文件 I/O 操作(如更新记录当前播放歌曲信息的文件)。 30 | 31 | 这种情况下可以配合外部单独运行的 File watcher 来进行更复杂的操作。 32 | 33 | ``` 34 | sudo ./ncmnp $(pgrep NeteaseMusic) 35 | ``` 36 | 37 | > 缺少 sudo 会无法 Attach 及对内存进行注入 38 | 39 | ## 其他 40 | 41 | 代码仍在整理中,目前 leaks 工具暂未发现运行时内存泄漏。欢迎提供发现的 Bug。 42 | -------------------------------------------------------------------------------- /src/cli/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../core/ncmnp_commons.h" 6 | 7 | extern char **environ; 8 | 9 | void on_updated(song_info_t *song_info) { 10 | printf("Now playing:\n"); 11 | printf("Song: %s\n", song_info->song); 12 | printf("Artist: %s\n", song_info->artist); 13 | printf("Album: %s\n", song_info->album); 14 | int pid = fork(); 15 | if (pid == -1) { 16 | printf("failed to fork child process to call Python script"); 17 | } else if (pid == 0) { 18 | int fd = open("/dev/null", O_WRONLY); 19 | close(fd); 20 | char *args[6] = {"python", "script.py", song_info->song, song_info->artist, song_info->album, 0}; 21 | execve("/usr/bin/python", args, environ); 22 | exit(0); 23 | } 24 | } 25 | 26 | int main(int argc, const char *argv[]) { 27 | if (argc != 2) { 28 | printf("NeteaseMusic Now Playing\n"); 29 | printf("Usage: %s PID\n", argv[0]); 30 | exit(0); 31 | } 32 | pid_t pid = (pid_t) strtol(argv[1], NULL, 10); 33 | attach(pid, &on_updated); 34 | } -------------------------------------------------------------------------------- /src/core/NSString_helper.m: -------------------------------------------------------------------------------- 1 | #import 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "NSString_helper.h" 7 | #include "ncmnp.h" 8 | #include "ncmnp_utils.h" 9 | 10 | const char NSTPS_ENCODING_TABLE[] = "eilotrm.apdnsIc ufkMShjTRxgC4013bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX"; 11 | 12 | // A helper function that converts NSTaggedPointerStrings to C strings 13 | // Special thanks to Mike Ash (https://www.mikeash.com/pyblog/friday-qa-2015-07-31-tagged-pointer-strings.html) 14 | void convert_NSTaggedPointerStrings_to_c_str(uint64_t ns_tps, char *buffer, unsigned long buffer_size) { 15 | // an NSTaggedPointerString can hold up to 11 characters (null-terminator not included) 16 | char _buffer[11]; 17 | if (buffer_size < 11) { 18 | FATAL("convert_NSTaggedPointerStrings_to_c_str failed: buffer size must not be smaller than 11\n"); 19 | } 20 | uint64_t length = ns_tps >> 0x4 & 0xf; 21 | if (length >= 0x8) { 22 | uint64_t stringData = ns_tps >> 0x8; 23 | uint64_t cursor = length; 24 | if (length < 0xa) { 25 | do { 26 | _buffer[cursor - 1] = NSTPS_ENCODING_TABLE[stringData & 0x3f]; 27 | cursor = cursor - 0x1; 28 | stringData = stringData >> 0x6; 29 | } while (cursor != 0x0); 30 | } else { 31 | do { 32 | _buffer[cursor - 1] = NSTPS_ENCODING_TABLE[stringData & 0x1f]; 33 | cursor = cursor - 0x1; 34 | stringData = stringData >> 0x5; 35 | } while (cursor != 0x0); 36 | } 37 | } else { 38 | *(uint64_t *) _buffer = ns_tps >> 0x8; 39 | } 40 | memcpy(buffer, _buffer, 11); 41 | buffer[10] = 0; 42 | } 43 | 44 | #ifdef __OBJC__ 45 | void copy_NSString_to_c_str(void *nss_ptr, char *buffer, unsigned long buffer_size){ 46 | void *ns_str_mem = calloc(buffer_size, 1); 47 | memcpy(ns_str_mem, nss_ptr, buffer_size); 48 | NSString *str = (__bridge NSString *) (ns_str_mem); 49 | const char *c_str = [str UTF8String]; 50 | memcpy(buffer, c_str, MIN(buffer_size, strlen(c_str) + 1)); 51 | buffer[buffer_size - 1] = 0; 52 | free(ns_str_mem); 53 | } 54 | #endif 55 | -------------------------------------------------------------------------------- /src/core/mach_exc.h: -------------------------------------------------------------------------------- 1 | #ifndef _mach_exc_user_ 2 | #define _mach_exc_user_ 3 | 4 | /* Module mach_exc */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* BEGIN VOUCHER CODE */ 17 | 18 | #ifndef KERNEL 19 | #if defined(__has_include) 20 | #if __has_include() 21 | #ifndef USING_VOUCHERS 22 | #define USING_VOUCHERS 23 | #endif 24 | #ifndef __VOUCHER_FORWARD_TYPE_DECLS__ 25 | #define __VOUCHER_FORWARD_TYPE_DECLS__ 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | #endif // __VOUCHER_FORWARD_TYPE_DECLS__ 34 | #endif // __has_include() 35 | #endif // __has_include 36 | #endif // !KERNEL 37 | 38 | /* END VOUCHER CODE */ 39 | 40 | 41 | /* BEGIN MIG_STRNCPY_ZEROFILL CODE */ 42 | 43 | #if defined(__has_include) 44 | #if __has_include() 45 | #ifndef USING_MIG_STRNCPY_ZEROFILL 46 | #define USING_MIG_STRNCPY_ZEROFILL 47 | #endif 48 | #ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ 49 | #define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import)); 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | #endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */ 58 | #endif /* __has_include() */ 59 | #endif /* __has_include */ 60 | 61 | /* END MIG_STRNCPY_ZEROFILL CODE */ 62 | 63 | 64 | #ifdef AUTOTEST 65 | #ifndef FUNCTION_PTR_T 66 | #define FUNCTION_PTR_T 67 | typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); 68 | typedef struct { 69 | char *name; 70 | function_ptr_t function; 71 | } function_table_entry; 72 | typedef function_table_entry *function_table_t; 73 | #endif /* FUNCTION_PTR_T */ 74 | #endif /* AUTOTEST */ 75 | 76 | #ifndef mach_exc_MSG_COUNT 77 | #define mach_exc_MSG_COUNT 3 78 | #endif /* mach_exc_MSG_COUNT */ 79 | 80 | #include 81 | #include 82 | #include 83 | #include 84 | 85 | #ifdef __BeforeMigUserHeader 86 | __BeforeMigUserHeader 87 | #endif /* __BeforeMigUserHeader */ 88 | 89 | #include 90 | __BEGIN_DECLS 91 | 92 | 93 | /* Routine mach_exception_raise */ 94 | #ifdef mig_external 95 | mig_external 96 | #else 97 | extern 98 | #endif /* mig_external */ 99 | kern_return_t mach_exception_raise 100 | ( 101 | mach_port_t exception_port, 102 | mach_port_t thread, 103 | mach_port_t task, 104 | exception_type_t exception, 105 | mach_exception_data_t code, 106 | mach_msg_type_number_t codeCnt 107 | ); 108 | 109 | /* Routine mach_exception_raise_state */ 110 | #ifdef mig_external 111 | mig_external 112 | #else 113 | extern 114 | #endif /* mig_external */ 115 | kern_return_t mach_exception_raise_state 116 | ( 117 | mach_port_t exception_port, 118 | exception_type_t exception, 119 | const mach_exception_data_t code, 120 | mach_msg_type_number_t codeCnt, 121 | int *flavor, 122 | const thread_state_t old_state, 123 | mach_msg_type_number_t old_stateCnt, 124 | thread_state_t new_state, 125 | mach_msg_type_number_t *new_stateCnt 126 | ); 127 | 128 | /* Routine mach_exception_raise_state_identity */ 129 | #ifdef mig_external 130 | mig_external 131 | #else 132 | extern 133 | #endif /* mig_external */ 134 | kern_return_t mach_exception_raise_state_identity 135 | ( 136 | mach_port_t exception_port, 137 | mach_port_t thread, 138 | mach_port_t task, 139 | exception_type_t exception, 140 | mach_exception_data_t code, 141 | mach_msg_type_number_t codeCnt, 142 | int *flavor, 143 | thread_state_t old_state, 144 | mach_msg_type_number_t old_stateCnt, 145 | thread_state_t new_state, 146 | mach_msg_type_number_t *new_stateCnt 147 | ); 148 | 149 | __END_DECLS 150 | 151 | /********************** Caution **************************/ 152 | /* The following data types should be used to calculate */ 153 | /* maximum message sizes only. The actual message may be */ 154 | /* smaller, and the position of the arguments within the */ 155 | /* message layout may vary from what is presented here. */ 156 | /* For example, if any of the arguments are variable- */ 157 | /* sized, and less than the maximum is sent, the data */ 158 | /* will be packed tight in the actual message to reduce */ 159 | /* the presence of holes. */ 160 | /********************** Caution **************************/ 161 | 162 | /* typedefs for all requests */ 163 | 164 | #ifndef __Request__mach_exc_subsystem__defined 165 | #define __Request__mach_exc_subsystem__defined 166 | 167 | #ifdef __MigPackStructs 168 | #pragma pack(4) 169 | #endif 170 | typedef struct { 171 | mach_msg_header_t Head; 172 | /* start of the kernel processed data */ 173 | mach_msg_body_t msgh_body; 174 | mach_msg_port_descriptor_t thread; 175 | mach_msg_port_descriptor_t task; 176 | /* end of the kernel processed data */ 177 | NDR_record_t NDR; 178 | exception_type_t exception; 179 | mach_msg_type_number_t codeCnt; 180 | int64_t code[2]; 181 | } __Request__mach_exception_raise_t __attribute__((unused)); 182 | #ifdef __MigPackStructs 183 | #pragma pack() 184 | #endif 185 | 186 | #ifdef __MigPackStructs 187 | #pragma pack(4) 188 | #endif 189 | typedef struct { 190 | mach_msg_header_t Head; 191 | NDR_record_t NDR; 192 | exception_type_t exception; 193 | mach_msg_type_number_t codeCnt; 194 | int64_t code[2]; 195 | int flavor; 196 | mach_msg_type_number_t old_stateCnt; 197 | natural_t old_state[224]; 198 | } __Request__mach_exception_raise_state_t __attribute__((unused)); 199 | #ifdef __MigPackStructs 200 | #pragma pack() 201 | #endif 202 | 203 | #ifdef __MigPackStructs 204 | #pragma pack(4) 205 | #endif 206 | typedef struct { 207 | mach_msg_header_t Head; 208 | /* start of the kernel processed data */ 209 | mach_msg_body_t msgh_body; 210 | mach_msg_port_descriptor_t thread; 211 | mach_msg_port_descriptor_t task; 212 | /* end of the kernel processed data */ 213 | NDR_record_t NDR; 214 | exception_type_t exception; 215 | mach_msg_type_number_t codeCnt; 216 | int64_t code[2]; 217 | int flavor; 218 | mach_msg_type_number_t old_stateCnt; 219 | natural_t old_state[224]; 220 | } __Request__mach_exception_raise_state_identity_t __attribute__((unused)); 221 | #ifdef __MigPackStructs 222 | #pragma pack() 223 | #endif 224 | #endif /* !__Request__mach_exc_subsystem__defined */ 225 | 226 | /* union of all requests */ 227 | 228 | #ifndef __RequestUnion__mach_exc_subsystem__defined 229 | #define __RequestUnion__mach_exc_subsystem__defined 230 | union __RequestUnion__mach_exc_subsystem { 231 | __Request__mach_exception_raise_t Request_mach_exception_raise; 232 | __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; 233 | __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; 234 | }; 235 | #endif /* !__RequestUnion__mach_exc_subsystem__defined */ 236 | /* typedefs for all replies */ 237 | 238 | #ifndef __Reply__mach_exc_subsystem__defined 239 | #define __Reply__mach_exc_subsystem__defined 240 | 241 | #ifdef __MigPackStructs 242 | #pragma pack(4) 243 | #endif 244 | typedef struct { 245 | mach_msg_header_t Head; 246 | NDR_record_t NDR; 247 | kern_return_t RetCode; 248 | } __Reply__mach_exception_raise_t __attribute__((unused)); 249 | #ifdef __MigPackStructs 250 | #pragma pack() 251 | #endif 252 | 253 | #ifdef __MigPackStructs 254 | #pragma pack(4) 255 | #endif 256 | typedef struct { 257 | mach_msg_header_t Head; 258 | NDR_record_t NDR; 259 | kern_return_t RetCode; 260 | int flavor; 261 | mach_msg_type_number_t new_stateCnt; 262 | natural_t new_state[224]; 263 | } __Reply__mach_exception_raise_state_t __attribute__((unused)); 264 | #ifdef __MigPackStructs 265 | #pragma pack() 266 | #endif 267 | 268 | #ifdef __MigPackStructs 269 | #pragma pack(4) 270 | #endif 271 | typedef struct { 272 | mach_msg_header_t Head; 273 | NDR_record_t NDR; 274 | kern_return_t RetCode; 275 | int flavor; 276 | mach_msg_type_number_t new_stateCnt; 277 | natural_t new_state[224]; 278 | } __Reply__mach_exception_raise_state_identity_t __attribute__((unused)); 279 | #ifdef __MigPackStructs 280 | #pragma pack() 281 | #endif 282 | #endif /* !__Reply__mach_exc_subsystem__defined */ 283 | 284 | /* union of all replies */ 285 | 286 | #ifndef __ReplyUnion__mach_exc_subsystem__defined 287 | #define __ReplyUnion__mach_exc_subsystem__defined 288 | union __ReplyUnion__mach_exc_subsystem { 289 | __Reply__mach_exception_raise_t Reply_mach_exception_raise; 290 | __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; 291 | __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; 292 | }; 293 | #endif /* !__RequestUnion__mach_exc_subsystem__defined */ 294 | 295 | #ifndef subsystem_to_name_map_mach_exc 296 | #define subsystem_to_name_map_mach_exc \ 297 | { "mach_exception_raise", 2405 },\ 298 | { "mach_exception_raise_state", 2406 },\ 299 | { "mach_exception_raise_state_identity", 2407 } 300 | #endif 301 | 302 | #ifdef __AfterMigUserHeader 303 | __AfterMigUserHeader 304 | #endif /* __AfterMigUserHeader */ 305 | 306 | #endif /* _mach_exc_user_ */ 307 | -------------------------------------------------------------------------------- /src/core/ncmnp.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "NSString_helper.h" 13 | #include "ncmnp.h" 14 | #include "ncmnp_traps.h" 15 | 16 | //#define NCMNP_LOGGING_COLORFUL 17 | 18 | #include "ncmnp_utils.h" 19 | 20 | byte_t _memory_backup[4]; 21 | vm_address_t base; 22 | mach_port_name_t target_task_port; 23 | uid_t startup_uid; 24 | uint detach_ctrl = 0; 25 | 26 | FUNC_ON_UPDATE_GENERATE(_func_on_update) = NULL; 27 | 28 | song_info_t current_song_info; 29 | 30 | byte_t *memory_backup_for(trap_t trap) { 31 | switch (trap) { 32 | case TRAP_SONG_NAME: 33 | return &_memory_backup[0]; 34 | case TRAP_ARTIST_NAME: 35 | return &_memory_backup[1]; 36 | case TRAP_ALBUM_NAME: 37 | return &_memory_backup[2]; 38 | case TRAP_RST: 39 | return &_memory_backup[3]; 40 | default: 41 | return 0; 42 | } 43 | } 44 | 45 | void arbitrary_copy_NSString_to_c_str(vm_address_t address, char *buffer, unsigned long buffer_size) { 46 | if (buffer_size < sizeof(vm_address_t)) { 47 | FATAL("arbitrary_copy_NSString_to_c_str failed: buffer size must not be smaller than %d", 48 | (int) sizeof(vm_address_t)); 49 | } 50 | kern_return_t kr; 51 | vm_offset_t data_out = 0; 52 | mach_msg_type_number_t data_out_size = 0; 53 | if ((kr = mach_vm_read(target_task_port, address, buffer_size, &data_out, &data_out_size)) != KERN_SUCCESS) { 54 | INFO("mach_vm_read failed: %s %x", mach_error_string(kr), kr); 55 | // the address itself is likely to be an NSTaggedPointerString but not NSString 56 | convert_NSTaggedPointerStrings_to_c_str(address, buffer, buffer_size); 57 | return; 58 | } 59 | copy_NSString_to_c_str((void *) data_out, buffer, buffer_size); 60 | buffer[buffer_size - 1] = 0; 61 | } 62 | 63 | void target_backup_mem(trap_t trap) { 64 | kern_return_t kr; 65 | if ((kr = mach_vm_protect(target_task_port, base + trap, 1, FALSE, VM_RWX)) != KERN_SUCCESS) { 66 | FATAL("mach_vm_protect failed: %s %x", mach_error_string(kr), kr); 67 | } 68 | 69 | vm_offset_t data_out = 0; 70 | mach_msg_type_number_t data_out_size = 0; 71 | if ((kr = mach_vm_read(target_task_port, base + trap, 1, &data_out, &data_out_size)) != KERN_SUCCESS) { 72 | FATAL("mach_vm_read failed: %s %x", mach_error_string(kr), kr); 73 | } 74 | memcpy(memory_backup_for(trap), (void *) data_out, 1); 75 | } 76 | 77 | void target_set_trap(trap_t trap) { 78 | kern_return_t kr; 79 | if ((kr = mach_vm_protect(target_task_port, base + trap, 1, FALSE, VM_RWX)) != KERN_SUCCESS) { 80 | FATAL("mach_vm_protect failed: %s %x", mach_error_string(kr), kr); 81 | } 82 | 83 | if ((kr = mach_vm_write(target_task_port, base + trap, TRAP, 1)) != KERN_SUCCESS) { 84 | FATAL("mach_vm_write failed: %s %x", mach_error_string(kr), kr); 85 | } 86 | INFO("target_set_trap: %#08llx set", trap); 87 | } 88 | 89 | void target_reset_trap(trap_t trap) { 90 | kern_return_t kr; 91 | if ((kr = mach_vm_protect(target_task_port, base + trap, 1, FALSE, VM_RWX)) != KERN_SUCCESS) { 92 | FATAL("mach_vm_protect failed: %s %x", mach_error_string(kr), kr); 93 | } 94 | 95 | if ((kr = mach_vm_write(target_task_port, base + trap, (vm_offset_t) memory_backup_for(trap), 1)) != KERN_SUCCESS) { 96 | FATAL("mach_vm_write failed: %s %x", mach_error_string(kr), kr); 97 | } 98 | INFO("target_reset_trap: %#08llx reset", trap); 99 | } 100 | 101 | void target_set_traps() { 102 | target_set_trap(TRAP_SONG_NAME); 103 | target_set_trap(TRAP_ARTIST_NAME); 104 | target_set_trap(TRAP_ALBUM_NAME); 105 | } 106 | 107 | void print_registers(th_state_t thread_state) { 108 | INFO("REGISTERS"); 109 | INFO(" RIP = %#016llx (-BASE = %#016llx)", thread_state.__rip, thread_state.__rip - base); 110 | INFO(" RAX = %#016llx", thread_state.__rax); 111 | #ifdef NCMNP_SHOW_ALL_REGS 112 | INFO(" RCX = %#016llx", thread_state.__rcx); 113 | INFO(" RDX = %#016llx", thread_state.__rdx); 114 | INFO(" RBP = %#016llx", thread_state.__rbp); 115 | INFO(" RSI = %#016llx", thread_state.__rsi); 116 | INFO(" RDI = %#016llx", thread_state.__rdi); 117 | INFO(" R8 = %#016llx", thread_state.__r8); 118 | INFO(" R9 = %#016llx", thread_state.__r9); 119 | #endif 120 | } 121 | 122 | void handle_trap(th_state_t *thread_state) { 123 | char buffer[2048]; 124 | trap_t trap = thread_state->__rip - 0x1 - base; 125 | switch (trap) { 126 | case TRAP_SONG_NAME: 127 | case TRAP_ARTIST_NAME: 128 | case TRAP_ALBUM_NAME: 129 | arbitrary_copy_NSString_to_c_str(thread_state->__rax, &buffer[0], 2048); 130 | INFO("\t\t\tNSString = %s", buffer); 131 | target_set_trap(TRAP_RST); 132 | break; 133 | case TRAP_RST: 134 | target_set_traps(); 135 | break; 136 | default: 137 | FATAL("handle_trap failed: unknown trap (%%rip = %#016llx)", thread_state->__rip); 138 | } 139 | switch (trap) { 140 | case TRAP_SONG_NAME: 141 | if (thread_state->__rax != current_song_info._song_addr) { 142 | memcpy(¤t_song_info.song[0], &buffer[0], strlen(buffer) + 1); 143 | current_song_info._song_addr = thread_state->__rax; 144 | current_song_info._song_updated = 1; 145 | } 146 | break; 147 | case TRAP_ARTIST_NAME: 148 | if (thread_state->__rax != current_song_info._artist_addr) { 149 | memcpy(¤t_song_info.artist[0], &buffer[0], strlen(buffer) + 1); 150 | current_song_info._artist_addr = thread_state->__rax; 151 | current_song_info._artist_updated = 1; 152 | } 153 | break; 154 | case TRAP_ALBUM_NAME: 155 | if (thread_state->__rax != current_song_info._album_addr) { 156 | memcpy(¤t_song_info.album[0], &buffer[0], strlen(buffer) + 1); 157 | current_song_info._album_addr = thread_state->__rax; 158 | current_song_info._album_updated = 1; 159 | } 160 | if (current_song_info._song_updated || current_song_info._artist_updated || 161 | current_song_info._album_updated) { 162 | if (_func_on_update != NULL) { 163 | _func_on_update(¤t_song_info); 164 | } 165 | } 166 | current_song_info._song_updated = 0; 167 | current_song_info._artist_updated = 0; 168 | current_song_info._album_updated = 0; 169 | break; 170 | default: 171 | break; 172 | } 173 | target_reset_trap(trap); 174 | thread_state->__rip--; 175 | } 176 | 177 | vm_address_t get_base_for_task(mach_port_name_t task) { 178 | kern_return_t krc; 179 | vm_address_t address = 0; 180 | vm_size_t size = 0; 181 | uint32_t depth = 1; 182 | while (1) { 183 | struct vm_region_submap_info_64 info; 184 | mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; 185 | krc = vm_region_recurse_64(task, &address, &size, &depth, (vm_region_info_64_t) &info, &count); 186 | if (krc == KERN_INVALID_ADDRESS) { 187 | break; 188 | } 189 | if (info.is_submap) { 190 | depth++; 191 | } else { 192 | return address; 193 | } 194 | } 195 | return 0; 196 | } 197 | 198 | vm_address_t get_base_for_pid(pid_t pid) { 199 | mach_port_name_t task; 200 | if (task_for_pid(mach_task_self(), pid, &task) != KERN_SUCCESS) { 201 | perror("task_for_pid"); 202 | return 0; 203 | } 204 | return get_base_for_task(task); 205 | } 206 | 207 | extern kern_return_t catch_mach_exception_raise( 208 | mach_port_t exception_port, 209 | mach_port_t thread_port, 210 | mach_port_t task_port, 211 | exception_type_t exception_type, 212 | mach_exception_data_t codes, 213 | mach_msg_type_number_t num_codes) { 214 | 215 | INFO("EXC_TYPE = %#x", exception_type); 216 | INFO("THREAD = %#x", thread_port); 217 | 218 | thread_suspend(task_port); 219 | INFO("thread suspended"); 220 | thread_t th; 221 | kern_return_t kr; 222 | 223 | th_state_t thread_state; 224 | mach_msg_type_number_t sc = TH_STATE_COUNT; 225 | 226 | if ((kr = mach_port_get_context(mach_task_self(), exception_port, (mach_vm_address_t *) &th)) != KERN_SUCCESS) { 227 | FATAL("mach_port_get_context failed: %s %x", mach_error_string(kr), kr); 228 | } 229 | if ((kr = thread_get_state(thread_port, TH_STATE, (thread_state_t) &thread_state, &sc)) != 230 | KERN_SUCCESS) { 231 | FATAL("thread_get_state failed: %s %x", mach_error_string(kr), kr); 232 | } 233 | print_registers(thread_state); 234 | 235 | handle_trap(&thread_state); 236 | 237 | if ((kr = thread_set_state(thread_port, TH_STATE, (thread_state_t) &thread_state, sc)) != 238 | KERN_SUCCESS) { 239 | FATAL("thread_set_state failed: %s %x", mach_error_string(kr), kr); 240 | } 241 | if ((kr = thread_get_state(thread_port, TH_STATE, (thread_state_t) &thread_state, &sc)) != 242 | KERN_SUCCESS) { 243 | FATAL("thread_get_state failed: %s %x", mach_error_string(kr), kr); 244 | } 245 | print_registers(thread_state); 246 | 247 | 248 | return KERN_SUCCESS; 249 | } 250 | 251 | extern kern_return_t catch_mach_exception_raise_state( 252 | mach_port_t exception_port, 253 | exception_type_t exception, 254 | const mach_exception_data_t code, 255 | mach_msg_type_number_t codeCnt, 256 | int *flavor, 257 | const thread_state_t old_state, 258 | mach_msg_type_number_t old_stateCnt, 259 | thread_state_t new_state, 260 | mach_msg_type_number_t *new_stateCnt) { 261 | 262 | return MACH_RCV_INVALID_TYPE; 263 | } 264 | 265 | extern kern_return_t catch_mach_exception_raise_state_identity( 266 | mach_port_t exception_port, 267 | mach_port_t thread, 268 | mach_port_t task, 269 | exception_type_t exception, 270 | mach_exception_data_t code, 271 | mach_msg_type_number_t codeCnt, 272 | int *flavor, 273 | thread_state_t old_state, 274 | mach_msg_type_number_t old_stateCnt, 275 | thread_state_t new_state, 276 | mach_msg_type_number_t *new_stateCnt) { 277 | 278 | return MACH_RCV_INVALID_TYPE; 279 | } 280 | 281 | extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); 282 | 283 | void detach(pid_t target_pid, mach_port_name_t target_exception_port) { 284 | task_suspend(target_task_port); 285 | target_reset_trap(TRAP_SONG_NAME); 286 | target_reset_trap(TRAP_ARTIST_NAME); 287 | target_reset_trap(TRAP_ALBUM_NAME); 288 | target_reset_trap(TRAP_RST); 289 | ptrace(PT_DETACH, target_pid, 0, 0); 290 | mach_port_deallocate(mach_task_self(), target_exception_port); 291 | task_resume(target_task_port); 292 | printf("Detached\n"); 293 | exit(0); 294 | } 295 | 296 | void sig_handler(int signo) { 297 | if (signo == SIGINT) { 298 | printf("SIGINT received\n"); 299 | printf("Detaching...\n"); 300 | detach_ctrl = 1; 301 | } 302 | } 303 | 304 | void attach(pid_t target_pid, FUNC_ON_UPDATE_GENERATE(func_on_update)) { 305 | printf("NeteaseMusic Now Playing Interceptor by Makito\n"); 306 | 307 | if (signal(SIGINT, sig_handler) == SIG_ERR) { 308 | FATAL("failed to setup signal handler for SIGINT"); 309 | } 310 | 311 | if (getuid() == 0) { 312 | WARN("running as root"); 313 | } 314 | setuid(0); 315 | if (getuid() != 0) { 316 | FATAL("interception is not available since setuid(0) has failed"); 317 | } 318 | 319 | current_song_info._song_addr = 0; 320 | current_song_info._artist_addr = 0; 321 | current_song_info._album_addr = 0; 322 | current_song_info._song_updated = 0; 323 | current_song_info._artist_updated = 0; 324 | current_song_info._album_updated = 0; 325 | 326 | task_for_pid(mach_task_self(), target_pid, &target_task_port); 327 | 328 | exception_mask_t saved_masks[EXC_TYPES_COUNT]; 329 | mach_port_t saved_ports[EXC_TYPES_COUNT]; 330 | exception_behavior_t saved_behaviors[EXC_TYPES_COUNT]; 331 | thread_state_flavor_t saved_flavors[EXC_TYPES_COUNT]; 332 | mach_msg_type_number_t saved_exception_types_count; 333 | 334 | exception_mask_t mask = EXC_MASK_BREAKPOINT; 335 | 336 | task_get_exception_ports(target_task_port, mask, saved_masks, &saved_exception_types_count, 337 | saved_ports, saved_behaviors, saved_flavors); 338 | 339 | mach_port_name_t target_exception_port; 340 | mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &target_exception_port); 341 | mach_port_insert_right(mach_task_self(), target_exception_port, target_exception_port, MACH_MSG_TYPE_MAKE_SEND); 342 | task_set_exception_ports(target_task_port, mask, target_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, 343 | MACHINE_THREAD_STATE); 344 | 345 | if (ptrace(PT_ATTACHEXC, target_pid, 0, 0) < 0) { 346 | perror("ptrace"); 347 | FATAL("failed to attach to process"); 348 | } 349 | INFO("attached"); 350 | task_suspend(target_task_port); 351 | INFO("process suspended"); 352 | base = get_base_for_task(target_task_port); 353 | INFO("base: %#016llx", (unsigned long long int) base); 354 | _func_on_update = func_on_update; 355 | 356 | kern_return_t kr; 357 | 358 | target_backup_mem(TRAP_SONG_NAME); 359 | target_backup_mem(TRAP_ARTIST_NAME); 360 | target_backup_mem(TRAP_ALBUM_NAME); 361 | target_backup_mem(TRAP_RST); 362 | 363 | INFO("injecting to process..."); 364 | 365 | target_set_traps(); 366 | task_resume(target_task_port); 367 | 368 | printf("Initialized\n"); 369 | printf("REMEMBER TO USE ^C TO DETACH THE INTERCEPTOR FIRST\n"); 370 | printf("OTHERWISE THE ATTACHED PROCESS MIGHT CRASH\n"); 371 | 372 | char req[128], rpl[128]; 373 | while (!detach_ctrl) { 374 | INFO("waiting"); 375 | while ((kr = mach_msg( 376 | (mach_msg_header_t *) req, 377 | MACH_RCV_MSG | MACH_RCV_TIMEOUT, 378 | 0, 379 | sizeof(req), 380 | target_exception_port, 381 | 100, 382 | MACH_PORT_NULL)) == MACH_RCV_TIMED_OUT) { 383 | if (detach_ctrl) { 384 | detach(target_pid, target_exception_port); 385 | } 386 | } 387 | 388 | if (kr == KERN_SUCCESS) { 389 | INFO("trapped"); 390 | task_suspend(target_task_port); 391 | INFO("process suspended"); 392 | if (!mach_exc_server((mach_msg_header_t *) req, (mach_msg_header_t *) rpl)) { 393 | kr = ((mig_reply_error_t *) rpl)->RetCode; 394 | FATAL("message_parse failed: %s %x", mach_error_string(kr), kr); 395 | } 396 | } else { 397 | FATAL("mach_msg recv failed: %s %x", mach_error_string(kr), kr); 398 | } 399 | task_resume(target_task_port); 400 | INFO("process resumed"); 401 | 402 | mach_msg_size_t send_sz = ((mach_msg_header_t *) rpl)->msgh_size; 403 | if ((kr = mach_msg( 404 | (mach_msg_header_t *) rpl, 405 | MACH_SEND_MSG, 406 | send_sz, 407 | 0, 408 | MACH_PORT_NULL, 409 | MACH_MSG_TIMEOUT_NONE, 410 | MACH_PORT_NULL) 411 | ) != MACH_MSG_SUCCESS) { 412 | FATAL("mach_msg failed: %s %x", mach_error_string(kr), kr); 413 | } 414 | } 415 | detach(target_pid, target_exception_port); 416 | } 417 | -------------------------------------------------------------------------------- /src/core/mach_excServer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * IDENTIFICATION: 3 | * stub generated Tue May 14 04:20:49 2019 4 | * with a MiG generated by bootstrap_cmds-96.20.2 5 | * OPTIONS: 6 | */ 7 | 8 | /* Module mach_exc */ 9 | 10 | #define __MIG_check__Request__mach_exc_subsystem__ 1 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | /* BEGIN VOUCHER CODE */ 23 | 24 | #ifndef KERNEL 25 | #if defined(__has_include) 26 | #if __has_include() 27 | #ifndef USING_VOUCHERS 28 | #define USING_VOUCHERS 29 | #endif 30 | #ifndef __VOUCHER_FORWARD_TYPE_DECLS__ 31 | #define __VOUCHER_FORWARD_TYPE_DECLS__ 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | #endif // __VOUCHER_FORWARD_TYPE_DECLS__ 40 | #endif // __has_include() 41 | #endif // __has_include 42 | #endif // !KERNEL 43 | 44 | /* END VOUCHER CODE */ 45 | 46 | 47 | /* BEGIN MIG_STRNCPY_ZEROFILL CODE */ 48 | 49 | #if defined(__has_include) 50 | #if __has_include() 51 | #ifndef USING_MIG_STRNCPY_ZEROFILL 52 | #define USING_MIG_STRNCPY_ZEROFILL 53 | #endif 54 | #ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ 55 | #define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import)); 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | #endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */ 64 | #endif /* __has_include() */ 65 | #endif /* __has_include */ 66 | 67 | /* END MIG_STRNCPY_ZEROFILL CODE */ 68 | 69 | 70 | #include 71 | #include 72 | #include 73 | #include 74 | 75 | #ifndef mig_internal 76 | #define mig_internal static __inline__ 77 | #endif /* mig_internal */ 78 | 79 | #ifndef mig_external 80 | #define mig_external 81 | #endif /* mig_external */ 82 | 83 | #if !defined(__MigTypeCheck) && defined(TypeCheck) 84 | #define __MigTypeCheck TypeCheck /* Legacy setting */ 85 | #endif /* !defined(__MigTypeCheck) */ 86 | 87 | #if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) 88 | #define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ 89 | #endif /* !defined(__MigKernelSpecificCode) */ 90 | 91 | #ifndef LimitCheck 92 | #define LimitCheck 0 93 | #endif /* LimitCheck */ 94 | 95 | #ifndef min 96 | #define min(a,b) ( ((a) < (b))? (a): (b) ) 97 | #endif /* min */ 98 | 99 | #if !defined(_WALIGN_) 100 | #define _WALIGN_(x) (((x) + 3) & ~3) 101 | #endif /* !defined(_WALIGN_) */ 102 | 103 | #if !defined(_WALIGNSZ_) 104 | #define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) 105 | #endif /* !defined(_WALIGNSZ_) */ 106 | 107 | #ifndef UseStaticTemplates 108 | #define UseStaticTemplates 0 109 | #endif /* UseStaticTemplates */ 110 | 111 | #ifndef __DeclareRcvRpc 112 | #define __DeclareRcvRpc(_NUM_, _NAME_) 113 | #endif /* __DeclareRcvRpc */ 114 | 115 | #ifndef __BeforeRcvRpc 116 | #define __BeforeRcvRpc(_NUM_, _NAME_) 117 | #endif /* __BeforeRcvRpc */ 118 | 119 | #ifndef __AfterRcvRpc 120 | #define __AfterRcvRpc(_NUM_, _NAME_) 121 | #endif /* __AfterRcvRpc */ 122 | 123 | #ifndef __DeclareRcvSimple 124 | #define __DeclareRcvSimple(_NUM_, _NAME_) 125 | #endif /* __DeclareRcvSimple */ 126 | 127 | #ifndef __BeforeRcvSimple 128 | #define __BeforeRcvSimple(_NUM_, _NAME_) 129 | #endif /* __BeforeRcvSimple */ 130 | 131 | #ifndef __AfterRcvSimple 132 | #define __AfterRcvSimple(_NUM_, _NAME_) 133 | #endif /* __AfterRcvSimple */ 134 | 135 | #define novalue void 136 | 137 | #define msgh_request_port msgh_local_port 138 | #define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) 139 | #define msgh_reply_port msgh_remote_port 140 | #define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) 141 | 142 | #define MIG_RETURN_ERROR(X, code) {\ 143 | ((mig_reply_error_t *)X)->RetCode = code;\ 144 | ((mig_reply_error_t *)X)->NDR = NDR_record;\ 145 | return;\ 146 | } 147 | 148 | /* typedefs for all requests */ 149 | 150 | #ifndef __Request__mach_exc_subsystem__defined 151 | #define __Request__mach_exc_subsystem__defined 152 | 153 | #ifdef __MigPackStructs 154 | #pragma pack(4) 155 | #endif 156 | typedef struct { 157 | mach_msg_header_t Head; 158 | /* start of the kernel processed data */ 159 | mach_msg_body_t msgh_body; 160 | mach_msg_port_descriptor_t thread; 161 | mach_msg_port_descriptor_t task; 162 | /* end of the kernel processed data */ 163 | NDR_record_t NDR; 164 | exception_type_t exception; 165 | mach_msg_type_number_t codeCnt; 166 | int64_t code[2]; 167 | } __Request__mach_exception_raise_t __attribute__((unused)); 168 | #ifdef __MigPackStructs 169 | #pragma pack() 170 | #endif 171 | 172 | #ifdef __MigPackStructs 173 | #pragma pack(4) 174 | #endif 175 | typedef struct { 176 | mach_msg_header_t Head; 177 | NDR_record_t NDR; 178 | exception_type_t exception; 179 | mach_msg_type_number_t codeCnt; 180 | int64_t code[2]; 181 | int flavor; 182 | mach_msg_type_number_t old_stateCnt; 183 | natural_t old_state[224]; 184 | } __Request__mach_exception_raise_state_t __attribute__((unused)); 185 | #ifdef __MigPackStructs 186 | #pragma pack() 187 | #endif 188 | 189 | #ifdef __MigPackStructs 190 | #pragma pack(4) 191 | #endif 192 | typedef struct { 193 | mach_msg_header_t Head; 194 | /* start of the kernel processed data */ 195 | mach_msg_body_t msgh_body; 196 | mach_msg_port_descriptor_t thread; 197 | mach_msg_port_descriptor_t task; 198 | /* end of the kernel processed data */ 199 | NDR_record_t NDR; 200 | exception_type_t exception; 201 | mach_msg_type_number_t codeCnt; 202 | int64_t code[2]; 203 | int flavor; 204 | mach_msg_type_number_t old_stateCnt; 205 | natural_t old_state[224]; 206 | } __Request__mach_exception_raise_state_identity_t __attribute__((unused)); 207 | #ifdef __MigPackStructs 208 | #pragma pack() 209 | #endif 210 | #endif /* !__Request__mach_exc_subsystem__defined */ 211 | 212 | /* typedefs for all replies */ 213 | 214 | #ifndef __Reply__mach_exc_subsystem__defined 215 | #define __Reply__mach_exc_subsystem__defined 216 | 217 | #ifdef __MigPackStructs 218 | #pragma pack(4) 219 | #endif 220 | typedef struct { 221 | mach_msg_header_t Head; 222 | NDR_record_t NDR; 223 | kern_return_t RetCode; 224 | } __Reply__mach_exception_raise_t __attribute__((unused)); 225 | #ifdef __MigPackStructs 226 | #pragma pack() 227 | #endif 228 | 229 | #ifdef __MigPackStructs 230 | #pragma pack(4) 231 | #endif 232 | typedef struct { 233 | mach_msg_header_t Head; 234 | NDR_record_t NDR; 235 | kern_return_t RetCode; 236 | int flavor; 237 | mach_msg_type_number_t new_stateCnt; 238 | natural_t new_state[224]; 239 | } __Reply__mach_exception_raise_state_t __attribute__((unused)); 240 | #ifdef __MigPackStructs 241 | #pragma pack() 242 | #endif 243 | 244 | #ifdef __MigPackStructs 245 | #pragma pack(4) 246 | #endif 247 | typedef struct { 248 | mach_msg_header_t Head; 249 | NDR_record_t NDR; 250 | kern_return_t RetCode; 251 | int flavor; 252 | mach_msg_type_number_t new_stateCnt; 253 | natural_t new_state[224]; 254 | } __Reply__mach_exception_raise_state_identity_t __attribute__((unused)); 255 | #ifdef __MigPackStructs 256 | #pragma pack() 257 | #endif 258 | #endif /* !__Reply__mach_exc_subsystem__defined */ 259 | 260 | 261 | /* union of all replies */ 262 | 263 | #ifndef __ReplyUnion__catch_mach_exc_subsystem__defined 264 | #define __ReplyUnion__catch_mach_exc_subsystem__defined 265 | union __ReplyUnion__catch_mach_exc_subsystem { 266 | __Reply__mach_exception_raise_t Reply_mach_exception_raise; 267 | __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; 268 | __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; 269 | }; 270 | #endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ 271 | /* Forward Declarations */ 272 | 273 | 274 | mig_internal novalue _Xmach_exception_raise 275 | (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); 276 | 277 | mig_internal novalue _Xmach_exception_raise_state 278 | (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); 279 | 280 | mig_internal novalue _Xmach_exception_raise_state_identity 281 | (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); 282 | 283 | 284 | #if ( __MigTypeCheck ) 285 | #if __MIG_check__Request__mach_exc_subsystem__ 286 | #if !defined(__MIG_check__Request__mach_exception_raise_t__defined) 287 | #define __MIG_check__Request__mach_exception_raise_t__defined 288 | 289 | mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P) 290 | { 291 | 292 | typedef __Request__mach_exception_raise_t __Request; 293 | #if __MigTypeCheck 294 | unsigned int msgh_size; 295 | #endif /* __MigTypeCheck */ 296 | 297 | #if __MigTypeCheck 298 | msgh_size = In0P->Head.msgh_size; 299 | if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || 300 | (In0P->msgh_body.msgh_descriptor_count != 2) || 301 | (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) 302 | return MIG_BAD_ARGUMENTS; 303 | #endif /* __MigTypeCheck */ 304 | 305 | #if __MigTypeCheck 306 | if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || 307 | In0P->thread.disposition != 17) 308 | return MIG_TYPE_ERROR; 309 | #endif /* __MigTypeCheck */ 310 | 311 | #if __MigTypeCheck 312 | if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || 313 | In0P->task.disposition != 17) 314 | return MIG_TYPE_ERROR; 315 | #endif /* __MigTypeCheck */ 316 | 317 | #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) 318 | if (In0P->NDR.int_rep != NDR_record.int_rep) 319 | __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); 320 | #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ 321 | #if __MigTypeCheck 322 | if ( In0P->codeCnt > 2 ) 323 | return MIG_BAD_ARGUMENTS; 324 | if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) || 325 | (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt))) 326 | return MIG_BAD_ARGUMENTS; 327 | #endif /* __MigTypeCheck */ 328 | 329 | return MACH_MSG_SUCCESS; 330 | } 331 | #endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */ 332 | #endif /* __MIG_check__Request__mach_exc_subsystem__ */ 333 | #endif /* ( __MigTypeCheck ) */ 334 | 335 | 336 | /* Routine mach_exception_raise */ 337 | #ifdef mig_external 338 | mig_external 339 | #else 340 | extern 341 | #endif /* mig_external */ 342 | kern_return_t catch_mach_exception_raise 343 | ( 344 | mach_port_t exception_port, 345 | mach_port_t thread, 346 | mach_port_t task, 347 | exception_type_t exception, 348 | mach_exception_data_t code, 349 | mach_msg_type_number_t codeCnt 350 | ); 351 | 352 | /* Routine mach_exception_raise */ 353 | mig_internal novalue _Xmach_exception_raise 354 | (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) 355 | { 356 | 357 | #ifdef __MigPackStructs 358 | #pragma pack(4) 359 | #endif 360 | typedef struct { 361 | mach_msg_header_t Head; 362 | /* start of the kernel processed data */ 363 | mach_msg_body_t msgh_body; 364 | mach_msg_port_descriptor_t thread; 365 | mach_msg_port_descriptor_t task; 366 | /* end of the kernel processed data */ 367 | NDR_record_t NDR; 368 | exception_type_t exception; 369 | mach_msg_type_number_t codeCnt; 370 | int64_t code[2]; 371 | mach_msg_trailer_t trailer; 372 | } Request __attribute__((unused)); 373 | #ifdef __MigPackStructs 374 | #pragma pack() 375 | #endif 376 | typedef __Request__mach_exception_raise_t __Request; 377 | typedef __Reply__mach_exception_raise_t Reply __attribute__((unused)); 378 | 379 | /* 380 | * typedef struct { 381 | * mach_msg_header_t Head; 382 | * NDR_record_t NDR; 383 | * kern_return_t RetCode; 384 | * } mig_reply_error_t; 385 | */ 386 | 387 | Request *In0P = (Request *) InHeadP; 388 | Reply *OutP = (Reply *) OutHeadP; 389 | #ifdef __MIG_check__Request__mach_exception_raise_t__defined 390 | kern_return_t check_result; 391 | #endif /* __MIG_check__Request__mach_exception_raise_t__defined */ 392 | 393 | __DeclareRcvRpc(2405, "mach_exception_raise") 394 | __BeforeRcvRpc(2405, "mach_exception_raise") 395 | 396 | #if defined(__MIG_check__Request__mach_exception_raise_t__defined) 397 | check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P); 398 | if (check_result != MACH_MSG_SUCCESS) 399 | { MIG_RETURN_ERROR(OutP, check_result); } 400 | #endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */ 401 | 402 | OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); 403 | 404 | OutP->NDR = NDR_record; 405 | 406 | 407 | __AfterRcvRpc(2405, "mach_exception_raise") 408 | } 409 | 410 | #if ( __MigTypeCheck ) 411 | #if __MIG_check__Request__mach_exc_subsystem__ 412 | #if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) 413 | #define __MIG_check__Request__mach_exception_raise_state_t__defined 414 | 415 | mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP) 416 | { 417 | 418 | typedef __Request__mach_exception_raise_state_t __Request; 419 | __Request *In1P; 420 | #if __MigTypeCheck 421 | unsigned int msgh_size; 422 | #endif /* __MigTypeCheck */ 423 | unsigned int msgh_size_delta; 424 | 425 | #if __MigTypeCheck 426 | msgh_size = In0P->Head.msgh_size; 427 | if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || 428 | (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) 429 | return MIG_BAD_ARGUMENTS; 430 | #endif /* __MigTypeCheck */ 431 | 432 | #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) 433 | if (In0P->NDR.int_rep != NDR_record.int_rep) 434 | __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); 435 | #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ 436 | msgh_size_delta = (8 * In0P->codeCnt); 437 | #if __MigTypeCheck 438 | if ( In0P->codeCnt > 2 ) 439 | return MIG_BAD_ARGUMENTS; 440 | if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || 441 | (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) 442 | return MIG_BAD_ARGUMENTS; 443 | msgh_size -= msgh_size_delta; 444 | #endif /* __MigTypeCheck */ 445 | 446 | *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); 447 | 448 | #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) 449 | if (In0P->NDR.int_rep != NDR_record.int_rep) 450 | __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); 451 | #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ 452 | #if __MigTypeCheck 453 | if ( In1P->old_stateCnt > 224 ) 454 | return MIG_BAD_ARGUMENTS; 455 | if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || 456 | (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) 457 | return MIG_BAD_ARGUMENTS; 458 | #endif /* __MigTypeCheck */ 459 | 460 | return MACH_MSG_SUCCESS; 461 | } 462 | #endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ 463 | #endif /* __MIG_check__Request__mach_exc_subsystem__ */ 464 | #endif /* ( __MigTypeCheck ) */ 465 | 466 | 467 | /* Routine mach_exception_raise_state */ 468 | #ifdef mig_external 469 | mig_external 470 | #else 471 | extern 472 | #endif /* mig_external */ 473 | kern_return_t catch_mach_exception_raise_state 474 | ( 475 | mach_port_t exception_port, 476 | exception_type_t exception, 477 | const mach_exception_data_t code, 478 | mach_msg_type_number_t codeCnt, 479 | int *flavor, 480 | const thread_state_t old_state, 481 | mach_msg_type_number_t old_stateCnt, 482 | thread_state_t new_state, 483 | mach_msg_type_number_t *new_stateCnt 484 | ); 485 | 486 | /* Routine mach_exception_raise_state */ 487 | mig_internal novalue _Xmach_exception_raise_state 488 | (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) 489 | { 490 | 491 | #ifdef __MigPackStructs 492 | #pragma pack(4) 493 | #endif 494 | typedef struct { 495 | mach_msg_header_t Head; 496 | NDR_record_t NDR; 497 | exception_type_t exception; 498 | mach_msg_type_number_t codeCnt; 499 | int64_t code[2]; 500 | int flavor; 501 | mach_msg_type_number_t old_stateCnt; 502 | natural_t old_state[224]; 503 | mach_msg_trailer_t trailer; 504 | } Request __attribute__((unused)); 505 | #ifdef __MigPackStructs 506 | #pragma pack() 507 | #endif 508 | typedef __Request__mach_exception_raise_state_t __Request; 509 | typedef __Reply__mach_exception_raise_state_t Reply __attribute__((unused)); 510 | 511 | /* 512 | * typedef struct { 513 | * mach_msg_header_t Head; 514 | * NDR_record_t NDR; 515 | * kern_return_t RetCode; 516 | * } mig_reply_error_t; 517 | */ 518 | 519 | Request *In0P = (Request *) InHeadP; 520 | Request *In1P; 521 | Reply *OutP = (Reply *) OutHeadP; 522 | #ifdef __MIG_check__Request__mach_exception_raise_state_t__defined 523 | kern_return_t check_result; 524 | #endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */ 525 | 526 | __DeclareRcvRpc(2406, "mach_exception_raise_state") 527 | __BeforeRcvRpc(2406, "mach_exception_raise_state") 528 | 529 | #if defined(__MIG_check__Request__mach_exception_raise_state_t__defined) 530 | check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P); 531 | if (check_result != MACH_MSG_SUCCESS) 532 | { MIG_RETURN_ERROR(OutP, check_result); } 533 | #endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ 534 | 535 | OutP->new_stateCnt = 224; 536 | 537 | OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); 538 | if (OutP->RetCode != KERN_SUCCESS) { 539 | MIG_RETURN_ERROR(OutP, OutP->RetCode); 540 | } 541 | 542 | OutP->NDR = NDR_record; 543 | 544 | 545 | OutP->flavor = In1P->flavor; 546 | OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); 547 | 548 | __AfterRcvRpc(2406, "mach_exception_raise_state") 549 | } 550 | 551 | #if ( __MigTypeCheck ) 552 | #if __MIG_check__Request__mach_exc_subsystem__ 553 | #if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) 554 | #define __MIG_check__Request__mach_exception_raise_state_identity_t__defined 555 | 556 | mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP) 557 | { 558 | 559 | typedef __Request__mach_exception_raise_state_identity_t __Request; 560 | __Request *In1P; 561 | #if __MigTypeCheck 562 | unsigned int msgh_size; 563 | #endif /* __MigTypeCheck */ 564 | unsigned int msgh_size_delta; 565 | 566 | #if __MigTypeCheck 567 | msgh_size = In0P->Head.msgh_size; 568 | if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || 569 | (In0P->msgh_body.msgh_descriptor_count != 2) || 570 | (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) 571 | return MIG_BAD_ARGUMENTS; 572 | #endif /* __MigTypeCheck */ 573 | 574 | #if __MigTypeCheck 575 | if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || 576 | In0P->thread.disposition != 17) 577 | return MIG_TYPE_ERROR; 578 | #endif /* __MigTypeCheck */ 579 | 580 | #if __MigTypeCheck 581 | if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || 582 | In0P->task.disposition != 17) 583 | return MIG_TYPE_ERROR; 584 | #endif /* __MigTypeCheck */ 585 | 586 | #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) 587 | if (In0P->NDR.int_rep != NDR_record.int_rep) 588 | __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); 589 | #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ 590 | msgh_size_delta = (8 * In0P->codeCnt); 591 | #if __MigTypeCheck 592 | if ( In0P->codeCnt > 2 ) 593 | return MIG_BAD_ARGUMENTS; 594 | if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || 595 | (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) 596 | return MIG_BAD_ARGUMENTS; 597 | msgh_size -= msgh_size_delta; 598 | #endif /* __MigTypeCheck */ 599 | 600 | *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); 601 | 602 | #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) 603 | if (In0P->NDR.int_rep != NDR_record.int_rep) 604 | __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); 605 | #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ 606 | #if __MigTypeCheck 607 | if ( In1P->old_stateCnt > 224 ) 608 | return MIG_BAD_ARGUMENTS; 609 | if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || 610 | (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) 611 | return MIG_BAD_ARGUMENTS; 612 | #endif /* __MigTypeCheck */ 613 | 614 | return MACH_MSG_SUCCESS; 615 | } 616 | #endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ 617 | #endif /* __MIG_check__Request__mach_exc_subsystem__ */ 618 | #endif /* ( __MigTypeCheck ) */ 619 | 620 | 621 | /* Routine mach_exception_raise_state_identity */ 622 | #ifdef mig_external 623 | mig_external 624 | #else 625 | extern 626 | #endif /* mig_external */ 627 | kern_return_t catch_mach_exception_raise_state_identity 628 | ( 629 | mach_port_t exception_port, 630 | mach_port_t thread, 631 | mach_port_t task, 632 | exception_type_t exception, 633 | mach_exception_data_t code, 634 | mach_msg_type_number_t codeCnt, 635 | int *flavor, 636 | thread_state_t old_state, 637 | mach_msg_type_number_t old_stateCnt, 638 | thread_state_t new_state, 639 | mach_msg_type_number_t *new_stateCnt 640 | ); 641 | 642 | /* Routine mach_exception_raise_state_identity */ 643 | mig_internal novalue _Xmach_exception_raise_state_identity 644 | (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) 645 | { 646 | 647 | #ifdef __MigPackStructs 648 | #pragma pack(4) 649 | #endif 650 | typedef struct { 651 | mach_msg_header_t Head; 652 | /* start of the kernel processed data */ 653 | mach_msg_body_t msgh_body; 654 | mach_msg_port_descriptor_t thread; 655 | mach_msg_port_descriptor_t task; 656 | /* end of the kernel processed data */ 657 | NDR_record_t NDR; 658 | exception_type_t exception; 659 | mach_msg_type_number_t codeCnt; 660 | int64_t code[2]; 661 | int flavor; 662 | mach_msg_type_number_t old_stateCnt; 663 | natural_t old_state[224]; 664 | mach_msg_trailer_t trailer; 665 | } Request __attribute__((unused)); 666 | #ifdef __MigPackStructs 667 | #pragma pack() 668 | #endif 669 | typedef __Request__mach_exception_raise_state_identity_t __Request; 670 | typedef __Reply__mach_exception_raise_state_identity_t Reply __attribute__((unused)); 671 | 672 | /* 673 | * typedef struct { 674 | * mach_msg_header_t Head; 675 | * NDR_record_t NDR; 676 | * kern_return_t RetCode; 677 | * } mig_reply_error_t; 678 | */ 679 | 680 | Request *In0P = (Request *) InHeadP; 681 | Request *In1P; 682 | Reply *OutP = (Reply *) OutHeadP; 683 | #ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined 684 | kern_return_t check_result; 685 | #endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */ 686 | 687 | __DeclareRcvRpc(2407, "mach_exception_raise_state_identity") 688 | __BeforeRcvRpc(2407, "mach_exception_raise_state_identity") 689 | 690 | #if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) 691 | check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P); 692 | if (check_result != MACH_MSG_SUCCESS) 693 | { MIG_RETURN_ERROR(OutP, check_result); } 694 | #endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ 695 | 696 | OutP->new_stateCnt = 224; 697 | 698 | OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); 699 | if (OutP->RetCode != KERN_SUCCESS) { 700 | MIG_RETURN_ERROR(OutP, OutP->RetCode); 701 | } 702 | 703 | OutP->NDR = NDR_record; 704 | 705 | 706 | OutP->flavor = In1P->flavor; 707 | OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); 708 | 709 | __AfterRcvRpc(2407, "mach_exception_raise_state_identity") 710 | } 711 | 712 | 713 | #ifdef mig_external 714 | mig_external 715 | #else 716 | extern 717 | #endif /* mig_external */ 718 | boolean_t mach_exc_server( 719 | mach_msg_header_t *InHeadP, 720 | mach_msg_header_t *OutHeadP); 721 | 722 | #ifdef mig_external 723 | mig_external 724 | #else 725 | extern 726 | #endif /* mig_external */ 727 | mig_routine_t mach_exc_server_routine( 728 | mach_msg_header_t *InHeadP); 729 | 730 | 731 | /* Description of this subsystem, for use in direct RPC */ 732 | const struct catch_mach_exc_subsystem { 733 | mig_server_routine_t server; /* Server routine */ 734 | mach_msg_id_t start; /* Min routine number */ 735 | mach_msg_id_t end; /* Max routine number + 1 */ 736 | unsigned int maxsize; /* Max msg size */ 737 | vm_address_t reserved; /* Reserved */ 738 | struct routine_descriptor /*Array of routine descriptors */ 739 | routine[3]; 740 | } catch_mach_exc_subsystem = { 741 | mach_exc_server_routine, 742 | 2405, 743 | 2408, 744 | (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem), 745 | (vm_address_t)0, 746 | { 747 | { (mig_impl_routine_t) 0, 748 | (mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)}, 749 | { (mig_impl_routine_t) 0, 750 | (mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)}, 751 | { (mig_impl_routine_t) 0, 752 | (mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)}, 753 | } 754 | }; 755 | 756 | mig_external boolean_t mach_exc_server 757 | (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) 758 | { 759 | /* 760 | * typedef struct { 761 | * mach_msg_header_t Head; 762 | * NDR_record_t NDR; 763 | * kern_return_t RetCode; 764 | * } mig_reply_error_t; 765 | */ 766 | 767 | register mig_routine_t routine; 768 | 769 | OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); 770 | OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; 771 | /* Minimal size: routine() will update it if different */ 772 | OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); 773 | OutHeadP->msgh_local_port = MACH_PORT_NULL; 774 | OutHeadP->msgh_id = InHeadP->msgh_id + 100; 775 | OutHeadP->msgh_reserved = 0; 776 | 777 | if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) || 778 | ((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) { 779 | ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; 780 | ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; 781 | return FALSE; 782 | } 783 | (*routine) (InHeadP, OutHeadP); 784 | return TRUE; 785 | } 786 | 787 | mig_external mig_routine_t mach_exc_server_routine 788 | (mach_msg_header_t *InHeadP) 789 | { 790 | register int msgh_id; 791 | 792 | msgh_id = InHeadP->msgh_id - 2405; 793 | 794 | if ((msgh_id > 2) || (msgh_id < 0)) 795 | return 0; 796 | 797 | return catch_mach_exc_subsystem.routine[msgh_id].stub_routine; 798 | } 799 | --------------------------------------------------------------------------------