diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 104e8458ff..cb248e3c5c 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -207,7 +207,6 @@ SubInclude HAIKU_TOP src bin screen_blanker ; SubInclude HAIKU_TOP src bin screenmode ; SubInclude HAIKU_TOP src bin sed ; SubInclude HAIKU_TOP src bin sharutils ; -SubInclude HAIKU_TOP src bin strace ; SubInclude HAIKU_TOP src bin unrar ; SubInclude HAIKU_TOP src bin vim ; SubInclude HAIKU_TOP src bin zic ; @@ -215,6 +214,9 @@ SubInclude HAIKU_TOP src bin zic ; # RCS commands SubInclude HAIKU_TOP src bin rcs ; +# debugging tools +SubInclude HAIKU_TOP src bin debug ; + # Network command line tools SubInclude HAIKU_TOP src bin network ; diff --git a/src/bin/debug/Jamfile b/src/bin/debug/Jamfile new file mode 100644 index 0000000000..77b39c071c --- /dev/null +++ b/src/bin/debug/Jamfile @@ -0,0 +1,20 @@ +SubDir HAIKU_TOP src bin debug ; + +UsePrivateHeaders debug ; +UsePrivateHeaders libroot ; +UsePrivateHeaders shared ; +UsePrivateSystemHeaders ; + +StaticLibrary debug_utils.a : debug_utils.cpp ; + +BinCommand profile + : profile.cpp + : + debug_utils.a + libdebug.so + $(TARGET_LIBSTDC++) + be +; + + +HaikuSubInclude strace ; diff --git a/src/bin/debug/debug_utils.cpp b/src/bin/debug/debug_utils.cpp new file mode 100644 index 0000000000..52a9e19c45 --- /dev/null +++ b/src/bin/debug/debug_utils.cpp @@ -0,0 +1,183 @@ +/* + * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "debug_utils.h" + +#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 + int 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, + &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 +void +set_team_debugging_flags(port_id nubPort, int32 flags) +{ + debug_nub_set_team_flags message; + message.flags = flags; + + while (true) { + status_t error = write_port(nubPort, B_DEBUG_MESSAGE_SET_TEAM_FLAGS, + &message, sizeof(message)); + if (error == B_OK) + return; + + if (error != B_INTERRUPTED) { + fprintf(stderr, "%s: Failed to set team debug flags: %s\n", + kCommandName, strerror(error)); + exit(1); + } + } +} + + +// set_thread_debugging_flags +void +set_thread_debugging_flags(port_id nubPort, thread_id thread, int32 flags) +{ + debug_nub_set_thread_flags message; + message.thread = thread; + message.flags = flags; + + while (true) { + status_t error = write_port(nubPort, B_DEBUG_MESSAGE_SET_THREAD_FLAGS, + &message, sizeof(message)); + if (error == B_OK) + return; + + if (error != B_INTERRUPTED) { + fprintf(stderr, "%s: Failed to set thread debug flags: %s\n", + kCommandName, strerror(error)); + exit(1); + } + } +} + + +// continue_thread +void +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; + + while (true) { + status_t error = write_port(nubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD, + &message, sizeof(message)); + if (error == B_OK) + return; + + if (error != B_INTERRUPTED) { + fprintf(stderr, "%s: Failed to run thread %ld: %s\n", + kCommandName, thread, strerror(error)); + exit(1); + } + } +} diff --git a/src/bin/debug/debug_utils.h b/src/bin/debug/debug_utils.h new file mode 100644 index 0000000000..0228360de8 --- /dev/null +++ b/src/bin/debug/debug_utils.h @@ -0,0 +1,20 @@ +/* + * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef BIN_DEBUG_DEBUG_UTILS_H +#define BIN_DEBUG_DEBUG_UTILS_H + +#include + + +thread_id load_program(const char* const* args, int32 argCount, + bool traceLoading); + +void set_team_debugging_flags(port_id nubPort, int32 flags); +void set_thread_debugging_flags(port_id nubPort, thread_id thread, + int32 flags); +void continue_thread(port_id nubPort, thread_id thread); + + +#endif // BIN_DEBUG_DEBUG_UTILS_H diff --git a/src/bin/debug/profile.cpp b/src/bin/debug/profile.cpp new file mode 100644 index 0000000000..c56959eb05 --- /dev/null +++ b/src/bin/debug/profile.cpp @@ -0,0 +1,403 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include "debug_utils.h" + + +extern const char* __progname; +static const char* kCommandName = __progname; + + +class Symbol { +public: + Symbol(addr_t base, size_t size, const char* name) + : + base(base), + size(size), + name(name) + { + } + + const char* Name() const { return name.String(); } + + addr_t base; + size_t size; + BString name; +}; + + +// TODO: Adjust! +static const char* kUsage = + "Usage: %s [ ] \n" + "Executes the given command line and print an analysis of\n" + "the user and kernel times of all threads that ran during that time.\n" + "\n" + "Options:\n" + " -h, --help - Print this usage info.\n" + " -o - Print the results to file .\n" + " -s - Also perform a scheduling analysis over the time the\n" + " child process ran. This requires that scheduler kernel\n" + " tracing had been enabled at compile time.\n" +; + + +static void +print_usage_and_exit(bool error) +{ + fprintf(error ? stderr : stdout, kUsage, __progname); + exit(error ? 1 : 0); +} + + +/* +// get_id +static bool +get_id(const char *str, int32 &id) +{ + int32 len = strlen(str); + for (int32 i = 0; i < len; i++) { + if (!isdigit(str[i])) + return false; + } + + id = atol(str); + return true; +} +*/ + + +int +main(int argc, const char* const* argv) +{ +// const char* outputFile = NULL; +// bool schedulingAnalysis = false; + + while (true) { + static struct option sLongOptions[] = { + { "help", no_argument, 0, 'h' }, +// { "output", required_argument, 0, 'o' }, + { 0, 0, 0, 0 } + }; + + opterr = 0; // don't print errors + int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage_and_exit(false); + break; +/* case 'o': + outputFile = optarg; + break; + case 's': + schedulingAnalysis = true; + break; +*/ + + default: + print_usage_and_exit(true); + break; + } + } + + if (optind >= argc) + print_usage_and_exit(true); + + const char* const* programArgs = argv + optind; + int programArgCount = argc - optind; + + // get thread/team to be debugged + thread_id thread = -1; + team_id team = -1; +// if (programArgCount > 1 +// || !get_id(*programArgs, (traceTeam ? team : thread))) { + // we've been given an executable and need to load it + thread = load_program(programArgs, programArgCount, false); + if (thread < 0) { + fprintf(stderr, "%s: Failed to start `%s': %s\n", kCommandName, + programArgs[0], strerror(thread)); + exit(1); + } +// } + + // get the team ID, if we have none yet + if (team < 0) { + thread_info threadInfo; + status_t error = get_thread_info(thread, &threadInfo); + if (error != B_OK) { + fprintf(stderr, "%s: Failed to get info for thread %ld: %s\n", + kCommandName, thread, strerror(error)); + exit(1); + } + team = threadInfo.team; + } + + // create a debugger port + port_id debuggerPort = create_port(10, "debugger port"); + if (debuggerPort < 0) { + fprintf(stderr, "%s: Failed to create debugger port: %s\n", + kCommandName, strerror(debuggerPort)); + exit(1); + } + + // install ourselves as the team debugger + port_id nubPort = install_team_debugger(team, debuggerPort); + if (nubPort < 0) { + fprintf(stderr, "%s: Failed to install team debugger: %s\n", + kCommandName, strerror(nubPort)); + exit(1); + } + + // init debug context + debug_context debugContext; + status_t error = init_debug_context(&debugContext, team, nubPort); + if (error != B_OK) { + fprintf(stderr, "%s: Failed to init debug context: %s\n", + kCommandName, strerror(error)); + exit(1); + } + + // create symbol lookup context + debug_symbol_lookup_context* lookupContext; + error = debug_create_symbol_lookup_context(&debugContext, + &lookupContext); + if (error != B_OK) { + fprintf(stderr, "%s: Failed to create symbol lookup context: %s\n", + kCommandName, strerror(error)); + exit(1); + } + + // iterate through the team's images and collect the symbols + BObjectList symbols(1000, true); + image_info imageInfo; + int32 cookie = 0; + while (get_next_image_info(team, &cookie, &imageInfo) == B_OK) { + printf("Loading symbols of image \"%s\" (%ld)...\n", + imageInfo.name, imageInfo.id); + // create symbol iterator + debug_symbol_iterator* iterator; + error = debug_create_image_symbol_iterator(lookupContext, imageInfo.id, + &iterator); + if (error != B_OK) { + printf("Failed to init symbol iterator: %s\n", strerror(error)); + continue; + } + + // iterate through the images + char symbolName[1024]; + int32 symbolType; + void* symbolLocation; + size_t symbolSize; + while (debug_next_image_symbol(iterator, symbolName, sizeof(symbolName), + &symbolType, &symbolLocation, &symbolSize) == B_OK) { +//if (symbolSize == 0) { +// printf(" %s %p (%6lu) %s\n", +// symbolType == B_SYMBOL_TYPE_TEXT ? "text" : "data", +// symbolLocation, symbolSize, symbolName); +//} + if (symbolType == B_SYMBOL_TYPE_TEXT) { + Symbol* symbol = new(std::nothrow) Symbol( + (addr_t)symbolLocation, symbolSize, symbolName); + if (symbol == NULL || !symbols.AddItem(symbol)) { + fprintf(stderr, "%s: Out of memory\n", kCommandName); + exit(1); + } + } + } + + debug_delete_image_symbol_iterator(iterator); + } + + debug_delete_symbol_lookup_context(lookupContext); + + // prepare the start profiler message + int32 symbolCount = symbols.CountItems(); + if (symbolCount == 0) { + fprintf(stderr, "%s: Got no symbols at all, exiting...\n", + kCommandName); + exit(1); + } + + size_t startProfilerSize = sizeof(debug_nub_start_profiler) + + (symbolCount - 1) * sizeof(debug_profile_function); + debug_nub_start_profiler* startProfiler + = (debug_nub_start_profiler*)malloc(startProfilerSize); + if (startProfiler == NULL) { + fprintf(stderr, "%s: Out of memory\n", kCommandName); + exit(1); + } + + startProfiler->reply_port = debugContext.reply_port; + startProfiler->thread = thread; + startProfiler->interval = 10; + startProfiler->function_count = symbolCount; + + for (int32 i = 0; i < symbolCount; i++) { + Symbol* symbol = symbols.ItemAt(i); + debug_profile_function& function = startProfiler->functions[i]; + function.base = symbol->base; + function.size = symbol->size; + } + + // allocate memory for the reply + size_t maxMessageSize = max_c(sizeof(debug_debugger_message_data), + sizeof(debug_profiler_stopped) + 8 * symbolCount); + debug_debugger_message_data* message = (debug_debugger_message_data*) + malloc(maxMessageSize); + if (message == NULL) { + fprintf(stderr, "%s: Out of memory\n", kCommandName); + exit(1); + } + + // set team debugging flags + int32 teamDebugFlags = 0; + set_team_debugging_flags(nubPort, teamDebugFlags); + + // set thread debugging flags and start profiling + if (thread >= 0) { + int32 threadDebugFlags = 0; +// if (!traceTeam) { +// threadDebugFlags = B_THREAD_DEBUG_POST_SYSCALL +// | (traceChildThreads +// ? B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS : 0); +// } + set_thread_debugging_flags(nubPort, thread, threadDebugFlags); + + // start profiling + debug_nub_start_profiler_reply reply; + error = send_debug_message(&debugContext, B_DEBUG_START_PROFILER, + startProfiler, startProfilerSize, &reply, sizeof(reply)); + if (error != B_OK || (error = reply.error) != B_OK) { + fprintf(stderr, "%s: Failed to start profiler: %s\n", + kCommandName, strerror(error)); + exit(1); + } + + // resume the target thread to be sure, it's running + resume_thread(thread); + } + + // debug loop + while (true) { + bool quitLoop = false; + int32 code; + ssize_t messageSize = read_port(debuggerPort, &code, message, + maxMessageSize); + + if (messageSize < 0) { + if (messageSize == B_INTERRUPTED) + continue; + + fprintf(stderr, "%s: Reading from debugger port failed: %s\n", + kCommandName, strerror(messageSize)); + exit(1); + } + + switch (code) { + case B_DEBUGGER_MESSAGE_PROFILER_STOPPED: + printf("B_DEBUGGER_MESSAGE_PROFILER_STOPPED\n"); + printf(" total ticks: %lld, missed: %lld\n", + message->profiler_stopped.total_ticks, + message->profiler_stopped.missed_ticks); + for (int32 i = 0; i < symbolCount; i++) { + int64 hits = message->profiler_stopped.function_ticks[i]; + if (hits > 0) + printf("%10lld %s\n", hits, symbols.ItemAt(i)->Name()); + } + + break; +/* +typedef struct { + debug_origin origin; + int32 function_count; + int64 total_ticks; // total number of sample ticks + int64 missed_ticks; // ticks that didn't hit a function + int64 function_ticks[1]; // number of hits for each function +} debug_profiler_stopped; +*/ + + + case B_DEBUGGER_MESSAGE_POST_SYSCALL: + case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: + case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: + case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: + case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: + case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: + case B_DEBUGGER_MESSAGE_SINGLE_STEP: + case B_DEBUGGER_MESSAGE_PRE_SYSCALL: + case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: + case B_DEBUGGER_MESSAGE_TEAM_CREATED: + case B_DEBUGGER_MESSAGE_THREAD_CREATED: + case B_DEBUGGER_MESSAGE_THREAD_DELETED: + case B_DEBUGGER_MESSAGE_IMAGE_CREATED: + case B_DEBUGGER_MESSAGE_IMAGE_DELETED: + break; + + case B_DEBUGGER_MESSAGE_TEAM_DELETED: + // the debugged team is gone + quitLoop = true; + break; + } + + if (quitLoop) + break; + + // tell the thread to continue (only when there is a thread and the + // message was synchronous) + if (message->origin.thread >= 0 && message->origin.nub_port >= 0) + continue_thread(message->origin.nub_port, message->origin.thread); + } + + + + destroy_debug_context(&debugContext); + +//kill_thread(thread); +//exit(0); + + +/* +typedef struct { + debug_origin origin; + int32 function_count; + int64 total_ticks; // total number of sample ticks + int64 missed_ticks; // ticks that didn't hit a function + int64 function_ticks[1]; // number of hits for each function +} debug_profiler_stopped; + +struct debug_profile_function { + addr_t base; // function base address + size_t size; // function size +}; + +typedef struct { + port_id reply_port; // port to send the reply to + thread_id thread; // thread to profile + bigtime_t interval; // sample interval + int32 function_count; // number of functions we count hits for + struct debug_profile_function functions[1]; + // functions that shall be tracked +} debug_nub_start_profiler; +*/ + + return 0; +} diff --git a/src/bin/strace/Context.cpp b/src/bin/debug/strace/Context.cpp similarity index 100% rename from src/bin/strace/Context.cpp rename to src/bin/debug/strace/Context.cpp diff --git a/src/bin/strace/Context.h b/src/bin/debug/strace/Context.h similarity index 100% rename from src/bin/strace/Context.h rename to src/bin/debug/strace/Context.h diff --git a/src/bin/strace/Jamfile b/src/bin/debug/strace/Jamfile similarity index 90% rename from src/bin/strace/Jamfile rename to src/bin/debug/strace/Jamfile index 0915d31025..2761424092 100644 --- a/src/bin/strace/Jamfile +++ b/src/bin/debug/strace/Jamfile @@ -1,4 +1,4 @@ -SubDir HAIKU_TOP src bin strace ; +SubDir HAIKU_TOP src bin debug strace ; UsePrivateHeaders device ; UsePrivateHeaders drivers ; @@ -7,6 +7,8 @@ UsePrivateHeaders shared ; UsePrivateHeaders net ; UsePrivateSystemHeaders ; +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; + # find headers generated by gensyscalls SubDirHdrs $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ; @@ -46,7 +48,11 @@ for i in $(straceSyscallsIndices) { OPTIM = $(oldOptim) ; BinCommand strace : $(straceSources) - : $(straceSyscallsObjects) libroot.so $(TARGET_LIBSTDC++) ; + : + $(straceSyscallsObjects) + debug_utils.a + $(TARGET_LIBSTDC++) +; # We need to specify the dependency on the generated syscalls file explicitly. Includes $(straceSyscallsSource) : strace_syscalls.h ; diff --git a/src/bin/strace/MemoryReader.cpp b/src/bin/debug/strace/MemoryReader.cpp similarity index 100% rename from src/bin/strace/MemoryReader.cpp rename to src/bin/debug/strace/MemoryReader.cpp diff --git a/src/bin/strace/MemoryReader.h b/src/bin/debug/strace/MemoryReader.h similarity index 100% rename from src/bin/strace/MemoryReader.h rename to src/bin/debug/strace/MemoryReader.h diff --git a/src/bin/strace/NetworkTypes.cpp b/src/bin/debug/strace/NetworkTypes.cpp similarity index 100% rename from src/bin/strace/NetworkTypes.cpp rename to src/bin/debug/strace/NetworkTypes.cpp diff --git a/src/bin/strace/Syscall.h b/src/bin/debug/strace/Syscall.h similarity index 100% rename from src/bin/strace/Syscall.h rename to src/bin/debug/strace/Syscall.h diff --git a/src/bin/strace/TypeHandler.cpp b/src/bin/debug/strace/TypeHandler.cpp similarity index 100% rename from src/bin/strace/TypeHandler.cpp rename to src/bin/debug/strace/TypeHandler.cpp diff --git a/src/bin/strace/TypeHandler.h b/src/bin/debug/strace/TypeHandler.h similarity index 100% rename from src/bin/strace/TypeHandler.h rename to src/bin/debug/strace/TypeHandler.h diff --git a/src/bin/strace/ioctl.cpp b/src/bin/debug/strace/ioctl.cpp similarity index 100% rename from src/bin/strace/ioctl.cpp rename to src/bin/debug/strace/ioctl.cpp diff --git a/src/bin/strace/strace.cpp b/src/bin/debug/strace/strace.cpp similarity index 81% rename from src/bin/strace/strace.cpp rename to src/bin/debug/strace/strace.cpp index 1c8db79bc4..db09551021 100644 --- a/src/bin/strace/strace.cpp +++ b/src/bin/debug/strace/strace.cpp @@ -16,9 +16,10 @@ #include #include -#include #include +#include "debug_utils.h" + #include "Context.h" #include "MemoryReader.h" #include "Syscall.h" @@ -114,7 +115,7 @@ static const char *kSignalName[] = { /* 22 */ "SIGTRAP", /* 23 */ "SIGPOLL", /* 24 */ "SIGPROF", - /* 25 */ "SIGSYS", + /* 25 */ "SIGSYS", /* 26 */ "SIGURG", /* 27 */ "SIGVTALRM", /* 28 */ "SIGXCPU", @@ -161,164 +162,6 @@ get_id(const char *str, int32 &id) return true; } -// find_program -static -status_t -find_program(const char *programName, 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 - 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; -} - -// 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 - 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 - int 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, - &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 -static -void -set_team_debugging_flags(port_id nubPort, int32 flags) -{ - debug_nub_set_team_flags message; - message.flags = flags; - - while (true) { - status_t error = write_port(nubPort, B_DEBUG_MESSAGE_SET_TEAM_FLAGS, - &message, sizeof(message)); - if (error == B_OK) - return; - - if (error != B_INTERRUPTED) { - fprintf(stderr, "%s: Failed to set team debug flags: %s\n", - kCommandName, strerror(error)); - exit(1); - } - } -} - -// set_thread_debugging_flags -static -void -set_thread_debugging_flags(port_id nubPort, thread_id thread, int32 flags) -{ - debug_nub_set_thread_flags message; - message.thread = thread; - message.flags = flags; - - while (true) { - status_t error = write_port(nubPort, B_DEBUG_MESSAGE_SET_THREAD_FLAGS, - &message, sizeof(message)); - if (error == B_OK) - return; - - if (error != B_INTERRUPTED) { - fprintf(stderr, "%s: Failed to set thread debug flags: %s\n", - kCommandName, strerror(error)); - exit(1); - } - } -} - -// continue_thread -static -void -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; - - while (true) { - status_t error = write_port(nubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD, - &message, sizeof(message)); - if (error == B_OK) - return; - - if (error != B_INTERRUPTED) { - fprintf(stderr, "%s: Failed to run thread %ld: %s\n", - kCommandName, thread, strerror(error)); - exit(1); - } - } -} - // get_syscall Syscall * get_syscall(const char *name) diff --git a/src/bin/strace/strace.h b/src/bin/debug/strace/strace.h similarity index 100% rename from src/bin/strace/strace.h rename to src/bin/debug/strace/strace.h diff --git a/src/bin/strace/strace_syscalls.cpp b/src/bin/debug/strace/strace_syscalls.cpp similarity index 100% rename from src/bin/strace/strace_syscalls.cpp rename to src/bin/debug/strace/strace_syscalls.cpp diff --git a/src/tools/gensyscalls/Jamfile b/src/tools/gensyscalls/Jamfile index 2ad365d3c5..3029a7a7e2 100644 --- a/src/tools/gensyscalls/Jamfile +++ b/src/tools/gensyscalls/Jamfile @@ -102,7 +102,7 @@ MakeLocate syscalls.S.inc : [ FDirName $(dir) system libroot os ] ; MakeLocate syscall_dispatcher.h : [ FDirName $(dir) system kernel ] ; MakeLocate syscall_numbers.h : [ FDirName $(dir) system kernel ] ; MakeLocate syscall_table.h : [ FDirName $(dir) system kernel ] ; -MakeLocate strace_syscalls.h : [ FDirName $(dir) bin strace ] ; +MakeLocate strace_syscalls.h : [ FDirName $(dir) bin debug strace ] ; rule GenSyscallsFile { Depends $(1) : gensyscalls ;