etv_term vector
Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
etv_term vector
Quoting from the toshyp:
"etv_term LONG 0x408 Logical GEMDOS vector 258. Should always be set via Setexc. Programs that hook into any system vectors should also hook into this vector. If the program is terminated in an abnormal manner, the operating system jumps first via this vector, so that one can withdraw cleanly from all changed vectors. As MagiC uses its own etv_term vector for each application, collisions can not arise there."
Do the default exception handlers of TOS and EmuTOS obey this handler, e.q. jump through this one? Or does only a clen process termination trigger this?
"etv_term LONG 0x408 Logical GEMDOS vector 258. Should always be set via Setexc. Programs that hook into any system vectors should also hook into this vector. If the program is terminated in an abnormal manner, the operating system jumps first via this vector, so that one can withdraw cleanly from all changed vectors. As MagiC uses its own etv_term vector for each application, collisions can not arise there."
Do the default exception handlers of TOS and EmuTOS obey this handler, e.q. jump through this one? Or does only a clen process termination trigger this?
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Re: etv_term vector
If you are asking if every possible crash would ensure etv_term() get's called, the answer is: yes, it shouldsimonsunnyboy wrote:...Do the default exception handlers of TOS and EmuTOS obey this handler, e.q. jump through this one? Or does only a clen process termination trigger this?

