1 /* 2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <TeamDebugger.h> 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <sys/stat.h> 12 13 #include <string.h> 14 15 #include <Path.h> 16 #include <String.h> 17 18 #include <libroot_private.h> 19 #include <syscalls.h> 20 21 22 BTeamDebugger::BTeamDebugger() 23 : 24 fDebuggerPort(-1) 25 { 26 } 27 28 29 BTeamDebugger::~BTeamDebugger() 30 { 31 Uninstall(); 32 } 33 34 35 status_t 36 BTeamDebugger::Install(team_id team) 37 { 38 Uninstall(); 39 40 // create a debugger port 41 char name[B_OS_NAME_LENGTH]; 42 snprintf(name, sizeof(name), "debugger for team %" B_PRId32, team); 43 fDebuggerPort = create_port(100, name); 44 if (fDebuggerPort < 0) 45 return fDebuggerPort; 46 47 port_id nubPort = install_team_debugger(team, fDebuggerPort); 48 if (nubPort < 0) { 49 delete_port(fDebuggerPort); 50 fDebuggerPort = -1; 51 return nubPort; 52 } 53 54 status_t error = BDebugContext::Init(team, nubPort); 55 if (error != B_OK) { 56 remove_team_debugger(team); 57 delete_port(fDebuggerPort); 58 fDebuggerPort = -1; 59 return error; 60 } 61 62 return B_OK; 63 } 64 65 66 status_t 67 BTeamDebugger::Uninstall() 68 { 69 if (Team() < 0) 70 return B_BAD_VALUE; 71 72 remove_team_debugger(Team()); 73 74 delete_port(fDebuggerPort); 75 76 BDebugContext::Uninit(); 77 78 fDebuggerPort = -1; 79 80 return B_OK; 81 } 82 83 84 status_t 85 BTeamDebugger::LoadProgram(const char* const* args, int32 argCount, 86 bool traceLoading) 87 { 88 // load the program 89 thread_id thread = _LoadProgram(args, argCount, traceLoading); 90 if (thread < 0) 91 return thread; 92 93 // install the debugger 94 status_t error = Install(thread); 95 if (error != B_OK) { 96 kill_team(thread); 97 return error; 98 } 99 100 return B_OK; 101 } 102 103 104 status_t 105 BTeamDebugger::ReadDebugMessage(int32& _messageCode, 106 debug_debugger_message_data& messageBuffer) 107 { 108 ssize_t bytesRead = read_port(fDebuggerPort, &_messageCode, &messageBuffer, 109 sizeof(messageBuffer)); 110 if (bytesRead < 0) 111 return bytesRead; 112 113 return B_OK; 114 } 115 116 117 118 /*static*/ thread_id 119 BTeamDebugger::_LoadProgram(const char* const* args, int32 argCount, 120 bool traceLoading) 121 { 122 // clone the argument vector so that we can change it 123 const char** mutableArgs = new const char*[argCount]; 124 for (int i = 0; i < argCount; i++) 125 mutableArgs[i] = args[i]; 126 127 // resolve the program path 128 BPath programPath; 129 status_t error = _FindProgram(args[0], programPath); 130 if (error != B_OK) { 131 delete[] mutableArgs; 132 return error; 133 } 134 mutableArgs[0] = programPath.Path(); 135 136 // count environment variables 137 int32 envCount = 0; 138 while (environ[envCount] != NULL) 139 envCount++; 140 141 // flatten the program args and environment 142 char** flatArgs = NULL; 143 size_t flatArgsSize; 144 error = __flatten_process_args(mutableArgs, argCount, environ, &envCount, 145 mutableArgs[0], &flatArgs, &flatArgsSize); 146 147 // load the program 148 thread_id thread; 149 if (error == B_OK) { 150 thread = _kern_load_image(flatArgs, flatArgsSize, argCount, envCount, 151 B_NORMAL_PRIORITY, (traceLoading ? 0 : B_WAIT_TILL_LOADED), -1, 0); 152 153 free(flatArgs); 154 } else 155 thread = error; 156 157 delete[] mutableArgs; 158 159 return thread; 160 } 161 162 163 /*static*/ status_t 164 BTeamDebugger::_FindProgram(const char* programName, BPath& resolvedPath) 165 { 166 // If the program name is absolute, then there's nothing to do. 167 // If the program name consists of more than one path element, then we 168 // consider it a relative path and don't search in PATH either. 169 if (*programName == '/' || strchr(programName, '/')) 170 return resolvedPath.SetTo(programName); 171 172 // get the PATH environment variable 173 const char* paths = getenv("PATH"); 174 if (!paths) 175 return B_ENTRY_NOT_FOUND; 176 177 // iterate through the paths 178 do { 179 const char* pathEnd = strchr(paths, ':'); 180 int pathLen = (pathEnd ? pathEnd - paths : strlen(paths)); 181 182 // We skip empty paths. 183 if (pathLen > 0) { 184 // get the program path 185 BString directory(paths, pathLen); 186 if (directory.Length() == 0) 187 return B_NO_MEMORY; 188 189 BPath path; 190 status_t error = path.SetTo(directory, programName); 191 if (error != B_OK) 192 continue; 193 194 // stat() the path to be sure, there is a file 195 struct stat st; 196 if (stat(path.Path(), &st) == 0 && S_ISREG(st.st_mode)) { 197 resolvedPath = path; 198 return B_OK; 199 } 200 } 201 202 paths = (pathEnd ? pathEnd + 1 : NULL); 203 } while (paths); 204 205 // not found in PATH 206 return B_ENTRY_NOT_FOUND; 207 } 208