1 /* 2 * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2013, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include "debug_utils.h" 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <sys/stat.h> 12 13 #include <string> 14 #include <string.h> 15 16 #include <debugger.h> 17 18 #include <libroot_private.h> 19 #include <syscalls.h> 20 #include <syscall_load_image.h> 21 22 23 extern const char* __progname; 24 static const char* kCommandName = __progname; 25 26 27 // find_program 28 static status_t 29 find_program(const char* programName, std::string& resolvedPath) 30 { 31 // If the program name is absolute, then there's nothing to do. 32 // If the program name consists of more than one path element, then we 33 // consider it a relative path and don't search in PATH either. 34 if (*programName == '/' || strchr(programName, '/')) { 35 resolvedPath = programName; 36 return B_OK; 37 } 38 39 // get the PATH environment variable 40 const char* paths = getenv("PATH"); 41 if (!paths) 42 return B_ENTRY_NOT_FOUND; 43 44 // iterate through the paths 45 do { 46 const char* pathEnd = strchr(paths, ':'); 47 int pathLen = (pathEnd ? pathEnd - paths : strlen(paths)); 48 49 // We skip empty paths. 50 if (pathLen > 0) { 51 // get the program path 52 std::string path(paths, pathLen); 53 path += "/"; 54 path += programName; 55 56 // stat() the path to be sure, there is a file 57 struct stat st; 58 if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { 59 resolvedPath = path; 60 return B_OK; 61 } 62 } 63 64 paths = (pathEnd ? pathEnd + 1 : NULL); 65 } while (paths); 66 67 // not found in PATH 68 return B_ENTRY_NOT_FOUND; 69 } 70 71 72 // #pragma mark - 73 74 75 // load_program 76 thread_id 77 load_program(const char* const* args, int32 argCount, bool traceLoading) 78 { 79 // clone the argument vector so that we can change it 80 const char** mutableArgs = new const char*[argCount]; 81 for (int i = 0; i < argCount; i++) 82 mutableArgs[i] = args[i]; 83 84 // resolve the program path 85 std::string programPath; 86 status_t error = find_program(args[0], programPath); 87 if (error != B_OK) { 88 delete[] mutableArgs; 89 return error; 90 } 91 mutableArgs[0] = programPath.c_str(); 92 93 // count environment variables 94 int32 envCount = 0; 95 while (environ[envCount] != NULL) 96 envCount++; 97 98 // flatten the program args and environment 99 char** flatArgs = NULL; 100 size_t flatArgsSize; 101 error = __flatten_process_args(mutableArgs, argCount, environ, &envCount, 102 mutableArgs[0], &flatArgs, &flatArgsSize); 103 104 // load the program 105 thread_id thread; 106 if (error == B_OK) { 107 thread = _kern_load_image(flatArgs, flatArgsSize, argCount, envCount, 108 B_NORMAL_PRIORITY, (traceLoading ? 0 : B_WAIT_TILL_LOADED), -1, 0); 109 110 free(flatArgs); 111 } else 112 thread = error; 113 114 delete[] mutableArgs; 115 116 return thread; 117 } 118 119 120 // set_team_debugging_flags 121 status_t 122 set_team_debugging_flags(port_id nubPort, int32 flags) 123 { 124 debug_nub_set_team_flags message; 125 message.flags = flags; 126 127 status_t error = B_OK; 128 do { 129 error = write_port(nubPort, B_DEBUG_MESSAGE_SET_TEAM_FLAGS, 130 &message, sizeof(message)); 131 } while (error == B_INTERRUPTED); 132 133 if (error != B_OK) { 134 fprintf(stderr, "%s: Failed to set team debug flags: %s\n", 135 kCommandName, strerror(error)); 136 } 137 138 return error; 139 } 140 141 142 // set_thread_debugging_flags 143 status_t 144 set_thread_debugging_flags(port_id nubPort, thread_id thread, int32 flags) 145 { 146 debug_nub_set_thread_flags message; 147 message.thread = thread; 148 message.flags = flags; 149 150 status_t error = B_OK; 151 do { 152 error = write_port(nubPort, B_DEBUG_MESSAGE_SET_THREAD_FLAGS, 153 &message, sizeof(message)); 154 } while (error == B_INTERRUPTED); 155 156 if (error != B_OK) { 157 fprintf(stderr, "%s: Failed to set thread debug flags: %s\n", 158 kCommandName, strerror(error)); 159 } 160 161 return error; 162 } 163 164 165 // continue_thread 166 status_t 167 continue_thread(port_id nubPort, thread_id thread) 168 { 169 debug_nub_continue_thread message; 170 message.thread = thread; 171 message.handle_event = B_THREAD_DEBUG_HANDLE_EVENT; 172 message.single_step = false; 173 174 status_t error = B_OK; 175 176 do { 177 error = write_port(nubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD, 178 &message, sizeof(message)); 179 } while (error == B_INTERRUPTED); 180 181 if (error != B_OK) { 182 fprintf(stderr, "%s: Failed to run thread %" B_PRId32 ": %s\n", 183 kCommandName, thread, strerror(error)); 184 } 185 186 return error; 187 } 188