diff --git a/src/bin/debug/strace/Context.cpp b/src/bin/debug/strace/Context.cpp index 9a9eb828bb..57b9d40ea6 100644 --- a/src/bin/debug/strace/Context.cpp +++ b/src/bin/debug/strace/Context.cpp @@ -12,6 +12,18 @@ #include #include + +Parameter * +Context::GetNextSibling(Parameter *param) const +{ + for (int32 i = 0; i + 1 < fSyscall->CountParameters(); i++) { + if (fSyscall->ParameterAt(i) == param) + return fSyscall->ParameterAt(i + 1); + } + return NULL; +} + + string Context::FormatSigned(int64 value, int bytes) const { diff --git a/src/bin/debug/strace/Context.h b/src/bin/debug/strace/Context.h index 377b2bd6de..657e6b2c13 100644 --- a/src/bin/debug/strace/Context.h +++ b/src/bin/debug/strace/Context.h @@ -33,10 +33,21 @@ public: return fSyscall->ParameterAt(index); } + Parameter *GetNextSibling(Parameter *param) const; + const void *GetValue(Parameter *param) const { return fData + param->Offset(); } + template + value_t ReadValue(Parameter *param) const { + const void *address = GetValue(param); + if (sizeof(align_t) > sizeof(value_t)) + return value_t(*(align_t*)address); + else + return *(value_t*)address; + } + uint64 GetReturnValue() const { return fReturnValue; } diff --git a/src/bin/debug/strace/Jamfile b/src/bin/debug/strace/Jamfile index bf3f3c4dc6..382f60853d 100644 --- a/src/bin/debug/strace/Jamfile +++ b/src/bin/debug/strace/Jamfile @@ -21,6 +21,7 @@ local straceSources = MemoryReader.cpp area.cpp + exec.cpp fcntl.cpp ioctl.cpp network.cpp diff --git a/src/bin/debug/strace/NetworkTypes.cpp b/src/bin/debug/strace/NetworkTypes.cpp index 9257525ae4..433582b95c 100644 --- a/src/bin/debug/strace/NetworkTypes.cpp +++ b/src/bin/debug/strace/NetworkTypes.cpp @@ -169,17 +169,6 @@ format_pointer(Context &context, flock *lock) -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) { @@ -192,7 +181,7 @@ format_signed_number(int32 value) static string read_pollfd(Context &context, void *data) { - nfds_t numfds = get_value(context.GetValue(context.GetSibling(1))); + nfds_t numfds = context.ReadValue(context.GetSibling(1)); if ((int64)numfds <= 0) return string(); @@ -424,10 +413,15 @@ format_pointer(Context &context, sockaddr *saddr) static string -read_sockaddr(Context &context, void *address) +read_sockaddr(Context &context, Parameter *param, void *address) { + param = context.GetNextSibling(param); + if (param == NULL) + return context.FormatPointer(address); + + socklen_t addrlen = context.ReadValue(param); + sockaddr_storage data; - socklen_t addrlen = get_value(context.GetValue(context.GetSibling(2))); if (addrlen > sizeof(data)) return context.FormatPointer(address); @@ -443,12 +437,12 @@ read_sockaddr(Context &context, void *address) template<> string -TypeHandlerImpl::GetParameterValue(Context &context, Parameter *, - const void *address) +TypeHandlerImpl::GetParameterValue(Context &context, + Parameter *param, const void *address) { void *data = *(void **)address; if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) - return read_sockaddr(context, data); + return read_sockaddr(context, param, data); return context.FormatPointer(data); } diff --git a/src/bin/debug/strace/exec.cpp b/src/bin/debug/strace/exec.cpp new file mode 100644 index 0000000000..44632181cf --- /dev/null +++ b/src/bin/debug/strace/exec.cpp @@ -0,0 +1,114 @@ +/* + * Copyright 2023, Trung Nguyen, trungnt282910@gmail.com. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + +#include "strace.h" +#include "Context.h" +#include "MemoryReader.h" +#include "TypeHandler.h" + + +using BPrivate::AutoDeleter; + + +class FlatArgsTypeHandler : public TypeHandler { +public: + string GetParameterValue(Context &context, Parameter *param, + const void *address) + { + size_t flatArgsSize; + int32 argCount, envCount; + char *flatArgs, *flatArgsEnd; + int32 bytesRead; + status_t err; + ArrayDeleter flatArgsDeleter; + string r; + + if (!context.GetContents(Context::COMPLEX_STRUCTS)) + goto fallback; + + param = context.GetNextSibling(param); + if (param == NULL) + goto fallback; + flatArgsSize = context.ReadValue(param); + + param = context.GetNextSibling(param); + if (param == NULL) + goto fallback; + argCount = context.ReadValue(param); + + param = context.GetNextSibling(param); + if (param == NULL) + goto fallback; + envCount = context.ReadValue(param); + + flatArgs = new (std::nothrow) char[flatArgsSize + 1]; + if (flatArgs == NULL) + goto fallback; + + flatArgsDeleter.SetTo(flatArgs); + + // Guard with a null byte to prevent faulty buffers. + flatArgsEnd = flatArgs + flatArgsSize; + *flatArgsEnd = '\0'; + + err = context.Reader().Read(*(void **)address, flatArgs, flatArgsSize, + bytesRead); + if (err != B_OK) + goto fallback; + + flatArgs += sizeof(void *) * (argCount + envCount + 2); + + r = "{args = ["; + + for (int32 i = 0; i < argCount && flatArgs < flatArgsEnd; i++) { + if (i > 0) + r += ", "; + size_t currentLen = strlen(flatArgs); + r += "\""; + r += flatArgs; + r += "\""; + flatArgs += currentLen + 1; + } + + r += "], env = ["; + + for (int32 i = 0; i < envCount && flatArgs < flatArgsEnd; i++) { + if (i > 0) + r += ", "; + size_t currentLen = strlen(flatArgs); + r += "\""; + r += flatArgs; + r += "\""; + flatArgs += currentLen + 1; + } + + r += "]}"; + + return r; + fallback: + return context.FormatPointer(address); + } + + string GetReturnValue(Context &context, uint64 value) + { + return context.FormatPointer((void *)value); + } +}; + + +void +patch_exec() +{ + Syscall *exec = get_syscall("_kern_exec"); + exec->GetParameter("flatArgs")->SetHandler(new FlatArgsTypeHandler()); + + Syscall *load_image = get_syscall("_kern_load_image"); + load_image->GetParameter("flatArgs")->SetHandler(new FlatArgsTypeHandler()); +} diff --git a/src/bin/debug/strace/strace.cpp b/src/bin/debug/strace/strace.cpp index 7fd95a2ab9..dd9b4de90a 100644 --- a/src/bin/debug/strace/strace.cpp +++ b/src/bin/debug/strace/strace.cpp @@ -230,6 +230,7 @@ patch_syscalls() // kernel/syscalls.h and have it parsed automatically extern void patch_area(); + extern void patch_exec(); extern void patch_fcntl(); extern void patch_ioctl(); extern void patch_network(); @@ -246,6 +247,7 @@ patch_syscalls() } patch_area(); + patch_exec(); patch_fcntl(); patch_ioctl(); patch_network();