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