IonicWind Software

Aurora Compiler => Tips and Tricks => Topic started by: sapero on November 08, 2006, 04:31:26 AM

Title: Exceptions handling
Post by: sapero on November 08, 2006, 04:31:26 AM
I've created two small fuctions for easier exceptions catching and handling. It uses the standard SEH based architecture, where in register FS is a pointer to some structure, at offset 0 is a pointer to EXCEPTION_REGISTRATION linked list (or -1):
struct EXCEPTION_REGISTRATION
{
ÂÃ,  ÂÃ, EXCEPTION_REGISTRATION *next;
}

Every time an exception occurs, the system loads the value from [FS:0] for current thread and checks it for a valid pointer.
If the value is -1 here is no exception handler, or the last node has been reached.

We can extend this structure by adding custom data like registers ESP and EBP (to be able to continue execution), or other usefull data like pointer to a laber where to continue after exception.
Right after 'next' member is a pointer to current exception handler. All other is optional, user defined.
I have added ESP,EBP and resume label to this structure, using pure assembly code ofc.

The usage is very near C++ exceptions handling: try and catch

if __try()
{
// paste here any unsafe code.
}
// point A

if __catch(&ExceptionCode, &ExceptionAddress, &pExceptionDescription)
{
// show a message - exception occured
}
else
{
// here was no exception inside __try block
}

The __try function appends new node to the EXCEPTION_REGISTRATION structure (as the first) and automatically saves pointer to code marked as point A, also outside the first IF instruction, then jumps directly inside IF.
This function returns TRUE, but your IF is not executed

Note to Paul:
if __try()
{
}
is assembled (and should be):
call __try
and eax,eaxÂÃ,  ÂÃ,  // 2 bytes
jz near label_if_not // 2 bytes + 4 bytes offset


The __try function reads the offset in 'jz near' and uses it to calculate code pointer outside IF.

Every call to __try MUST be matched by a call to __catch, to restore original stack pointer, and remove the node form thread linked list. Before it is removed, a validation is performed.
You can call __try inside other __try...
if __try()
{
// paste here any unsafe code.
if __try() {/*unsafe code*/}
// after exception, or success
if __catch(&ExceptionCode, &ExceptionAddress, &pszExceptionDescription)
{/*exception!*/} else {/*ok*/}
}
// after exception, or success
if __catch(&ExceptionCode, &ExceptionAddress, &pExceptionDescription)
{
// show a message - exception occured
}
else
{
// here was no exception inside __try block
}

Let's go with example code:
// #use "gp.lib"
extern int __try(); // returns always TRUE, use it with: if __try() {dangerous code}
extern int __catch(int *ppExceptionCode,int *ppExceptionAddress,string *ppExceptionDescription); // returns TRUE only after exception

sub main()
{
unsigned int ExceptionCode,ExceptionAddress;
string *pExceptionDescription;

// DEMO 1: generate Privileged Instruction exception
if __try()
{
// paste here any unsafe code
print("executing al = in(LPT1) ...");
#emit mov dx,888
#emit in al,dx
}
// -> here <- your code continues after exception.
// Do safe coding only, before __catch() !!

// always call __catch after __try to cleanup stack ...
// and restore previous exceptions handler
if __catch(&ExceptionCode, &ExceptionAddress, &pExceptionDescription)
{
ShowException(ExceptionCode, ExceptionAddress, pExceptionDescription);
}
else
{
print("port accessed successfully! Windows 98/ME ?");
}



// DEMO 2: generate "Integer Divide by Zero" exception
if __try()
{
print("dividing by zero ...");
int x = 8/0;
}
// -> here <- your code continues after exception.
if __catch(&ExceptionCode, &ExceptionAddress, &pExceptionDescription)
{
ShowException(ExceptionCode, ExceptionAddress, pExceptionDescription);
}


// DEMO 3: generate "Access Violation" exception
if __try()
{
print("writing a byte to address 0x000000 ...");
int *pAddr = NULL;
*pAddr = 0;
}
if __catch(&ExceptionCode, &ExceptionAddress, &pExceptionDescription)
{
ShowException(ExceptionCode, ExceptionAddress, pExceptionDescription);
}


// DEMO 4: generate "Breakpoint" exception
if __try()
{
print("executing breakpoint int3 ...");
#emit int3
}
if __catch(&ExceptionCode, &ExceptionAddress, &pExceptionDescription)
{
ShowException(ExceptionCode, ExceptionAddress, pExceptionDescription);
}


MessageBox(0,"finito!","");
}


