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