except_native.inc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************
  12. Exception support
  13. ****************************************************************************}
  14. {$ifdef FPC_HAS_FEATURE_THREADING}
  15. ThreadVar
  16. {$else FPC_HAS_FEATURE_THREADING}
  17. Var
  18. {$endif FPC_HAS_FEATURE_THREADING}
  19. ExceptObjectStack : PExceptObject;
  20. ExceptTryLevel : ObjpasInt;
  21. {$ifdef FPC_USE_PSABIEH}
  22. {$i psabieh.inc}
  23. {$endif}
  24. Function RaiseList : PExceptObject;
  25. begin
  26. RaiseList:=ExceptObjectStack;
  27. end;
  28. function AcquireExceptionObject: Pointer;
  29. var
  30. _ExceptObjectStack : PExceptObject;
  31. begin
  32. _ExceptObjectStack:=ExceptObjectStack;
  33. If _ExceptObjectStack<>nil then
  34. begin
  35. Inc(_ExceptObjectStack^.refcount);
  36. AcquireExceptionObject := _ExceptObjectStack^.FObject;
  37. end
  38. else
  39. RunError(231);
  40. end;
  41. procedure ReleaseExceptionObject;
  42. var
  43. _ExceptObjectStack : PExceptObject;
  44. begin
  45. _ExceptObjectStack:=ExceptObjectStack;
  46. If _ExceptObjectStack <> nil then
  47. begin
  48. if _ExceptObjectStack^.refcount > 0 then
  49. Dec(_ExceptObjectStack^.refcount);
  50. end
  51. else
  52. RunError(231);
  53. end;
  54. { This routine is called only from fpc_raiseexception, which uses ExceptTryLevel
  55. flag to guard against repeated exceptions which can occur due to corrupted stack
  56. or heap. }
  57. function PushExceptObject(Obj : TObject; AnAddr : CodePointer; AFrame : Pointer): PExceptObject;
  58. var
  59. Newobj : PExceptObject;
  60. _ExceptObjectStack : ^PExceptObject;
  61. framebufsize,
  62. framecount : PtrInt;
  63. frames : PCodePointer;
  64. prev_frame,
  65. curr_frame : Pointer;
  66. curr_addr : CodePointer;
  67. begin
  68. {$ifdef excdebug}
  69. writeln ('In PushExceptObject');
  70. {$endif}
  71. _ExceptObjectStack:=@ExceptObjectStack;
  72. NewObj:=AllocMem(sizeof(TExceptObject));
  73. NewObj^.Next:=_ExceptObjectStack^;
  74. _ExceptObjectStack^:=NewObj;
  75. NewObj^.FObject:=Obj;
  76. NewObj^.Addr:=AnAddr;
  77. if assigned(get_frame) then
  78. begin
  79. NewObj^.refcount:=0;
  80. { Backtrace }
  81. curr_frame:=AFrame;
  82. curr_addr:=AnAddr;
  83. frames:=nil;
  84. framecount:=0;
  85. framebufsize:=0;
  86. { The frame pointer of this procedure is used as initial stack bottom value. }
  87. prev_frame:=get_frame;
  88. while (framecount<RaiseMaxFrameCount) and (curr_frame > prev_frame) and
  89. (curr_frame<StackTop) do
  90. Begin
  91. prev_frame:=curr_frame;
  92. get_caller_stackinfo(curr_frame,curr_addr);
  93. if (curr_addr=nil) or
  94. (curr_frame=nil) then
  95. break;
  96. if (framecount>=framebufsize) then
  97. begin
  98. inc(framebufsize,16);
  99. reallocmem(frames,framebufsize*sizeof(codepointer));
  100. end;
  101. frames[framecount]:=curr_addr;
  102. inc(framecount);
  103. End;
  104. NewObj^.framecount:=framecount;
  105. NewObj^.frames:=frames;
  106. end;
  107. Result:=NewObj;
  108. end;
  109. Procedure DoUnHandledException;[Public, Alias : 'FPC_DOUNHANDLEDEXCEPTION'];
  110. var
  111. _ExceptObjectStack : PExceptObject;
  112. begin
  113. _ExceptObjectStack:=ExceptObjectStack;
  114. If (ExceptProc<>Nil) and (_ExceptObjectStack<>Nil) then
  115. with _ExceptObjectStack^ do
  116. begin
  117. TExceptProc(ExceptProc)(FObject,Addr,FrameCount,Frames);
  118. halt(217)
  119. end;
  120. if erroraddr = nil then
  121. RunError(217)
  122. else
  123. Halt(errorcode);
  124. end;
  125. {$ifndef FPC_SYSTEM_HAS_RAISEEXCEPTION}
  126. procedure fpc_RaiseException (Obj : TObject; AnAddr : CodePointer; AFrame : Pointer);[Public, Alias : 'FPC_RAISEEXCEPTION']; compilerproc;
  127. var
  128. _ExceptObjectStack : PExceptObject;
  129. _ExceptAddrstack : PExceptAddr;
  130. begin
  131. {$ifdef excdebug}
  132. writeln ('In RaiseException');
  133. {$endif}
  134. if ExceptTryLevel<>0 then
  135. Halt(217);
  136. ExceptTryLevel:=1;
  137. PushExceptObject(Obj,AnAddr,AFrame);
  138. { if PushExceptObject causes another exception, the following won't be executed,
  139. causing halt upon entering this routine recursively. }
  140. ExceptTryLevel:=0;
  141. // _ExceptAddrstack:=ExceptAddrStack;
  142. // If _ExceptAddrStack=Nil then
  143. // DoUnhandledException;
  144. _ExceptObjectStack:=ExceptObjectStack;
  145. if (RaiseProc <> nil) and (_ExceptObjectStack <> nil) then
  146. with _ExceptObjectStack^ do
  147. RaiseProc(FObject,Addr,FrameCount,Frames);
  148. //longjmp(_ExceptAddrStack^.Buf^,FPC_Exception);
  149. fpc_wasm32_throw_fpcexception;
  150. end;
  151. {$endif FPC_SYSTEM_HAS_RAISEEXCEPTION}
  152. function fpc_PopObjectStack : TObject;[Public, Alias : 'FPC_POPOBJECTSTACK']; compilerproc;
  153. var
  154. hp : PExceptObject;
  155. begin
  156. {$ifdef excdebug}
  157. writeln ('In PopObjectstack');
  158. {$endif}
  159. hp:=ExceptObjectStack;
  160. if hp=nil then
  161. begin
  162. {$ifdef excdebug}
  163. writeln ('At end of ExceptionObjectStack');
  164. {$endif}
  165. halt (1);
  166. end
  167. else
  168. begin
  169. { we need to return the exception object to dispose it }
  170. if hp^.refcount = 0 then
  171. fpc_PopObjectStack:=hp^.FObject
  172. else
  173. fpc_PopObjectStack:=nil;
  174. ExceptObjectStack:=hp^.next;
  175. if assigned(hp^.frames) then
  176. freemem(hp^.frames);
  177. dispose(hp);
  178. erroraddr:=nil;
  179. end;
  180. end;
  181. { this is for popping exception objects when a second exception is risen }
  182. { in an except/on }
  183. function fpc_PopSecondObjectStack : TObject;[Public, Alias : 'FPC_POPSECONDOBJECTSTACK']; compilerproc;
  184. var
  185. hp,_ExceptObjectStack : PExceptObject;
  186. begin
  187. {$ifdef excdebug}
  188. writeln ('In PopSecondObjectstack');
  189. {$endif}
  190. _ExceptObjectStack:=ExceptObjectStack;
  191. If not(assigned(_ExceptObjectStack)) or
  192. not(assigned(_ExceptObjectStack^.next)) then
  193. begin
  194. {$ifdef excdebug}
  195. writeln ('At end of ExceptionObjectStack');
  196. {$endif}
  197. halt (1);
  198. end
  199. else
  200. begin
  201. if _ExceptObjectStack^.next^.refcount=0 then
  202. { we need to return the exception object to dispose it if refcount=0 }
  203. fpc_PopSecondObjectStack:=_ExceptObjectStack^.next^.FObject
  204. else
  205. fpc_PopSecondObjectStack:=nil;
  206. hp:=_ExceptObjectStack^.next;
  207. _ExceptObjectStack^.next:=hp^.next;
  208. if assigned(hp^.frames) then
  209. freemem(hp^.frames);
  210. dispose(hp);
  211. end;
  212. end;
  213. {$ifndef FPC_SYSTEM_HAS_RERAISE}
  214. Procedure fpc_ReRaise;[Public, Alias : 'FPC_RERAISE']; compilerproc;
  215. var
  216. _ExceptAddrStack : PExceptAddr;
  217. begin
  218. {$ifdef excdebug}
  219. writeln ('In reraise');
  220. {$endif}
  221. // _ExceptAddrStack:=ExceptAddrStack;
  222. // If _ExceptAddrStack=Nil then
  223. // DoUnHandledException;
  224. ExceptObjectStack^.refcount := 0;
  225. // longjmp(_ExceptAddrStack^.Buf^,FPC_Exception);
  226. fpc_wasm32_throw_fpcexception;
  227. end;
  228. {$endif FPC_SYSTEM_HAS_RERAISE}
  229. function Internal_PopSecondObjectStack : TObject; external name 'FPC_POPSECONDOBJECTSTACK';
  230. function Internal_PopObjectStack: TObject; external name 'FPC_POPOBJECTSTACK';
  231. procedure Internal_Reraise; external name 'FPC_RERAISE';
  232. Procedure fpc_ReRaise2;[Public, Alias : 'FPC_RERAISE2']; compilerproc;
  233. var
  234. Newobj : PExceptObject;
  235. _ExceptObjectStack : PExceptObject;
  236. begin
  237. {$ifdef excdebug}
  238. writeln ('In reraise2');
  239. {$endif}
  240. _ExceptObjectStack:=ExceptObjectStack;
  241. NewObj:=AllocMem(sizeof(TExceptObject));
  242. NewObj^.Next:=_ExceptObjectStack^.Next;
  243. _ExceptObjectStack^.Next:=NewObj;
  244. Internal_Reraise;
  245. end;
  246. Function fpc_Catches(Objtype : TClass) : TObject;[Public, Alias : 'FPC_CATCHES']; compilerproc;
  247. var
  248. _ExceptObjectStack : PExceptObject;
  249. begin
  250. _ExceptObjectStack:=ExceptObjectStack;
  251. If _ExceptObjectStack=Nil then
  252. begin
  253. {$ifdef excdebug}
  254. Writeln ('Internal error.');
  255. {$endif}
  256. halt (255);
  257. end;
  258. if Not ((Objtype = TClass(CatchAllExceptions)) or
  259. (_ExceptObjectStack^.FObject is ObjType)) then
  260. fpc_Catches:=Nil
  261. else
  262. begin
  263. // catch !
  264. fpc_Catches:=_ExceptObjectStack^.FObject;
  265. { this can't be done, because there could be a reraise (PFV)
  266. PopObjectStack;
  267. Also the PopAddrStack shouldn't be done, we do it now
  268. immediatly in the exception handler (FK)
  269. PopAddrStack; }
  270. end;
  271. end;
  272. Procedure SysInitExceptions;
  273. {
  274. Initialize exceptionsupport
  275. }
  276. begin
  277. ExceptObjectstack:=Nil;
  278. end;
  279. {$ifndef FPC_SYSTEM_HAS_DONEEXCEPTION}
  280. procedure fpc_doneexception;[public,alias:'FPC_DONEEXCEPTION'] compilerproc;
  281. begin
  282. {$ifdef excdebug}
  283. Writeln('In doneexception');
  284. {$endif}
  285. Internal_PopObjectStack.Free;
  286. end;
  287. {$endif FPC_SYSTEM_HAS_DONEEXCEPTION}
  288. {$ifndef FPC_SYSTEM_HAS_RAISENESTED}
  289. procedure fpc_raise_nested;[public,alias:'FPC_RAISE_NESTED']compilerproc;
  290. begin
  291. {$ifdef excdebug}
  292. Writeln('In raise_nested');
  293. {$endif}
  294. Internal_PopSecondObjectStack.Free;
  295. Internal_Reraise;
  296. end;
  297. {$endif FPC_SYSTEM_HAS_RAISENESTED}
  298. {$ifndef FPC_SYSTEM_HAS_SAFECALLHANDLER}
  299. function fpc_safecallhandler(obj: TObject): HResult; [public,alias:'FPC_SAFECALLHANDLER']; compilerproc;
  300. var
  301. raiselist: PExceptObject;
  302. adr: CodePointer;
  303. exc: TObject;
  304. begin
  305. raiselist:=ExceptObjectStack;
  306. if Assigned(raiseList) then
  307. adr:=raiseList^.Addr
  308. else
  309. adr:=nil;
  310. exc:=Internal_PopObjectStack;
  311. if Assigned(obj) and Assigned(exc) then
  312. result:=obj.SafeCallException(exc,adr)
  313. else
  314. result:=E_UNEXPECTED;
  315. exc.Free;
  316. end;
  317. {$endif FPC_SYSTEM_HAS_SAFECALLHANDLER}