sub ShowException(unsigned int ExceptionCode,unsigned int ExceptionAddress,string *pExceptionDescription)
{
MessageBox(0,sprint("Exception 0x",hex$(ExceptionCode), " (",*pExceptionDescription,") at address 0x", hex$(ExceptionAddress), " occured!"),"",16);
}


the asm codeÂÃ,  gp.asm:
struc EXCEPTION_REGISTRATION
.nextÂÃ,  ÂÃ,  ÂÃ, resd 1
.handlerÂÃ,  resd 1
; user defined
.resumeÂÃ,  ÂÃ, resd 1 ;// end of __try block
.ebpÂÃ,  ÂÃ,  ÂÃ,  resd 1 ;// saved ebp
.espÂÃ,  ÂÃ,  ÂÃ,  resd 1 ;// saved esp
.codeÂÃ,  ÂÃ,  ÂÃ, resd 1 ;// ExceptionCode
.addrÂÃ,  ÂÃ,  ÂÃ, resd 1 ;// ExceptionAddress
endstruc
//-----------------------------------------------------------
align 4
__try:
popÂÃ,  eaxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, ; address of 'test eax, eax' - 85 C0
leaÂÃ,  ecx,[eax+8]ÂÃ,  ÂÃ, ; address after 'if __try'
addÂÃ,  eax,2ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, ; address of jz near
addÂÃ,  eax,[eax+2]ÂÃ,  ÂÃ, ; add the offset from jz near
addÂÃ,  eax,6ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, ; skip the jz near
xorÂÃ,  edx,edx
push edxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // EXCEPTION_REGISTRATION.addr
push edxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // EXCEPTION_REGISTRATION.code
push edxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // EXCEPTION_REGISTRATION.espÂÃ,  ÂÃ, // invalid!
push ebpÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // EXCEPTION_REGISTRATION.ebp
push eaxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // EXCEPTION_REGISTRATION.resume
push _exception_handler // EXCEPTION_REGISTRATION.handler
push dword[fs:0]ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // EXCEPTION_REGISTRATION.next
movÂÃ,  [fs:0],esp

movÂÃ,  [esp+EXCEPTION_REGISTRATION.esp],esp ;// fix invalid esp
jmpÂÃ,  ecx
//-----------------------------------------------------------

align 4
__leave:
popÂÃ,  ÂÃ,  ecxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ; return address
xchgÂÃ,  ÂÃ, edx,esiÂÃ,  ÂÃ,  ÂÃ,  ; save esi in edx
movÂÃ,  ÂÃ,  esi,[fs:0]
assume esi,EXCEPTION_REGISTRATION

cmpÂÃ,  ÂÃ,  dword EXCEPTION_REGISTRATION(handler),_exception_handler
jneÂÃ,  ÂÃ, .q
popÂÃ,  ÂÃ,  dword[fs:0]
addÂÃ,  ÂÃ,  esp,sizeof(EXCEPTION_REGISTRATION)
.q:
xchgÂÃ,  ÂÃ, edx,esi
jmpÂÃ,  ÂÃ,  ecx

//-----------------------------------------------------------

align 4
__catch: ;// code*, addr*, string*
enterÂÃ,  0,0
pushÂÃ,  ÂÃ, edi
pushÂÃ,  ÂÃ, esi
movÂÃ,  ÂÃ,  esi,[fs:0]
assume esi,EXCEPTION_REGISTRATION

xorÂÃ,  ÂÃ,  eax,eax
cmpÂÃ,  ÂÃ,  dword EXCEPTION_REGISTRATION(handler),_exception_handler
jneÂÃ,  ÂÃ, .q

movÂÃ,  ÂÃ,  ecx,EXCEPTION_REGISTRATION(code)
movÂÃ,  ÂÃ,  eax,EXCEPTION_REGISTRATION(addr)
andÂÃ,  ÂÃ,  ecx,ecx
jzÂÃ,  ÂÃ,  .qÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ; here was no exception
movÂÃ,  ÂÃ,  edi,[ebp+8]
movÂÃ,  ÂÃ,  [edi],ecx
movÂÃ,  ÂÃ,  edi,[ebp+12]
movÂÃ,  ÂÃ,  [edi],eax

xorÂÃ,  ÂÃ,  edx,edxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ; reset the exception
movÂÃ,  ÂÃ,  EXCEPTION_REGISTRATION(code),edx

