Skip to content

Instantly share code, notes, and snippets.

@ysbaddaden
Created October 17, 2016 13:29
Show Gist options
  • Select an option

  • Save ysbaddaden/67a2a4ab9c076aa96aa886f5f3d9a06b to your computer and use it in GitHub Desktop.

Select an option

Save ysbaddaden/67a2a4ab9c076aa96aa886f5f3d9a06b to your computer and use it in GitHub Desktop.
diff --git a/src/exception.cr b/src/exception.cr
index b9bdc8a..c583f0b 100644
--- a/src/exception.cr
+++ b/src/exception.cr
@@ -44,9 +44,21 @@ struct CallStack
callstack = [] of Void*
backtrace_fn = ->(context : LibUnwind::Context, data : Void*) do
bt = data.as(typeof(callstack))
- ip = Pointer(Void).new(LibUnwind.get_ip(context))
+
+ ip = #{% if flag?(:arm) %}
+ # Pointer(Void).new(__crystal_unwind_get_ip(context))
+ #{% else %}
+ Pointer(Void).new(LibUnwind.get_ip(context))
+ #{% end %}
bt << ip
+ frame = decode_frame(ip)
+ if frame
+ puts "DEBUG: #{ip.address.to_s(16)}: #{String.new(frame[1])}"
+ else
+ puts "DEBUG: #{ip.address.to_s(16)}: ???"
+ end
+
{% if flag?(:i686) %}
# This is a workaround for glibc bug: https://sourceware.org/bugzilla/show_bug.cgi?id=18635
# The unwind info is corrupted when `makecontext` is used.
@@ -78,7 +90,13 @@ struct CallStack
def self.print_backtrace
backtrace_fn = ->(context : LibUnwind::Context, data : Void*) do
last_frame = data.as(RepeatedFrame*)
- ip = Pointer(Void).new(LibUnwind.get_ip(context))
+
+ ip = #{% if flag?(:arm) %}
+ # Pointer(Void).new(__crystal_unwind_get_ip(context))
+ #{% else %}
+ Pointer(Void).new(LibUnwind.get_ip(context))
+ #{% end %}
+
if last_frame.value.ip == ip
last_frame.value.incr
else
diff --git a/src/raise.cr b/src/raise.cr
index da7be11..aa98d31 100644
--- a/src/raise.cr
+++ b/src/raise.cr
@@ -36,11 +36,21 @@ end
# :nodoc:
fun __crystal_personality(version : Int32, actions : LibUnwind::Action, exception_class : UInt64, exception_object : LibUnwind::Exception*, context : Void*) : LibUnwind::ReasonCode
+ #{% if flag?(:arm) %}
+ # if actions.force_unwind?
+ # return LibUnwind::ReasonCode::NO_REASON
+ # end
+ #{% end %}
+
start = LibUnwind.get_region_start(context)
- ip = LibUnwind.get_ip(context)
+ ip = #{% if flag?(:arm) %}
+ # __crystal_unwind_get_ip(context)
+ #{% else %}
+ LibUnwind.get_ip(context)
+ #{% end %}
throw_offset = ip - 1 - start
lsd = LibUnwind.get_language_specific_data(context)
- # puts "Personality - actions : #{actions}, start: #{start}, ip: #{ip}, throw_offset: #{throw_offset}"
+ puts "Personality - actions : #{actions}, start: #{start}, ip: #{ip}, throw_offset: #{throw_offset}"
leb = LEBReader.new(lsd)
leb.read_uint8 # @LPStart encoding
@@ -56,27 +66,33 @@ fun __crystal_personality(version : Int32, actions : LibUnwind::Action, exceptio
cs_length = leb.read_uint32
cs_addr = leb.read_uint32
action = leb.read_uleb128
- # puts "cs_offset: #{cs_offset}, cs_length: #{cs_length}, cs_addr: #{cs_addr}, action: #{action}"
+ puts "cs_offset: #{cs_offset}, cs_length: #{cs_length}, cs_addr: #{cs_addr}, action: #{action}"
if cs_addr != 0
if cs_offset <= throw_offset && throw_offset <= cs_offset + cs_length
if actions.includes? LibUnwind::Action::SEARCH_PHASE
- # puts "found"
+ puts "found"
return LibUnwind::ReasonCode::HANDLER_FOUND
end
if actions.includes? LibUnwind::Action::HANDLER_FRAME
- LibUnwind.set_gr(context, LibUnwind::EH_REGISTER_0, exception_object.address)
- LibUnwind.set_gr(context, LibUnwind::EH_REGISTER_1, exception_object.value.exception_type_id)
- LibUnwind.set_ip(context, start + cs_addr)
- # puts "install"
+ #{% if flag?(:arm) %}
+ # __crystal_unwind_set_gr(context, LibUnwind::EH_REGISTER_0, exception_object.address.to_u32)
+ # __crystal_unwind_set_gr(context, LibUnwind::EH_REGISTER_1, exception_object.value.exception_type_id.to_u32)
+ # __crystal_unwind_set_ip(context, start + cs_addr)
+ #{% else %}
+ LibUnwind.set_gr(context, LibUnwind::EH_REGISTER_0, exception_object.address)
+ LibUnwind.set_gr(context, LibUnwind::EH_REGISTER_1, exception_object.value.exception_type_id)
+ LibUnwind.set_ip(context, start + cs_addr)
+ #{% end %}
+ puts "install"
return LibUnwind::ReasonCode::INSTALL_CONTEXT
end
end
end
end
- # puts "continue"
+ puts "continue"
return LibUnwind::ReasonCode::CONTINUE_UNWIND
end
@@ -95,18 +111,13 @@ fun __crystal_get_exception(unwind_ex : LibUnwind::Exception*) : UInt64
end
def raise(ex : Exception) : NoReturn
- {% if flag?(:arm) %}
- puts "UNRAISED EXCEPTION: #{ex.message} (#{ex.class.name})"
- LibC.exit(-1)
- {% else %}
- ex.callstack = CallStack.new
- unwind_ex = Pointer(LibUnwind::Exception).malloc
- unwind_ex.value.exception_class = LibC::SizeT.zero
- unwind_ex.value.exception_cleanup = LibC::SizeT.zero
- unwind_ex.value.exception_object = ex.object_id
- unwind_ex.value.exception_type_id = ex.crystal_type_id
- __crystal_raise(unwind_ex)
- {% end %}
+ ex.callstack = CallStack.new
+ unwind_ex = Pointer(LibUnwind::Exception).malloc
+ unwind_ex.value.exception_class = LibC::SizeT.zero
+ unwind_ex.value.exception_cleanup = LibC::SizeT.zero
+ unwind_ex.value.exception_object = ex.object_id
+ unwind_ex.value.exception_type_id = ex.crystal_type_id
+ __crystal_raise(unwind_ex)
end
def raise(message : String) : NoReturn
diff --git a/src/unwind.cr b/src/unwind.cr
index f494545..19a2541 100644
--- a/src/unwind.cr
+++ b/src/unwind.cr
@@ -1,12 +1,26 @@
+{% if flag?(:arm) %}
+ @[Link("unwind")]
+{% end %}
lib LibUnwind
- struct Exception
- exception_class : LibC::SizeT
- exception_cleanup : LibC::SizeT
- private1 : UInt64
- private2 : UInt64
- exception_object : UInt64
- exception_type_id : Int32
- end
+ {% if flag?(:arm) %}
+ struct Exception
+ exception_class : UInt64
+ exception_cleanup : LibC::SizeT
+ private1 : LibC::ULong
+ private2 : LibC::ULong
+ exception_object : UInt64
+ exception_type_id : Int32
+ end
+ {% else %}
+ struct Exception
+ exception_class : LibC::SizeT
+ exception_cleanup : LibC::SizeT
+ private1 : UInt64
+ private2 : UInt64
+ exception_object : UInt64
+ exception_type_id : Int32
+ end
+ {% end %}
@[Flags]
enum Action
@@ -39,11 +53,81 @@ lib LibUnwind
alias Context = Void*
- fun raise_exception = _Unwind_RaiseException(ex : Exception*) : ReasonCode
- fun get_region_start = _Unwind_GetRegionStart(Context) : LibC::SizeT
- fun get_ip = _Unwind_GetIP(Context) : LibC::SizeT
- fun set_ip = _Unwind_SetIP(context : Context, ip : LibC::SizeT) : LibC::SizeT
- fun set_gr = _Unwind_SetGR(context : Context, index : Int32, value : LibC::SizeT)
- fun get_language_specific_data = _Unwind_GetLanguageSpecificData(Context) : UInt8*
- fun backtrace = _Unwind_Backtrace((Context, Void*) -> ReasonCode, Void*) : Int32
+ {% if flag?(:arm) %}
+ fun raise_exception = __libunwind_Unwind_RaiseException(ex : Exception*) : ReasonCode
+ fun get_region_start = __libunwind_Unwind_GetRegionStart(Context) : LibC::SizeT
+ fun get_ip = __libunwind_Unwind_GetIP(Context) : LibC::SizeT
+ fun set_ip = __libunwind_Unwind_SetIP(context : Context, ip : LibC::SizeT) : LibC::SizeT
+ fun set_gr = __libunwind_Unwind_SetGR(context : Context, index : Int32, value : LibC::SizeT)
+ fun get_language_specific_data = __libunwind_Unwind_GetLanguageSpecificData(Context) : UInt8*
+ fun backtrace = __libunwind_Unwind_Backtrace((Context, Void*) -> ReasonCode, Void*) : Int32
+ {% else %}
+ fun raise_exception = _Unwind_RaiseException(ex : Exception*) : ReasonCode
+ fun get_region_start = _Unwind_GetRegionStart(Context) : LibC::SizeT
+ fun get_ip = _Unwind_GetIP(Context) : LibC::SizeT
+ fun set_ip = _Unwind_SetIP(context : Context, ip : LibC::SizeT) : LibC::SizeT
+ fun set_gr = _Unwind_SetGR(context : Context, index : Int32, value : LibC::SizeT)
+ fun get_language_specific_data = _Unwind_GetLanguageSpecificData(Context) : UInt8*
+ fun backtrace = _Unwind_Backtrace((Context, Void*) -> ReasonCode, Void*) : Int32
+ {% end %}
+
+ #{% if flag?(:arm) %}
+ # enum UVRSC
+ # CORE = 0
+ # VFP = 1
+ # WMMXD = 3
+ # WMMXC = 4
+ # end
+ #
+ # enum UVRSD
+ # UINT32 = 0
+ # VFPX = 1
+ # UINT64 = 3
+ # FLOAT = 4
+ # DOUBLE = 5
+ # end
+ #
+ # enum UVRSR
+ # OK = 0,
+ # NOT_IMPLEMENTED = 1,
+ # FAILED = 2
+ # end
+ #
+ # fun vrs_get = _Unwind_VRS_Get(context : Context, regclass : UVRSC, regno : UInt32, representation : UVRSD, valuep : Void*) : UVRSR
+ # fun vrs_set = _Unwind_VRS_Set(context : Context, regclass : UVRSC, regno : UInt32, representation : UVRSD, valuep : Void*) : UVRSR
+ #{% else %}
+ # fun get_ip = _Unwind_GetIP(Context) : LibC::SizeT
+ # fun set_ip = _Unwind_SetIP(context : Context, ip : LibC::SizeT) : LibC::SizeT
+ # fun set_gr = _Unwind_SetGR(context : Context, index : Int32, value : LibC::SizeT)
+ #{% end %}
end
+
+#{% if flag?(:arm) %}
+# # :nodoc:
+# @[AlwaysInline]
+# fun __crystal_unwind_get_gr(context : LibUnwind::Context, index : Int32) : UInt32
+# value = 0_u32
+# LibUnwind.vrs_get(context, LibUnwind::UVRSC::CORE, index.to_u32, LibUnwind::UVRSD::UINT32, pointerof(value).as(Void*))
+# value
+# end
+#
+# # :nodoc:
+# @[AlwaysInline]
+# fun __crystal_unwind_set_gr(context : LibUnwind::Context, index : Int32, value : UInt32) : Void
+# LibUnwind.vrs_set(context, LibUnwind::UVRSC::CORE, index.to_u32, LibUnwind::UVRSD::UINT32, pointerof(value).as(Void*))
+# end
+#
+# # :nodoc:
+# @[AlwaysInline]
+# fun __crystal_unwind_get_ip(context : LibUnwind::Context) : LibC::UInt
+# # remove the thumb-bit before returning
+# __crystal_unwind_get_gr(context, 15) & (~0x1_u32)
+# end
+#
+# # :nodoc:
+# @[AlwaysInline]
+# fun __crystal_unwind_set_ip(context : LibUnwind::Context, ip : UInt32) : Void
+# thumb_bit = __crystal_unwind_get_gr(context, 15) & (0x1_u32)
+# __crystal_unwind_set_gr(context, 15, ip | thumb_bit)
+# end
+#{% end %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment