Jonathan Harston
2022-07-18 20:46:12 UTC
Is there something special on BSD2.9 with sbrk() or signal()?
If I claim memory and stick the stack there, and set a signal,
when the signal is triggered everything blows up with the
signal dispatcher in the kernel unable to access memory to
stack to call the signal handler.
This doesn't happen if I leave the stack at the value on
entry at &FF00+xxx, and doesn't happen with Bell Unix v5/6/7.
I can't just leave the stack at &FFxx as it will descend
across I/O memory at &E000 upwards.
I've stripped my test code down to this:
ORG 0
EQUW &0107 ; magic number, also branch to code
EQUW _DATA%-_TEXT% ; size of text
EQUW _BSS%-_DATA% ; size of initialised data
EQUW _END%-_BSS% ; size of uninitialised data
EQUW &0000 ; size of symbol data
EQUW _ENTRY%-_TEXT% ; entry point
EQUW &0000 ; not used
EQUW &0001 ; no relocation info
;
ORG 0
_TEXT%:
_ENTRY%:
mov #1,r0
trap 4 ; write(stdout, "RUN"..)
equw msg1
equw msg2-msg1
;
trap 17 ; sbrk(&E000)
equw &E000
bcs quit ; failed
mov #1,r0
trap 4 ; write(stdout, "SBRK"..)
equw msg2
equw msg3-msg2
;
trap 48 ; signal(SIGQUIT, quit)
equw 3
equw quit
mov #1,r0
trap 4 ; write(stdout, "SET"..)
equw msg3
equw msg4-msg3
;
mov #&E000,sp ; put stack at top of memory
mov #1,r0
trap 4 ; write(stdout, "STOP"..)
equw msg4
equw msg5-msg4
stop:
jmp stop
quit:
mov #1,r0
trap 4 ; write(stdout, "QUIT"..)
equw msg5
equw msg6-msg5
clr r0
trap 1 ; exit
_DATA%:
msg1: equb "RUN",13,10
msg2: equb "SBRK",13,10
msg3: equb "SET",13,10
msg4: equb "STOP",13,10
msg5: equb "QUIT",13,10
msg6:
align
_BSS%:
_END%:
When run, this should display:
RUN
SBRK
SET
STOP
then when I press Ctrl-\ should display
QUIT
and cleanly exit.
Instead it does this:
Berkeley Unix 2.9BSD
:login: root
Welcome to the 2.9BSD (Berkeley) UNIX system.
# cd usr/jgh
# infile
RUN
SBRK
SET
STOP
^\Segmentation fault (core dumped)
#
It does this for any signal I try, and any value of SP I set up.
The memory claimed up to &E000 is actually there, if I put in a
little loop to dump memory from 0000 to DFFF is happily dumps
it all out
0000 blah blah blah blah
etc.
DFF0 blah blah blah blah
E000 Segmentation fault (core dumped) (as expected, it's gone
past the end of memory)
Compiling a short bit of C does as expected:
#include <signal.h>
int null()
{ exit(); }
int main()
{ signal(3,null); while(1) ; }
And examining the generated source is essentially identical to
the above handmade PDP11 code.... *other* than setting the
sbrk() and stack.
So. What is BSD2.9 sbrk() or signal() doing or not doing such
that the signal dispatcher in the kernal explodes trying to
JSR PC,signalhandler
jgh
If I claim memory and stick the stack there, and set a signal,
when the signal is triggered everything blows up with the
signal dispatcher in the kernel unable to access memory to
stack to call the signal handler.
This doesn't happen if I leave the stack at the value on
entry at &FF00+xxx, and doesn't happen with Bell Unix v5/6/7.
I can't just leave the stack at &FFxx as it will descend
across I/O memory at &E000 upwards.
I've stripped my test code down to this:
ORG 0
EQUW &0107 ; magic number, also branch to code
EQUW _DATA%-_TEXT% ; size of text
EQUW _BSS%-_DATA% ; size of initialised data
EQUW _END%-_BSS% ; size of uninitialised data
EQUW &0000 ; size of symbol data
EQUW _ENTRY%-_TEXT% ; entry point
EQUW &0000 ; not used
EQUW &0001 ; no relocation info
;
ORG 0
_TEXT%:
_ENTRY%:
mov #1,r0
trap 4 ; write(stdout, "RUN"..)
equw msg1
equw msg2-msg1
;
trap 17 ; sbrk(&E000)
equw &E000
bcs quit ; failed
mov #1,r0
trap 4 ; write(stdout, "SBRK"..)
equw msg2
equw msg3-msg2
;
trap 48 ; signal(SIGQUIT, quit)
equw 3
equw quit
mov #1,r0
trap 4 ; write(stdout, "SET"..)
equw msg3
equw msg4-msg3
;
mov #&E000,sp ; put stack at top of memory
mov #1,r0
trap 4 ; write(stdout, "STOP"..)
equw msg4
equw msg5-msg4
stop:
jmp stop
quit:
mov #1,r0
trap 4 ; write(stdout, "QUIT"..)
equw msg5
equw msg6-msg5
clr r0
trap 1 ; exit
_DATA%:
msg1: equb "RUN",13,10
msg2: equb "SBRK",13,10
msg3: equb "SET",13,10
msg4: equb "STOP",13,10
msg5: equb "QUIT",13,10
msg6:
align
_BSS%:
_END%:
When run, this should display:
RUN
SBRK
SET
STOP
then when I press Ctrl-\ should display
QUIT
and cleanly exit.
Instead it does this:
Berkeley Unix 2.9BSD
:login: root
Welcome to the 2.9BSD (Berkeley) UNIX system.
# cd usr/jgh
# infile
RUN
SBRK
SET
STOP
^\Segmentation fault (core dumped)
#
It does this for any signal I try, and any value of SP I set up.
The memory claimed up to &E000 is actually there, if I put in a
little loop to dump memory from 0000 to DFFF is happily dumps
it all out
0000 blah blah blah blah
etc.
DFF0 blah blah blah blah
E000 Segmentation fault (core dumped) (as expected, it's gone
past the end of memory)
Compiling a short bit of C does as expected:
#include <signal.h>
int null()
{ exit(); }
int main()
{ signal(3,null); while(1) ; }
And examining the generated source is essentially identical to
the above handmade PDP11 code.... *other* than setting the
sbrk() and stack.
So. What is BSD2.9 sbrk() or signal() doing or not doing such
that the signal dispatcher in the kernal explodes trying to
JSR PC,signalhandler
jgh