; // search for exception string (code in edx, set esi to string)
movÂÃ,  ÂÃ, esi,_e_codes
.f1:
lodsd
cmpÂÃ,  ÂÃ,  eax,0
jeÂÃ,  ÂÃ,  .fq
cmpÂÃ,  ÂÃ,  eax,ecx
jeÂÃ,  ÂÃ,  .fq
.f2:
; skip string
lodsb
andÂÃ,  ÂÃ,  al,al
jnzÂÃ,  ÂÃ,  .f2
; align
movÂÃ,  ÂÃ,  eax,4
subÂÃ,  ÂÃ,  eax,esi
andÂÃ,  ÂÃ,  eax,3
addÂÃ,  ÂÃ,  esi,eax
jmpÂÃ,  ÂÃ, .f1
.fq:
movÂÃ,  ÂÃ,  edi,[ebp+16]
movÂÃ,  ÂÃ,  [edi],esi
movÂÃ,  ÂÃ,  al,1
.q:
popÂÃ,  ÂÃ,  esi
popÂÃ,  ÂÃ,  edi
leave
; retÂÃ,  ÂÃ,  12
popÂÃ,  ÂÃ,  edxÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ; return ddress
addÂÃ,  ÂÃ,  esp,12
; we are now in caller stack frame. Imitating __leave() call from the caller...
pushÂÃ,  ÂÃ, edx
jmpÂÃ,  ÂÃ,  __leaveÂÃ,  ÂÃ,  ÂÃ,  ; don't worry about eax

//-----------------------------------------------------------
align 4
_exception_handler: // EXCEPTION_RECORD*, EXCEPTION_REGISTRATION*, CONTEXT*, void *DispatcherContext)
enter 0,0
pushÂÃ,  esi
pushÂÃ,  edi
movÂÃ,  ÂÃ, edi,[ebp+12] // EXCEPTION_REGISTRATION
movÂÃ,  ÂÃ, esi,[ebp+16] // CONTEXT *

assume edi,EXCEPTION_REGISTRATION
assume esi,CONTEXT

movÂÃ,  eax,EXCEPTION_REGISTRATION(esp)
movÂÃ,  ecx,EXCEPTION_REGISTRATION(ebp)
movÂÃ,  edx,EXCEPTION_REGISTRATION(resume)

movÂÃ,  CONTEXT(esp),eax
movÂÃ,  CONTEXT(ebp),ecx
movÂÃ,  CONTEXT(eip),edx

movÂÃ,  esi,[ebp+8] // EXCEPTION_RECORD
assume esi,EXCEPTION_RECORD
movÂÃ,  eax,EXCEPTION_RECORD(ExceptionCode)
movÂÃ,  ecx,EXCEPTION_RECORD(ExceptionAddress)
movÂÃ,  EXCEPTION_REGISTRATION(code),eax
movÂÃ,  EXCEPTION_REGISTRATION(addr),ecx

popÂÃ,  edi
popÂÃ,  esi
leave
xorÂÃ,  eax,eax
ret 16


//-----------------------------------------------------------
%macro EXCEPTION 3
%push e
dd %2
db %3,0
align 4
%$
%pop
%endm

