From eba6b399af59d5d58e3afd71c1c27209393c7dab Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Thu, 28 Dec 2023 23:56:58 +0800 Subject: [PATCH 1/2] Make integers and pointers interchangeable in `Crystal::System.print_error` --- spec/std/crystal/system_spec.cr | 4 ++++ src/crystal/system/print_error.cr | 28 ++++++++++++++++++--------- src/crystal/system/unix/signal.cr | 2 +- src/exception/call_stack/libunwind.cr | 2 +- src/exception/call_stack/stackwalk.cr | 4 ++-- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/spec/std/crystal/system_spec.cr b/spec/std/crystal/system_spec.cr index 06bc789055d4..9fad50461ac3 100644 --- a/spec/std/crystal/system_spec.cr +++ b/spec/std/crystal/system_spec.cr @@ -42,5 +42,9 @@ describe "Crystal::System" do print_error_to_s("%lu,%lu,%llu,%llu", *values).should eq(values.join(',')) print_error_to_s("%lx,%lx,%llx,%llx", *values).should eq(values.join(',', &.to_s(16))) end + + it "can mix pointers and ints" do + print_error_to_s("%d,%p,%s", Pointer(UInt8).new(123), 0x456, "abc".to_unsafe.address).should eq("123,0x456,abc") + end end end diff --git a/src/crystal/system/print_error.cr b/src/crystal/system/print_error.cr index 3832eed5d9f4..984b37467665 100644 --- a/src/crystal/system/print_error.cr +++ b/src/crystal/system/print_error.cr @@ -56,26 +56,26 @@ module Crystal::System case fmt_ptr.value when 's' - read_arg(String | Pointer(UInt8)) do |arg| + read_arg(String, Int::Primitive, Pointer) do |arg| yield to_string_slice(arg) end when 'd' - read_arg(Int::Primitive) do |arg| + read_arg(Int::Primitive, Pointer) do |arg| to_int_slice(arg, 10, true, width) { |bytes| yield bytes } end when 'u' - read_arg(Int::Primitive) do |arg| + read_arg(Int::Primitive, Pointer) do |arg| to_int_slice(arg, 10, false, width) { |bytes| yield bytes } end when 'x' - read_arg(Int::Primitive) do |arg| + read_arg(Int::Primitive, Pointer) do |arg| to_int_slice(arg, 16, false, width) { |bytes| yield bytes } end when 'p' - read_arg(Pointer(Void)) do |arg| + read_arg(Int::Primitive, Pointer) do |arg| # NOTE: MSVC uses `%X` rather than `0x%x`, we follow the latter on all platforms yield "0x".to_slice - to_int_slice(arg.address, 16, false, 2) { |bytes| yield bytes } + to_int_slice(arg, 16, false, 2) { |bytes| yield bytes } end else yield Slice.new(next_percent, fmt_ptr + 1 - next_percent) @@ -85,10 +85,12 @@ module Crystal::System end end - private macro read_arg(type, &block) - {{ block.args[0] }} = args[arg_index].as?({{ type }}) - if !{{ block.args[0] }}.nil? + private macro read_arg(*types, &block) + case {{ block.args[0] }} = args[arg_index] + {% for t in types %} + when {{ t }} {{ block.body }} + {% end %} else yield "(???)".to_slice end @@ -96,6 +98,10 @@ module Crystal::System end private def self.to_string_slice(str) + if str.is_a?(Int::Primitive) + str = Pointer(UInt8).new(str) + end + if str.is_a?(UInt8*) if str.null? "(null)".to_slice @@ -109,6 +115,10 @@ module Crystal::System # simplified version of `Int#internal_to_s` private def self.to_int_slice(num, base, signed, width, &) + if num.is_a?(Pointer) + num = num.address + end + if num == 0 yield "0".to_slice return diff --git a/src/crystal/system/unix/signal.cr b/src/crystal/system/unix/signal.cr index c30a2b985af2..f7c0ad31e326 100644 --- a/src/crystal/system/unix/signal.cr +++ b/src/crystal/system/unix/signal.cr @@ -149,7 +149,7 @@ module Crystal::System::Signal if is_stack_overflow Crystal::System.print_error "Stack overflow (e.g., infinite or very deep recursion)\n" else - Crystal::System.print_error "Invalid memory access (signal %d) at address 0x%lx\n", sig, addr + Crystal::System.print_error "Invalid memory access (signal %d) at address %p\n", sig, addr end Exception::CallStack.print_backtrace diff --git a/src/exception/call_stack/libunwind.cr b/src/exception/call_stack/libunwind.cr index 220db21b71f0..9f17512491fe 100644 --- a/src/exception/call_stack/libunwind.cr +++ b/src/exception/call_stack/libunwind.cr @@ -102,7 +102,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index f49c87fae623..a6a400b1befd 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -37,7 +37,7 @@ struct Exception::CallStack case exception_info.value.exceptionRecord.value.exceptionCode when LibC::EXCEPTION_ACCESS_VIOLATION addr = exception_info.value.exceptionRecord.value.exceptionInformation[1] - Crystal::System.print_error "Invalid memory access (C0000005) at address 0x%llx\n", addr + Crystal::System.print_error "Invalid memory access (C0000005) at address %p\n", Pointer(Void).new(addr) print_backtrace(exception_info) LibC._exit(1) when LibC::EXCEPTION_STACK_OVERFLOW @@ -150,7 +150,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" From c97503b97b67f8fc4723ad3c07c1c4f671952a73 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Thu, 4 Jan 2024 15:31:25 +0800 Subject: [PATCH 2/2] fixup --- src/crystal/system/unix/signal.cr | 2 +- src/exception/call_stack/libunwind.cr | 2 +- src/exception/call_stack/stackwalk.cr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crystal/system/unix/signal.cr b/src/crystal/system/unix/signal.cr index f7c0ad31e326..c30a2b985af2 100644 --- a/src/crystal/system/unix/signal.cr +++ b/src/crystal/system/unix/signal.cr @@ -149,7 +149,7 @@ module Crystal::System::Signal if is_stack_overflow Crystal::System.print_error "Stack overflow (e.g., infinite or very deep recursion)\n" else - Crystal::System.print_error "Invalid memory access (signal %d) at address %p\n", sig, addr + Crystal::System.print_error "Invalid memory access (signal %d) at address 0x%lx\n", sig, addr end Exception::CallStack.print_backtrace diff --git a/src/exception/call_stack/libunwind.cr b/src/exception/call_stack/libunwind.cr index 9f17512491fe..220db21b71f0 100644 --- a/src/exception/call_stack/libunwind.cr +++ b/src/exception/call_stack/libunwind.cr @@ -102,7 +102,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[%p] ", repeated_frame.ip + Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index a6a400b1befd..f49c87fae623 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -37,7 +37,7 @@ struct Exception::CallStack case exception_info.value.exceptionRecord.value.exceptionCode when LibC::EXCEPTION_ACCESS_VIOLATION addr = exception_info.value.exceptionRecord.value.exceptionInformation[1] - Crystal::System.print_error "Invalid memory access (C0000005) at address %p\n", Pointer(Void).new(addr) + Crystal::System.print_error "Invalid memory access (C0000005) at address 0x%llx\n", addr print_backtrace(exception_info) LibC._exit(1) when LibC::EXCEPTION_STACK_OVERFLOW @@ -150,7 +150,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[%p] ", repeated_frame.ip + Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n"