To my knowledge, EmuTOS should have that right, however.
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
Code: Select all
marndt@silentbox:~/Projects/external/EmuTOS$ grep -r "etv_term" *
bdos/proc.c: etv_term();
bios/bios.c: etv_term = just_rts;
bios/tosvars.S: .globl _etv_term
bios/tosvars.S:_etv_term: .ds.l 1 // GEM program termination vector
bios/tosvars.h:extern void (*etv_term)(void);
doc/bios.txt: etv_term (long) $408
doc/changelog.txt: never called (hdv_init, hdv_boot, etv_term, etv_critic). Is it a bug? (LVL)
doc/changelog.txt:- BDOS: implement etv_term()
emutos.map: 0x0000000000000408 _etv_term
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Re: etv_term vector
Yes, etv_term is called by Pterm. Your point being? Look what happens after displaying an exception: https://github.com/emutos/emutos/blob/c ... int.c#L586
-
- Hardware Guru
- Posts: 3003
- Joined: Sat Sep 10, 2005 11:11 am
- Location: Kosice, Slovakia
- Contact:
Re: etv_term vector
Wow, I have never heard about this one before and it sounds like a totally useful thing! Does this applies also to exceptions? I mean if an app tries to access hardware or causes memory violation, will this vector still be called?
-
- Fuji Shaped Bastard
- Posts: 2370
- Joined: Sun Aug 03, 2014 5:54 pm
Re: etv_term vector
Yes, it's done as part of process termination, which is also called on uncaught exceptions (see the source Christian quoted, kill_program at the end will just call Pterm()). Even Ptermres() will call this.mikro wrote:Does this applies also to exceptions? I mean if an app tries to access hardware or causes memory violation, will this vector still be called?
-
- Hardware Guru
- Posts: 3003
- Joined: Sat Sep 10, 2005 11:11 am
- Location: Kosice, Slovakia
- Contact:
Re: etv_term vector
But this is totally awesome! How come so few apps use it? Just a few days ago someone asked on the mint mailing list how come NetSurf takes down the whole OS on a memory violation exception. Well, because it's not using this vector to restore its IKBD handlers!
Does it work properly also in FreeMiNT? (I mean the explicit note about Magic having it for each app separately).
Does it work properly also in FreeMiNT? (I mean the explicit note about Magic having it for each app separately).
-
- Fuji Shaped Bastard
- Posts: 2370
- Joined: Sun Aug 03, 2014 5:54 pm
Re: etv_term vector
Never tried in practice, but i think it should. Just make sure you to use Setexc() to install the vector, not just switching to Super() and install the vector by hand.mikro wrote:Does it work properly also in FreeMiNT? (I mean the explicit note about Magic having it for each app separately).
I didn't look yet how NetSurf does this (i just wonder why they need to do that at all), but of course it's not that easy to cleanly uninstall the IKBD vectors in a multi-tasking environment, especially if there are other programs that might have hooked those vectors, too.mikro wrote:Just a few days ago someone asked on the mint mailing list how come NetSurf takes down the whole OS on a memory violation exception. Well, because it's not using this vector to restore its IKBD handlers!
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
That's my use case. I would like to exploit it to execute a hook to call the Hatari native features and activate Hatari's debugger when the exception happens.mikro wrote:Wow, I have never heard about this one before and it sounds like a totally useful thing! Does this applies also to exceptions? I mean if an app tries to access hardware or causes memory violation, will this vector still be called?
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
Thanks, seems the call is hidden inside EmuTOS. Does regular TOS do the same?czietz wrote:Yes, etv_term is called by Pterm. Your point being? Look what happens after displaying an exception: https://github.com/emutos/emutos/blob/c ... int.c#L586
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
I browsed the Atari ST Profibuch, atleast the 1988 edition I have lists a generic exception handler drawing bombs in assembly language, TOS 1.0 presumably. This indeed seems to call Pterm0() at the end of the bombs.
If this is in place for others, I have to test.
With EmuTOS only the wait for keypress is less attractive.
So I think all should work, and it is the place to add an atexit() handler aswell, making the thing really useful.
If this is in place for others, I have to test.
With EmuTOS only the wait for keypress is less attractive.
So I think all should work, and it is the place to add an atexit() handler aswell, making the thing really useful.
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
- Eero Tamminen
- Fuji Shaped Bastard
- Posts: 2837
- Joined: Sun Jul 31, 2011 1:11 pm
Re: etv_term vector
Easier would be just ask Hatari to invoke debugger when exceptions happen. To do that for all exceptions, use following option:simonsunnyboy wrote:That's my use case. I would like to exploit it to execute a hook to call the Hatari native features and activate Hatari's debugger when the exception happens.
Code: Select all
--debug-except all
Catching is toggled with the "-D" option. However, if you use that when starting Hatari, exceptions at bootup (from HW probing done by TOS) would also invoke debugger.
To avoid that, you have two options:
1. Toggle exception catching at run time from debugger with:
Code: Select all
setopt -D
2. Use the "autostart" Hatari option to tell exception catching to be enabled when a program is auto-started by Hatari:
Code: Select all
--debug-except autostart,all
Code: Select all
--debug-except help
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
Yes but I also want to execute additional code to dump my program's state through the Debugger console print functions, a program specific coredump facility.
Unless you provide the Hatari debugger with the ability to list my variables correctly with datatypes and readable names
Unless you provide the Hatari debugger with the ability to list my variables correctly with datatypes and readable names

Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Re: etv_term vector
Remember that you can't expect to (reliably) call GEMDOS functions from the etv_term vector. So its usefulness might be pretty limited.simonsunnyboy wrote: ... So I think all should work, and it is the place to add an atexit() handler aswell, making the thing really useful...
Re: etv_term vector
IIRC Thing! use this vector to catch memory violations.mikro wrote:I mean if an app tries to access hardware or causes memory violation, will this vector still be called?
Jo Even
VanillaMiNT - Falcon060 - Milan060 - Falcon040 - MIST - Mega STE - Mega ST - STM - STE - Amiga 600 - Sharp MZ700 - MSX - Amstrad CPC - C64
VanillaMiNT - Falcon060 - Milan060 - Falcon040 - MIST - Mega STE - Mega ST - STM - STE - Amiga 600 - Sharp MZ700 - MSX - Amstrad CPC - C64
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
The output is all NATFEATS calls, I am using this from my asserts already. But I can check there is no GEMDOS involved.mfro wrote:Remember that you can't expect to (reliably) call GEMDOS functions from the etv_term vector. So its usefulness might be pretty limited.simonsunnyboy wrote: ... So I think all should work, and it is the place to add an atexit() handler aswell, making the thing really useful...
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Re: etv_term vector
Newer TOS/GEMDOS versions call Pterm(-1) to kill a process after an exception, as you will find documented e.g. in the Profibuch. This means that the etv_term handler is also called. See this German article by Julian Reschke, where he suggests hooking into etv_term to provide the user with sort of a crash dump in case of an exception:simonsunnyboy wrote:I browsed the Atari ST Profibuch, atleast the 1988 edition I have lists a generic exception handler drawing bombs in assembly language, TOS 1.0 presumably. This indeed seems to call Pterm0() at the end of the bombs.
If this is in place for others, I have to test.
http://www.stcarchiv.de/stc1996/03/atarium
EDIT: For official documentation about the fact that Pterm(-1) is called in case of an exception, see p. 38 in http://dev-docs.exxoshost.co.uk/Rainbow ... 5-1991.pdf
Last edited by czietz on Sat Nov 18, 2017 10:59 am, edited 1 time in total.
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
Exactly what I need then, I only have to hookup my existing code to the vector...
see http://www.atari-forum.com/viewtopic.ph ... 49#p293615 what I am using with slight improvements.
see http://www.atari-forum.com/viewtopic.ph ... 49#p293615 what I am using with slight improvements.
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
- Eero Tamminen
- Fuji Shaped Bastard
- Posts: 2837
- Joined: Sun Jul 31, 2011 1:11 pm
Re: etv_term vector
If you have symbols for your variables, you can list their values. I don't know how readable it's though:simonsunnyboy wrote:Yes but I also want to execute additional code to dump my program's state through the Debugger console print functions, a program specific coredump facility.
Unless you provide the Hatari debugger with the ability to list my variables correctly with datatypes and readable names
Code: Select all
> symbols data
0x0003a7b4 D __app
0x0003a7b8 D _win_handle
0x0003a7bc D _win_name
0x0003a7cb D _filename
0x0003a7ec D _mode_cplx
0x0003a7f0 D _mode_trig
0x0003a7f4 D _mode_out
...
> evaluate (_filename)
value in RAM at ($3a7cb).l = $636c6163
= %1100011011011000110000101100011 (bin), #1668047203 (dec), $636c6163 (hex)
> memdump _filename
0003A7CB: 63 6c 61 63 5f 72 73 63 2e 72 73 63 00 00 00 00 clac_rsc.rsc....
...
Evaluate command always reads long when asked to get value from given address (using '()'), but when using hexadecimals, that's not a problem.
You can also use it to convert values:
Code: Select all
> e $6163
= %110000101100011 (bin), #24931 (dec), $6163 (hex)
> e #24931
= %110000101100011 (bin), #24931 (dec), $6163 (hex)
> e %110000101100011
= %110000101100011 (bin), #24931 (dec), $6163 (hex)
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
Well how does Hatari know that I want $6163 to be a uint16_t instead? Esp. if it is part of a structure?
This evaluation thing does not help with true source level debugging. I do not wat to dig everything behind data to know how to interpret the raw memory dumps.
So I add code to provide this information.
This evaluation thing does not help with true source level debugging. I do not wat to dig everything behind data to know how to interpret the raw memory dumps.
So I add code to provide this information.
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
-
- Fuji Shaped Bastard
- Posts: 2370
- Joined: Sun Aug 03, 2014 5:54 pm
Re: etv_term vector
The symbols Hatari reads just don't provide such information. For this, you would need to read the debug informations, and then re-implement about 90% of gdb. Good luck with thissimonsunnyboy wrote:This evaluation thing does not help with true source level debugging.