segment .data
_e_codes:
EXCEPTION DBG_CONTROL_BREAKÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0x40010008),"Control-Break"
EXCEPTION DBG_CONTROL_CÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0x40010005),"Control-C"
EXCEPTION STATUS_GUARD_PAGE_VIOLATIONÂÃ,  ÂÃ,  ÂÃ, , (0x80000001), "Guard Page Violation"
EXCEPTION STATUS_DATATYPE_MISALIGNMENTÂÃ,  ÂÃ,  , (0x80000002), "Datatype Misalignment"
EXCEPTION STATUS_BREAKPOINTÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0x80000003), "Breakpoint"
EXCEPTION STATUS_SINGLE_STEPÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  , (0x80000004), "Single Step"
EXCEPTION STATUS_ACCESS_VIOLATIONÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0xC0000005), "Access Violation"
EXCEPTION STATUS_IN_PAGE_ERRORÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  , (0xC0000006), "In Page Error"
EXCEPTION STATUS_INVALID_HANDLEÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0xC0000008), "Invalid Handle"
EXCEPTION STATUS_NO_MEMORYÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  , (0xC0000017), "No Memory"
EXCEPTION STATUS_ILLEGAL_INSTRUCTIONÂÃ,  ÂÃ,  ÂÃ,  , (0xC000001D), "Illegal Instruction"
EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION , (0xC0000025), "Noncontinuable Exception"
EXCEPTION STATUS_INVALID_DISPOSITIONÂÃ,  ÂÃ,  ÂÃ,  , (0xC0000026), "Invalid Disposition"
EXCEPTION STATUS_ARRAY_BOUNDS_EXCEEDEDÂÃ,  ÂÃ,  , (0xC000008C), "Array Bounds Exceeded"
EXCEPTION STATUS_FLOAT_DENORMAL_OPERANDÂÃ,  ÂÃ, , (0xC000008D), "Float Denormal Operand"
EXCEPTION STATUS_FLOAT_DIVIDE_BY_ZEROÂÃ,  ÂÃ,  ÂÃ, , (0xC000008E), "Float Divide by Zero"
EXCEPTION STATUS_FLOAT_INEXACT_RESULTÂÃ,  ÂÃ,  ÂÃ, , (0xC000008F), "Float Inexact Result"
EXCEPTION STATUS_FLOAT_INVALID_OPERATIONÂÃ,  , (0xC0000090), "Float Invalid Operation"
EXCEPTION STATUS_FLOAT_OVERFLOWÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0xC0000091), "Float Overflow"
EXCEPTION STATUS_FLOAT_STACK_CHECKÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  , (0xC0000092), "Float Stack Check"
EXCEPTION STATUS_FLOAT_UNDERFLOWÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  , (0xC0000093), "Float Underflow"
EXCEPTION STATUS_INTEGER_DIVIDE_BY_ZEROÂÃ,  ÂÃ, , (0xC0000094), "Integer Divide by Zero"
EXCEPTION STATUS_INTEGER_OVERFLOWÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0xC0000095), "Integer Overflow"
EXCEPTION STATUS_PRIVILEGED_INSTRUCTIONÂÃ,  ÂÃ, , (0xC0000096), "Privileged Instruction"
EXCEPTION STATUS_STACK_OVERFLOWÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0xC00000FD), "Stack Overflow"
EXCEPTION STATUS_CONTROL_C_EXITÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, , (0xC000013A), "Control-C Exit"
EXCEPTION STATUS_FLOAT_MULTIPLE_FAULTSÂÃ,  ÂÃ,  , (0xC00002B4), "Float Multiple Faults"
EXCEPTION STATUS_FLOAT_MULTIPLE_TRAPSÂÃ,  ÂÃ,  ÂÃ, , (0xC00002B5), "Float Multiple Traps"
EXCEPTION 0,0,"Unknown Exception"


A project and gp.asm with makefile attached in zip:
Title: Re: Exceptions handling
Post by: Steven Picard on November 08, 2006, 07:36:25 AM
This is awesome!!
Title: Re: Exceptions handling
Post by: Parker on November 08, 2006, 08:23:00 AM
Ditto ;)

Do you by chance have a __throw subroutine?
Title: Re: Exceptions handling
Post by: sapero on November 08, 2006, 12:52:03 PM
No problem! Uploaded new version.
Added __throw(string*) - will be ignored if no handler is active, orwill throw exception with custom code -2.
Currentry it writes a dword to address NULL to force the system to execute exception handler, here is no need to call external apis like Get/SetThreadContext.
The string message is copied to a buffer and is limited to 256 bytes, including terminating zero.
if __try()
{
void *memory = NULL;
if (!memory)
{
__throw("Failed to allocate memory!");
}
}
if __catch(&ExceptionCode, &ExceptionAddress, &pExceptionDescription)
{
MessageBox(0, "Exception raised: " + *pExceptionDescription, "", 16);
}


The __leave function has been rolled back to global function (is exported), if you do not need exception informations, call __leave() instead __catch(...)
if __try()
{
int www = 2/0;
}
__leave();


Added [fs:0] validation before read/write.
dividing by 0.0 does not throw exceptions (float flt=1/0.0), or directly (fldz \n fdivp st0).
When this will be a part of Aurora? ;D
Title: Re: Exceptions handling
Post by: Steven Picard on November 08, 2006, 01:12:17 PM
Quote from: sapero on November 08, 2006, 12:52:03 PM
When this will be a part of Aurora? ;D
I agree entirely.  I'd really like to see this as a standard part of Aurora.
Title: Re: Exceptions handling
Post by: Ionic Wind Support Team on November 08, 2006, 02:07:09 PM
It will require some testing.  It does use some interesting tricks to make it work and depends on the fact that I never change the implimentation of the IF statement.

