12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250 |
- {
- This file is part of the Free Pascal run time library.
- Translated to Pascal by Jonas Maebe,
- member of the Free Pascal development team
- This file is based on the source code of libsupc++ from GCC 4.2.1.
- See below for details about the copyright. While it is GPLv2 rather
- than LGPLv2 like the rest of the FPC RTL, it has the same linking
- exception as the rest of the FPC RTL and hence it can be used in the
- same way.
- **********************************************************************}
- // -*- C++ -*- The GNU C++ exception personality routine.
- // Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
- //
- // This file is part of GCC.
- //
- // GCC is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2, or (at your option)
- // any later version.
- //
- // GCC is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with GCC; see the file COPYING. If not, write to
- // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- // Boston, MA 02110-1301, USA.
- // As a special exception, you may use this file as part of a free software
- // library without restriction. Specifically, if other files instantiate
- // templates or use macros or inline functions from this file, or you compile
- // this file and link it with other files to produce an executable, this
- // file does not by itself cause the resulting executable to be covered by
- // the GNU General Public License. This exception does not however
- // invalidate any other reasons why the executable file might be covered by
- // the GNU General Public License.
- {$packrecords c}
- {$ifdef linux}
- {$linklib c}
- {$linklib libgcc_s}
- {$endif}
- {$ifdef __ARM_EABI_UNWINDER__}
- {$define PSABIEH_NO_SIZEOF_ENCODED_VALUE}
- {$endif}
- function FPC_psabieh_GetExceptionWrapper(exceptionObject: PFPC_Unwind_Exception): PExceptObject; inline;
- begin
- { go to end of the wrapped exception (it's the last field in PFPC_Unwind_Exception), then to the start }
- result:=PExceptObject(exceptionObject+1)-1;
- end;
- function _Unwind_Resume_or_Rethrow (context:PFPC_Unwind_Context): FPC_Unwind_Reason_Code;cdecl;external;
- procedure _Unwind_DeleteException(context:PFPC_Unwind_Context);cdecl;external;
- function _Unwind_GetRegionStart(context:PFPC_Unwind_Context):PtrUInt;cdecl;external;
- function _Unwind_GetLanguageSpecificData(context:PFPC_Unwind_Context):PtrUInt;cdecl;external;
- function _Unwind_GetDataRelBase(context:PFPC_Unwind_Context):PtrUInt;cdecl;external;
- function _Unwind_GetTextRelBase(context:PFPC_Unwind_Context):PtrUInt;cdecl;external;
- {$ifdef __ARM_EABI_UNWINDER__}
- procedure _Unwind_Complete(exceptionObject: PFPC_Unwind_Exception);cdecl;external;
- function __gnu_unwind_frame(exception:PFPC_Unwind_Exception;context:PFPC_Unwind_Context):FPC_Unwind_Reason_Code;cdecl;external;
- type
- FPC_Unwind_VRS_RegClass = UInt32;
- const
- FPC_UVRSC_CORE = FPC_Unwind_VRS_RegClass(0); // integer register
- FPC_UVRSC_VFP = FPC_Unwind_VRS_RegClass(1); // vfp
- FPC_UVRSC_FPA = FPC_Unwind_VRS_RegClass(2); // fpa
- FPC_UVRSC_WMMXD = FPC_Unwind_VRS_RegClass(3); // Intel WMMX data register
- FPC_UVRSC_WMMXC = FPC_Unwind_VRS_RegClass(4); // Intel WMMX control register
- type
- FPC_Unwind_VRS_DataRepresentation = UInt32;
- const
- FPC_UVRSD_UINT32 = FPC_Unwind_VRS_DataRepresentation(0);
- FPC_UVRSD_VFPX = FPC_Unwind_VRS_DataRepresentation(1);
- FPC_UVRSD_FPAX = FPC_Unwind_VRS_DataRepresentation(2);
- FPC_UVRSD_UINT64 = FPC_Unwind_VRS_DataRepresentation(3);
- FPC_UVRSD_FLOAT = FPC_Unwind_VRS_DataRepresentation(4);
- FPC_UVRSD_DOUBLE = FPC_Unwind_VRS_DataRepresentation(5);
- type
- FPC_Unwind_VRS_Result = UInt32;
- const
- FPC_UVRSR_OK = FPC_Unwind_VRS_Result(0);
- FPC_UVRSR_NOT_IMPLEMENTED = FPC_Unwind_VRS_Result(1);
- FPC_UVRSR_FAILED = FPC_Unwind_VRS_Result(2);
- Function _Unwind_VRS_Set(context: PFPC_Unwind_Context; regclass: FPC_Unwind_VRS_RegClass;
- regnr: PTRUint {uw}; repr: FPC_Unwind_VRS_DataRepresentation;
- value: pointer): FPC_Unwind_VRS_Result; cdecl; external;
- function _Unwind_VRS_Get(context: PFPC_Unwind_Context; regclass: FPC_Unwind_VRS_RegClass;
- regnr: PTRUint {uw}; repr: FPC_Unwind_VRS_DataRepresentation;
- value: pointer): FPC_Unwind_VRS_Result; cdecl; external;
- procedure _Unwind_SetGR(context:PFPC_Unwind_Context;index:cint; new_value:PtrUInt); inline;
- begin
- _Unwind_VRS_Set(context,FPC_UVRSC_CORE, index, FPC_UVRSD_UINT32, @new_Value);
- end;
- function _Unwind_GetGR(context:PFPC_Unwind_Context;index:cint):PtrUInt; inline;
- begin
- _Unwind_VRS_Get(context,FPC_UVRSC_CORE, index, FPC_UVRSD_UINT32, @result);
- end;
- procedure _Unwind_SetIP(context:PFPC_Unwind_Context;new_value:PtrUInt); inline;
- begin
- _Unwind_SetGR(context,15,new_value or (_Unwind_GetGR(context,15) and 1));
- end;
- function _Unwind_GetIP(context:PFPC_Unwind_Context):PtrUInt;cdecl; inline;
- begin
- result:=_Unwind_GetGR(context,15) and not(1);
- end;
- {$else}
- function _Unwind_GetGR(context:PFPC_Unwind_Context; index:cint):PtrUInt;cdecl;external;
- procedure _Unwind_SetGR(context:PFPC_Unwind_Context; index:cint; new_value:PtrUInt);cdecl;external;
- function _Unwind_GetIP(context:PFPC_Unwind_Context):PtrUInt;cdecl;external;
- procedure _Unwind_SetIP(context:PFPC_Unwind_Context; new_value:PtrUInt);cdecl;external;
- {$endif}
- procedure DoUnHandledException; forward;
- { _Unwind_Backtrace() is a gcc extension that walks the stack and calls the }
- { _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack }
- { or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON. }
- { }
- type
- FPC_Unwind_Trace_Fn = function (_para1:PFPC_Unwind_Context; _para2:pointer):FPC_Unwind_Reason_Code;cdecl;
- function _Unwind_Backtrace(_para1:FPC_Unwind_Trace_Fn; _para2:pointer):FPC_Unwind_Reason_Code;cdecl;weakexternal;
- { _Unwind_GetCFA is a gcc extension that can be called from within a personality }
- { handler to get the CFA (stack pointer before call) of current frame. }
- { }
- function _Unwind_GetCFA(_para1:PFPC_Unwind_Context):PtrUInt;cdecl;weakexternal;
- const
- DW_EH_PE_absptr = $00;
- DW_EH_PE_omit = $ff;
- DW_EH_PE_uleb128 = $01;
- DW_EH_PE_udata2 = $02;
- DW_EH_PE_udata4 = $03;
- DW_EH_PE_udata8 = $04;
- DW_EH_PE_sleb128 = $09;
- DW_EH_PE_sdata2 = $0A;
- DW_EH_PE_sdata4 = $0B;
- DW_EH_PE_sdata8 = $0C;
- DW_EH_PE_signed = $08;
- DW_EH_PE_pcrel = $10;
- DW_EH_PE_textrel = $20;
- DW_EH_PE_datarel = $30;
- DW_EH_PE_funcrel = $40;
- DW_EH_PE_aligned = $50;
- DW_EH_PE_indirect = $80;
- {$ifndef PSABIEH_NO_SIZEOF_ENCODED_VALUE}
- function FPC_psabieh_size_of_encoded_value(encoding: byte): longint;
- begin
- if encoding = DW_EH_PE_omit then
- exit(0);
- case (encoding and 7) of
- DW_EH_PE_absptr:
- exit(sizeof(pointer));
- DW_EH_PE_udata2:
- exit(2);
- DW_EH_PE_udata4:
- exit(4);
- DW_EH_PE_udata8:
- exit(8);
- else
- begin
- {$ifdef excdebug}
- writeln('Unsupported encoding: $', hexstr(encoding,sizeof(encoding)*2));
- {$endif}
- halt(217);
- end;
- end
- end;
- {$endif PSABIEH_NO_SIZEOF_ENCODED_VALUE}
- { Given an encoding and an _Unwind_Context, return the base to which
- the encoding is relative. This base may then be passed to
- read_encoded_value_with_base for use when the _Unwind_Context is
- not available. }
- function FPC_psabieh_base_of_encoded_value (encoding: byte; context: PFPC_Unwind_Context): PtrUInt;
- begin
- if encoding = DW_EH_PE_omit then
- exit(0);
- case (encoding and $70) of
- DW_EH_PE_absptr,
- DW_EH_PE_pcrel,
- DW_EH_PE_aligned:
- exit(0);
- DW_EH_PE_textrel:
- exit(_Unwind_GetTextRelBase(context));
- DW_EH_PE_datarel:
- exit(_Unwind_GetDataRelBase(context));
- DW_EH_PE_funcrel:
- exit(_Unwind_GetRegionStart(context));
- else
- begin
- {$ifdef excdebug}
- writeln('Unsupported base of encoding: $', hexstr(encoding,sizeof(encoding)*2));
- {$endif}
- halt(217);
- end;
- end;
- end;
- function fpc_read_uleb128 (p: PByte; out val: PTRUInt): PByte;
- var
- shift: longint;
- b: byte;
- res: PtrUInt;
- begin
- shift:=0;
- res:=0;
- repeat
- b:=p^;
- inc(p);
- res:=res or (PtrUInt(b and $7f) shl shift);
- inc(shift,7);
- until (b and $80)=0;
- val:=res;
- result:=p;
- end;
- function fpc_read_sleb128 (p: PByte; out val: PtrInt): PByte;
- var
- shift: longint;
- b: byte;
- res: PtrUInt;
- begin
- shift:=0;
- res:=0;
- repeat
- b:=p^;
- inc(p);
- res:=res or (PtrUInt(b and $7f) shl shift);
- inc(shift,7);
- until (b and $80)=0;
- if (shift<8*(sizeof(res))) and
- ((b and $40)<>0) then
- res:=res or -(PtrUInt(1) shl shift);
- val:=PTRInt(res);
- result:=p;
- end;
- function FPC_psabieh_read_encoded_value_with_base (encoding: byte; base: PtrUInt; p: PByte; out val: PtrUInt): PByte;
- var
- res: PtrUInt;
- tmpres: PtrInt;
- alignedp: PPtrUint;
- begin
- if encoding=DW_EH_PE_aligned then
- begin
- alignedp:=PPtrUint(align(PtrUInt(p),sizeof(PtrUint)));
- res:=alignedp^;
- result:=PByte(alignedp)+sizeof(PtrUInt);
- end
- else
- begin
- case encoding and $0f of
- DW_EH_PE_absptr:
- begin
- res:=unaligned(PPtrUint(p)^);
- result:=p+sizeof(PtrUInt);
- end;
- DW_EH_PE_uleb128:
- begin
- result:=fpc_read_uleb128(p,res);
- end;
- DW_EH_PE_sleb128:
- begin
- result:=fpc_read_sleb128(p,tmpres);
- res:=PtrUInt(tmpres);;
- end;
- DW_EH_PE_udata2:
- begin
- res:=unaligned(pword(p)^);
- result:=p+2;
- end;
- DW_EH_PE_udata4:
- begin
- res:=unaligned(pdword(p)^);
- result:=p+4;
- end;
- DW_EH_PE_udata8:
- begin
- res:=unaligned(pqword(p)^);
- result:=p+8;
- end;
- DW_EH_PE_sdata2:
- begin
- res:=PtrUInt(unaligned(psmallint(p)^));
- result:=p+2;
- end;
- DW_EH_PE_sdata4:
- begin
- res:=PtrUInt(unaligned(plongint(p)^));
- result:=p+4;
- end;
- DW_EH_PE_sdata8:
- begin
- res:=PtrUInt(unaligned(pint64(p)^));
- result:=p+8;
- end;
- else
- begin
- {$ifdef excdebug}
- writeln('Unsupported encoding of value with base: $', hexstr(encoding,sizeof(encoding)*2));
- {$endif}
- halt(217);
- end;
- end;
- if res<>0 then
- begin
- if (encoding and $70)=DW_EH_PE_pcrel then
- inc(res,PtrUInt(p))
- else
- inc(res, base);
- if (encoding and DW_EH_PE_indirect)<>0 then
- res:=PPtrUInt(res)^;
- end;
- end;
- val:=res;
- end;
- function FPC_psabieh_read_encoded_value (context: PFPC_Unwind_Context; encoding: byte; p: PByte; out val: PtrUInt): PByte; inline;
- begin
- result:=FPC_psabieh_read_encoded_value_with_base(encoding,FPC_psabieh_base_of_encoded_value(encoding,context),p,val);
- end;
- type
- FPC_psabieh_lsda_header_info = record
- Start: PtrUInt;
- LPStart: PtrUInt;
- ttype_base: PtrUInt;
- TType: Pointer;
- action_table: pointer;
- ttype_encoding: byte;
- call_site_encoding: byte;
- end;
- function FPC_psabieh_parse_lsda_header(context: PFPC_Unwind_Context; p: PByte; out info: FPC_psabieh_lsda_header_info): PByte;
- var
- tmp: PTRUint;
- lpstart_encoding: byte;
- begin
- if assigned(context) then
- info.Start:=_Unwind_GetRegionStart(context)
- else
- info.Start:=0;
- // Find @LPStart, the base to which landing pad offsets are relative.
- lpstart_encoding:=p^;
- inc(p);
- if lpstart_encoding<>DW_EH_PE_omit then
- p:=FPC_psabieh_read_encoded_value(context,lpstart_encoding,p,info.LPStart)
- else
- info.LPStart:=info.Start;
- // Find @TType, the base of the handler and exception spec type data.
- info.ttype_encoding:=p^;
- inc(p);
- if info.ttype_encoding<>DW_EH_PE_omit then
- begin
- p:=fpc_read_uleb128(p,tmp);
- info.TType:=p+tmp;
- end
- else
- info.TType:=nil;
- // The encoding and length of the call-site table; the action table
- // immediately follows.
- info.call_site_encoding:=p^;
- inc(p);
- p:=fpc_read_uleb128(p,tmp);
- info.action_table:=p+tmp;
- {$ifdef excdebug}
- writeln('lsda header');
- writeln(' * start: $',hexstr(info.start,sizeof(info.start)*2));
- writeln(' * lp_start encoding: $',hexstr(lpstart_encoding,sizeof(lpstart_encoding)*2));
- writeln(' * lp_start: $',hexstr(info.LPStart,sizeof(info.LPStart)*2));
- writeln(' * ttype_encoding: $',hexstr(info.ttype_encoding,sizeof(info.ttype_encoding)*2));
- writeln(' * ttype base: $',hexstr(info.TType));
- writeln(' * call_site_encoding: $',hexstr(info.call_site_encoding,sizeof(info.call_site_encoding)*2));
- writeln(' * action table: $', hexstr(p),' (offset: ',tmp,')');
- {$endif}
- result:=p;
- end;
- {$ifdef __ARM_EABI_UNWINDER__}
- function FPC_psabieh_Unwind_decode_target2(ptr: PtrUInt {_Unwind_Word}): PtrUInt {_Unwind_Word}; inline;
- begin
- result:=PPtrUInt(ptr)^;
- // Zero values are always NULL.
- if result<>0 then
- begin
- {$if defined(linux) or defined(netbsd)}
- // Pc-relative indirect.
- inc(result,ptr);
- result:=PPtrUint(result)^;
- {$else}
- // Pc-relative pointer.
- inc(result,ptr);
- {$endif}
- end;
- end;
- {$endif __ARM_EABI_UNWINDER__}
- // Return an element from a type table.
- {$ifdef __ARM_EABI_UNWINDER__}
- function FPC_psabieh_get_ttype_entry(const info: FPC_psabieh_lsda_header_info; i: PtrUInt {_Unwind_Word}): TClass;
- var
- ptr: PtrUInt {_Unwind_Word};
- begin
- ptr:=PtrUInt(info.TType)-(i*4);
- ptr:=FPC_psabieh_Unwind_decode_target2(ptr);
- result:=TClass(ptr);
- end;
- {$else}
- function FPC_psabieh_get_ttype_entry(const info: FPC_psabieh_lsda_header_info; i: PtrUInt): TClass;
- var
- ptr: PtrUInt;
- begin
- i:=i*FPC_psabieh_size_of_encoded_value(info.ttype_encoding);
- FPC_psabieh_read_encoded_value_with_base(info.ttype_encoding,info.ttype_base,info.TType-i,ptr);
- result:=TClass(ptr);
- end;
- {$endif}
- // Return true if THROW_TYPE matches one if the filter types.
- function FPC_psabieh_check_exception_spec(const info: FPC_psabieh_lsda_header_info; thrown: TObject; filter_value: PtrInt): boolean;
- var
- e: PByte;
- catch_type: TClass;
- tmp: PtrUInt;
- begin
- e:=info.TType - filter_value - 1;
- repeat
- e:=fpc_read_uleb128(e,tmp);
- // Zero signals the end of the list. If we've not found
- // a match by now, then we've failed the specification.
- if tmp=0 then
- exit(false);
- {$ifdef __ARM_EABI_UNWINDER__}
- tmp:=FPC_psabieh_Unwind_decode_target2(PtrUInt(e)); {_Unwind_Word}
- {$endif}
- // Match a ttype entry.
- catch_type:=FPC_psabieh_get_ttype_entry(info,tmp);
- until thrown is catch_type;
- result:=true;
- end;
- {$ifdef __ARM_EABI_UNWINDER__}
- // Save stage1 handler information in the exception object
- procedure FPC_psabieh_save_caught_exception(ue_header: PFPC_Unwind_Exception;
- context: PFPC_Unwind_Context;
- handler_switch_value: longint;
- language_specific_data: PByte;
- landing_pad: PtrUInt);
- begin
- with ue_header^.barrier_cache do
- begin
- sp:=_Unwind_GetGR(context,13);
- { bitpattern[0] is assigned but never used in the original code }
- bitpattern[1]:=handler_switch_value;
- bitpattern[2]:=PtrUInt(language_specific_data);
- bitpattern[3]:=landing_pad;
- end;
- end;
- // Restore the catch handler information saved during phase1.
- procedure FPC_psabieh_restore_caught_exception(ue_header: PFPC_Unwind_Exception;
- out handler_switch_value: longint;
- out language_specific_data: PByte;
- out landing_pad: PtrUInt);
- begin
- with ue_header^.barrier_cache do
- begin
- handler_switch_value:=longint(bitpattern[1]);
- language_specific_data:=PByte(bitpattern[2]);
- landing_pad:=bitpattern[3];
- end;
- end;
- {$else __ARM_EABI_UNWINDER__}
- // Save stage1 handler information in the exception object
- procedure FPC_psabieh_save_caught_exception(ue_header: PFPC_Unwind_Exception;
- context: PFPC_Unwind_Context;
- handler_switch_value: longint;
- language_specific_data: PByte;
- landing_pad: PtrUInt);
- var
- xh: PExceptObject;
- begin
- xh:=FPC_psabieh_GetExceptionWrapper(ue_header);
- xh^.handler_switch_value:=handler_switch_value;
- xh^.language_specific_data:=language_specific_data;
- xh^.landing_pad:=landing_pad;
- end;
- // Restore the catch handler information saved during phase1.
- procedure FPC_psabieh_restore_caught_exception(ue_header: PFPC_Unwind_Exception;
- out handler_switch_value: longint;
- out language_specific_data: PByte;
- out landing_pad: PtrUInt);
- var
- xh: PExceptObject;
- begin
- xh:=FPC_psabieh_GetExceptionWrapper(ue_header);
- handler_switch_value:=xh^.handler_switch_value;
- language_specific_data:=xh^.language_specific_data;
- landing_pad:=xh^.landing_pad;
- end;
- {$endif __ARM_EABI_UNWINDER__}
- function FPC_psabieh_find_action_record(const info: FPC_psabieh_lsda_header_info; var p: PByte; const ip: PTRUint; var landing_pad: PtrUInt; var action_record: PByte): boolean;
- var
- cs_start, cs_len, cs_lp: PtrUint{_Unwind_Ptr};
- cs_action: PtrUInt {_Unwind_Word};
- begin
- result:=false;
- {$ifdef excdebug}
- writeln('find action record start: p: $',hexstr(p),'; lsda covered code start: $',hexstr(info.Start,sizeof(info.start)*2),'; lsda action table: $',hexstr(info.action_table),'; lsda call site encoding: $',hexstr(info.call_site_encoding,2),'; ip: $', hexstr(ip,sizeof(ip)*2));
- {$endif}
- while (p<info.action_table) do
- begin
- // Note that all call-site encodings are "absolute" displacements.
- p:=FPC_psabieh_read_encoded_value (nil, info.call_site_encoding, p, cs_start);
- p:=FPC_psabieh_read_encoded_value (nil, info.call_site_encoding, p, cs_len);
- p:=FPC_psabieh_read_encoded_value (nil, info.call_site_encoding, p, cs_lp);
- p:=FPC_read_uleb128 (p, &cs_action);
- {$ifdef excdebug}
- writeln('find action record: cs_start: $',hexstr(cs_start,sizeof(cs_start)*2),', len: ',cs_len,
- ' (ip=$',hexstr(info.Start+cs_start,sizeof(PtrUInt)*2),'...$',hexstr(info.Start+cs_start+cs_len,sizeof(PtrUInt)*2),')',
- ', lp: ', cs_lp,' action ofs: ',cs_action);
- {$endif}
- // The table is sorted, so if we've passed the ip, stop.
- if ip<info.Start+cs_start then
- p:=info.action_table
- else if (ip<(info.Start+cs_start+cs_len)) then
- begin
- if cs_lp<>0 then
- landing_pad:=info.LPStart+cs_lp;
- if cs_action<>0 then
- action_record:=info.action_table+cs_action-1;
- {$ifdef excdebug}
- writeln('action record result: action_record: $',hexstr(cs_start,sizeof(cs_start)*2),', len: ',cs_len,', lp: ', cs_lp,
- ',landing_pad: $',hexstr(landing_pad,sizeof(landing_pad)*2));
- {$endif}
- result:=true;
- exit;
- end;
- end;
- {$ifdef excdebug}
- writeln('find action record failed');
- {$endif}
- end;
- // Return true if the filter spec is empty, ie throw().
- function fpc_psabieh_empty_exception_spec(const info: FPC_psabieh_lsda_header_info; const filter_value: PtrInt {_Unwind_Sword}): boolean;
- var
- e: PByte;
- tmp: PtrUInt;
- begin
- e:=PByte(info.ttype - filter_value - 1);
- e:=fpc_read_uleb128(e,tmp);
- result:=tmp = 0;
- end;
- type
- FPC_psabieh_found_handler_type = (
- found_nothing,
- found_terminate,
- found_cleanup,
- found_handler
- );
- function FPC_psabieh_find_handler(const info: FPC_psabieh_lsda_header_info; const foreign_exception: boolean; actions: FPC_Unwind_Action; thrown: TObject; var action_record: PByte; var handler_switch_value: longint): FPC_psabieh_found_handler_type;
- var
- ar_filter, ar_disp: PtrInt;
- catch_type: TClass;
- throw_type: TOBject;
- saw_cleanup, saw_handler: boolean;
- p: PByte;
- begin
- saw_cleanup:=false;
- saw_handler:=false;
- // During forced unwinding, we only run cleanups. With a foreign
- // exception class, there's no exception type.
- if ((actions and FPC_UA_FORCE_UNWIND)<>0) or
- foreign_exception then
- throw_type:=nil
- else
- throw_type:=thrown;
- while true do
- begin
- p:=action_record;
- p:=fpc_read_sleb128(p,ar_filter);
- fpc_read_sleb128(p,ar_disp);
- if ar_filter=0 then
- begin
- // Zero filter values are cleanups.
- saw_cleanup:=true;
- end
- else if ar_filter>0 then
- begin
- // Positive filter values are handlers.
- catch_type:=FPC_psabieh_get_ttype_entry(info,ar_filter);
- // Null catch type is a catch-all handler; we can catch foreign
- // exceptions with this. Otherwise we must match types.
- if not assigned(catch_type) or
- (assigned(throw_type) and
- (throw_type is catch_type)) then
- begin
- saw_handler:=true;
- break;
- end
- end
- else
- begin
- // Negative filter values are exception specifications.
- // ??? How do foreign exceptions fit in? As far as I can
- // see we can't match because there's no __cxa_exception
- // object to stuff bits in for __cxa_call_unexpected to use.
- // Allow them iff the exception spec is non-empty. I.e.
- // a throw() specification results in __unexpected.
- if (assigned(throw_type) and
- not FPC_psabieh_check_exception_spec(info,thrown,ar_filter)) or
- (not assigned(throw_type) and
- FPC_psabieh_empty_exception_spec(info,ar_filter)) then
- begin
- saw_handler:=true;
- break;
- end;
- end;
- if ar_disp=0 then
- break;
- action_record:=p+ar_disp;
- end;
- if saw_handler then
- begin
- handler_switch_value:=ar_filter;
- result:=found_handler;
- end
- else
- begin
- if saw_cleanup then
- result:=found_cleanup
- else
- result:=found_nothing;
- end;
- end;
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- procedure __gxx_personality_v0(version: cint; actions: FPC_Unwind_Action; exceptionClass: cuint64; libunwind_exception: PFPC_Unwind_Exception; context: PFPC_Unwind_Context); cdecl; external;
- {$endif FPC_PSABIEH_CPLUSPLUSSUPPORT}
- {$ifdef __ARM_EABI_UNWINDER__}
- function continue_unwinding(libunwind_exception: PFPC_Unwind_Exception; context: PFPC_Unwind_Context): FPC_Unwind_Reason_Code; inline;
- begin
- if __gnu_unwind_frame(libunwind_exception, context)<>FPC_URC_OK then
- result:=FPC_URC_FAILURE
- else
- result:=FPC_URC_CONTINUE_UNWIND;
- end;
- function _FPC_psabieh_personality_v0(state: FPC_Unwind_State; libunwind_exception: PFPC_Unwind_Exception; context: PFPC_Unwind_Context): FPC_Unwind_Reason_Code; cdecl;
- {$else}
- function continue_unwinding(libunwind_exception: PFPC_Unwind_Exception; context: PFPC_Unwind_Context): FPC_Unwind_Reason_Code; inline;
- begin
- result:=FPC_URC_CONTINUE_UNWIND;
- end;
- function _FPC_psabieh_personality_v0(version: longint; actions: FPC_Unwind_Action; exceptionClass: qword; libunwind_exception: PFPC_Unwind_Exception; context: PFPC_Unwind_Context): FPC_Unwind_Reason_Code; cdecl;
- {$endif}
- var
- WrappedException: PExceptObject;
- found_type: FPC_psabieh_found_handler_type;
- info: FPC_psabieh_lsda_header_info;
- language_specific_data: PByte;
- action_record: PByte;
- p: PByte;
- landing_pad, ip: PtrUInt; { _Unwind_Ptr }
- handler_switch_value: longint;
- foreign_exception: boolean;
- {$ifdef __ARM_EABI_UNWINDER__}
- actions: FPC_Unwind_Action;
- {$endif}
- begin
- {$ifdef __ARM_EABI_UNWINDER__}
- { convert the state flags to FPC_Unwind_Action flags so we can share the rest of the code }
- case (state and FPC_US_ACTION_MASK) of
- FPC_US_VIRTUAL_UNWIND_FRAME:
- begin
- actions:=FPC_UA_SEARCH_PHASE;
- end;
- FPC_US_UNWIND_FRAME_STARTING:
- begin
- actions:=FPC_UA_CLEANUP_PHASE;
- if ((state and FPC_US_FORCE_UNWIND)<>0) and
- (libunwind_exception^.barrier_cache.sp=_Unwind_GetGR(context,13)) then
- actions:=actions or FPC_UA_HANDLER_FRAME;
- end;
- FPC_US_UNWIND_FRAME_RESUME:
- begin
- result:=continue_unwinding(libunwind_exception,context);
- exit;
- end;
- end;
- actions:=actions or (state and FPC_US_FORCE_UNWIND);
- // The dwarf unwinder assumes the context structure holds things like the
- // function and LSDA pointers. The ARM implementation caches these in
- // the exception header (UCB). To avoid rewriting everything we make the
- // virtual IP register point at the UCB.
- ip:=PtrUInt(libunwind_exception);
- _Unwind_SetGR(context, 12, ip);
- { foreign exception type -> let c++ runtime handle it }
- foreign_exception:=libunwind_exception^.exception_class<>FPC_psabieh_exceptionClass_ID.u;
- {$else __ARM_EABI_UNWINDER__}
- { unsupported version -> failure }
- if version<>1 then
- begin
- result:=FPC_URC_FATAL_PHASE1_ERROR;
- exit;
- end;
- { foreign exception type -> let c++ runtime handle it }
- foreign_exception:=exceptionClass<>FPC_psabieh_exceptionClass_ID.u;
- {$endif __ARM_EABI_UNWINDER__}
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- if foreign_exception then
- begin
- result:=__gxx_personality_v0(version, actions, exceptionClass, libunwind_exception, context)
- exit;
- end;
- {$endif FPC_PSABIEH_CPLUSPLUSSUPPORT}
- WrappedException:=FPC_psabieh_GetExceptionWrapper(libunwind_exception);
- {$ifdef excdebug}
- writeln('Personality (version = ',{$ifndef __ARM_EABI_UNWINDER__}version{$else}0{$endif},', actions = $',hexstr(actions,4),') started for wrapper ',hexstr(WrappedException),' = fpc exc ',hexstr(WrappedException^.FObject),
- ', refcount is now ',WrappedException^.refcount);
- writeln(' ip=$',hexstr(_Unwind_GetIP(context),sizeof(pointer)*2));
- {$endif}
- // Shortcut for phase 2 found handler for domestic exception.
- if (actions=(FPC_UA_CLEANUP_PHASE or FPC_UA_HANDLER_FRAME)) and
- not foreign_exception then
- begin
- {$ifdef excdebug}
- writeln('restoring caught exception');
- {$endif}
- FPC_psabieh_restore_caught_exception(libunwind_exception,handler_switch_value,
- language_specific_data,landing_pad);
- {$ifdef excdebug}
- writeln('restoring caught exception, landing_pad = $',hexstr(landing_pad,sizeof(landing_pad)*2));
- {$endif}
- if landing_pad<>0 then
- found_type:=found_handler
- else
- found_type:=found_terminate;
- end
- else
- begin
- language_specific_data:=PByte(_Unwind_GetLanguageSpecificData(context));
- // If no LSDA, then there are no handlers or cleanups.
- if not assigned(language_specific_data) then
- begin
- {$ifdef excdebug}
- writeln('did not find lsda for ip $',hexstr(_Unwind_GetIP(context),sizeof(pointer)*2));
- {$endif}
- exit(continue_unwinding(libunwind_exception,context));
- end;
- // Parse the LSDA header.
- p:=FPC_psabieh_parse_lsda_header(context,language_specific_data,info);
- info.ttype_base:=FPC_psabieh_base_of_encoded_value(info.ttype_encoding,context);
- ip:=_Unwind_GetIP(context);
- dec(ip);
- landing_pad:=0;
- action_record:=nil;
- handler_switch_value:=0;
- // Search the call-site table for the action associated with this IP.
- if FPC_psabieh_find_action_record(info,p,ip,landing_pad,action_record) then
- begin
- {$ifdef excdebug}
- writeln('found action record for ip ',hexstr(_Unwind_GetIP(context),sizeof(pointer)*2));
- {$endif}
- if landing_pad=0 then
- begin
- // If ip is present, and has a null landing pad, there are
- // no cleanups or handlers to be run.
- found_type:=found_nothing;
- end
- else if action_record=nil then
- begin
- // If ip is present, has a non-null landing pad, and a null
- // action table offset, then there are only cleanups present.
- // Cleanups use a zero switch value, as set above.
- found_type:=found_cleanup;
- end
- else
- begin
- // Otherwise we have a catch handler or exception specification.
- found_type:=FPC_psabieh_find_handler(info,foreign_exception,actions,WrappedException^.FObject,action_record,handler_switch_value);
- end
- end
- else
- begin
- // If ip is not present in the table, call terminate. This is for
- // a destructor inside a cleanup, or a library routine the compiler
- // was not expecting to throw.
- found_type:=found_terminate;
- end;
- {$ifdef excdebug}
- writeln('find_handler: ',found_type);
- {$endif}
- if found_type=found_nothing then
- exit(continue_unwinding(libunwind_exception,context));
- if (actions and FPC_UA_SEARCH_PHASE)<>0 then
- begin
- if found_type=found_cleanup then
- exit(continue_unwinding(libunwind_exception,context));
- if not foreign_exception then
- begin
- {$ifdef excdebug}
- writeln('saving native exception: $',hexstr(landing_pad,sizeof(landing_pad)*2));
- {$endif}
- // For domestic exceptions, we cache data from phase 1 for phase 2.
- FPC_psabieh_save_caught_exception(libunwind_exception,context,
- handler_switch_value,language_specific_data,
- landing_pad);
- end;
- exit(FPC_URC_HANDLER_FOUND);
- end;
- end;
- if ((actions and FPC_UA_FORCE_UNWIND)<>0) or
- foreign_exception then
- begin
- if found_type=found_terminate then
- begin
- {$ifdef excdebug}
- writeln('foreign exception or force unwind, and found type = found terminate; actions = $',hexstr(actions,sizeof(actions)*2),'; foreign exception ', foreign_exception);
- {$endif}
- DoUnHandledException;
- end
- { can only perform cleanups when force-unwinding }
- else if handler_switch_value<0 then
- begin
- {$ifdef excdebug}
- writeln('foreign exception or force unwind, handler_switch_value < 0: ', handler_switch_value);
- {$endif}
- DoUnHandledException;
- end
- end
- else
- begin
- if found_type=found_terminate then
- begin
- {$ifdef excdebug}
- writeln('native exception and no force unwind, and force_terminate');
- {$endif}
- DoUnHandledException;
- end
- else if handler_switch_value<0 then
- begin
- { C++ calls __cxa_call_unexpected in this case }
- {$ifdef excdebug}
- writeln('native exception and no force unwind, and handler_switch_value<0: ', handler_switch_value);
- {$endif}
- DoUnHandledException;
- end;
- end;
- { For targets with pointers smaller than the word size, we must extend the
- pointer, and this extension is target dependent. }
- {$if sizeof(pointer)<>sizeof(SizeInt)}
- {$error Add support for extending pointer values}
- {$endif}
- {$ifdef excdebug}
- writeln('returning exception $',hexstr(libunwind_exception),' with switch value ',handler_switch_value);
- {$endif}
- _Unwind_SetGR(context,fpc_eh_return_data_regno(0),PtrUInt(libunwind_exception));
- _Unwind_SetGR (context,fpc_eh_return_data_regno(1),handler_switch_value);
- _Unwind_SetIP(context,landing_pad);
- result:=FPC_URC_INSTALL_CONTEXT;
- end;
- //////////////////////////////
- ///// Raising an exception
- //////////////////////////////
- procedure FPC_psabieh_ExceptionCleanUp(reason: FPC_Unwind_Reason_Code; exc:PFPC_Unwind_Exception); cdecl;
- var
- ExceptWrapper: PExceptObject;
- begin
- // If we haven't been caught by a foreign handler, then this is
- // some sort of unwind error. In that case just die immediately.
- // _Unwind_DeleteException in the HP-UX IA64 libunwind library
- // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
- // like the GCC _Unwind_DeleteException function does.
- if (reason<>FPC_URC_FOREIGN_EXCEPTION_CAUGHT) and
- (reason<>FPC_URC_NO_REASON) then
- begin
- {$ifdef excdebug}
- writeln('exception cleanup and reason not foreign exception or no reason, reason = $',hexstr(reason,sizeof(reason)*2));
- {$endif}
- halt(217);
- end;
- ExceptWrapper:=FPC_psabieh_GetExceptionWrapper(exc);
- {$ifdef excdebug}
- writeln('exception cleanup: deleting wrapper ',hexstr(ExceptWrapper),' and fpc exception ',hexstr(ExceptWrapper^.FObject));
- {$endif}
- ExceptWrapper^.FObject.free;
- ExceptWrapper^.FObject:=nil;
- if assigned(ExceptWrapper^.frames) then
- freemem(ExceptWrapper^.frames);
- Dispose(ExceptWrapper);
- end;
- function PushExceptObject(Obj : TObject; AnAddr : CodePointer; AFrame : Pointer): PExceptObject; forward;
- {$define FPC_SYSTEM_HAS_RAISEEXCEPTION}
- procedure fpc_RaiseException(Obj: TObject; AnAddr: CodePointer; AFrame: Pointer); compilerproc;
- var
- _ExceptObjectStack : PExceptObject;
- _ExceptAddrstack : PExceptAddr;
- ExceptWrapper: PExceptObject;
- RaiseResult: FPC_Unwind_Reason_Code;
- begin
- {$ifdef excdebug}
- writeln ('In psabieh RaiseException for object ',hexstr(obj),' of class type ',obj.classname);
- {$endif}
- if ExceptTryLevel<>0 then
- begin
- {$ifdef excdebug}
- writeln('exception while raising exception, aborting');
- {$endif}
- Halt(217);
- end;
- ExceptTryLevel:=1;
- ExceptWrapper:=PushExceptObject(Obj,AnAddr,AFrame);
- ExceptWrapper^.unwind_exception.exception_class:=FPC_psabieh_exceptionClass_ID.u;
- ExceptWrapper^.unwind_exception.exception_cleanup:=@FPC_psabieh_ExceptionCleanUp;
- { if PushExceptObject causes another exception, the following won't be executed,
- causing halt upon entering this routine recursively. }
- ExceptTryLevel:=0;
- _ExceptObjectStack:=ExceptObjectStack;
- if (RaiseProc <> nil) and (_ExceptObjectStack <> nil) then
- with _ExceptObjectStack^ do
- RaiseProc(FObject,Addr,FrameCount,Frames);
- RaiseResult:=_Unwind_RaiseException(@ExceptWrapper^.unwind_exception);
- // Only returns if there is no exception catching block anymore
- {$ifdef excdebug}
- writeln('_Unwind_RaiseException returned: ',RaiseResult);
- {$endif}
- DoUnHandledException;
- end;
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- function __cxa_begin_catch(exc:PFPC_Unwind_Exception): pointer; cdecl; external;
- {$endif FPC_PSABIEH_CPLUSPLUSSUPPORT}
- function FPC_psabi_begin_catch(exc:PFPC_Unwind_Exception): pointer; compilerproc;
- var
- ExceptWrapper: PExceptObject;
- _ExceptObjectStack : PExceptObject;
- count: longint;
- begin
- {$ifdef excdebug}
- writeln('start begin_catch unwind exception ',hexstr(exc));
- {$endif}
- _ExceptObjectStack:=ExceptObjectStack;
- // hand off foreign exceptions to the C++ runtime
- if exc^.exception_class<>FPC_psabieh_exceptionClass_ID.u then
- begin
- // Can't link foreign exceptions with our stack
- if assigned(_ExceptObjectStack) then
- begin
- {$ifdef excdebug}
- writeln('begin catch for nested foreign exception');
- {$endif}
- DoUnHandledException;
- end;
- // This is a wrong conversion, but as long as afterwards we only access
- // fields of PFPC_Unwind_Exception, it's fine
- _ExceptObjectStack:=FPC_psabieh_GetExceptionWrapper(exc);
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- result:=__cxa_begin_catch(exc);
- {$else}
- // ??? No sensible value to return; we don't know what the
- // object is, much less where it is in relation to the header.
- result:=nil;
- {$endif}
- exit;
- end;
- ExceptWrapper:=FPC_psabieh_GetExceptionWrapper(exc);
- count:=ExceptWrapper^.refcount;
- // Count is less than zero if this exception was rethrown from an
- // immediately enclosing region.
- if count < 0 then
- count:=-count+1
- else
- inc(count);
- ExceptWrapper^.refcount:=count;
- // globals->uncaughtExceptions -= 1;
- if _ExceptObjectStack<>ExceptWrapper then
- begin
- ExceptWrapper^.Next:=_ExceptObjectStack;
- ExceptObjectStack:=ExceptWrapper;
- end;
- {$ifdef excdebug}
- writeln('stop begin_catch for wrapper ',hexstr(ExceptWrapper),' = fpc exc ',hexstr(ExceptWrapper^.FObject),', refcount is now ',count);
- {$endif}
- result:= ExceptWrapper^.FObject;
- {$ifdef __ARM_EABI_UNWINDER__}
- _Unwind_Complete(exc);
- {$endif}
- end;
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- procedure __cxa_end_catch; cdecl; external;
- {$endif FPC_PSABIEH_CPLUSPLUSSUPPORT}
- procedure FPC_psabi_end_catch; cdecl; compilerproc;
- var
- _ExceptObjectStack: PExceptObject;
- refcount: longint;
- begin
- _ExceptObjectStack:=ExceptObjectStack;
- {$ifdef excdebug}
- writeln('start end_catch unwind exception ',hexstr(@_ExceptObjectStack^.unwind_exception));
- {$endif}
- // A rethrow of a foreign exception will be removed from the
- // the exception stack immediately by __cxa_rethrow -> stack could be empty here
- if not assigned(_ExceptObjectStack) then
- exit;
- // Pass foreign exception to the C++ runtime
- if _ExceptObjectStack^.unwind_exception.exception_class<>FPC_psabieh_exceptionClass_ID.u then
- begin
- { remove foreign exception; since we never link multiple foreign
- exceptions, we know the stack is now empty }
- ExceptObjectStack:=nil;
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- __cxa_end_catch();
- {$else}
- _Unwind_DeleteException(@_ExceptObjectStack^.unwind_exception);
- {$endif}
- exit;
- end;
- refcount:=_ExceptObjectStack^.refcount;
- {$ifdef excdebug}
- writeln('middle end_catch for wrapper ',hexstr(_ExceptObjectStack),' = fpc exception ',hexstr(_ExceptObjectStack^.FObject),' with refcount ',refcount);
- {$endif}
- if refcount<0 then
- begin
- { Can happen in the original glibc code, but not for us. When re-raising an
- exception, we always immediately do this to an outer frame }
- halt(217);
- end
- else
- begin
- dec(refcount);
- {$ifdef excdebug}
- writeln('stop end_catch, not rethrown, new refcount: ',refcount);
- {$endif}
- if refcount=0 then
- begin
- // Handling for this exception is complete. Destroy the object.
- ExceptObjectStack:=_ExceptObjectStack^.next;
- _Unwind_DeleteException(@_ExceptObjectStack^.unwind_exception);
- exit;
- end
- else if refcount<0 then
- begin
- // A bug in the exception handling library or compiler.
- {$ifdef excdebug}
- writeln('refcount for exception is negative in end catch');
- {$endif}
- RunError(217);
- end;
- end;
- _ExceptObjectStack^.refcount:=refcount;
- end;
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- procedure __cxa_rethrow; cdecl; external; noreturn;
- {$endif FPC_PSABIEH_CPLUSPLUSSUPPORT}
- {$define FPC_SYSTEM_HAS_RERAISE}
- procedure fpc_ReRaise; [public,alias:'FPC_RERAISE']; compilerproc;
- var
- _ExceptObjectStack: PExceptObject;
- refcount: longint;
- reraise_error: FPC_Unwind_Reason_Code;
- begin
- _ExceptObjectStack:=ExceptObjectStack;
- // globals->uncaughtExceptions += 1;
- {$ifdef excdebug}
- writeln('start reraise for wrapper ',hexstr(_ExceptObjectStack));
- {$endif}
- // Watch for luser rethrowing with no active exception.
- if assigned(_ExceptObjectStack) then
- begin
- // Tell __cxa_end_catch this is a rethrow.
- if _ExceptObjectStack^.unwind_exception.exception_class<>FPC_psabieh_exceptionClass_ID.u then
- {$ifdef FPC_PSABIEH_CPLUSPLUSSUPPORT}
- begin
- { remove foreign exception; since we never link multiple foreign
- exceptions, we know the stack is now empty }
- ExceptObjectStack:=nil;
- __cxa_rethrow;
- { should never be reached }
- DoUnHandledException;
- end
- {$endif FPC_PSABIEH_CPLUSPLUSSUPPORT}
- else
- begin
- { reraise has to reset the refcount, this is also what the
- generic exception handling does }
- _ExceptObjectStack^.refcount := 0;
- end;
- {$ifdef excdebug}
- writeln('Stop reraise, new refcount = ',_ExceptObjectStack^.refcount);
- {$endif}
- // #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
- // _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader);
- // #else
- // #if defined(_LIBUNWIND_STD_ABI)
- // _Unwind_RaiseException (@_ExceptObjectStack^.unwind_exception);
- // #else
- reraise_error:=_Unwind_Resume_or_Rethrow (@_ExceptObjectStack^.unwind_exception);
- {$ifdef excdebug}
- writeln('reraise failed, error = ',reraise_error);
- {$endif}
- // #endif
- // #endif
- // Some sort of unwinding error.
- DoUnHandledException;
- end;
- DoUnHandledException;
- end;
- {$define FPC_SYSTEM_HAS_RAISENESTED}
- procedure fpc_raise_nested;compilerproc;
- var
- hp, _ExceptObjectStack: PExceptObject;
- begin
- _ExceptObjectStack:=ExceptObjectStack;
- if not(assigned(_ExceptObjectStack)) or
- not(assigned(_ExceptObjectStack^.next)) then
- begin
- {$ifdef excdebug}
- writeln ('raise_nested: At end of ExceptionObjectStack');
- {$endif}
- halt(1);
- end;
- if _ExceptObjectStack^.unwind_exception.exception_class<>FPC_psabieh_exceptionClass_ID.u then
- begin
- {$ifdef excdebug}
- writeln ('raise_nested: top of stack contains foreign exception');
- {$endif}
- halt(1);
- end;
- hp:=_ExceptObjectStack^.next;
- _ExceptObjectStack^.next:=hp^.next;
- {$ifdef excdebug}
- writeln('raise_nested: raising nested wrapper ',hexstr(_ExceptObjectStack),' = fpc exception ',hexstr(_ExceptObjectStack^.FObject),' with refcount ',_ExceptObjectStack^.refcount{,' (will increase to ',_ExceptObjectStack^.refcount+1,')'});
- writeln('raise_nested: previous exception ',hexstr(hp),' = fpc exception ',hexstr(hp^.FObject),' with refcount ',hp^.refcount,' (will delete if refcount = 1, otherwise decrease to',hp^.refcount-1,')');
- {$endif}
- if hp^.refcount=1 then
- { we need to free the original exception object if its refcount=1
- (means it was not acquired, only refcount increase by begin_catch) }
- _Unwind_DeleteException(@hp^.unwind_exception)
- else
- dec(hp^.refcount);
- _Unwind_RaiseException(@_ExceptObjectStack^.unwind_exception);
- DoUnHandledException;
- end;
- procedure FPC_DummyPotentialRaise; nostackframe; assembler;
- asm
- end;
|