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