From 502309ab5a08cc5113b7d8be192617bf0e613da7 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 27 Mar 2023 21:15:42 -0400 Subject: [PATCH] strace: Introduce FlagsTypeHandler, and use it for O_* modes. Change-Id: I1569084a71c32834c0ff3d8dc71ef3de9d5a817d Reviewed-on: https://review.haiku-os.org/c/haiku/+/6263 Reviewed-by: Adrien Destugues Tested-by: Automation --- src/bin/debug/strace/TypeHandler.cpp | 49 +++++++++++++++++++++++++++ src/bin/debug/strace/TypeHandler.h | 22 +++++++++++- src/bin/debug/strace/fcntl.cpp | 50 ++++++++++++++++++++++++---- 3 files changed, 113 insertions(+), 8 deletions(-) diff --git a/src/bin/debug/strace/TypeHandler.cpp b/src/bin/debug/strace/TypeHandler.cpp index 2d2d1ad668..f9ded7b176 100644 --- a/src/bin/debug/strace/TypeHandler.cpp +++ b/src/bin/debug/strace/TypeHandler.cpp @@ -10,6 +10,7 @@ #include "TypeHandler.h" #include +#include #include "Context.h" #include "MemoryReader.h" @@ -182,6 +183,54 @@ EnumTypeHandler::RenderValue(Context &context, unsigned int value) const return context.FormatUnsigned(value); } +FlagsTypeHandler::FlagsTypeHandler(const FlagsList &m) : fList(m) {} + +string +FlagsTypeHandler::GetParameterValue(Context &context, Parameter *, + const void *address) +{ + return RenderValue(context, get_value(address)); +} + +string +FlagsTypeHandler::GetReturnValue(Context &context, uint64 value) +{ + return RenderValue(context, value); +} + +string +FlagsTypeHandler::RenderValue(Context &context, unsigned int value) const +{ + if (context.GetContents(Context::ENUMERATIONS)) { + // Enumerate the list in reverse. That way, any later values which use + // the same bits as earlier values will be processed correctly. + string rendered; + FlagsList::const_reverse_iterator i = fList.rbegin(); + for (; i != fList.rend(); i++) { + if ((value & i->value) != i->value) + continue; + + if (!rendered.empty()) + rendered.insert(0, " | "); + rendered.insert(0, i->name); + value &= ~(i->value); + } + if (value != 0) { + if (!rendered.empty()) + rendered += " | "; + + char hex[20]; + snprintf(hex, 20, "%x", value); + rendered += hex; + } + if (rendered.empty()) + rendered = "0"; + return rendered; + } + + return context.FormatUnsigned(value); +} + TypeHandlerSelector::TypeHandlerSelector(const SelectMap &m, int sibling, TypeHandler *def) : fMap(m), fSibling(sibling), fDefault(def) {} diff --git a/src/bin/debug/strace/TypeHandler.h b/src/bin/debug/strace/TypeHandler.h index c9d3046439..854bbb9ccf 100644 --- a/src/bin/debug/strace/TypeHandler.h +++ b/src/bin/debug/strace/TypeHandler.h @@ -9,8 +9,9 @@ #ifndef STRACE_TYPE_HANDLER_H #define STRACE_TYPE_HANDLER_H -#include +#include #include +#include #include #include @@ -49,6 +50,25 @@ private: const EnumMap &fMap; }; +class FlagsTypeHandler : public TypeHandler { +public: + struct FlagInfo { + unsigned int value; + const char* name; + }; + typedef std::list FlagsList; + + FlagsTypeHandler(const FlagsList &); + + string GetParameterValue(Context &c, Parameter *, const void *); + string GetReturnValue(Context &, uint64 value); + +private: + string RenderValue(Context &, unsigned int value) const; + + const FlagsList &fList; +}; + // currently limited to select ints class TypeHandlerSelector : public TypeHandler { public: diff --git a/src/bin/debug/strace/fcntl.cpp b/src/bin/debug/strace/fcntl.cpp index 08bc8aa9cc..46555938f6 100644 --- a/src/bin/debug/strace/fcntl.cpp +++ b/src/bin/debug/strace/fcntl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2022, Haiku Inc. All rights reserved. + * Copyright 2022-2023, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -14,6 +14,34 @@ #include "TypeHandler.h" +#define FLAG_INFO_ENTRY(name) \ + { name, #name } + +static const FlagsTypeHandler::FlagInfo kOpenFlagInfos[] = { + FLAG_INFO_ENTRY(O_WRONLY), + FLAG_INFO_ENTRY(O_RDWR), + + FLAG_INFO_ENTRY(O_EXCL), + FLAG_INFO_ENTRY(O_CREAT), + FLAG_INFO_ENTRY(O_TRUNC), + FLAG_INFO_ENTRY(O_NOCTTY), + FLAG_INFO_ENTRY(O_NOTRAVERSE), + + FLAG_INFO_ENTRY(O_CLOEXEC), + FLAG_INFO_ENTRY(O_NONBLOCK), + FLAG_INFO_ENTRY(O_APPEND), + FLAG_INFO_ENTRY(O_SYNC), + FLAG_INFO_ENTRY(O_RSYNC), + FLAG_INFO_ENTRY(O_DSYNC), + FLAG_INFO_ENTRY(O_NOFOLLOW), + FLAG_INFO_ENTRY(O_DIRECT), + + FLAG_INFO_ENTRY(O_DIRECTORY), + + { 0, NULL } +}; + + struct fcntl_info { unsigned int index; const char *name; @@ -31,31 +59,39 @@ static const fcntl_info kFcntls[] = { FCNTL_INFO_ENTRY(F_GETFD), FCNTL_INFO_ENTRY_TYPE(F_SETFD, int), FCNTL_INFO_ENTRY(F_GETFL), - FCNTL_INFO_ENTRY_TYPE(F_SETFL, int), + FCNTL_INFO_ENTRY(F_SETFL), FCNTL_INFO_ENTRY_TYPE(F_GETLK, struct flock*), FCNTL_INFO_ENTRY_TYPE(F_SETLK, struct flock*), FCNTL_INFO_ENTRY_TYPE(F_SETLKW, struct flock*), { 0, NULL, NULL } }; +static FlagsTypeHandler::FlagsList kOpenFlags; static EnumTypeHandler::EnumMap kFcntlNames; static TypeHandlerSelector::SelectMap kFcntlTypeHandlers; void patch_fcntl() { + for (int i = 0; kOpenFlagInfos[i].name != NULL; i++) { + kOpenFlags.push_back(kOpenFlagInfos[i]); + } + for (int i = 0; kFcntls[i].name != NULL; i++) { kFcntlNames[kFcntls[i].index] = kFcntls[i].name; if (kFcntls[i].handler != NULL) kFcntlTypeHandlers[kFcntls[i].index] = kFcntls[i].handler; } - Syscall *fcntl = get_syscall("_kern_fcntl"); + kFcntlTypeHandlers[F_SETFL] = new FlagsTypeHandler(kOpenFlags); - fcntl->GetParameter("op")->SetHandler( - new EnumTypeHandler(kFcntlNames)); + Syscall *open = get_syscall("_kern_open"); + open->GetParameter("openMode")->SetHandler(new FlagsTypeHandler(kOpenFlags)); + + Syscall *fcntl = get_syscall("_kern_fcntl"); + fcntl->GetParameter("op")->SetHandler(new EnumTypeHandler(kFcntlNames)); fcntl->GetParameter("argument")->SetHandler( - new TypeHandlerSelector(kFcntlTypeHandlers, - 1, TypeHandlerFactory::Create())); + new TypeHandlerSelector(kFcntlTypeHandlers, + 1, TypeHandlerFactory::Create())); }