hrev45797 adds 9 changesets to branch 'master' old head: 91a5e061488eeb84b78a1eae97009141d1a006b3 new head: 77ea49f4f2cb0e369fa27a5ca8870207e3046af6 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=77ea49f+%5E91a5e06 ---------------------------------------------------------------------------- d08227b: Add SyscallInfoEvent model class. 23f48a2: Add event class for the post-syscall debug message. 4dc355e: Adjust debug_utils functions. The functions in question now return an error rather than simply calling exit() directly when they fail, as this behavior wasn't acceptable for e.g. Debugger. Adjusted all calling apps accordingly. d692e33: Extend Team's listener interface. Add hooks for sending and listening for console output events. fe44883: TeamDebugger: Implement post syscall event handling. We now watch for file write syscalls in the target team. If they constitute a write to either stdout or stderr, we attempt to capture the output, and notify interested listeners accordingly. 7910d8b: Adjust BCheckBox::MaxSize. Previously BCheckBox returned unlimited width for its max size. This became problematic if one wanted to put a checkbox in any kind of horizontal layout with other controls, since they would expand to use as much space as possible. This is also in contrast to other controls such as BButton, which simply return the max to be the same as the preferred. As such, adjust BCheckBox to do the same. b8b4219: Implement #9758. - Add ConsoleOutputView for showing the debugged team's console output. The view presents checkboxes for controlling whether or not stdout and/or stderr output is captured and shown, as well as the ability to clear the current output. 277945a: Add support for auto-scrolling. - If the console output is currently at the bottom, any new output will automatically be scrolled into view. Otherwise, its current position will be maintained. 77ea49f: Adjust debug API to address some x86-64 concerns. - The argument buffer contained in the debug_{pre,post}_syscall message structures wasn't large enough to accomodate all arguments for some syscalls on x86-64, which could potentially have led to kernel memory corruption when using syscall tracing via the debug API. As such, enlarge it to accomodate 64-bit platforms as well. - Adjust TeamDebugger/SyscallInfo to discriminate the target architecture and read the arguments when trapping console output. Gets the latter working on x86-64. [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- 22 files changed, 620 insertions(+), 60 deletions(-) headers/os/kernel/debugger.h | 4 +- src/apps/debugger/Jamfile | 11 ++ src/apps/debugger/MessageCodes.h | 1 + src/apps/debugger/controllers/TeamDebugger.cpp | 67 +++++++- src/apps/debugger/controllers/TeamDebugger.h | 2 + .../debugger/debugger_interface/DebugEvent.cpp | 12 ++ .../debugger/debugger_interface/DebugEvent.h | 15 ++ .../debugger_interface/DebuggerInterface.cpp | 21 ++- src/apps/debugger/model/SyscallInfo.cpp | 54 ++++++ src/apps/debugger/model/SyscallInfo.h | 43 +++++ src/apps/debugger/model/Team.cpp | 32 ++++ src/apps/debugger/model/Team.h | 26 +++ .../gui/team_window/ConsoleOutputView.cpp | 168 +++++++++++++++++++ .../gui/team_window/ConsoleOutputView.h | 46 +++++ .../gui/team_window/TeamWindow.cpp | 52 ++++++ .../user_interface/gui/team_window/TeamWindow.h | 7 +- src/bin/debug/debug_utils.cpp | 68 ++++---- src/bin/debug/debug_utils.h | 6 +- src/bin/debug/profile/Team.cpp | 12 +- src/bin/debug/profile/profile.cpp | 10 +- src/bin/debug/strace/strace.cpp | 17 +- src/kits/interface/CheckBox.cpp | 6 +- ############################################################################ Commit: d08227bb68d298ef019b410fa6c0e0da29478a56 URL: http://cgit.haiku-os.org/haiku/commit/?id=d08227b Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu Jun 27 01:43:57 2013 UTC Add SyscallInfoEvent model class. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index f6300ed..03831a5 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -154,6 +154,7 @@ Application Debugger : StackTrace.cpp Statement.cpp SymbolInfo.cpp + SyscallInfo.cpp SystemInfo.cpp Team.cpp TeamInfo.cpp diff --git a/src/apps/debugger/model/SyscallInfo.cpp b/src/apps/debugger/model/SyscallInfo.cpp new file mode 100644 index 0000000..21b615e --- /dev/null +++ b/src/apps/debugger/model/SyscallInfo.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + +#include "SyscallInfo.h" + +#include <string.h> + + +SyscallInfo::SyscallInfo() + : + fStartTime(0), + fEndTime(0), + fReturnValue(0), + fSyscall(0) +{ + memset(fArguments, 0, sizeof(fArguments)); +} + + +SyscallInfo::SyscallInfo(const SyscallInfo& other) + : + fStartTime(other.fStartTime), + fEndTime(other.fEndTime), + fReturnValue(other.fReturnValue), + fSyscall(other.fSyscall) +{ + memcpy(fArguments, other.fArguments, sizeof(fArguments)); +} + + +SyscallInfo::SyscallInfo(bigtime_t startTime, bigtime_t endTime, + uint64 returnValue, uint32 syscall, const uint32* args) + : + fStartTime(startTime), + fEndTime(endTime), + fReturnValue(returnValue), + fSyscall(syscall) +{ + memcpy(fArguments, args, sizeof(fArguments)); +} + + +void +SyscallInfo::SetTo(bigtime_t startTime, bigtime_t endTime, uint64 returnValue, + uint32 syscall, const uint32* args) +{ + fStartTime = startTime; + fEndTime = endTime; + fReturnValue = returnValue; + fSyscall = syscall; + memcpy(fArguments, args, sizeof(fArguments)); +} diff --git a/src/apps/debugger/model/SyscallInfo.h b/src/apps/debugger/model/SyscallInfo.h new file mode 100644 index 0000000..c2609c8 --- /dev/null +++ b/src/apps/debugger/model/SyscallInfo.h @@ -0,0 +1,43 @@ +/* + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef SYSCALL_INFO_H +#define SYSCALL_INFO_H + +#include "Types.h" + + +class SyscallInfo { +public: + SyscallInfo(); + SyscallInfo(const SyscallInfo& other); + SyscallInfo(bigtime_t startTime, + bigtime_t endTime, + uint64 returnValue, + uint32 syscall, + const uint32* args); + + void SetTo(bigtime_t startTime, + bigtime_t endTime, + uint64 returnValue, + uint32 syscall, + const uint32* args); + + bigtime_t StartTime() const { return fStartTime; } + bigtime_t EndTime() const { return fEndTime; } + uint64 ReturnValue() const { return fReturnValue; } + uint32 Syscall() const { return fSyscall; } + + const uint32* Arguments() const { return fArguments; } + +private: + bigtime_t fStartTime; + bigtime_t fEndTime; + uint64 fReturnValue; + uint32 fSyscall; + uint32 fArguments[16]; +}; + + +#endif // SYSCALL_INFO_H ############################################################################ Commit: 23f48a24d02a4c7249bad637d756f54b73331c5f URL: http://cgit.haiku-os.org/haiku/commit/?id=23f48a2 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu Jun 27 01:44:45 2013 UTC Add event class for the post-syscall debug message. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 6026df6..7fce6fb 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -441,7 +441,8 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, int argc, // set team debugging flags fDebuggerInterface->SetTeamDebuggingFlags( - B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_IMAGES); + B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_IMAGES + | B_TEAM_DEBUG_POST_SYSCALL); // get the initial state of the team AutoLocker< ::Team> teamLocker(fTeam); diff --git a/src/apps/debugger/debugger_interface/DebugEvent.cpp b/src/apps/debugger/debugger_interface/DebugEvent.cpp index c3bf127..16dac73 100644 --- a/src/apps/debugger/debugger_interface/DebugEvent.cpp +++ b/src/apps/debugger/debugger_interface/DebugEvent.cpp @@ -215,6 +215,18 @@ ImageDeletedEvent::ImageDeletedEvent(team_id team, thread_id thread, } +// #pragma mark - PostSyscallEvent + + +PostSyscallEvent::PostSyscallEvent(team_id team, thread_id thread, + const SyscallInfo& info) + : + DebugEvent(B_DEBUGGER_MESSAGE_POST_SYSCALL, team, thread), + fInfo(info) +{ +} + + // #pragma mark - HandedOverEvent diff --git a/src/apps/debugger/debugger_interface/DebugEvent.h b/src/apps/debugger/debugger_interface/DebugEvent.h index dda16cb..edd8140 100644 --- a/src/apps/debugger/debugger_interface/DebugEvent.h +++ b/src/apps/debugger/debugger_interface/DebugEvent.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef DEBUG_EVENT_H @@ -8,6 +9,7 @@ #include <debugger.h> #include "ImageInfo.h" +#include "SyscallInfo.h" #include "Types.h" @@ -196,6 +198,19 @@ private: }; +class PostSyscallEvent : public DebugEvent { +public: + PostSyscallEvent(team_id team, + thread_id thread, + const SyscallInfo& info); + + const SyscallInfo& GetSyscallInfo() const { return fInfo; } + +private: + SyscallInfo fInfo; +}; + + class HandedOverEvent : public DebugEvent { public: HandedOverEvent(team_id team, diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp index d641f24..0af3105 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp @@ -830,13 +830,22 @@ DebuggerInterface::_CreateDebugEvent(int32 messageCode, info.data_size)); break; } + case B_DEBUGGER_MESSAGE_POST_SYSCALL: + { + event = new(std::nothrow) PostSyscallEvent(message.origin.team, + message.origin.thread, + SyscallInfo(message.post_syscall.start_time, + message.post_syscall.end_time, + message.post_syscall.return_value, + message.post_syscall.syscall, message.post_syscall.args)); + break; + } default: printf("DebuggerInterface for team %" B_PRId32 ": unknown message " "from kernel: %" B_PRId32 "\n", fTeamID, messageCode); // fall through... case B_DEBUGGER_MESSAGE_TEAM_CREATED: case B_DEBUGGER_MESSAGE_PRE_SYSCALL: - case B_DEBUGGER_MESSAGE_POST_SYSCALL: case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: case B_DEBUGGER_MESSAGE_PROFILER_UPDATE: case B_DEBUGGER_MESSAGE_HANDED_OVER: ############################################################################ Commit: 4dc355e9a98bf91d5e0851e432692fb267839de0 URL: http://cgit.haiku-os.org/haiku/commit/?id=4dc355e Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu Jun 27 23:20:42 2013 UTC Adjust debug_utils functions. The functions in question now return an error rather than simply calling exit() directly when they fail, as this behavior wasn't acceptable for e.g. Debugger. Adjusted all calling apps accordingly. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp index 0af3105..9d413a4 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp @@ -351,8 +351,10 @@ DebuggerInterface::GetNextDebugEvent(DebugEvent*& _event) if (ignore) { if (message.origin.thread >= 0 && message.origin.nub_port >= 0) - continue_thread(message.origin.nub_port, + error = continue_thread(message.origin.nub_port, message.origin.thread); + if (error != B_OK) + return error; continue; } @@ -373,16 +375,14 @@ DebuggerInterface::GetNextDebugEvent(DebugEvent*& _event) status_t DebuggerInterface::SetTeamDebuggingFlags(uint32 flags) { - set_team_debugging_flags(fNubPort, flags); - return B_OK; + return set_team_debugging_flags(fNubPort, flags); } status_t DebuggerInterface::ContinueThread(thread_id thread) { - continue_thread(fNubPort, thread); - return B_OK; + return continue_thread(fNubPort, thread); } diff --git a/src/bin/debug/debug_utils.cpp b/src/bin/debug/debug_utils.cpp index fa9d431..e91bf36 100644 --- a/src/bin/debug/debug_utils.cpp +++ b/src/bin/debug/debug_utils.cpp @@ -1,5 +1,6 @@ /* * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -116,52 +117,52 @@ load_program(const char* const* args, int32 argCount, bool traceLoading) // set_team_debugging_flags -void +status_t 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, + status_t error = B_OK; + do { + 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); - } + } 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 -void +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; - while (true) { - status_t error = write_port(nubPort, B_DEBUG_MESSAGE_SET_THREAD_FLAGS, + status_t error = B_OK; + do { + 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); - } + } 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 -void +status_t continue_thread(port_id nubPort, thread_id thread) { debug_nub_continue_thread message; @@ -169,16 +170,17 @@ continue_thread(port_id nubPort, thread_id 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, + status_t error = B_OK; + + do { + 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 %" B_PRId32 ": %s\n", - kCommandName, thread, strerror(error)); - exit(1); - } + } 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; } diff --git a/src/bin/debug/debug_utils.h b/src/bin/debug/debug_utils.h index 0228360..b4c4f67 100644 --- a/src/bin/debug/debug_utils.h +++ b/src/bin/debug/debug_utils.h @@ -11,10 +11,10 @@ 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, +status_t set_team_debugging_flags(port_id nubPort, int32 flags); +status_t set_thread_debugging_flags(port_id nubPort, thread_id thread, int32 flags); -void continue_thread(port_id nubPort, thread_id thread); +status_t continue_thread(port_id nubPort, thread_id thread); #endif // BIN_DEBUG_DEBUG_UTILS_H diff --git a/src/bin/debug/profile/Team.cpp b/src/bin/debug/profile/Team.cpp index 331b28e..433fde1 100644 --- a/src/bin/debug/profile/Team.cpp +++ b/src/bin/debug/profile/Team.cpp @@ -1,5 +1,6 @@ /* * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -86,7 +87,9 @@ Team::Init(team_id teamID, port_id debuggerPort) // set team debugging flags int32 teamDebugFlags = B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_TEAM_CREATION | B_TEAM_DEBUG_IMAGES; - set_team_debugging_flags(fNubPort, teamDebugFlags); + error = set_team_debugging_flags(fNubPort, teamDebugFlags); + if (error != B_OK) + return error; return B_OK; } @@ -138,7 +141,10 @@ Team::InitThread(Thread* thread) // | (traceChildThreads // ? B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS : 0); // } - set_thread_debugging_flags(fNubPort, thread->ID(), threadDebugFlags); + status_t error = set_thread_debugging_flags(fNubPort, thread->ID(), + threadDebugFlags); + if (error != B_OK) + return error; // start profiling debug_nub_start_profiler message; @@ -150,7 +156,7 @@ Team::InitThread(Thread* thread) message.variable_stack_depth = gOptions.analyze_full_stack; debug_nub_start_profiler_reply reply; - status_t error = send_debug_message(&fDebugContext, + error = send_debug_message(&fDebugContext, B_DEBUG_START_PROFILER, &message, sizeof(message), &reply, sizeof(reply)); if (error != B_OK || (error = reply.error) != B_OK) { diff --git a/src/bin/debug/profile/profile.cpp b/src/bin/debug/profile/profile.cpp index dd50dcd..22f6338 100644 --- a/src/bin/debug/profile/profile.cpp +++ b/src/bin/debug/profile/profile.cpp @@ -1,5 +1,6 @@ /* * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -542,7 +543,8 @@ process_event_buffer(ThreadManager& threadManager, uint8* buffer, system_profiler_team_added* event = (system_profiler_team_added*)buffer; - threadManager.AddTeam(event); + if (threadManager.AddTeam(event) != B_OK) + exit(1); break; } @@ -575,8 +577,10 @@ process_event_buffer(ThreadManager& threadManager, uint8* buffer, system_profiler_thread_added* event = (system_profiler_thread_added*)buffer; - threadManager.AddThread(event->team, event->thread, - event->name); + if (threadManager.AddThread(event->team, event->thread, + event->name) != B_OK) { + exit(1); + } break; } diff --git a/src/bin/debug/strace/strace.cpp b/src/bin/debug/strace/strace.cpp index 046efbd..a232a9c 100644 --- a/src/bin/debug/strace/strace.cpp +++ b/src/bin/debug/strace/strace.cpp @@ -1,5 +1,6 @@ /* * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -144,7 +145,8 @@ struct Team { int32 teamDebugFlags = (traceTeam ? B_TEAM_DEBUG_POST_SYSCALL : 0) | (traceChildTeams ? B_TEAM_DEBUG_TEAM_CREATION : 0) | (traceSignal ? B_TEAM_DEBUG_SIGNALS : 0); - set_team_debugging_flags(fNubPort, teamDebugFlags); + if (set_team_debugging_flags(fNubPort, teamDebugFlags) != B_OK) + exit(1); return fMemoryReader.Init(fNubPort); } @@ -568,7 +570,10 @@ main(int argc, const char *const *argv) | (traceChildThreads ? B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS : 0); } - set_thread_debugging_flags(nubPort, threadID, threadDebugFlags); + if (set_thread_debugging_flags(nubPort, threadID, threadDebugFlags) + != B_OK) { + exit(1); + } // resume the target thread to be sure, it's running resume_thread(threadID); @@ -672,8 +677,12 @@ main(int argc, const char *const *argv) // 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); + if (message.origin.thread >= 0 && message.origin.nub_port >= 0) { + if (continue_thread(message.origin.nub_port, + message.origin.thread) != B_OK) { + exit(1); + } + } } if (outputFile != NULL && outputFile != stdout) ############################################################################ Commit: d692e338d47e995efcac47fd4108b0d5c77200cd URL: http://cgit.haiku-os.org/haiku/commit/?id=d692e33 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu Jun 27 23:36:47 2013 UTC Extend Team's listener interface. Add hooks for sending and listening for console output events. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index af38083..016da1c 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -1,5 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -614,6 +615,18 @@ Team::NotifyImageDebugInfoChanged(Image* image) void +Team::NotifyConsoleOutputReceived(int32 fd, const BString& output) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->ConsoleOutputReceived( + ConsoleOutputEvent(TEAM_EVENT_CONSOLE_OUTPUT_RECEIVED, this, + fd, output)); + } +} + + +void Team::NotifyUserBreakpointChanged(UserBreakpoint* breakpoint) { for (ListenerList::Iterator it = fListeners.GetIterator(); @@ -731,6 +744,19 @@ Team::BreakpointEvent::BreakpointEvent(uint32 type, Team* team, } +// #pragma mark - ConsoleOutputEvent + + +Team::ConsoleOutputEvent::ConsoleOutputEvent(uint32 type, Team* team, + int32 fd, const BString& output) + : + Event(type, team), + fDescriptor(fd), + fOutput(output) +{ +} + + // #pragma mark - DebugReportEvent @@ -824,6 +850,12 @@ Team::Listener::ImageDebugInfoChanged(const Team::ImageEvent& event) void +Team::Listener::ConsoleOutputReceived(const Team::ConsoleOutputEvent& event) +{ +} + + +void Team::Listener::BreakpointAdded(const Team::BreakpointEvent& event) { } diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 4b89c02..98a2fb2 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef TEAM_H @@ -32,6 +33,8 @@ enum { TEAM_EVENT_IMAGE_DEBUG_INFO_CHANGED, + TEAM_EVENT_CONSOLE_OUTPUT_RECEIVED, + TEAM_EVENT_BREAKPOINT_ADDED, TEAM_EVENT_BREAKPOINT_REMOVED, TEAM_EVENT_USER_BREAKPOINT_CHANGED, @@ -41,6 +44,7 @@ enum { TEAM_EVENT_WATCHPOINT_CHANGED, TEAM_EVENT_DEBUG_REPORT_CHANGED + }; @@ -63,6 +67,7 @@ class Team { public: class Event; class BreakpointEvent; + class ConsoleOutputEvent; class DebugReportEvent; class ImageEvent; class ThreadEvent; @@ -178,6 +183,10 @@ public: // service methods for Image void NotifyImageDebugInfoChanged(Image* image); + // service methods for console output + void NotifyConsoleOutputReceived( + int32 fd, const BString& output); + // breakpoint related service methods void NotifyUserBreakpointChanged( UserBreakpoint* breakpoint); @@ -268,6 +277,20 @@ protected: }; +class Team::ConsoleOutputEvent : public Event { +public: + ConsoleOutputEvent(uint32 type, Team* team, + int32 fd, const BString& output); + + int32 Descriptor() const { return fDescriptor; } + const BString& Output() const { return fOutput; } + +protected: + int32 fDescriptor; + BString fOutput; +}; + + class Team::DebugReportEvent : public Event { public: DebugReportEvent(uint32 type, Team* team, @@ -323,6 +346,9 @@ public: virtual void ImageDebugInfoChanged( const Team::ImageEvent& event); + virtual void ConsoleOutputReceived( + const Team::ConsoleOutputEvent& event); + virtual void BreakpointAdded( const Team::BreakpointEvent& event); virtual void BreakpointRemoved( ############################################################################ Commit: fe448830c9e93906af7319af226af06e0738e759 URL: http://cgit.haiku-os.org/haiku/commit/?id=fe44883 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu Jun 27 23:40:41 2013 UTC TeamDebugger: Implement post syscall event handling. We now watch for file write syscalls in the target team. If they constitute a write to either stdout or stderr, we attempt to capture the output, and notify interested listeners accordingly. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 03831a5..8cd2620 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -4,6 +4,10 @@ CCFLAGS += -Werror ; C++FLAGS += -Werror ; UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ; + +# for syscall_numbers.h +UseHeaders [ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR) system kernel ] ; + UsePrivateHeaders app debug interface kernel shared libroot ; UsePrivateSystemHeaders ; @@ -58,6 +62,11 @@ SourceHdrs : [ FDirName $(SUBDIR) dwarf ] ; +# since syscall_numbers.h is generated on the fly, we need to explicitly +# let Jam know about the dependency. +Includes [ FGristFiles TeamDebugger.cpp ] + : <syscalls>syscall_numbers.h ; + Application Debugger : Debugger.cpp diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 7fce6fb..8a0b42d 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -18,6 +18,7 @@ #include <AutoLocker.h> #include "debug_utils.h" +#include "syscall_numbers.h" #include "BreakpointManager.h" #include "BreakpointSetting.h" @@ -1261,8 +1262,16 @@ TeamDebugger::_HandleDebuggerMessage(DebugEvent* event) handled = _HandleImageDeleted(imageEvent); break; } - case B_DEBUGGER_MESSAGE_PRE_SYSCALL: case B_DEBUGGER_MESSAGE_POST_SYSCALL: + { + PostSyscallEvent* postSyscallEvent + = dynamic_cast<PostSyscallEvent*>(event); + TRACE_EVENTS("B_DEBUGGER_MESSAGE_POST_SYSCALL: syscall: %" + B_PRIu32 "\n", postSyscallEvent->GetSyscallInfo().Syscall()); + handled = _HandlePostSyscall(postSyscallEvent); + break; + } + case B_DEBUGGER_MESSAGE_PRE_SYSCALL: case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: case B_DEBUGGER_MESSAGE_PROFILER_UPDATE: case B_DEBUGGER_MESSAGE_HANDED_OVER: @@ -1402,6 +1411,37 @@ TeamDebugger::_HandleImageDeleted(ImageDeletedEvent* event) } +bool +TeamDebugger::_HandlePostSyscall(PostSyscallEvent* event) +{ + const SyscallInfo& info = event->GetSyscallInfo(); + const uint32* args = info.Arguments(); + + switch (info.Syscall()) { + case SYSCALL_WRITE: + { + int32 fd = (int32)args[0]; + if (fd == 1 || fd == 2) { + BString data; + ssize_t result = fDebuggerInterface->ReadMemoryString( + (target_addr_t)args[3], (size_t)args[4], data); + if (result >= 0) + fTeam->NotifyConsoleOutputReceived(fd, data); + } + break; + } + case SYSCALL_WRITEV: + { + // TODO: handle + } + default: + break; + } + + return false; +} + + void TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID) { diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index 3aa5f1f..bfdfc45 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -141,6 +141,8 @@ private: ImageCreatedEvent* event); bool _HandleImageDeleted( ImageDeletedEvent* event); + bool _HandlePostSyscall( + PostSyscallEvent* event); void _HandleImageDebugInfoChanged(image_id imageID); void _HandleImageFileChanged(image_id imageID); ############################################################################ Commit: 7910d8b89cc2285eba6efc8c16475dd06617bc8b URL: http://cgit.haiku-os.org/haiku/commit/?id=7910d8b Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Fri Jun 28 01:43:14 2013 UTC Adjust BCheckBox::MaxSize. Previously BCheckBox returned unlimited width for its max size. This became problematic if one wanted to put a checkbox in any kind of horizontal layout with other controls, since they would expand to use as much space as possible. This is also in contrast to other controls such as BButton, which simply return the max to be the same as the preferred. As such, adjust BCheckBox to do the same. ---------------------------------------------------------------------------- diff --git a/src/kits/interface/CheckBox.cpp b/src/kits/interface/CheckBox.cpp index cde4220..ff06aae 100644 --- a/src/kits/interface/CheckBox.cpp +++ b/src/kits/interface/CheckBox.cpp @@ -366,7 +366,7 @@ BCheckBox::MouseDown(BPoint point) Invalidate(); Window()->UpdateIfNeeded(); } - } + } } @@ -452,7 +452,7 @@ BSize BCheckBox::MaxSize() { return BLayoutUtils::ComposeSize(ExplicitMaxSize(), - BSize(B_SIZE_UNLIMITED, _ValidatePreferredSize().height)); + _ValidatePreferredSize()); } @@ -631,6 +631,6 @@ B_IF_GCC_2(InvalidateLayout__9BCheckBoxb, _ZN9BCheckBox16InvalidateLayoutEb)( perform_data_layout_invalidated data; data.descendants = descendants; - box->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data); + box->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data); } ############################################################################ Commit: b8b4219f26ca324dbaca060885173cbb01331447 URL: http://cgit.haiku-os.org/haiku/commit/?id=b8b4219 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Fri Jun 28 01:05:42 2013 UTC Ticket: https://dev.haiku-os.org/ticket/9758 Implement #9758. - Add ConsoleOutputView for showing the debugged team's console output. The view presents checkboxes for controlling whether or not stdout and/or stderr output is captured and shown, as well as the ability to clear the current output. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 8cd2620..ed049c8 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -244,6 +244,7 @@ Application Debugger : # user_interface/gui/team_window BreakpointListView.cpp BreakpointsView.cpp + ConsoleOutputView.cpp ExceptionConfigWindow.cpp ImageFunctionsView.cpp ImageListView.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 560ec53..093e729 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -28,6 +28,7 @@ enum { MSG_THREAD_STACK_TRACE_CHANGED = 'tstc', MSG_STACK_FRAME_VALUE_RETRIEVED = 'sfvr', MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic', + MSG_CONSOLE_OUTPUT_RECEIVED = 'core', MSG_IMAGE_FILE_CHANGED = 'ifch', MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc', MSG_USER_BREAKPOINT_CHANGED = 'ubrc', diff --git a/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.cpp b/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.cpp new file mode 100644 index 0000000..618f25a --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.cpp @@ -0,0 +1,157 @@ +/* + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "ConsoleOutputView.h" + +#include <new> + +#include <Button.h> +#include <CheckBox.h> +#include <LayoutBuilder.h> +#include <ScrollView.h> +#include <String.h> +#include <TextView.h> + + +enum { + MSG_CLEAR_OUTPUT = 'clou' +}; + + +// #pragma mark - ConsoleOutputView + + +ConsoleOutputView::ConsoleOutputView() + : + BGroupView(B_VERTICAL, 0.0f), + fStdoutEnabled(NULL), + fStderrEnabled(NULL), + fConsoleOutput(NULL), + fClearButton(NULL) +{ + SetName("ConsoleOutput"); +} + + +ConsoleOutputView::~ConsoleOutputView() +{ +} + + +/*static*/ ConsoleOutputView* +ConsoleOutputView::Create() +{ + ConsoleOutputView* self = new ConsoleOutputView(); + + try { + self->_Init(); + } catch (...) { + delete self; + throw; + } + + return self; +} + + +void +ConsoleOutputView::ConsoleOutputReceived(int32 fd, const BString& output) +{ + if (fd == 1 && fStdoutEnabled->Value() != B_CONTROL_ON) + return; + else if (fd == 2 && fStderrEnabled->Value() != B_CONTROL_ON) + return; + + text_run_array run; + run.count = 1; + run.runs[0].font = be_fixed_font; + run.runs[0].offset = 0; + run.runs[0].color.red = fd == 1 ? 0 : 192; + run.runs[0].color.green = 0; + run.runs[0].color.blue = 0; + run.runs[0].color.alpha = 255; + + fConsoleOutput->Insert(fConsoleOutput->TextLength(), output.String(), + output.Length(), &run); +} + + +void +ConsoleOutputView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_CLEAR_OUTPUT: + { + fConsoleOutput->SetText(""); + break; + } + default: + BGroupView::MessageReceived(message); + break; + } +} + + +void +ConsoleOutputView::AttachedToWindow() +{ + BGroupView::AttachedToWindow(); + + fStdoutEnabled->SetValue(B_CONTROL_ON); + fStderrEnabled->SetValue(B_CONTROL_ON); + fClearButton->SetTarget(this); +} + + +void +ConsoleOutputView::LoadSettings(const BMessage& settings) +{ + fStdoutEnabled->SetValue(settings.GetBool("showStdout", true) + ? B_CONTROL_ON : B_CONTROL_OFF); + fStderrEnabled->SetValue(settings.GetBool("showStderr", true) + ? B_CONTROL_ON : B_CONTROL_OFF); +} + + +status_t +ConsoleOutputView::SaveSettings(BMessage& settings) +{ + bool value = fStdoutEnabled->Value() == B_CONTROL_ON; + if (settings.AddBool("showStdout", value) != B_OK) + return B_NO_MEMORY; + + value = fStderrEnabled->Value() == B_CONTROL_ON; + if (settings.AddBool("showStderr", value) != B_OK) + return B_NO_MEMORY; + + return B_OK; +} + + +void +ConsoleOutputView::_Init() +{ + BScrollView* consoleScrollView; + + BLayoutBuilder::Group<>(this, B_HORIZONTAL, 0.0f) + .Add(consoleScrollView = new BScrollView("console scroll", NULL, 0, + true, true), 3.0f) + .AddGroup(B_VERTICAL, 0.0f) + .SetInsets(B_USE_SMALL_SPACING) + .Add(fStdoutEnabled = new BCheckBox("Stdout")) + .Add(fStderrEnabled = new BCheckBox("Stderr")) + .Add(fClearButton = new BButton("Clear")) + .AddGlue() + .End() + .End(); + + consoleScrollView->SetTarget(fConsoleOutput = new BTextView("Console")); + + fClearButton->SetMessage(new BMessage(MSG_CLEAR_OUTPUT)); + fConsoleOutput->MakeEditable(false); + fConsoleOutput->SetStylable(true); + fConsoleOutput->SetDoesUndo(false); +} diff --git a/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.h b/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.h new file mode 100644 index 0000000..5413323 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.h @@ -0,0 +1,46 @@ +/* + * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef CONSOLE_OUTPUT_VIEW_H_ +#define CONSOLE_OUTPUT_VIEW_H_ + + +#include <GroupView.h> + + +class BButton; +class BCheckBox; +class BTextView; + + +class ConsoleOutputView : public BGroupView { +public: + ConsoleOutputView(); + ~ConsoleOutputView(); + + static ConsoleOutputView* Create(); + // throws + + void ConsoleOutputReceived( + int32 fd, const BString& output); + + virtual void MessageReceived(BMessage* message); + virtual void AttachedToWindow(); + + void LoadSettings(const BMessage& settings); + status_t SaveSettings(BMessage& settings); + +private: + void _Init(); + +private: + BCheckBox* fStdoutEnabled; + BCheckBox* fStderrEnabled; + BTextView* fConsoleOutput; + BButton* fClearButton; +}; + + + +#endif // CONSOLE_OUTPUT_VIEW_H diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 948351a..031c4c0 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -29,6 +29,7 @@ #include <AutoLocker.h> #include "Breakpoint.h" +#include "ConsoleOutputView.h" #include "CpuState.h" #include "DisassembledCode.h" #include "ExceptionConfigWindow.h" @@ -116,6 +117,14 @@ TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener) fStepOverButton(NULL), fStepIntoButton(NULL), fStepOutButton(NULL), + fMenuBar(NULL), + fSourcePathView(NULL), + fConsoleOutputView(NULL), + fFunctionSplitView(NULL), + fSourceSplitView(NULL), + fImageSplitView(NULL), + fThreadSplitView(NULL), + fConsoleSplitView(NULL), fExceptionConfigWindow(NULL), fInspectorWindow(NULL), fFilePanel(NULL) @@ -429,6 +438,18 @@ TeamWindow::MessageReceived(BMessage* message) break; } + case MSG_CONSOLE_OUTPUT_RECEIVED: + { + int32 fd; + BString output; + if (message->FindInt32("fd", &fd) != B_OK + || message->FindString("output", &output) != B_OK) { + break; + } + fConsoleOutputView->ConsoleOutputReceived(fd, output); + break; + } + case MSG_USER_BREAKPOINT_CHANGED: { UserBreakpoint* breakpoint; @@ -505,6 +526,9 @@ TeamWindow::LoadSettings(const GuiTeamUiSettings* settings) if (teamWindowSettings.FindMessage("threadSplit", &archive) == B_OK) GuiSettingsUtils::UnarchiveSplitView(archive, fThreadSplitView); + if (teamWindowSettings.FindMessage("consoleSplit", &archive) == B_OK) + GuiSettingsUtils::UnarchiveSplitView(archive, fConsoleSplitView); + if (teamWindowSettings.FindMessage("imageListView", &archive) == B_OK) fImageListView->LoadSettings(archive); @@ -526,6 +550,9 @@ TeamWindow::LoadSettings(const GuiTeamUiSettings* settings) if (teamWindowSettings.FindMessage("breakpointsView", &archive) == B_OK) fBreakpointsView->LoadSettings(archive); + if (teamWindowSettings.FindMessage("consoleOutputView", &archive) == B_OK) + fConsoleOutputView->LoadSettings(archive); + fUiSettings = *settings; return B_OK; @@ -570,6 +597,11 @@ TeamWindow::SaveSettings(GuiTeamUiSettings* settings) if (teamWindowSettings.AddMessage("threadSplit", &archive)) return B_NO_MEMORY; + if (GuiSettingsUtils::ArchiveSplitView(archive, fConsoleSplitView) != B_OK) + return B_NO_MEMORY; + if (teamWindowSettings.AddMessage("consoleSplit", &archive)) + return B_NO_MEMORY; + if (fImageListView->SaveSettings(archive) != B_OK) return B_NO_MEMORY; if (teamWindowSettings.AddMessage("imageListView", &archive)) @@ -605,6 +637,11 @@ TeamWindow::SaveSettings(GuiTeamUiSettings* settings) if (teamWindowSettings.AddMessage("breakpointsView", &archive)) return B_NO_MEMORY; + if (fConsoleOutputView->SaveSettings(archive) != B_OK) + return B_NO_MEMORY; + if (teamWindowSettings.AddMessage("consoleOutputView", &archive)) + return B_NO_MEMORY; + if (!settings->AddSettings("teamWindow", teamWindowSettings)) return B_NO_MEMORY; @@ -764,6 +801,16 @@ TeamWindow::ImageDebugInfoChanged(const Team::ImageEvent& event) void +TeamWindow::ConsoleOutputReceived(const Team::ConsoleOutputEvent& event) +{ + BMessage message(MSG_CONSOLE_OUTPUT_RECEIVED); + message.AddInt32("fd", event.Descriptor()); + message.AddString("output", event.Output()); + PostMessage(&message); +} + + +void TeamWindow::UserBreakpointChanged(const Team::UserBreakpointEvent& event) { BMessage message(MSG_USER_BREAKPOINT_CHANGED); @@ -838,6 +885,11 @@ TeamWindow::_Init() .End() .Add(fLocalsTabView = new BTabView("locals view")) .End() + .AddSplit(B_VERTICAL, splitSpacing) + .GetSplitView(&fConsoleSplitView) + .SetInsets(0.0) + .Add(fConsoleOutputView = ConsoleOutputView::Create()) + .End() .End(); // add source view diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index d734d06..7a2157f 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2010-2011, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2010-2013, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef TEAM_WINDOW_H @@ -29,6 +29,7 @@ class BMenuBar; class BSplitView; class BStringView; class BTabView; +class ConsoleOutputView; class ExceptionConfigWindow; class Image; class InspectorWindow; @@ -129,6 +130,8 @@ private: const Team::ThreadEvent& event); virtual void ImageDebugInfoChanged( const Team::ImageEvent& event); + virtual void ConsoleOutputReceived( + const Team::ConsoleOutputEvent& event); virtual void UserBreakpointChanged( const Team::UserBreakpointEvent& event); virtual void WatchpointChanged( @@ -195,10 +198,12 @@ private: BButton* fStepOutButton; BMenuBar* fMenuBar; BStringView* fSourcePathView; + ConsoleOutputView* fConsoleOutputView; BSplitView* fFunctionSplitView; BSplitView* fSourceSplitView; BSplitView* fImageSplitView; BSplitView* fThreadSplitView; + BSplitView* fConsoleSplitView; ExceptionConfigWindow* fExceptionConfigWindow; InspectorWindow* fInspectorWindow; GuiTeamUiSettings fUiSettings; ############################################################################ Commit: 277945a648f560f98910198d96a7ef34e8f86a51 URL: http://cgit.haiku-os.org/haiku/commit/?id=277945a Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Fri Jun 28 22:29:26 2013 UTC Add support for auto-scrolling. - If the console output is currently at the bottom, any new output will automatically be scrolled into view. Otherwise, its current position will be maintained. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.cpp b/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.cpp index 618f25a..cc5876f 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/ConsoleOutputView.cpp @@ -74,8 +74,19 @@ ConsoleOutputView::ConsoleOutputReceived(int32 fd, const BString& output) run.runs[0].color.blue = 0; run.runs[0].color.alpha = 255; + bool autoScroll = false; + BScrollBar* scroller = fConsoleOutput->ScrollBar(B_VERTICAL); + float min, max; + scroller->GetRange(&min, &max); + if (min == max || scroller->Value() == max) + autoScroll = true; + fConsoleOutput->Insert(fConsoleOutput->TextLength(), output.String(), output.Length(), &run); + if (autoScroll) { + scroller->GetRange(&min, &max); + fConsoleOutput->ScrollTo(0.0, max); + } } ############################################################################ Revision: hrev45797 Commit: 77ea49f4f2cb0e369fa27a5ca8870207e3046af6 URL: http://cgit.haiku-os.org/haiku/commit/?id=77ea49f Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Fri Jun 28 22:42:40 2013 UTC Adjust debug API to address some x86-64 concerns. - The argument buffer contained in the debug_{pre,post}_syscall message structures wasn't large enough to accomodate all arguments for some syscalls on x86-64, which could potentially have led to kernel memory corruption when using syscall tracing via the debug API. As such, enlarge it to accomodate 64-bit platforms as well. - Adjust TeamDebugger/SyscallInfo to discriminate the target architecture and read the arguments when trapping console output. Gets the latter working on x86-64. ---------------------------------------------------------------------------- diff --git a/headers/os/kernel/debugger.h b/headers/os/kernel/debugger.h index c443b39..770d0b7 100644 --- a/headers/os/kernel/debugger.h +++ b/headers/os/kernel/debugger.h @@ -487,7 +487,7 @@ typedef struct { typedef struct { debug_origin origin; uint32 syscall; // the syscall number - uint32 args[16]; // syscall arguments + uint8 args[128]; // syscall arguments } debug_pre_syscall; // B_DEBUGGER_MESSAGE_POST_SYSCALL @@ -498,7 +498,7 @@ typedef struct { bigtime_t end_time; // time of syscall completion uint64 return_value; // the syscall's return value uint32 syscall; // the syscall number - uint32 args[16]; // syscall arguments + uint8 args[128]; // syscall arguments } debug_post_syscall; // B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 8a0b42d..7885590 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -20,6 +20,7 @@ #include "debug_utils.h" #include "syscall_numbers.h" +#include "Architecture.h" #include "BreakpointManager.h" #include "BreakpointSetting.h" #include "CpuState.h" @@ -1415,16 +1416,37 @@ bool TeamDebugger::_HandlePostSyscall(PostSyscallEvent* event) { const SyscallInfo& info = event->GetSyscallInfo(); - const uint32* args = info.Arguments(); switch (info.Syscall()) { case SYSCALL_WRITE: { - int32 fd = (int32)args[0]; + int32 fd; + target_addr_t address; + size_t size; + // TODO: decoding the syscall arguments should probably be + // factored out into an Architecture method of its own, since + // there's no guarantee the target architecture has the same + // endianness as the host. This could re-use the syscall + // argument parser that strace uses, though that would need to + // be adapted to handle the aforementioned endian differences. + // This works for x86{-64} for now though. + if (fTeam->GetArchitecture()->AddressSize() == 4) { + const uint32* args = (const uint32*)info.Arguments(); + fd = args[0]; + address = args[3]; + size = args[4]; + } else { + const uint64* args = (const uint64*)info.Arguments(); + fd = args[0]; + address = args[2]; + size = args[3]; + } + if (fd == 1 || fd == 2) { BString data; + ssize_t result = fDebuggerInterface->ReadMemoryString( - (target_addr_t)args[3], (size_t)args[4], data); + address, size, data); if (result >= 0) fTeam->NotifyConsoleOutputReceived(fd, data); } diff --git a/src/apps/debugger/model/SyscallInfo.cpp b/src/apps/debugger/model/SyscallInfo.cpp index 21b615e..e6b6ea4 100644 --- a/src/apps/debugger/model/SyscallInfo.cpp +++ b/src/apps/debugger/model/SyscallInfo.cpp @@ -31,7 +31,7 @@ SyscallInfo::SyscallInfo(const SyscallInfo& other) SyscallInfo::SyscallInfo(bigtime_t startTime, bigtime_t endTime, - uint64 returnValue, uint32 syscall, const uint32* args) + uint64 returnValue, uint32 syscall, const uint8* args) : fStartTime(startTime), fEndTime(endTime), @@ -44,7 +44,7 @@ SyscallInfo::SyscallInfo(bigtime_t startTime, bigtime_t endTime, void SyscallInfo::SetTo(bigtime_t startTime, bigtime_t endTime, uint64 returnValue, - uint32 syscall, const uint32* args) + uint32 syscall, const uint8* args) { fStartTime = startTime; fEndTime = endTime; diff --git a/src/apps/debugger/model/SyscallInfo.h b/src/apps/debugger/model/SyscallInfo.h index c2609c8..4bb597f 100644 --- a/src/apps/debugger/model/SyscallInfo.h +++ b/src/apps/debugger/model/SyscallInfo.h @@ -16,27 +16,27 @@ public: bigtime_t endTime, uint64 returnValue, uint32 syscall, - const uint32* args); + const uint8* args); void SetTo(bigtime_t startTime, bigtime_t endTime, uint64 returnValue, uint32 syscall, - const uint32* args); + const uint8* args); bigtime_t StartTime() const { return fStartTime; } bigtime_t EndTime() const { return fEndTime; } uint64 ReturnValue() const { return fReturnValue; } uint32 Syscall() const { return fSyscall; } - const uint32* Arguments() const { return fArguments; } + const uint8* Arguments() const { return fArguments; } private: bigtime_t fStartTime; bigtime_t fEndTime; uint64 fReturnValue; uint32 fSyscall; - uint32 fArguments[16]; + uint8 fArguments[128]; };