You wouldn't want to use it in multithreaded code.
Title: Re: Exceptions handling
Post by: J B Wood (Zumwalt) on November 08, 2006, 02:49:05 PM
There is alot you don't use in multi-threaded code, unless you have an 'attach to process' since the thread is a new process, atleast as to how I understand it, I could be wrong.

It will still come in handy.
Title: Re: Exceptions handling
Post by: Ionic Wind Support Team on November 08, 2006, 02:50:55 PM
Message processing is multithreaded.  If your message handler generates another message you can get bit by global variables.
Title: Re: Exceptions handling
Post by: Steven Picard on November 08, 2006, 03:10:55 PM
How hard would it be to make a multi-threaded version of this?
Title: Re: Exceptions handling
Post by: Ionic Wind Support Team on November 08, 2006, 03:18:36 PM
Actually I just tested it and it works fine.  So no problem there.
Title: Re: Exceptions handling
Post by: Steven Picard on November 08, 2006, 03:22:40 PM
That's great news!!
Title: Re: Exceptions handling
Post by: Ionic Wind Support Team on November 08, 2006, 03:35:42 PM
To add it to Aurora I would add a TRY macro and a CATCH macro allowing the parser to generate the needed construct provided by the IF statement.  Which frees me up to modify the implimentation of the IF statement in the future.

So TRY {...} would generate:

call __try
and eax,eax    // 2 bytes
jz near label_if_not // 2 bytes + 4 bytes offset
...
label_if_not

Also would need to come up with a keyword for the 'else' in the catch block.  Its not really the same as a FINALLY construct used in other languages.  CATCH_ELSE?

Title: Re: Exceptions handling
Post by: Steven Picard on November 08, 2006, 03:40:45 PM
Quote from: Paul Turley on November 08, 2006, 03:35:42 PMCATCH_ELSE?
That sounds logical enough to me.
Title: Re: Exceptions handling
Post by: sapero on November 08, 2006, 03:55:44 PM
CATCH_ELSE is funny :)
I have tested it in multithreaded application and it worked fine:#include "gp.inc"
import int  CloseHandle(int handle);
import int  Sleep(int time);
import void ExitThread(int code);
import int  CreateThread(void *sa,int stack,int addr,
opt void *param,opt int flags=0,opt DWORD *lpThreadId=0);


sub main()
{
int count = 0;
openconsole();

CloseHandle(CreateThread(0,0,&thread, &count));
CloseHandle(CreateThread(0,0,&thread, &count));
CloseHandle(CreateThread(0,0,&thread, &count));
CloseHandle(CreateThread(0,0,&thread, &count));
CloseHandle(CreateThread(0,0,&thread, &count));

Sleep(6<<8);
print("waiting for threads...");
while (count) {Sleep(500);}
}


sub thread(int *time)
{
*time++;
int number = *time;
print("thread ", number, " running");
Sleep(number<<8);

if __try()
{
int x = 0/0;
}
if __catch()
{
MessageBox(0, sprint("exception in thread ", number), "", 0x80000000);
}
*time--;
print("thread ", number, " exiting");
ExitThread(0);
}


but here was a problem with this code: (the division was performed before call to try)
if __try() int x=0/0;
Title: Re: Exceptions handling
Post by: Parker on November 08, 2006, 04:27:13 PM
Can ELSE be reused with a catch block?

try
{
...
}
catch (Exception e)
{

}
else
{

}


-- If the ELSE comes right after a catch block it is a "catch else", otherwise it is an "if else". Also I would assume __leave is inserted automatically if no catch block is found, and class based exception handling like in Java and other languages would be nice if possible, instead of the string based approach. Is it possible to just change the string parameter in __throw and __catch to a CException class pointer (that would be built in) without breaking anything? That would be an excellent opportunity for parameters in constructors:
if( something_is_wrong ) throw new MyException( "Something went wrong", something_value );

... Sorry, I got carried away. All things to think about though...
Title: Re: Exceptions handling
Post by: Ionic Wind Support Team on November 08, 2006, 04:29:29 PM
You want fries with that order?  How about a nice frosty milkshake.
Title: Re: Exceptions handling
Post by: Parker on November 08, 2006, 09:24:23 PM
Sorry :-[
Title: Re: Exceptions handling
Post by: Mike Stefanik on November 09, 2006, 12:19:35 AM
This will be a great (and much needed) addition to the language.
Title: Re: Exceptions handling
Post by: Zen on November 09, 2006, 03:24:13 AM
Wow this is awesome!

I feel so ashamed lol. I make silly little programs that do hardly anything, but when they work im all like wow cool! Then there's Sapero who comes along and is like look what else i've hacked into Aurora today ;)