- Eero Tamminen
- Fuji Shaped Bastard
- Posts: 2837
- Joined: Sun Jul 31, 2011 1:11 pm
Re: etv_term vector
Well, if you're debugging your own code, you can look up the variable types from your sources, or otherwise remember them. Memdump is probably easiest way to look at the values (for 16-bit variable, just take the 4 first hex digits at given address). And if you want to know hex e.g. in decimal, use the evaluate ('e') command. It's not as convenient as source level debugger like Gdb, but at least doable.
-
- Moderator
- Posts: 5520
- Joined: Wed Oct 23, 2002 4:36 pm
- Location: Friedrichshafen, Germany
- Contact:
Re: etv_term vector
No problem, it is just a matter of adding some stubs to output data, basically printf to Hatari console instread of Atari side output device.ThorstenOtto wrote:The symbols Hatari reads just don't provide such information. For this, you would need to read the debug informations, and then re-implement about 90% of gdb. Good luck with thissimonsunnyboy wrote:This evaluation thing does not help with true source level debugging.
And yes, it is only done because there is no gdb for debugging TOS applications outside of an Atari environment, e.q. I atm treat Hatari as an embedded target without proper in-circuit debugging abilities.
But I also had great success, it just worked and I can even decode the proc_lives etc information from TOS exceptions:
I provoked an uneven address acces here:
Code: Select all
Address Error at address $50001, PC=$d4b4 addr_e3=d4b4 op_e3=3010
_*
|
###
#####
###
---- EXCEPTION TRIGGERED ----------------------------------------------
---- COREDUMP -----------------------------------------------------------
saved CPU state:
D0: 00050001 D1: 00022079 D2: 00000000 D3: 00000000
D4: 00000000 D5: 00000000 D6: 00000000 D7: 00000001
A0: 00050001 A1: 00000006 A2: 003F8000 A3: 00000000
A4: 00021F56 A5: 00000000 A6: 003F7FC6 A7: 0000D084
uPC: 03E010E8 USP: 0000D0C0
stack values: 3015 0005 0001 3010 2300 0000
---- DEBUGGER ENTRY ---------------------------------------------------
CPU=$11ed8, VBL=622, FrameCycles=113716, HBL=222, LineCycles=52, DSP=N/A
$00011ed8 : 7301 DC.W $7301
>
my coredump misses output of program side information but this working from my asserts in other places.
I will make my debugging environment available on GitHub in the upcoming days.
Simon Sunnyboy/Paradize - http://paradize.atari.org/
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
Stay cool, stay Atari!
1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee
-
- Hardware Guru
- Posts: 3003
- Joined: Sat Sep 10, 2005 11:11 am
- Location: Kosice, Slovakia
- Contact:
Re: etv_term vector
A year and a half later I have found some time to test it and indeed it works flawlessly. To properly test this I had to actually fix unhook_xbra() described in The Atari Compendium to make it multitasking-aware and voila! It really works even if the app is terminated due to memory violation!ThorstenOtto wrote:Yes, it's done as part of process termination, which is also called on uncaught exceptions (see the source Christian quoted, kill_program at the end will just call Pterm()). Even Ptermres() will call this.mikro wrote:Does this applies also to exceptions? I mean if an app tries to access hardware or causes memory violation, will this vector still be called?
As I'm most likely going to forget how to do this properly in two hours :), here is the full source code:
xbra.c:
Code: Select all
#include <mint/osbind.h>
#include <stdio.h>
#include <stdlib.h>
#define XBRA_ID 0x58425241L /* 'XBRA' */
#define LONG long
#define WORD short
#define VOID void
typedef struct xbra
{
LONG xbra_id;
LONG app_id;
VOID (*oldvec)();
} XBRA;
extern XBRA my_trap1;
extern void my_trap1_asm_handler(void);
/* this code becomes invalid as soon as app terminates */
void my_trap1_c_handler(void)
{
/* your custom code */
}
static void restore_trap1(void)
{
XBRA *rx;
LONG vecadr, *stepadr;
vecadr = (LONG)Setexc(VEC_GEMDOS, VEC_INQUIRE);
rx = (XBRA*)(vecadr - sizeof(XBRA));
/* Special Case: Vector to remove is first in chain. */
if(rx->xbra_id == XBRA_ID && rx->app_id == my_trap1.app_id
&& vecadr == (LONG)my_trap1_asm_handler)
{
Setexc(VEC_GEMDOS, rx->oldvec);
return;
}
stepadr = (LONG*)&rx->oldvec;
rx = (XBRA*)((LONG)rx->oldvec - sizeof(XBRA));
while(rx->xbra_id == XBRA_ID)
{
if(rx->app_id == my_trap1.app_id
&& *stepadr == (LONG)my_trap1_asm_handler)
{
*stepadr = (LONG)rx->oldvec;
break;
}
stepadr = (LONG*)&rx->oldvec;
rx = (XBRA*)((LONG)rx->oldvec - sizeof(XBRA));
}
}
int main()
{
my_trap1.oldvec = Setexc(VEC_GEMDOS, my_trap1_asm_handler);
/* install a safe net - can call only (X)BIOS there */
Setexc(VEC_PROCTERM, restore_trap1);
printf("Testing GEMDOS...press ENTER\n");
getchar();
/* something terrible has happened */
return -1;
/* never reached! */
Supexec(restore_trap1);
return EXIT_SUCCESS;
}
Code: Select all
.globl _my_trap1
.globl _my_trap1_asm_handler
.globl _my_trap1_c_handler
.text
_my_trap1:
.ascii "XBRA"
.ascii "TEST"
oldvec:
.dc.l 0
_my_trap1_asm_handler:
| no need to store any registers, gcc saves d2-d7/a2-a6
| for us in _my_trap1_c_handler()
jsr _my_trap1_c_handler
move.l oldvec(pc),-(sp)
rts
Code: Select all
m68k-atari-mint-gcc -O2 -fomit-frame-pointer -Wall -pedantic -ansi -o xbra.tos xbra.c xbra_s.S && m68k-atari-mint-flags -S xbra.tos
P.S. That 'flags' command is for FreeMiNT + MP, that way you tell the kernel that it is OK to read from your process' memory when processing the trap handler.
P.P.S. I'm not sure whether etv_term code should save any registers -- it is the first function to execute in Pterm() so it shouldn't use any registers before.
Last edited by mikro on Sun Apr 21, 2019 5:26 pm, edited 4 times in total.
-
- Fuji Shaped Bastard
- Posts: 2370
- Joined: Sun Aug 03, 2014 5:54 pm
Re: etv_term vector
You can achieve the same by using -Wl,-mprg-flags,0x27mikro wrote: P.S. That 'flags' command is for FreeMiNT + MP, that way you tell the kernel that it is OK to read from your process' memory when processing the trap handler.
BTW your example my_trap1_c_handler for the gemdos trap only works by accident. If you would do anything useful there, and the compiler chooses to save some registers to the stack first, you cannot just call the old vector, because the original saved parameters to that function are at the wrong offset. It would also not work when compiled without optimization, because then the call to oldvec is done by a jsr.