annotate lldb/tools/darwin-debug/darwin-debug.cpp @ 203:0d4b2609c30f

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 05 Jun 2021 11:18:24 +0900
parents 1d019706d866
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===-- darwin-debug.cpp ----------------------------------------*- C++ -*-===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 // Darwin launch helper
anatofuz
parents:
diff changeset
10 //
anatofuz
parents:
diff changeset
11 // This program was written to allow programs to be launched in a new
anatofuz
parents:
diff changeset
12 // Terminal.app window and have the application be stopped for debugging
anatofuz
parents:
diff changeset
13 // at the program entry point.
anatofuz
parents:
diff changeset
14 //
anatofuz
parents:
diff changeset
15 // Although it uses posix_spawn(), it uses Darwin specific posix spawn
anatofuz
parents:
diff changeset
16 // attribute flags to accomplish its task. It uses an "exec only" flag
anatofuz
parents:
diff changeset
17 // which avoids forking this process, and it uses a "stop at entry"
anatofuz
parents:
diff changeset
18 // flag to stop the program at the entry point.
anatofuz
parents:
diff changeset
19 //
anatofuz
parents:
diff changeset
20 // Since it uses darwin specific flags this code should not be compiled
anatofuz
parents:
diff changeset
21 // on other systems.
anatofuz
parents:
diff changeset
22 #if defined(__APPLE__)
anatofuz
parents:
diff changeset
23
anatofuz
parents:
diff changeset
24 #include <crt_externs.h>
anatofuz
parents:
diff changeset
25 #include <getopt.h>
anatofuz
parents:
diff changeset
26 #include <limits.h>
anatofuz
parents:
diff changeset
27 #include <mach/machine.h>
anatofuz
parents:
diff changeset
28 #include <signal.h>
anatofuz
parents:
diff changeset
29 #include <spawn.h>
anatofuz
parents:
diff changeset
30 #include <stdio.h>
anatofuz
parents:
diff changeset
31 #include <stdlib.h>
anatofuz
parents:
diff changeset
32 #include <string.h>
anatofuz
parents:
diff changeset
33 #include <sys/socket.h>
anatofuz
parents:
diff changeset
34 #include <sys/stat.h>
anatofuz
parents:
diff changeset
35 #include <sys/types.h>
anatofuz
parents:
diff changeset
36 #include <sys/un.h>
anatofuz
parents:
diff changeset
37
anatofuz
parents:
diff changeset
38 #include <string>
anatofuz
parents:
diff changeset
39
anatofuz
parents:
diff changeset
40 #ifndef _POSIX_SPAWN_DISABLE_ASLR
anatofuz
parents:
diff changeset
41 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
anatofuz
parents:
diff changeset
42 #endif
anatofuz
parents:
diff changeset
43
anatofuz
parents:
diff changeset
44 #define streq(a, b) strcmp(a, b) == 0
anatofuz
parents:
diff changeset
45
anatofuz
parents:
diff changeset
46 static struct option g_long_options[] = {
anatofuz
parents:
diff changeset
47 {"arch", required_argument, NULL, 'a'},
anatofuz
parents:
diff changeset
48 {"disable-aslr", no_argument, NULL, 'd'},
anatofuz
parents:
diff changeset
49 {"no-env", no_argument, NULL, 'e'},
anatofuz
parents:
diff changeset
50 {"help", no_argument, NULL, 'h'},
anatofuz
parents:
diff changeset
51 {"setsid", no_argument, NULL, 's'},
anatofuz
parents:
diff changeset
52 {"unix-socket", required_argument, NULL, 'u'},
anatofuz
parents:
diff changeset
53 {"working-dir", required_argument, NULL, 'w'},
anatofuz
parents:
diff changeset
54 {"env", required_argument, NULL, 'E'},
anatofuz
parents:
diff changeset
55 {NULL, 0, NULL, 0}};
anatofuz
parents:
diff changeset
56
anatofuz
parents:
diff changeset
57 static void usage() {
anatofuz
parents:
diff changeset
58 puts("NAME\n"
anatofuz
parents:
diff changeset
59 " darwin-debug -- posix spawn a process that is stopped at the entry "
anatofuz
parents:
diff changeset
60 "point\n"
anatofuz
parents:
diff changeset
61 " for debugging.\n"
anatofuz
parents:
diff changeset
62 "\n"
anatofuz
parents:
diff changeset
63 "SYNOPSIS\n"
anatofuz
parents:
diff changeset
64 " darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] "
anatofuz
parents:
diff changeset
65 "[--working-dir=<PATH>] [--disable-aslr] [--no-env] [--setsid] [--help] "
anatofuz
parents:
diff changeset
66 "-- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
anatofuz
parents:
diff changeset
67 "\n"
anatofuz
parents:
diff changeset
68 "DESCRIPTION\n"
anatofuz
parents:
diff changeset
69 " darwin-debug will exec itself into a child process <PROGRAM> that "
anatofuz
parents:
diff changeset
70 "is\n"
anatofuz
parents:
diff changeset
71 " halted for debugging. It does this by using posix_spawn() along "
anatofuz
parents:
diff changeset
72 "with\n"
anatofuz
parents:
diff changeset
73 " darwin specific posix_spawn flags that allows exec only (no fork), "
anatofuz
parents:
diff changeset
74 "and\n"
anatofuz
parents:
diff changeset
75 " stop at the program entry point. Any program arguments "
anatofuz
parents:
diff changeset
76 "<PROGRAM-ARG> are\n"
anatofuz
parents:
diff changeset
77 " passed on to the exec as the arguments for the new process. The "
anatofuz
parents:
diff changeset
78 "current\n"
anatofuz
parents:
diff changeset
79 " environment will be passed to the new process unless the "
anatofuz
parents:
diff changeset
80 "\"--no-env\"\n"
anatofuz
parents:
diff changeset
81 " option is used. A unix socket must be supplied using the\n"
anatofuz
parents:
diff changeset
82 " --unix-socket=<SOCKET> option so the calling program can handshake "
anatofuz
parents:
diff changeset
83 "with\n"
anatofuz
parents:
diff changeset
84 " this process and get its process id.\n"
anatofuz
parents:
diff changeset
85 "\n"
anatofuz
parents:
diff changeset
86 "EXAMPLE\n"
anatofuz
parents:
diff changeset
87 " darwin-debug --arch=i386 -- /bin/ls -al /tmp\n");
anatofuz
parents:
diff changeset
88 exit(1);
anatofuz
parents:
diff changeset
89 }
anatofuz
parents:
diff changeset
90
anatofuz
parents:
diff changeset
91 static void exit_with_errno(int err, const char *prefix) {
anatofuz
parents:
diff changeset
92 if (err) {
anatofuz
parents:
diff changeset
93 fprintf(stderr, "%s%s", prefix ? prefix : "", strerror(err));
anatofuz
parents:
diff changeset
94 exit(err);
anatofuz
parents:
diff changeset
95 }
anatofuz
parents:
diff changeset
96 }
anatofuz
parents:
diff changeset
97
anatofuz
parents:
diff changeset
98 pid_t posix_spawn_for_debug(char *const *argv, char *const *envp,
anatofuz
parents:
diff changeset
99 const char *working_dir, cpu_type_t cpu_type,
anatofuz
parents:
diff changeset
100 int disable_aslr) {
anatofuz
parents:
diff changeset
101 pid_t pid = 0;
anatofuz
parents:
diff changeset
102
anatofuz
parents:
diff changeset
103 const char *path = argv[0];
anatofuz
parents:
diff changeset
104
anatofuz
parents:
diff changeset
105 posix_spawnattr_t attr;
anatofuz
parents:
diff changeset
106
anatofuz
parents:
diff changeset
107 exit_with_errno(::posix_spawnattr_init(&attr),
anatofuz
parents:
diff changeset
108 "::posix_spawnattr_init (&attr) error: ");
anatofuz
parents:
diff changeset
109
anatofuz
parents:
diff changeset
110 // Here we are using a darwin specific feature that allows us to exec only
anatofuz
parents:
diff changeset
111 // since we want this program to turn into the program we want to debug,
anatofuz
parents:
diff changeset
112 // and also have the new program start suspended (right at __dyld_start)
anatofuz
parents:
diff changeset
113 // so we can debug it
anatofuz
parents:
diff changeset
114 short flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETEXEC |
anatofuz
parents:
diff changeset
115 POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
anatofuz
parents:
diff changeset
116
anatofuz
parents:
diff changeset
117 // Disable ASLR if we were asked to
anatofuz
parents:
diff changeset
118 if (disable_aslr)
anatofuz
parents:
diff changeset
119 flags |= _POSIX_SPAWN_DISABLE_ASLR;
anatofuz
parents:
diff changeset
120
anatofuz
parents:
diff changeset
121 sigset_t no_signals;
anatofuz
parents:
diff changeset
122 sigset_t all_signals;
anatofuz
parents:
diff changeset
123 sigemptyset(&no_signals);
anatofuz
parents:
diff changeset
124 sigfillset(&all_signals);
anatofuz
parents:
diff changeset
125 ::posix_spawnattr_setsigmask(&attr, &no_signals);
anatofuz
parents:
diff changeset
126 ::posix_spawnattr_setsigdefault(&attr, &all_signals);
anatofuz
parents:
diff changeset
127
anatofuz
parents:
diff changeset
128 // Set the flags we just made into our posix spawn attributes
anatofuz
parents:
diff changeset
129 exit_with_errno(::posix_spawnattr_setflags(&attr, flags),
anatofuz
parents:
diff changeset
130 "::posix_spawnattr_setflags (&attr, flags) error: ");
anatofuz
parents:
diff changeset
131
anatofuz
parents:
diff changeset
132 // Another darwin specific thing here where we can select the architecture
anatofuz
parents:
diff changeset
133 // of the binary we want to re-exec as.
anatofuz
parents:
diff changeset
134 if (cpu_type != 0) {
anatofuz
parents:
diff changeset
135 size_t ocount = 0;
anatofuz
parents:
diff changeset
136 exit_with_errno(
anatofuz
parents:
diff changeset
137 ::posix_spawnattr_setbinpref_np(&attr, 1, &cpu_type, &ocount),
anatofuz
parents:
diff changeset
138 "posix_spawnattr_setbinpref_np () error: ");
anatofuz
parents:
diff changeset
139 }
anatofuz
parents:
diff changeset
140
anatofuz
parents:
diff changeset
141 // I wish there was a posix_spawn flag to change the working directory of
anatofuz
parents:
diff changeset
142 // the inferior process we will spawn, but there currently isn't. If there
anatofuz
parents:
diff changeset
143 // ever is a better way to do this, we should use it. I would rather not
anatofuz
parents:
diff changeset
144 // manually fork, chdir in the child process, and then posix_spawn with exec
anatofuz
parents:
diff changeset
145 // as the whole reason for doing posix_spawn is to not hose anything up
anatofuz
parents:
diff changeset
146 // after the fork and prior to the exec...
anatofuz
parents:
diff changeset
147 if (working_dir)
anatofuz
parents:
diff changeset
148 ::chdir(working_dir);
anatofuz
parents:
diff changeset
149
anatofuz
parents:
diff changeset
150 exit_with_errno(::posix_spawnp(&pid, path, NULL, &attr, (char *const *)argv,
anatofuz
parents:
diff changeset
151 (char *const *)envp),
anatofuz
parents:
diff changeset
152 "posix_spawn() error: ");
anatofuz
parents:
diff changeset
153
anatofuz
parents:
diff changeset
154 // This code will only be reached if the posix_spawn exec failed...
anatofuz
parents:
diff changeset
155 ::posix_spawnattr_destroy(&attr);
anatofuz
parents:
diff changeset
156
anatofuz
parents:
diff changeset
157 return pid;
anatofuz
parents:
diff changeset
158 }
anatofuz
parents:
diff changeset
159
anatofuz
parents:
diff changeset
160 int main(int argc, char *const *argv, char *const *envp, const char **apple) {
anatofuz
parents:
diff changeset
161 #if defined(DEBUG_LLDB_LAUNCHER)
anatofuz
parents:
diff changeset
162 const char *program_name = strrchr(apple[0], '/');
anatofuz
parents:
diff changeset
163
anatofuz
parents:
diff changeset
164 if (program_name)
anatofuz
parents:
diff changeset
165 program_name++; // Skip the last slash..
anatofuz
parents:
diff changeset
166 else
anatofuz
parents:
diff changeset
167 program_name = apple[0];
anatofuz
parents:
diff changeset
168
anatofuz
parents:
diff changeset
169 printf("%s called with:\n", program_name);
anatofuz
parents:
diff changeset
170 for (int i = 0; i < argc; ++i)
anatofuz
parents:
diff changeset
171 printf("argv[%u] = '%s'\n", i, argv[i]);
anatofuz
parents:
diff changeset
172 #endif
anatofuz
parents:
diff changeset
173
anatofuz
parents:
diff changeset
174 cpu_type_t cpu_type = 0;
anatofuz
parents:
diff changeset
175 bool show_usage = false;
anatofuz
parents:
diff changeset
176 int ch;
anatofuz
parents:
diff changeset
177 int disable_aslr = 0; // By default we disable ASLR
anatofuz
parents:
diff changeset
178 bool pass_env = true;
anatofuz
parents:
diff changeset
179 std::string unix_socket_name;
anatofuz
parents:
diff changeset
180 std::string working_dir;
anatofuz
parents:
diff changeset
181
anatofuz
parents:
diff changeset
182 #if __GLIBC__
anatofuz
parents:
diff changeset
183 optind = 0;
anatofuz
parents:
diff changeset
184 #else
anatofuz
parents:
diff changeset
185 optreset = 1;
anatofuz
parents:
diff changeset
186 optind = 1;
anatofuz
parents:
diff changeset
187 #endif
anatofuz
parents:
diff changeset
188
anatofuz
parents:
diff changeset
189 while ((ch = getopt_long_only(argc, argv, "a:deE:hsu:?", g_long_options,
anatofuz
parents:
diff changeset
190 NULL)) != -1) {
anatofuz
parents:
diff changeset
191 switch (ch) {
anatofuz
parents:
diff changeset
192 case 0:
anatofuz
parents:
diff changeset
193 break;
anatofuz
parents:
diff changeset
194
anatofuz
parents:
diff changeset
195 case 'a': // "-a i386" or "--arch=i386"
anatofuz
parents:
diff changeset
196 if (optarg) {
anatofuz
parents:
diff changeset
197 if (streq(optarg, "i386"))
anatofuz
parents:
diff changeset
198 cpu_type = CPU_TYPE_I386;
anatofuz
parents:
diff changeset
199 else if (streq(optarg, "x86_64"))
anatofuz
parents:
diff changeset
200 cpu_type = CPU_TYPE_X86_64;
anatofuz
parents:
diff changeset
201 else if (streq(optarg, "x86_64h"))
anatofuz
parents:
diff changeset
202 cpu_type = 0; // Don't set CPU type when we have x86_64h
anatofuz
parents:
diff changeset
203 else if (strstr(optarg, "arm") == optarg)
anatofuz
parents:
diff changeset
204 cpu_type = CPU_TYPE_ARM;
anatofuz
parents:
diff changeset
205 else {
anatofuz
parents:
diff changeset
206 ::fprintf(stderr, "error: unsupported cpu type '%s'\n", optarg);
anatofuz
parents:
diff changeset
207 ::exit(1);
anatofuz
parents:
diff changeset
208 }
anatofuz
parents:
diff changeset
209 }
anatofuz
parents:
diff changeset
210 break;
anatofuz
parents:
diff changeset
211
anatofuz
parents:
diff changeset
212 case 'd':
anatofuz
parents:
diff changeset
213 disable_aslr = 1;
anatofuz
parents:
diff changeset
214 break;
anatofuz
parents:
diff changeset
215
anatofuz
parents:
diff changeset
216 case 'e':
anatofuz
parents:
diff changeset
217 pass_env = false;
anatofuz
parents:
diff changeset
218 break;
anatofuz
parents:
diff changeset
219
anatofuz
parents:
diff changeset
220 case 'E': {
anatofuz
parents:
diff changeset
221 // Since we will exec this program into our new program, we can just set
anatofuz
parents:
diff changeset
222 // environment
anatofuz
parents:
diff changeset
223 // variables in this process and they will make it into the child process.
anatofuz
parents:
diff changeset
224 std::string name;
anatofuz
parents:
diff changeset
225 std::string value;
anatofuz
parents:
diff changeset
226 const char *equal_pos = strchr(optarg, '=');
anatofuz
parents:
diff changeset
227 if (equal_pos) {
anatofuz
parents:
diff changeset
228 name.assign(optarg, equal_pos - optarg);
anatofuz
parents:
diff changeset
229 value.assign(equal_pos + 1);
anatofuz
parents:
diff changeset
230 } else {
anatofuz
parents:
diff changeset
231 name = optarg;
anatofuz
parents:
diff changeset
232 }
anatofuz
parents:
diff changeset
233 ::setenv(name.c_str(), value.c_str(), 1);
anatofuz
parents:
diff changeset
234 } break;
anatofuz
parents:
diff changeset
235
anatofuz
parents:
diff changeset
236 case 's':
anatofuz
parents:
diff changeset
237 // Create a new session to avoid having control-C presses kill our current
anatofuz
parents:
diff changeset
238 // terminal session when this program is launched from a .command file
anatofuz
parents:
diff changeset
239 ::setsid();
anatofuz
parents:
diff changeset
240 break;
anatofuz
parents:
diff changeset
241
anatofuz
parents:
diff changeset
242 case 'u':
anatofuz
parents:
diff changeset
243 unix_socket_name.assign(optarg);
anatofuz
parents:
diff changeset
244 break;
anatofuz
parents:
diff changeset
245
anatofuz
parents:
diff changeset
246 case 'w': {
anatofuz
parents:
diff changeset
247 struct stat working_dir_stat;
anatofuz
parents:
diff changeset
248 if (stat(optarg, &working_dir_stat) == 0)
anatofuz
parents:
diff changeset
249 working_dir.assign(optarg);
anatofuz
parents:
diff changeset
250 else
anatofuz
parents:
diff changeset
251 ::fprintf(stderr, "warning: working directory doesn't exist: '%s'\n",
anatofuz
parents:
diff changeset
252 optarg);
anatofuz
parents:
diff changeset
253 } break;
anatofuz
parents:
diff changeset
254
anatofuz
parents:
diff changeset
255 case 'h':
anatofuz
parents:
diff changeset
256 case '?':
anatofuz
parents:
diff changeset
257 default:
anatofuz
parents:
diff changeset
258 show_usage = true;
anatofuz
parents:
diff changeset
259 break;
anatofuz
parents:
diff changeset
260 }
anatofuz
parents:
diff changeset
261 }
anatofuz
parents:
diff changeset
262 argc -= optind;
anatofuz
parents:
diff changeset
263 argv += optind;
anatofuz
parents:
diff changeset
264
anatofuz
parents:
diff changeset
265 if (show_usage || argc <= 0 || unix_socket_name.empty())
anatofuz
parents:
diff changeset
266 usage();
anatofuz
parents:
diff changeset
267
anatofuz
parents:
diff changeset
268 #if defined(DEBUG_LLDB_LAUNCHER)
anatofuz
parents:
diff changeset
269 printf("\n%s post options:\n", program_name);
anatofuz
parents:
diff changeset
270 for (int i = 0; i < argc; ++i)
anatofuz
parents:
diff changeset
271 printf("argv[%u] = '%s'\n", i, argv[i]);
anatofuz
parents:
diff changeset
272 #endif
anatofuz
parents:
diff changeset
273
anatofuz
parents:
diff changeset
274 // Open the socket that was passed in as an option
anatofuz
parents:
diff changeset
275 struct sockaddr_un saddr_un;
anatofuz
parents:
diff changeset
276 int s = ::socket(AF_UNIX, SOCK_STREAM, 0);
anatofuz
parents:
diff changeset
277 if (s < 0) {
anatofuz
parents:
diff changeset
278 perror("error: socket (AF_UNIX, SOCK_STREAM, 0)");
anatofuz
parents:
diff changeset
279 exit(1);
anatofuz
parents:
diff changeset
280 }
anatofuz
parents:
diff changeset
281
anatofuz
parents:
diff changeset
282 saddr_un.sun_family = AF_UNIX;
anatofuz
parents:
diff changeset
283 ::strncpy(saddr_un.sun_path, unix_socket_name.c_str(),
anatofuz
parents:
diff changeset
284 sizeof(saddr_un.sun_path) - 1);
anatofuz
parents:
diff changeset
285 saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
anatofuz
parents:
diff changeset
286 saddr_un.sun_len = SUN_LEN(&saddr_un);
anatofuz
parents:
diff changeset
287
anatofuz
parents:
diff changeset
288 if (::connect(s, (struct sockaddr *)&saddr_un, SUN_LEN(&saddr_un)) < 0) {
anatofuz
parents:
diff changeset
289 perror("error: connect (socket, &saddr_un, saddr_un_len)");
anatofuz
parents:
diff changeset
290 exit(1);
anatofuz
parents:
diff changeset
291 }
anatofuz
parents:
diff changeset
292
anatofuz
parents:
diff changeset
293 // We were able to connect to the socket, now write our PID so whomever
anatofuz
parents:
diff changeset
294 // launched us will know this process's ID
anatofuz
parents:
diff changeset
295 char pid_str[64];
anatofuz
parents:
diff changeset
296 const int pid_str_len =
anatofuz
parents:
diff changeset
297 ::snprintf(pid_str, sizeof(pid_str), "%i", ::getpid());
anatofuz
parents:
diff changeset
298 const int bytes_sent = ::send(s, pid_str, pid_str_len, 0);
anatofuz
parents:
diff changeset
299
anatofuz
parents:
diff changeset
300 if (pid_str_len != bytes_sent) {
anatofuz
parents:
diff changeset
301 perror("error: send (s, pid_str, pid_str_len, 0)");
anatofuz
parents:
diff changeset
302 exit(1);
anatofuz
parents:
diff changeset
303 }
anatofuz
parents:
diff changeset
304
anatofuz
parents:
diff changeset
305 // We are done with the socket
anatofuz
parents:
diff changeset
306 close(s);
anatofuz
parents:
diff changeset
307
anatofuz
parents:
diff changeset
308 system("clear");
anatofuz
parents:
diff changeset
309 printf("Launching: '%s'\n", argv[0]);
anatofuz
parents:
diff changeset
310 if (working_dir.empty()) {
anatofuz
parents:
diff changeset
311 char cwd[PATH_MAX];
anatofuz
parents:
diff changeset
312 const char *cwd_ptr = getcwd(cwd, sizeof(cwd));
anatofuz
parents:
diff changeset
313 printf("Working directory: '%s'\n", cwd_ptr);
anatofuz
parents:
diff changeset
314 } else {
anatofuz
parents:
diff changeset
315 printf("Working directory: '%s'\n", working_dir.c_str());
anatofuz
parents:
diff changeset
316 }
anatofuz
parents:
diff changeset
317 printf("%i arguments:\n", argc);
anatofuz
parents:
diff changeset
318
anatofuz
parents:
diff changeset
319 for (int i = 0; i < argc; ++i)
anatofuz
parents:
diff changeset
320 printf("argv[%u] = '%s'\n", i, argv[i]);
anatofuz
parents:
diff changeset
321
anatofuz
parents:
diff changeset
322 // Now we posix spawn to exec this process into the inferior that we want
anatofuz
parents:
diff changeset
323 // to debug.
anatofuz
parents:
diff changeset
324 posix_spawn_for_debug(
anatofuz
parents:
diff changeset
325 argv,
anatofuz
parents:
diff changeset
326 pass_env ? *_NSGetEnviron() : NULL, // Pass current environment as we may
anatofuz
parents:
diff changeset
327 // have modified it if "--env" options
anatofuz
parents:
diff changeset
328 // was used, do NOT pass "envp" here
anatofuz
parents:
diff changeset
329 working_dir.empty() ? NULL : working_dir.c_str(), cpu_type, disable_aslr);
anatofuz
parents:
diff changeset
330
anatofuz
parents:
diff changeset
331 return 0;
anatofuz
parents:
diff changeset
332 }
anatofuz
parents:
diff changeset
333
anatofuz
parents:
diff changeset
334 #endif // #if defined (__APPLE__)