diff --git a/src/bin/debug/strace/Context.h b/src/bin/debug/strace/Context.h index f8ba3bfbeb..377b2bd6de 100644 --- a/src/bin/debug/strace/Context.h +++ b/src/bin/debug/strace/Context.h @@ -19,13 +19,15 @@ public: SIMPLE_STRUCTS = 1 << 2, COMPLEX_STRUCTS = 1 << 3, POINTER_VALUES = 1 << 4, - ALL = 0xffffffff + INPUT_VALUES = 1 << 5, + OUTPUT_VALUES = 1 << 6, + ALL = 0xffffff9f }; Context(Syscall *sc, char *data, MemoryReader &reader, - uint32 flags, bool decimal) + uint32 flags, bool decimal, uint64 returnValue = 0) : fSyscall(sc), fData(data), fReader(reader), - fFlags(flags), fDecimal(decimal) {} + fFlags(flags), fDecimal(decimal), fReturnValue(returnValue) {} Parameter *GetSibling(int32 index) const { return fSyscall->ParameterAt(index); @@ -35,6 +37,10 @@ public: return fData + param->Offset(); } + uint64 GetReturnValue() const { + return fReturnValue; + } + MemoryReader &Reader() { return fReader; } bool GetContents(uint32 what) const { return fFlags & what; } @@ -50,6 +56,7 @@ private: MemoryReader &fReader; uint32 fFlags; bool fDecimal; + uint64 fReturnValue; }; #endif // STRACE_CONTEXT_H diff --git a/src/bin/debug/strace/NetworkTypes.cpp b/src/bin/debug/strace/NetworkTypes.cpp index 9d5d2c4e72..a5411e7748 100644 --- a/src/bin/debug/strace/NetworkTypes.cpp +++ b/src/bin/debug/strace/NetworkTypes.cpp @@ -8,6 +8,7 @@ */ #include +#include #include #include @@ -110,6 +111,138 @@ TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) } +template +static inline value_t +get_value(const void *address) +{ + if (sizeof(align_t) > sizeof(value_t)) + return value_t(*(align_t*)address); + else + return *(value_t*)address; +} + + +static string +format_signed_number(int32 value) +{ + char tmp[32]; + snprintf(tmp, sizeof(tmp), "%d", (signed int)value); + return tmp; +} + + +static string +read_pollfd(Context &context, void *data) +{ + nfds_t numfds = 0; + if (context.GetContents(Context::INPUT_VALUES)) + numfds = get_value(context.GetValue(context.GetSibling(1))); + else if (context.GetContents(Context::OUTPUT_VALUES)) + numfds = context.GetReturnValue(); + if ((int64)numfds <= 0) + return string(); + + pollfd tmp[numfds]; + int32 bytesRead; + + status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead); + if (err != B_OK) + return context.FormatPointer(data); + + int added = 0; + + string r; + r.reserve(16); + + r = "["; + + for (nfds_t i = 0; i < numfds && added < 8; i++) { + if (added > 0) + r += ", "; + r += "{fd=" + format_signed_number(tmp[i].fd); + if (tmp[i].fd != -1 && context.GetContents(Context::INPUT_VALUES)) { + r += ", events="; + int flags = 0; + if ((tmp[i].events & POLLIN) != 0) { + if (flags > 0) + r += "|"; + r += "POLLIN"; + flags++; + } + if ((tmp[i].events & POLLOUT) != 0) { + if (flags > 0) + r += "|"; + r += "POLLOUT"; + flags++; + } + } + if (tmp[i].fd != -1 && context.GetContents(Context::OUTPUT_VALUES)) { + r += ", revents="; + int flags = 0; + if ((tmp[i].revents & POLLIN) != 0) { + if (flags > 0) + r += "|"; + r += "POLLIN"; + flags++; + } + if ((tmp[i].revents & POLLOUT) != 0) { + if (flags > 0) + r += "|"; + r += "POLLOUT"; + flags++; + } + if ((tmp[i].revents & POLLERR) != 0) { + if (flags > 0) + r += "|"; + r += "POLLERR"; + flags++; + } + if ((tmp[i].revents & POLLHUP) != 0) { + if (flags > 0) + r += "|"; + r += "POLLHUP"; + flags++; + } + if ((tmp[i].revents & POLLNVAL) != 0) { + if (flags > 0) + r += "|"; + r += "POLLNVAL"; + flags++; + } + } + added++; + r += "}"; + } + + if (added >= 8) + r += " ..."; + + r += "]"; + + return r; +} + + +template<> +string +TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, + const void *address) +{ + void *data = *(void **)address; + if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) + return read_pollfd(context, data); + return context.FormatPointer(data); +} + + +template<> +string +TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) +{ + return context.FormatPointer((void *)value); +} + + template static string format_pointer_value(Context &context, void *address) @@ -502,6 +635,7 @@ class SpecializedPointerTypeHandler : public TypeHandler { DEFINE_TYPE(fdset_ptr, fd_set *); POINTER_TYPE(ifconf_ptr, ifconf); POINTER_TYPE(ifreq_ptr, ifreq); +DEFINE_TYPE(pollfd_ptr, pollfd *); #if 0 POINTER_TYPE(message_args_ptr, message_args); POINTER_TYPE(msghdr_ptr, msghdr); diff --git a/src/bin/debug/strace/Syscall.h b/src/bin/debug/strace/Syscall.h index a59904ea76..29971c2c0e 100644 --- a/src/bin/debug/strace/Syscall.h +++ b/src/bin/debug/strace/Syscall.h @@ -48,10 +48,13 @@ public: const string &Name() const { return fName; } int32 Offset() const { return fOffset; } + bool InOut() const { return fInOut; } + void SetInOut(bool inout) { fInOut = inout; } private: string fName; int32 fOffset; + bool fInOut; }; // Syscall @@ -106,10 +109,21 @@ public: return NULL; } + bool IsPreSyscall() const + { + return fPreSyscall; + } + + void SetPreSyscall(bool preSyscall) + { + fPreSyscall = preSyscall; + } + private: string fName; Type *fReturnType; vector fParameters; + bool fPreSyscall; }; #endif // STRACE_SYSCALL_H diff --git a/src/bin/debug/strace/TypeHandler.h b/src/bin/debug/strace/TypeHandler.h index 86e80e5948..ce7367303d 100644 --- a/src/bin/debug/strace/TypeHandler.h +++ b/src/bin/debug/strace/TypeHandler.h @@ -101,6 +101,7 @@ struct fd_set; struct ifconf; struct ifreq; struct message_args; +struct pollfd; struct sockaddr_args; struct socket_args; struct sockopt_args; @@ -109,6 +110,7 @@ DEFINE_FACTORY(fdset_ptr, fd_set *); DEFINE_FACTORY(ifconf_ptr, ifconf *); DEFINE_FACTORY(ifreq_ptr, ifreq *); DEFINE_FACTORY(message_args_ptr, message_args *); +DEFINE_FACTORY(pollfd_ptr, pollfd *); DEFINE_FACTORY(sockaddr_args_ptr, sockaddr_args *); DEFINE_FACTORY(socket_args_ptr, socket_args *); DEFINE_FACTORY(sockopt_args_ptr, sockopt_args *); diff --git a/src/bin/debug/strace/strace.cpp b/src/bin/debug/strace/strace.cpp index 7d17b704e8..9a0e7ce599 100644 --- a/src/bin/debug/strace/strace.cpp +++ b/src/bin/debug/strace/strace.cpp @@ -262,6 +262,16 @@ patch_syscalls() extern void patch_ioctl(); patch_ioctl(); + + Syscall *poll = get_syscall("_kern_poll"); + poll->SetPreSyscall(true); + poll->ParameterAt(0)->SetInOut(true); + + Syscall *select = get_syscall("_kern_select"); + select->SetPreSyscall(true); + select->ParameterAt(1)->SetInOut(true); + select->ParameterAt(2)->SetInOut(true); + select->ParameterAt(3)->SetInOut(true); } @@ -338,15 +348,15 @@ print_to_string(char **_buffer, int32 *_length, const char *format, ...) static void -print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message, +print_syscall(FILE *outputFile, Syscall* syscall, debug_pre_syscall &message, MemoryReader &memoryReader, bool printArguments, uint32 contentsFlags, - bool printReturnValue, bool colorize, bool decimal) + bool colorize, bool decimal) { char buffer[4096], *string = buffer; int32 length = (int32)sizeof(buffer); Context ctx(syscall, (char *)message.args, memoryReader, - contentsFlags, decimal); + contentsFlags | Context::INPUT_VALUES, decimal); // print syscall name, without the "_kern_" if (colorize) { @@ -376,6 +386,50 @@ print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message, print_to_string(&string, &length, ")"); + print_buffer(outputFile, buffer, sizeof(buffer) - length); +} + + +static void +print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message, + MemoryReader &memoryReader, bool printArguments, uint32 contentsFlags, + bool printReturnValue, bool colorize, bool decimal) +{ + char buffer[4096], *string = buffer; + int32 length = (int32)sizeof(buffer); + + Context ctx(syscall, (char *)message.args, memoryReader, + contentsFlags | Context::OUTPUT_VALUES, decimal, message.return_value); + + if (!syscall->IsPreSyscall()) { + // print syscall name, without the "_kern_" + if (colorize) { + print_to_string(&string, &length, "[%6" B_PRId32 "] %s%s%s(", + message.origin.thread, kTerminalTextBlue, + syscall->Name().c_str() + 6, kTerminalTextNormal); + } else { + print_to_string(&string, &length, "[%6" B_PRId32 "] %s(", + message.origin.thread, syscall->Name().c_str() + 6); + } + + // print arguments + if (printArguments) { + int32 count = syscall->CountParameters(); + for (int32 i = 0; i < count; i++) { + // get the value + Parameter *parameter = syscall->ParameterAt(i); + TypeHandler *handler = parameter->Handler(); + ::string value = + handler->GetParameterValue(ctx, parameter, + ctx.GetValue(parameter)); + + print_to_string(&string, &length, (i > 0 ? ", %s" : "%s"), + value.c_str()); + } + } + + print_to_string(&string, &length, ")"); + } // print return value if (printReturnValue) { Type *returnType = syscall->ReturnType(); @@ -395,6 +449,30 @@ print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message, } } + if (syscall->IsPreSyscall()) { + // print arguments + if (printArguments) { + int32 count = syscall->CountParameters(); + int added = 0; + print_to_string(&string, &length, " ("); + for (int32 i = 0; i < count; i++) { + // get the value + Parameter *parameter = syscall->ParameterAt(i); + if (!parameter->InOut()) + continue; + TypeHandler *handler = parameter->Handler(); + ::string value = + handler->GetParameterValue(ctx, parameter, + ctx.GetValue(parameter)); + + print_to_string(&string, &length, (added > 0 ? ", %s" : "%s"), + value.c_str()); + added++; + } + print_to_string(&string, &length, ")"); + } + } + if (colorize) { print_to_string(&string, &length, " %s(%lld us)%s\n", kTerminalTextMagenta, message.end_time - message.start_time, kTerminalTextNormal); @@ -684,7 +762,7 @@ main(int argc, const char *const *argv) if (threadID >= 0) { int32 threadDebugFlags = 0; if (!traceTeam) { - threadDebugFlags = B_THREAD_DEBUG_POST_SYSCALL + threadDebugFlags = B_THREAD_DEBUG_PRE_SYSCALL | B_THREAD_DEBUG_POST_SYSCALL | (traceChildThreads ? B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS : 0); } @@ -715,6 +793,31 @@ main(int argc, const char *const *argv) } switch (code) { + case B_DEBUGGER_MESSAGE_PRE_SYSCALL: + { + TeamMap::iterator it = debuggedTeams.find(message.origin.team); + if (it == debuggedTeams.end()) + break; + + Team* team = it->second; + MemoryReader& memoryReader = team->GetMemoryReader(); + + uint32 syscallNumber = message.pre_syscall.syscall; + if (syscallNumber >= sSyscallVector.size()) { + fprintf(stderr, "%s: invalid syscall %" B_PRIu32 " attempted\n", + kCommandName, syscallNumber); + break; + } + Syscall* syscall = sSyscallVector[syscallNumber]; + + if (syscall->IsPreSyscall() && trace) { + print_syscall(outputFile, syscall, message.pre_syscall, + memoryReader, printArguments, contentsFlags, + colorize, decimalFormat); + } + break; + } + case B_DEBUGGER_MESSAGE_POST_SYSCALL: { TeamMap::iterator it = debuggedTeams.find(message.origin.team); @@ -755,7 +858,6 @@ main(int argc, const char *const *argv) 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_THREAD_CREATED: case B_DEBUGGER_MESSAGE_THREAD_DELETED: