Welcome, Guest. Please login or register.

Author Topic: From low level exception handling to high level...  (Read 9846 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #14 on: October 22, 2006, 06:59:47 PM »
Hmm, I think I got a bit confused: I was thinking that a7 was the SSP during the trap handling but your code implies it's the USP ?

int p; // A
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: From low level exception handling to high level...
« Reply #15 on: October 22, 2006, 09:09:55 PM »
That is SSP.

The exec exception handler pushes 1 extra longword to stack, it's the vector number (say division by zero 0x14 >> 2 = 5 will be in stack).

Before exiting the exception handler the extra longword must be popped out of the stack. After that it's the regular stackframe in the SSP. With 68010++, all stackframes begin with:
Code: [Select]

UWORD sr;
APTR  returnaddr;

Thus poking 2(sp) with new address will make the exception return to poked address.
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #16 on: October 22, 2006, 09:14:01 PM »
Right, now that makes sense :-D

Sorry, it's been a while ;-)

I don't seem to have my 680x0 UM's handy anyplace atm either...

Assuming that I write a handler that doesn't trash any registers right up until the 'throw ' is invoked, I'm wondering how much the context matters. The actual try { } block that would surround the code at the high level gives you your basic restore point anyway.

-edit-

It's quite amusing really, I only want to do all this just so I can get away with not having to test certain things before executing statements that might result in a problem :-)

I'm sure most people would be perfectly happy with 'if (b==0) { throw ZeroDivide(); }' before any such division...
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #17 on: October 22, 2006, 09:46:48 PM »
Enough theorising for now, methinks it is time to test the idea out :-)
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #18 on: October 23, 2006, 12:24:58 AM »
Quote

motorollin wrote:
I suppose that would be an advantage (and would mean I started hacking at age 3 :lol: )

--
moto


How old do you think he was when he started:


;-)
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #19 on: October 23, 2006, 01:58:47 AM »
Quote

Karlos wrote:
Enough theorising for now, methinks it is time to test the idea out :-)


Well, I tried it with a quick and dirty test program and it appears to work fine:

For those interested:

Code: [Select]

mc68020

SECTION ":0", CODE

XREF _throwBoom
XDEF _trap_68K

_trap_68K
lea    4(a7), a7
move.l #_throwBoom, 2(a7)
rte


All this does trap handler does is cause the execution to jump to a function called "throwBoom()":

Code: [Select]

/*

Evil low level -> high level exception test code

*/

#include
#include
#include


struct Boom {}; // simple exception struct

extern "C" {

void trap_68K(); // defined in trap.asm
void throwBoom() // referenced by trap_68K
{
throw Boom();
}

}


int main(int argN, char** argV)
{
// install our trap
Task* me = FindTask(0);
void* oldTrap = me->tc_TrapCode;
me->tc_TrapCode = (void*)(&trap_68K);
std::puts("Installed custom Trap");

// try it out
try {
int a = 1, b=0;
std::puts("Time to try something naughty...");
int c = a/b;
std::printf("\n%d\n",c);
}
catch (Boom) {
std::puts("Caught a Boom");
}
catch (...) {
std::puts("Caught... something anyway");
}


// restore the original trap
me->tc_TrapCode = oldTrap;
std::puts("Restored Trap");

return 0;
}


Running this produces the anticipated output:

Quote

Installed custom Trap
Time to try something naughty...
Caught a Boom
Restored Trap


In all, I'm quite happy about that. Some more detailed analysis needs to be done, however, to see what it does in more complicated examples ;-)
int p; // A
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: From low level exception handling to high level...
« Reply #20 on: October 23, 2006, 02:07:24 AM »
I believe in this case you're lucky to have "close" enough environment in both the code nuking and the catch part. However, I'm pretty confident this isn't always the case.

So I believe to be fully functional in all cases this thing requires some sort of state saving and restoring. For simple cases this could well be enough, however.
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #21 on: October 23, 2006, 02:19:12 AM »
Don't worry, I intend to investigate it in greater depth. The state information is largely taken care of by the C++ stack unwinding. I've managed to ascertain so far that in a slightly modified version of this example where a, b and c are declared outside the try {} block that each have the value they had right up until the exception is raised, which is what I was expecting.

If I can ensure it satisfies the same criteria as a normal C++ exception then I'll be happy enough.

Dealing with low level locks etc. is slightly beyond the scope of any language level exception processing mechanism in any event.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #22 on: October 23, 2006, 02:33:27 AM »
Ok, I've confirmed that objects created prior to the exception   that was raised in this "underhand" way still have their destructors called during the stack unwind. In other words, it seems to be indistinguishable so far from invoking a C++ exception manually :-)
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #23 on: October 23, 2006, 12:54:45 PM »
Right...

Assuming all threads in my code (including the main one) have Task->tc_UserData pointing to a handle (containing a special identifier) that gives access to the actual Thread class instance, the next trick is:

Within the supervisor mode trap, can I call FindTask(0) safely  so that I can test to see if the executing task is one of my Thread instances?

The reason being that when I install my own trap handler, I'd like to be able to get the original tc_TrapCode if my trap decides it cannot handle the error (that is to say, find a reasonable C++ exception to throw for it).

Naturally I'd use my Thread class implementation to store the original tc_TrapCode, so that all the asm handler has to do is first ascertain if the thread is one of mine (which it should be to be even called in the first place) then if it falls through all the cmp #trapNumber, (a7) tests it can load the old tc_TrapCode from the Thread, pop it on the stack then rts to it...

I don't really want to handle things like Line A emulation errors and the like...
int p; // A
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: From low level exception handling to high level...
« Reply #24 on: October 23, 2006, 01:14:17 PM »
Quote
Within the supervisor mode trap, can I call FindTask(0) safely so that I can test to see if the executing task is one of my Thread instances?

Yes. FindTask(NULL) is "return SysBase->ThisTask;" basically. It's always safe.

Quote
Naturally I'd use my Thread class implementation to store the original tc_TrapCode, so that all the asm handler has to do is first ascertain if the thread is one of mine (which it should be to be even called in the first place) then if it falls through all the cmp #trapNumber, (a7) tests it can load the old tc_TrapCode from the Thread, pop it on the stack then rts to it...

I don't really want to handle things like Line A emulation errors and the like...

Sounds good.
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #25 on: October 23, 2006, 01:38:36 PM »
This idea is starting to shape up quite nicely :-)

From the point of view of describing a trap, do the following exceptions make sense (remember that these exception classes are meant to be meaningful on other platforms than the 68K/AmigaOS) in your opinion?

TRAP #2 (access fault) -> class SegmentationFault
TRAP #3 (address error) -> class BadAlignment
TRAP #5 (our favourite) -> class ZeroDivide
TRAP #6 (chk/chk2) -> class RangeError

these might also make sense, if the FPU is triggered to trap

TRAP #50 (FP zero divide) -> class ZeroDivide
TRAP #51 (FP underflow) -> class Underflow
TRAP #53 (FP overlflow) -> class Overflow
TRAP #54 (FP NAN) -> class InvalidOperand

Naturally, these classes fall into a heirarchy and are ultimately all derived from RuntimeError
int p; // A
 

Offline Speelgoedmannetje

  • Hero Member
  • *****
  • Join Date: Oct 2002
  • Posts: 9656
    • Show only replies by Speelgoedmannetje
Re: From low level exception handling to high level...
« Reply #26 on: October 23, 2006, 01:48:54 PM »
I haven't had the time to read every post in the thread, and I have never programmed for the 68k, but usually, when I code in assembly I use a watchdog timer if things can become critical (only IF - when I program I usually try to minimize the 'working environment' as much as possible.)
And the canary said: \'chirp\'
 

Offline Speelgoedmannetje

  • Hero Member
  • *****
  • Join Date: Oct 2002
  • Posts: 9656
    • Show only replies by Speelgoedmannetje
Re: From low level exception handling to high level...
« Reply #27 on: October 23, 2006, 01:51:52 PM »
Quote

motorollin wrote:
How do you guys know all this stuff?  :-o

--
moto
With patience.
And the canary said: \'chirp\'
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #28 on: October 23, 2006, 02:06:51 PM »
@Speel

The basic idea here is to utilize the CPU's own ability to detect certain errors in order to invoke the language level exception mechanism (in this case, C++).

So, for example, instead of always having to check if you are about to divide by zero in some function, you can just do the division. If it goes wrong, an exception is thrown at the point the divide operation takes place.

Other errors you might encounter come from bad data alignment, accessing memory that doesnt exist and that kind of thing.

C++ itself offers no mechanism to detect these, but the system does. All I am doing is marrying the system level ability to detect a problem with C++ ability to report it at user code level.

And so far, it's working ;-)
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: From low level exception handling to high level...
« Reply #29 from previous page: October 24, 2006, 11:47:42 AM »
Quote

Speelgoedmannetje wrote:

and I have never programmed for the 68k


You are missing out, my friend! M86K assembly is actually fun. I wish I could say the same about PPC or x86, both of which I can manage (PPC moreso than x86) but they always seem to be a bit of a grind.
int p; // A