Created
October 17, 2016 13:29
-
-
Save ysbaddaden/67a2a4ab9c076aa96aa886f5f3d9a06b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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