diff options
author | Ben Wiederhake <BenWiederhake.GitHub@gmx.de> | 2021-11-26 23:14:50 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-12-05 22:59:09 +0100 |
commit | 152d455143ec3a7a010f47f94bfbfa484ada2370 (patch) | |
tree | dafa7458a99acc5075a12967dcc3d774ebc188ea /Userland | |
parent | 0e6e1092f0af0c69a639105bc16bd9efcf1ad690 (diff) | |
download | serenity-152d455143ec3a7a010f47f94bfbfa484ada2370.zip |
strace: Handle strings more gracefully
In particular, strace can now stomach memory errors while copying
invalid strings.
Example with a valid string:
dbgputstr("95.976 traceme(38:38) Well, Hello Friends!") = 55
Example with an invalid string:
dbgputstr(Error(errno=14){0x00012345, 678b}) = -14 EFAULT
(ANSI escapes removed for readability.)
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Utilities/strace.cpp | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/Userland/Utilities/strace.cpp b/Userland/Utilities/strace.cpp index 5c3d332e35..a71c80e7f9 100644 --- a/Userland/Utilities/strace.cpp +++ b/Userland/Utilities/strace.cpp @@ -333,8 +333,45 @@ struct Formatter<PointerArgument> : StandardFormatter { }; } -class FormattedSyscallBuilder { +struct StringArgument { + Syscall::StringArgument argument; + StringView trim_by {}; +}; + +namespace AK { +template<> +struct Formatter<StringArgument> : StandardFormatter { + Formatter() = default; + explicit Formatter(StandardFormatter formatter) + : StandardFormatter(formatter) + { + } + + ErrorOr<void> format(FormatBuilder& format_builder, StringArgument const& string_argument) + { + auto& builder = format_builder.builder(); + if (string_argument.argument.characters == nullptr) { + builder.append("null"); + return {}; + } + // TODO: Avoid trying to copy excessively long strings. + auto string_buffer = copy_from_process(string_argument.argument.characters, string_argument.argument.length); + if (string_buffer.is_error()) { + builder.appendff("{}{{{:p}, {}b}}", string_buffer.error(), (void const*)string_argument.argument.characters, string_argument.argument.length); + } else { + auto view = StringView(string_buffer.value()); + if (!string_argument.trim_by.is_empty()) + view = view.trim(string_argument.trim_by); + builder.appendff("\"{}\"", view); + } + + return {}; + } +}; +} + +class FormattedSyscallBuilder { public: FormattedSyscallBuilder(StringView syscall_name) { @@ -355,19 +392,6 @@ public: add_argument("{}", forward<T>(arg)); } - void add_string_argument(Syscall::StringArgument const& string_argument, StringView trim_by = {}) - { - if (string_argument.characters == nullptr) - add_argument("null"); - else { - auto string_buffer = copy_from_process(string_argument.characters, string_argument.length).release_value_but_fixme_should_propagate_errors(); - auto view = StringView(string_buffer); - if (!trim_by.is_empty()) - view = view.trim(trim_by); - add_argument("\"{}\"", view); - } - } - template<typename... Ts> void add_arguments(Ts&&... args) { @@ -431,13 +455,7 @@ static void format_getrandom(FormattedSyscallBuilder& builder, void* buffer, siz static void format_realpath(FormattedSyscallBuilder& builder, Syscall::SC_realpath_params* params_p) { auto params = copy_from_process(params_p).release_value_but_fixme_should_propagate_errors(); - builder.add_string_argument(params.path); - if (params.buffer.size == 0) - builder.add_argument("null"); - else { - auto buffer = copy_from_process(params.buffer.data, params.buffer.size).release_value_but_fixme_should_propagate_errors(); - builder.add_argument("\"{}\"", StringView { (const char*)buffer.data() }); - } + builder.add_arguments(StringArgument { params.path }, StringArgument { { params.buffer.data, params.buffer.size } }); } static void format_exit(FormattedSyscallBuilder& builder, int status) @@ -463,9 +481,7 @@ static void format_open(FormattedSyscallBuilder& builder, Syscall::SC_open_param else builder.add_argument(params.dirfd); - builder.add_string_argument(params.path); - - builder.add_argument(OpenOptions { params.options }); + builder.add_arguments(StringArgument { params.path }, OpenOptions { params.options }); if (params.options & O_CREAT) builder.add_argument("{:04o}", params.mode); @@ -530,8 +546,7 @@ static void format_stat(FormattedSyscallBuilder& builder, Syscall::SC_stat_param builder.add_argument("AT_FDCWD"); else builder.add_argument(params.dirfd); - builder.add_string_argument(params.path); - builder.add_arguments(copy_from_process(params.statbuf), params.follow_symlinks); + builder.add_arguments(StringArgument { params.path }, copy_from_process(params.statbuf), params.follow_symlinks); } static void format_lseek(FormattedSyscallBuilder& builder, int fd, off_t offset, int whence) @@ -636,8 +651,7 @@ struct MemoryProtectionFlags : BitflagBase { static void format_mmap(FormattedSyscallBuilder& builder, Syscall::SC_mmap_params* params_p) { auto params = copy_from_process(params_p).release_value_but_fixme_should_propagate_errors(); - builder.add_arguments(params.addr, params.size, MemoryProtectionFlags { params.prot }, MmapFlags { params.flags }, params.fd, params.offset, params.alignment); - builder.add_string_argument(params.name); + builder.add_arguments(params.addr, params.size, MemoryProtectionFlags { params.prot }, MmapFlags { params.flags }, params.fd, params.offset, params.alignment, StringArgument { params.name }); } static void format_munmap(FormattedSyscallBuilder& builder, void* addr, size_t size) @@ -653,8 +667,7 @@ static void format_mprotect(FormattedSyscallBuilder& builder, void* addr, size_t static void format_set_mmap_name(FormattedSyscallBuilder& builder, Syscall::SC_set_mmap_name_params* params_p) { auto params = copy_from_process(params_p).release_value_but_fixme_should_propagate_errors(); - builder.add_arguments(params.addr, params.size); - builder.add_string_argument(params.name); + builder.add_arguments(params.addr, params.size, StringArgument { params.name }); } static void format_clock_gettime(FormattedSyscallBuilder& builder, clockid_t clockid, struct timespec* time) @@ -664,12 +677,12 @@ static void format_clock_gettime(FormattedSyscallBuilder& builder, clockid_t clo static void format_dbgputstr(FormattedSyscallBuilder& builder, char* characters, size_t size) { - builder.add_string_argument({ characters, size }, "\0\n"sv); + builder.add_argument(StringArgument { { characters, size }, "\0\n"sv }); } static void format_get_process_name(FormattedSyscallBuilder& builder, char* buffer, size_t buffer_size) { - builder.add_string_argument({ buffer, buffer_size }); + builder.add_argument(StringArgument { { buffer, buffer_size }, "\0"sv }); } static void format_syscall(FormattedSyscallBuilder& builder, Syscall::Function syscall_function, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3, syscall_arg_t res) |