xref: /aosp_15_r20/external/google-breakpad/src/client/mac/tests/spawn_child_process.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2010 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 // Utility functions for spawning a helper process using a different
30 // CPU architecture.
31 
32 #ifndef GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
33 #define GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
34 
35 #include <AvailabilityMacros.h>
36 #ifndef MAC_OS_X_VERSION_10_6
37 #define MAC_OS_X_VERSION_10_6 1060
38 #endif
39 #include <crt_externs.h>
40 #include <mach-o/dyld.h>
41 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
42 #include <spawn.h>
43 #endif
44 
45 #include <string>
46 #include <vector>
47 
48 #include "google_breakpad/common/minidump_format.h"
49 
50 namespace google_breakpad_test {
51 
52 using std::string;
53 using std::vector;
54 
55 const MDCPUArchitecture kNativeArchitecture =
56 #if defined(__i386__)
57   MD_CPU_ARCHITECTURE_X86
58 #elif defined(__x86_64__)
59   MD_CPU_ARCHITECTURE_AMD64
60 #elif defined(__ppc__) || defined(__ppc64__)
61   MD_CPU_ARCHITECTURE_PPC
62 #else
63 #error "This file has not been ported to this CPU architecture."
64 #endif
65   ;
66 
67 const uint32_t kNativeContext =
68 #if defined(__i386__)
69   MD_CONTEXT_X86
70 #elif defined(__x86_64__)
71   MD_CONTEXT_AMD64
72 #elif defined(__ppc__) || defined(__ppc64__)
73   MD_CONTEXT_PPC
74 #else
75 #error "This file has not been ported to this CPU architecture."
76 #endif
77   ;
78 
GetExecutablePath()79 string GetExecutablePath() {
80   char self_path[PATH_MAX];
81   uint32_t size = sizeof(self_path);
82   if (_NSGetExecutablePath(self_path, &size) != 0)
83     return "";
84   return self_path;
85 }
86 
GetHelperPath()87 string GetHelperPath() {
88   string helper_path(GetExecutablePath());
89   size_t pos = helper_path.rfind('/');
90   if (pos == string::npos)
91     return "";
92 
93   helper_path.erase(pos + 1);
94   helper_path += "minidump_generator_test_helper";
95   return helper_path;
96 }
97 
98 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
99 
spawn_child_process(const char ** argv)100 pid_t spawn_child_process(const char** argv) {
101   posix_spawnattr_t spawnattr;
102   if (posix_spawnattr_init(&spawnattr) != 0)
103     return (pid_t)-1;
104 
105   cpu_type_t pref_cpu_types[2] = {
106 #if defined(__x86_64__)
107     CPU_TYPE_X86,
108 #elif defined(__i386__)
109     CPU_TYPE_X86_64,
110 #endif
111     CPU_TYPE_ANY
112   };
113 
114   // Set spawn attributes.
115   size_t attr_count = sizeof(pref_cpu_types) / sizeof(pref_cpu_types[0]);
116   size_t attr_ocount = 0;
117   if (posix_spawnattr_setbinpref_np(&spawnattr,
118                                     attr_count,
119                                     pref_cpu_types,
120                                     &attr_ocount) != 0 ||
121       attr_ocount != attr_count) {
122     posix_spawnattr_destroy(&spawnattr);
123     return (pid_t)-1;
124   }
125 
126   // Create an argv array.
127   vector<char*> argv_v;
128   while (*argv) {
129     argv_v.push_back(strdup(*argv));
130     argv++;
131   }
132   argv_v.push_back(NULL);
133   pid_t new_pid = 0;
134   int result = posix_spawnp(&new_pid, argv_v[0], NULL, &spawnattr,
135                             &argv_v[0], *_NSGetEnviron());
136   posix_spawnattr_destroy(&spawnattr);
137 
138   for (unsigned i = 0; i < argv_v.size(); i++) {
139     free(argv_v[i]);
140   }
141 
142   return result == 0 ? new_pid : -1;
143 }
144 #endif
145 
146 }  // namespace google_breakpad_test
147 
148 #endif  // GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
149