Just joking of course. Sapero you are a good influence to everyone and someone to look upto aswell as  Paul. Well at least for me anyway ;)

Lewis
Title: Re: Exceptions handling
Post by: sapero on November 09, 2006, 06:30:47 AM
Paul, be sure to remove the g_user_message string from static variables, it is here only for demo purpose, for one thread app. This string should be saved in in EXCEPTION_REGISTRATION as string or better, strdup()
And small note about __leave:
1. the custom EXCEPTION_REGISTRATION structure has unused member .userdata - you can remove it.
2. stack cleanup goes in two steps:
pop dword[fs:0]
add esp,sizeof(EXCEPTION_REGISTRATION) -4

the -4 was missing, sorry
Title: Re: Exceptions handling
Post by: J B Wood (Zumwalt) on November 09, 2006, 07:39:11 AM
I think CATCH_ELSE is cool, and fully defines what the else is for.
You have no idea how badly I needed this.
Title: Re: Exceptions handling
Post by: Zen on November 09, 2006, 07:58:25 AM
Quote from: Jonathan (zumwalt) Wood on November 09, 2006, 07:39:11 AM
You have no idea how badly I needed this.

Like a kid too close to christams to wait? :P

Lewis
Title: Re: Exceptions handling
Post by: J B Wood (Zumwalt) on November 09, 2006, 12:21:40 PM
basically
Title: Re: Exceptions handling
Post by: Zen on January 06, 2007, 07:43:05 PM
Hey paul. Just wondering how the implementation of this is coming along and do you have am eta? I am just anctious to play as usual

Lewis
Title: Re: Exceptions handling
Post by: Ionic Wind Support Team on January 06, 2007, 08:14:22 PM
See my post in the developers forum. 
Title: Re: Exceptions handling
Post by: efgee on July 16, 2007, 05:04:06 PM
Is exception handling now build in into Aurora?
If so what is the syntax, same as sapero's examples?

Also:
Quote from: Paul Turley on January 06, 2007, 08:14:22 PM
See my post in the developers forum. 

looked for more info but to no avail.
Title: Re: Exceptions handling
Post by: Brice Manuel on July 17, 2007, 05:12:05 AM
Quote from: efgee on July 16, 2007, 05:04:06 PMlooked for more info but to no avail.
You do not have access to that forum as you are not a developer.
Title: Re: Exceptions handling
Post by: efgee on July 17, 2007, 10:16:17 AM
So is it implemented or not?
Title: Re: Exceptions handling
Post by: Ionic Wind Support Team on July 17, 2007, 06:02:19 PM
Nope.
Title: Re: Exceptions handling
Post by: sapero on June 11, 2009, 06:19:08 AM
I have updated it a bit for use with multiple threads.
The __try function creates a TLS slot, and in this slot stores a pointer to newly, from heap allocated bufer with EXCEPTION_POINTERS, EXCEPTION_RECORD and CONTEXT structures. Having these structures separate for each running thread, I could add two usefull functions: GetExceptionCode and GetExceptionInformation.
Both functions can be called at any moment, but the data returned will be usefull after the first exception.

GetExceptionInformation can return NULL if the active thread didn't called __try.#include "windows.inc"
#include "gp.inc"
#use "gp.lib"

sub main()
{
unsigned int code, address;
string *info;

if __try()
{
__throw("my message"); // generate exception, custom code 0xEFFFFFFE
}
if __catch(&code, &address, &info)
{
print(hex$(GetExceptionInformation()->ExceptionRecord->ExceptionCode));
print(hex$(GetExceptionCode()));
MessageBox(0, using("& (&) at &", info, hex$(code), hex$(address)),"",0);
}
}


$include "windowssdk.inc"
$include "ebgp.inc"
$use "gp.lib"

uint code, address
pointer info

if __try()
__throw("my message") ' generate exception, custom code 0xEFFFFFFE
endif

if __catch(&code, &address, &info)
pointer pep = GetExceptionInformation()
settype pep, EXCEPTION_POINTERS
print hex$(*pep.*<EXCEPTION_RECORD>ExceptionRecord.ExceptionCode)
print hex$(GetExceptionCode())
MessageBox 0, using("& (&) at &", info, hex$(code), hex$(address)),"",0
endif