1*4d495c6eSApple OSS Distributions #include <darwintest.h>
2*4d495c6eSApple OSS Distributions #include <darwintest_utils.h>
3*4d495c6eSApple OSS Distributions
4*4d495c6eSApple OSS Distributions #include <TargetConditionals.h>
5*4d495c6eSApple OSS Distributions
6*4d495c6eSApple OSS Distributions #include <mach/mach.h>
7*4d495c6eSApple OSS Distributions #include <mach/mach_types.h>
8*4d495c6eSApple OSS Distributions #include <mach/mach_vm.h>
9*4d495c6eSApple OSS Distributions #include <mach/mach_error.h>
10*4d495c6eSApple OSS Distributions #include <mach/task.h>
11*4d495c6eSApple OSS Distributions
12*4d495c6eSApple OSS Distributions #include <servers/bootstrap.h>
13*4d495c6eSApple OSS Distributions
14*4d495c6eSApple OSS Distributions #include <sys/resource.h>
15*4d495c6eSApple OSS Distributions
16*4d495c6eSApple OSS Distributions #include <kern/kcdata.h>
17*4d495c6eSApple OSS Distributions
18*4d495c6eSApple OSS Distributions #include <os/reason_private.h>
19*4d495c6eSApple OSS Distributions
20*4d495c6eSApple OSS Distributions #include <System/uuid/uuid.h>
21*4d495c6eSApple OSS Distributions #include "exc_helpers.h"
22*4d495c6eSApple OSS Distributions
23*4d495c6eSApple OSS Distributions #include <unistd.h>
24*4d495c6eSApple OSS Distributions #include <errno.h>
25*4d495c6eSApple OSS Distributions
26*4d495c6eSApple OSS Distributions T_GLOBAL_META(
27*4d495c6eSApple OSS Distributions T_META_NAMESPACE("xnu.ipc"),
28*4d495c6eSApple OSS Distributions T_META_RUN_CONCURRENTLY(TRUE),
29*4d495c6eSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
30*4d495c6eSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("IPC"));
31*4d495c6eSApple OSS Distributions
32*4d495c6eSApple OSS Distributions
33*4d495c6eSApple OSS Distributions bool expect_backtrace = TRUE;
34*4d495c6eSApple OSS Distributions
35*4d495c6eSApple OSS Distributions static kern_return_t
exc_handler_backtrace(mach_port_t kcdata_object,exception_type_t exception,mach_exception_data_t codes)36*4d495c6eSApple OSS Distributions exc_handler_backtrace(
37*4d495c6eSApple OSS Distributions mach_port_t kcdata_object,
38*4d495c6eSApple OSS Distributions exception_type_t exception,
39*4d495c6eSApple OSS Distributions mach_exception_data_t codes)
40*4d495c6eSApple OSS Distributions {
41*4d495c6eSApple OSS Distributions kern_return_t kr;
42*4d495c6eSApple OSS Distributions mach_vm_address_t btinfo_begin;
43*4d495c6eSApple OSS Distributions mach_vm_size_t btinfo_size;
44*4d495c6eSApple OSS Distributions
45*4d495c6eSApple OSS Distributions if (expect_backtrace == FALSE) {
46*4d495c6eSApple OSS Distributions T_FAIL("Does not expect backtrace for this test case");
47*4d495c6eSApple OSS Distributions }
48*4d495c6eSApple OSS Distributions
49*4d495c6eSApple OSS Distributions T_LOG("Received backtrace exception.");
50*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exception, EXC_CORPSE_NOTIFY, "Exception should be corpse notify");
51*4d495c6eSApple OSS Distributions T_ASSERT_EQ(codes[0], EXC_GUARD, "Effective exception should be EXC_GUARD");
52*4d495c6eSApple OSS Distributions
53*4d495c6eSApple OSS Distributions kr = task_map_kcdata_object_64(mach_task_self(), kcdata_object, &btinfo_begin, &btinfo_size);
54*4d495c6eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "task_map_kcdata_object_64() should succeed");
55*4d495c6eSApple OSS Distributions
56*4d495c6eSApple OSS Distributions kcdata_iter_t btdata = kcdata_iter((void *)btinfo_begin, (unsigned long)btinfo_size);
57*4d495c6eSApple OSS Distributions if (kcdata_iter_valid(btdata) && kcdata_iter_type(btdata) == TASK_BTINFO_BEGIN) {
58*4d495c6eSApple OSS Distributions /* loop through data provided by kernel */
59*4d495c6eSApple OSS Distributions KCDATA_ITER_FOREACH(btdata) {
60*4d495c6eSApple OSS Distributions switch (kcdata_iter_type(btdata)) {
61*4d495c6eSApple OSS Distributions case TASK_BTINFO_GID: {
62*4d495c6eSApple OSS Distributions int gid = *(int *)(kcdata_iter_payload(btdata));
63*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_GID: %d", gid);
64*4d495c6eSApple OSS Distributions break;
65*4d495c6eSApple OSS Distributions }
66*4d495c6eSApple OSS Distributions case TASK_BTINFO_CPUTYPE: {
67*4d495c6eSApple OSS Distributions cpu_type_t type = *(cpu_type_t *)(kcdata_iter_payload(btdata));
68*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_CPUTYPE: %d", type);
69*4d495c6eSApple OSS Distributions break;
70*4d495c6eSApple OSS Distributions }
71*4d495c6eSApple OSS Distributions case TASK_BTINFO_THREAD_STATE: {
72*4d495c6eSApple OSS Distributions struct btinfo_thread_state_data_t data = *(struct btinfo_thread_state_data_t *)(kcdata_iter_payload(btdata));
73*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_THREAD_STATE: Flavor %d, Count %d", data.flavor, data.count);
74*4d495c6eSApple OSS Distributions break;
75*4d495c6eSApple OSS Distributions }
76*4d495c6eSApple OSS Distributions case TASK_BTINFO_THREAD_EXCEPTION_STATE: {
77*4d495c6eSApple OSS Distributions struct btinfo_thread_state_data_t data = *(struct btinfo_thread_state_data_t *)(kcdata_iter_payload(btdata));
78*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_THREAD_EXCEPTION_STATE: Flavor %d, Count %d", data.flavor, data.count);
79*4d495c6eSApple OSS Distributions break;
80*4d495c6eSApple OSS Distributions }
81*4d495c6eSApple OSS Distributions case TASK_BTINFO_PROC_NAME: {
82*4d495c6eSApple OSS Distributions #define MAXCOMLEN 16
83*4d495c6eSApple OSS Distributions char process_name[MAXCOMLEN + 1];
84*4d495c6eSApple OSS Distributions memcpy(process_name, kcdata_iter_payload(btdata), MAXCOMLEN); // limited to 16 chars
85*4d495c6eSApple OSS Distributions process_name[MAXCOMLEN] = '\0'; // ensure string is null terminated
86*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_PROC_NAME: %s", process_name);
87*4d495c6eSApple OSS Distributions break;
88*4d495c6eSApple OSS Distributions }
89*4d495c6eSApple OSS Distributions case TASK_BTINFO_PROC_PATH: {
90*4d495c6eSApple OSS Distributions const char *c_str = (const char *)kcdata_iter_payload(btdata);
91*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_PROC_PATH: %s", c_str);
92*4d495c6eSApple OSS Distributions break;
93*4d495c6eSApple OSS Distributions }
94*4d495c6eSApple OSS Distributions case TASK_BTINFO_PLATFORM: {
95*4d495c6eSApple OSS Distributions uint32_t platform = *(uint32_t *)(kcdata_iter_payload(btdata));
96*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_PLATFORM: %d", platform);
97*4d495c6eSApple OSS Distributions break;
98*4d495c6eSApple OSS Distributions }
99*4d495c6eSApple OSS Distributions case TASK_BTINFO_RUSAGE_INFO: {
100*4d495c6eSApple OSS Distributions struct rusage_info_v0 rui = *(struct rusage_info_v0 *)kcdata_iter_payload(btdata);
101*4d495c6eSApple OSS Distributions uuid_string_t uuid;
102*4d495c6eSApple OSS Distributions uint64_t _proc_start_abstime = rui.ri_proc_start_abstime;
103*4d495c6eSApple OSS Distributions uint64_t _proc_exit_abstime = rui.ri_proc_exit_abstime;
104*4d495c6eSApple OSS Distributions uuid_unparse(rui.ri_uuid, uuid);
105*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_RUSAGE_INFO: uuid: %s, start time: %llu, \
106*4d495c6eSApple OSS Distributions exit time: %llu", uuid, _proc_start_abstime, _proc_exit_abstime);
107*4d495c6eSApple OSS Distributions break;
108*4d495c6eSApple OSS Distributions }
109*4d495c6eSApple OSS Distributions case TASK_BTINFO_SC_LOADINFO64: {
110*4d495c6eSApple OSS Distributions struct btinfo_sc_load_info64 info = *(struct btinfo_sc_load_info64 *)kcdata_iter_payload(btdata);
111*4d495c6eSApple OSS Distributions uuid_string_t uuid;
112*4d495c6eSApple OSS Distributions uuid_unparse(info.sharedCacheUUID, uuid);
113*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_SC_LOADINFO64: uuid: %s, slide: %llu, base: %llu",
114*4d495c6eSApple OSS Distributions uuid, info.sharedCacheSlide, info.sharedCacheBaseAddress);
115*4d495c6eSApple OSS Distributions break;
116*4d495c6eSApple OSS Distributions }
117*4d495c6eSApple OSS Distributions case TASK_BTINFO_SC_LOADINFO: {
118*4d495c6eSApple OSS Distributions struct btinfo_sc_load_info info = *(struct btinfo_sc_load_info *)kcdata_iter_payload(btdata);
119*4d495c6eSApple OSS Distributions uuid_string_t uuid;
120*4d495c6eSApple OSS Distributions uuid_unparse(info.sharedCacheUUID, uuid);
121*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_SC_LOADINFO: uuid: %s, slide: %d, base: %d",
122*4d495c6eSApple OSS Distributions uuid, info.sharedCacheSlide, info.sharedCacheBaseAddress);
123*4d495c6eSApple OSS Distributions break;
124*4d495c6eSApple OSS Distributions }
125*4d495c6eSApple OSS Distributions case EXIT_REASON_SNAPSHOT: {
126*4d495c6eSApple OSS Distributions struct exit_reason_snapshot *snapshot = (struct exit_reason_snapshot *)kcdata_iter_payload(btdata);
127*4d495c6eSApple OSS Distributions T_LOG("Found EXIT_REASON_SNAPSHOT with namespace %x code %x", snapshot->ers_namespace, snapshot->ers_code);
128*4d495c6eSApple OSS Distributions break;
129*4d495c6eSApple OSS Distributions }
130*4d495c6eSApple OSS Distributions case KCDATA_TYPE_ARRAY: {
131*4d495c6eSApple OSS Distributions int count = kcdata_iter_array_elem_count(btdata);
132*4d495c6eSApple OSS Distributions uint32_t type = kcdata_iter_array_elem_type(btdata);
133*4d495c6eSApple OSS Distributions uint32_t size = kcdata_iter_array_elem_size(btdata);
134*4d495c6eSApple OSS Distributions
135*4d495c6eSApple OSS Distributions if (type == TASK_BTINFO_BACKTRACE64) {
136*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_BACKTRACE64, with %d backtrace frames", count);
137*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(size, sizeof(uint64_t), "Address size should be 64 bits");
138*4d495c6eSApple OSS Distributions
139*4d495c6eSApple OSS Distributions for (int i = 0; i < count; i++) {
140*4d495c6eSApple OSS Distributions T_LOG("Frame %d: %p", i, ((uint64_t *)kcdata_iter_payload(btdata))[i]);
141*4d495c6eSApple OSS Distributions }
142*4d495c6eSApple OSS Distributions } else if (type == TASK_BTINFO_DYLD_LOADINFO64) {
143*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_DYLD_LOADINFO64, with %d image infos", count);
144*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(size, sizeof(struct dyld_uuid_info_64), "Struct size should match");
145*4d495c6eSApple OSS Distributions
146*4d495c6eSApple OSS Distributions for (int i = 0; i < count; i++) {
147*4d495c6eSApple OSS Distributions uuid_string_t uuid_str;
148*4d495c6eSApple OSS Distributions uuid_unparse(((struct dyld_uuid_info_64 *)kcdata_iter_payload(btdata))[i].imageUUID, uuid_str);
149*4d495c6eSApple OSS Distributions
150*4d495c6eSApple OSS Distributions T_LOG("Image %d: <%s, %p>", i, uuid_str,
151*4d495c6eSApple OSS Distributions ((struct dyld_uuid_info_64 *)kcdata_iter_payload(btdata))[i].imageLoadAddress);
152*4d495c6eSApple OSS Distributions }
153*4d495c6eSApple OSS Distributions } else if (type == TASK_BTINFO_BACKTRACE) {
154*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_BACKTRACE, with %d backtrace frames", count);
155*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(size, sizeof(uint64_t), "Address size on arm64_32 should be 64 bits");
156*4d495c6eSApple OSS Distributions
157*4d495c6eSApple OSS Distributions for (int i = 0; i < count; i++) {
158*4d495c6eSApple OSS Distributions T_LOG("Frame %d: %p", i, ((uint32_t *)kcdata_iter_payload(btdata))[i]);
159*4d495c6eSApple OSS Distributions }
160*4d495c6eSApple OSS Distributions } else if (type == TASK_BTINFO_DYLD_LOADINFO) {
161*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_DYLD_LOADINFO, with %d image infos", count);
162*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(size, sizeof(struct dyld_uuid_info_32), "Struct size should match");
163*4d495c6eSApple OSS Distributions
164*4d495c6eSApple OSS Distributions for (int i = 0; i < count; i++) {
165*4d495c6eSApple OSS Distributions uuid_string_t uuid_str;
166*4d495c6eSApple OSS Distributions uuid_unparse(((struct dyld_uuid_info_32 *)kcdata_iter_payload(btdata))[i].imageUUID, uuid_str);
167*4d495c6eSApple OSS Distributions
168*4d495c6eSApple OSS Distributions T_LOG("Image %d: <%s, %p>", i, uuid_str,
169*4d495c6eSApple OSS Distributions ((struct dyld_uuid_info_32 *)kcdata_iter_payload(btdata))[i].imageLoadAddress);
170*4d495c6eSApple OSS Distributions }
171*4d495c6eSApple OSS Distributions }
172*4d495c6eSApple OSS Distributions break;
173*4d495c6eSApple OSS Distributions }
174*4d495c6eSApple OSS Distributions case TASK_BTINFO_THREAD_ID: {
175*4d495c6eSApple OSS Distributions uint64_t thread_id = *(uint64_t *)(kcdata_iter_payload(btdata));
176*4d495c6eSApple OSS Distributions T_LOG("Found TASK_BTINFO_THREAD_ID: 0x%lx", thread_id);
177*4d495c6eSApple OSS Distributions break;
178*4d495c6eSApple OSS Distributions }
179*4d495c6eSApple OSS Distributions default:
180*4d495c6eSApple OSS Distributions break;
181*4d495c6eSApple OSS Distributions }
182*4d495c6eSApple OSS Distributions }
183*4d495c6eSApple OSS Distributions } else {
184*4d495c6eSApple OSS Distributions T_FAIL("Unexpected kcdata object type");
185*4d495c6eSApple OSS Distributions }
186*4d495c6eSApple OSS Distributions
187*4d495c6eSApple OSS Distributions mach_vm_deallocate(mach_task_self(), btinfo_begin, btinfo_size);
188*4d495c6eSApple OSS Distributions mach_port_deallocate(mach_task_self(), kcdata_object);
189*4d495c6eSApple OSS Distributions
190*4d495c6eSApple OSS Distributions T_END;
191*4d495c6eSApple OSS Distributions }
192*4d495c6eSApple OSS Distributions
193*4d495c6eSApple OSS Distributions static size_t
exc_handler_identity_protected(task_id_token_t token,__unused uint64_t thread_id,__unused exception_type_t type,__unused exception_data_t codes)194*4d495c6eSApple OSS Distributions exc_handler_identity_protected(
195*4d495c6eSApple OSS Distributions task_id_token_t token,
196*4d495c6eSApple OSS Distributions __unused uint64_t thread_id,
197*4d495c6eSApple OSS Distributions __unused exception_type_t type,
198*4d495c6eSApple OSS Distributions __unused exception_data_t codes)
199*4d495c6eSApple OSS Distributions {
200*4d495c6eSApple OSS Distributions mach_port_t port1, port2;
201*4d495c6eSApple OSS Distributions kern_return_t kr;
202*4d495c6eSApple OSS Distributions
203*4d495c6eSApple OSS Distributions if (expect_backtrace) {
204*4d495c6eSApple OSS Distributions T_FAIL("Expect backtrace for this test case");
205*4d495c6eSApple OSS Distributions }
206*4d495c6eSApple OSS Distributions
207*4d495c6eSApple OSS Distributions T_LOG("Got protected exception!");
208*4d495c6eSApple OSS Distributions
209*4d495c6eSApple OSS Distributions port1 = mach_task_self();
210*4d495c6eSApple OSS Distributions kr = task_identity_token_get_task_port(token, TASK_FLAVOR_CONTROL, &port2); /* Immovable control port for self */
211*4d495c6eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "task_identity_token_get_task_port() - CONTROL");
212*4d495c6eSApple OSS Distributions T_EXPECT_EQ(port1, port2, "Control port matches!");
213*4d495c6eSApple OSS Distributions
214*4d495c6eSApple OSS Distributions T_END;
215*4d495c6eSApple OSS Distributions }
216*4d495c6eSApple OSS Distributions
217*4d495c6eSApple OSS Distributions /* Lightweight corpse not enabled on macOS yet */
218*4d495c6eSApple OSS Distributions #if !TARGET_OS_OSX
219*4d495c6eSApple OSS Distributions T_DECL(corpse_backtrace_os_log_lightweight,
220*4d495c6eSApple OSS Distributions "Test os_log_fault() fast backtracing with lightweight corpse",
221*4d495c6eSApple OSS Distributions T_META_CHECK_LEAKS(false), T_META_TAG_VM_PREFERRED) /* Test may otherwise time out after T_END */
222*4d495c6eSApple OSS Distributions {
223*4d495c6eSApple OSS Distributions mach_port_t exc_port = MACH_PORT_NULL;
224*4d495c6eSApple OSS Distributions
225*4d495c6eSApple OSS Distributions expect_backtrace = TRUE;
226*4d495c6eSApple OSS Distributions
227*4d495c6eSApple OSS Distributions exc_port = create_exception_port_behavior64(EXC_MASK_CORPSE_NOTIFY,
228*4d495c6eSApple OSS Distributions EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_BACKTRACE_PREFERRED);
229*4d495c6eSApple OSS Distributions
230*4d495c6eSApple OSS Distributions T_ASSERT_NE(exc_port, MACH_PORT_NULL, "Exception port should be valid.");
231*4d495c6eSApple OSS Distributions
232*4d495c6eSApple OSS Distributions T_LOG("Exception port: %d\n", exc_port);
233*4d495c6eSApple OSS Distributions
234*4d495c6eSApple OSS Distributions run_exception_handler_behavior64(exc_port, exc_handler_backtrace, NULL,
235*4d495c6eSApple OSS Distributions EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_BACKTRACE_PREFERRED, true);
236*4d495c6eSApple OSS Distributions
237*4d495c6eSApple OSS Distributions /* Generate a non-fatal EXC_GUARD */
238*4d495c6eSApple OSS Distributions uint64_t payload = 0xDEADBEEF;
239*4d495c6eSApple OSS Distributions int ret = os_fault_with_payload(OS_REASON_LIBSYSTEM, OS_REASON_LIBSYSTEM_CODE_FAULT,
240*4d495c6eSApple OSS Distributions &payload, sizeof(payload), "Generating a user fault", 0);
241*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(ret, 0, "os_fault_with_payload should succeed");
242*4d495c6eSApple OSS Distributions
243*4d495c6eSApple OSS Distributions T_LOG("Wait for exception on main thread..");
244*4d495c6eSApple OSS Distributions for (int i = 0; i < 10; i++) {
245*4d495c6eSApple OSS Distributions sleep(2);
246*4d495c6eSApple OSS Distributions }
247*4d495c6eSApple OSS Distributions
248*4d495c6eSApple OSS Distributions T_FAIL("Did not receive exception within timeout");
249*4d495c6eSApple OSS Distributions }
250*4d495c6eSApple OSS Distributions #endif
251*4d495c6eSApple OSS Distributions
252*4d495c6eSApple OSS Distributions T_DECL(corpse_backtrace_bad_access,
253*4d495c6eSApple OSS Distributions "Test os_bad_access fast backtracing with lightweight corpse",
254*4d495c6eSApple OSS Distributions T_META_CHECK_LEAKS(false), T_META_TAG_VM_PREFERRED)
255*4d495c6eSApple OSS Distributions {
256*4d495c6eSApple OSS Distributions mach_port_t exc_port = MACH_PORT_NULL;
257*4d495c6eSApple OSS Distributions
258*4d495c6eSApple OSS Distributions expect_backtrace = FALSE;
259*4d495c6eSApple OSS Distributions /* Prefer backtrace on EXC_BAD_ACCESS, but should be ignored by kernel */
260*4d495c6eSApple OSS Distributions exc_port = create_exception_port_behavior64(EXC_MASK_BAD_ACCESS,
261*4d495c6eSApple OSS Distributions EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_BACKTRACE_PREFERRED);
262*4d495c6eSApple OSS Distributions
263*4d495c6eSApple OSS Distributions T_ASSERT_NE(exc_port, MACH_PORT_NULL, "Exception port should be valid.");
264*4d495c6eSApple OSS Distributions
265*4d495c6eSApple OSS Distributions T_LOG("Exception port 2: %d\n", exc_port);
266*4d495c6eSApple OSS Distributions
267*4d495c6eSApple OSS Distributions run_exception_handler_behavior64(exc_port, exc_handler_backtrace, exc_handler_identity_protected,
268*4d495c6eSApple OSS Distributions EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_BACKTRACE_PREFERRED, true);
269*4d495c6eSApple OSS Distributions
270*4d495c6eSApple OSS Distributions /* Generate an EXC_BAD_ACCESS */
271*4d495c6eSApple OSS Distributions *(void *volatile*)0 = 0;
272*4d495c6eSApple OSS Distributions
273*4d495c6eSApple OSS Distributions T_FAIL("Should not reach here");
274*4d495c6eSApple OSS Distributions }
275*4d495c6eSApple OSS Distributions
276*4d495c6eSApple OSS Distributions T_DECL(corpse_backtrace_os_log_lightweight_reportcrash,
277*4d495c6eSApple OSS Distributions "Test os_log_fault() fast backtracing with lightweight corpse and report crash",
278*4d495c6eSApple OSS Distributions T_META_ENABLED(false), T_META_TAG_VM_PREFERRED)
279*4d495c6eSApple OSS Distributions {
280*4d495c6eSApple OSS Distributions mach_port_t rc_port = MACH_PORT_NULL, bootstrap = MACH_PORT_NULL;
281*4d495c6eSApple OSS Distributions kern_return_t kr;
282*4d495c6eSApple OSS Distributions
283*4d495c6eSApple OSS Distributions expect_backtrace = TRUE;
284*4d495c6eSApple OSS Distributions
285*4d495c6eSApple OSS Distributions kr = task_get_bootstrap_port(mach_task_self(), &bootstrap);
286*4d495c6eSApple OSS Distributions
287*4d495c6eSApple OSS Distributions kr = bootstrap_look_up(bootstrap, "com.apple.ReportCrash", &rc_port);
288*4d495c6eSApple OSS Distributions
289*4d495c6eSApple OSS Distributions T_ASSERT_NE(rc_port, MACH_PORT_NULL, "Exception port should be valid.");
290*4d495c6eSApple OSS Distributions
291*4d495c6eSApple OSS Distributions T_LOG("ReportCrash exception port: %d\n", rc_port);
292*4d495c6eSApple OSS Distributions
293*4d495c6eSApple OSS Distributions #ifndef ARM_THREAD_STATE
294*4d495c6eSApple OSS Distributions #define ARM_THREAD_STATE 1
295*4d495c6eSApple OSS Distributions #endif
296*4d495c6eSApple OSS Distributions
297*4d495c6eSApple OSS Distributions kr = task_set_exception_ports(mach_task_self(),
298*4d495c6eSApple OSS Distributions EXC_MASK_CORPSE_NOTIFY,
299*4d495c6eSApple OSS Distributions rc_port,
300*4d495c6eSApple OSS Distributions EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_BACKTRACE_PREFERRED | MACH_EXCEPTION_CODES,
301*4d495c6eSApple OSS Distributions ARM_THREAD_STATE);
302*4d495c6eSApple OSS Distributions
303*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(kr, KERN_SUCCESS, "Registration with ReportCrash should succeed");
304*4d495c6eSApple OSS Distributions
305*4d495c6eSApple OSS Distributions /* Generate a non-fatal EXC_GUARD */
306*4d495c6eSApple OSS Distributions uint64_t payload = 0xDEADBEEF;
307*4d495c6eSApple OSS Distributions int ret = os_fault_with_payload(OS_REASON_LIBSYSTEM, OS_REASON_LIBSYSTEM_CODE_FAULT,
308*4d495c6eSApple OSS Distributions &payload, sizeof(payload), "Generating a user fault", 0);
309*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(ret, 0, "os_fault_with_payload should succeed");
310*4d495c6eSApple OSS Distributions
311*4d495c6eSApple OSS Distributions T_LOG("Kernel should have delivered a message to ReportCrash. Exit now.");
312*4d495c6eSApple OSS Distributions T_END;
313*4d495c6eSApple OSS Distributions }
314