/* * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2013, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #include "debug_utils.h" #include #include #include #include #include #include #include #include #include extern const char* __progname; static const char* kCommandName = __progname; // find_program static status_t find_program(const char* programName, std::string& resolvedPath) { // If the program name is absolute, then there's nothing to do. // If the program name consists of more than one path element, then we // consider it a relative path and don't search in PATH either. if (*programName == '/' || strchr(programName, '/')) { resolvedPath = programName; return B_OK; } // get the PATH environment variable const char* paths = getenv("PATH"); if (!paths) return B_ENTRY_NOT_FOUND; // iterate through the paths do { const char* pathEnd = strchr(paths, ':'); int pathLen = (pathEnd ? pathEnd - paths : strlen(paths)); // We skip empty paths. if (pathLen > 0) { // get the program path std::string path(paths, pathLen); path += "/"; path += programName; // stat() the path to be sure, there is a file struct stat st; if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { resolvedPath = path; return B_OK; } } paths = (pathEnd ? pathEnd + 1 : NULL); } while (paths); // not found in PATH return B_ENTRY_NOT_FOUND; } // #pragma mark - // load_program thread_id load_program(const char* const* args, int32 argCount, bool traceLoading) { // clone the argument vector so that we can change it const char** mutableArgs = new const char*[argCount]; for (int i = 0; i < argCount; i++) mutableArgs[i] = args[i]; // resolve the program path std::string programPath; status_t error = find_program(args[0], programPath); if (error != B_OK) { delete[] mutableArgs; return error; } mutableArgs[0] = programPath.c_str(); // count environment variables int32 envCount = 0; while (environ[envCount] != NULL) envCount++; // flatten the program args and environment char** flatArgs = NULL; size_t flatArgsSize; error = __flatten_process_args(mutableArgs, argCount, environ, &envCount, mutableArgs[0], &flatArgs, &flatArgsSize); // load the program thread_id thread; if (error == B_OK) { thread = _kern_load_image(flatArgs, flatArgsSize, argCount, envCount, B_NORMAL_PRIORITY, (traceLoading ? 0 : B_WAIT_TILL_LOADED), -1, 0); free(flatArgs); } else thread = error; delete[] mutableArgs; return thread; } // set_team_debugging_flags status_t set_team_debugging_flags(port_id nubPort, int32 flags) { debug_nub_set_team_flags message; message.flags = flags; status_t error = B_OK; do { error = write_port(nubPort, B_DEBUG_MESSAGE_SET_TEAM_FLAGS, &message, sizeof(message)); } while (error == B_INTERRUPTED); if (error != B_OK) { fprintf(stderr, "%s: Failed to set team debug flags: %s\n", kCommandName, strerror(error)); } return error; } // set_thread_debugging_flags status_t set_thread_debugging_flags(port_id nubPort, thread_id thread, int32 flags) { debug_nub_set_thread_flags message; message.thread = thread; message.flags = flags; status_t error = B_OK; do { error = write_port(nubPort, B_DEBUG_MESSAGE_SET_THREAD_FLAGS, &message, sizeof(message)); } while (error == B_INTERRUPTED); if (error != B_OK) { fprintf(stderr, "%s: Failed to set thread debug flags: %s\n", kCommandName, strerror(error)); } return error; } // continue_thread status_t continue_thread(port_id nubPort, thread_id thread) { debug_nub_continue_thread message; message.thread = thread; message.handle_event = B_THREAD_DEBUG_HANDLE_EVENT; message.single_step = false; status_t error = B_OK; do { error = write_port(nubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD, &message, sizeof(message)); } while (error == B_INTERRUPTED); if (error != B_OK) { fprintf(stderr, "%s: Failed to run thread %" B_PRId32 ": %s\n", kCommandName, thread, strerror(error)); } return error; }