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