Re: __stack_start for ColdFire uClinux

Larry Baker <[email protected]>
Newsgroups gmane.linux.uclinux.devel
Message-ID <[email protected]>
Greg,

> I don't recall off-hand what you will see by forcing a trap 7.
> But it is easy to check, try a strait trap 7 call in a test program.

I hacked the .s file to force a trap #7.  That looked like a normal program exit -- no messages on the console, nothing in dmesg or /var/log/messages.  I'll look at the kernel trap handler and see what trap #7 means.

I use trap #7 because the conditional trap instructions use trap vector #7.

> I am not familiar with gcc's stack checking options and code.
> Does it just check the value of sp at function entry and exit?
> Or is it more elaborate than that?

Stack checking is at function entry only.  So, stack variables declared at the start of a code block within a function are not checked.

Here's the .s files compared side-by-side.  You can see the extra code in the function preamble of overflow() and main():

savaii:gcc baker$ diff -y {no-,}check-stack-overflow.s
#NO_APP								#NO_APP
	.file	"stack-overflow.c"					.file	"stack-overflow.c"
	.section	.rodata						.section	.rodata
.LC0:								.LC0:
	.string	"i = %i\n"						.string	"i = %i\n"
	.text								.text
	.align	2							.align	2
	.globl	overflow						.globl	overflow
	.type	overflow, @function					.type	overflow, @function
overflow:							overflow:
							      >		move.l __stack_start@GOT(%a5),%a0
							      >		lea (404,%a0),%a0
							      >		cmp.l %sp,%a0
							      >		bls.s .+4
							      >		trap #7
	lea (-400,%sp),%sp						lea (-400,%sp),%sp
	move.l %a5,-(%sp)						move.l %a5,-(%sp)
	move.l 408(%sp),%d0						move.l 408(%sp),%d0
	lsl.l #2,%d0							lsl.l #2,%d0
	move.l #404,%d1							move.l #404,%d1
	add.l %sp,%d1							add.l %sp,%d1
	add.l %d1,%d0							add.l %d1,%d0
	lea (408,%sp),%a1						lea (408,%sp),%a1
	move.l %d0,%a0							move.l %d0,%a0
	move.l (%a1),-400(%a0)						move.l (%a1),-400(%a0)
	addq.l #1,408(%sp)						addq.l #1,408(%sp)
	move.l .LC0@GOT(%a5),%d0					move.l .LC0@GOT(%a5),%d0
	move.l 408(%sp),-(%sp)						move.l 408(%sp),-(%sp)
	move.l %d0,-(%sp)						move.l %d0,-(%sp)
	move.l printf@GOT(%a5),%d0					move.l printf@GOT(%a5),%d0
	move.l %d0,%a0							move.l %d0,%a0
	jsr (%a0)							jsr (%a0)
	addq.l #8,%sp							addq.l #8,%sp
	move.l 408(%sp),-(%sp)						move.l 408(%sp),-(%sp)
	move.l overflow@GOT(%a5),%d0					move.l overflow@GOT(%a5),%d0
	move.l %d0,%a1							move.l %d0,%a1
	jsr (%a1)							jsr (%a1)
	addq.l #4,%sp							addq.l #4,%sp
	move.l (%sp)+,%a5						move.l (%sp)+,%a5
	lea (400,%sp),%sp						lea (400,%sp),%sp
	rts								rts
	.size	overflow, .-overflow					.size	overflow, .-overflow
	.align	2							.align	2
	.globl	main							.globl	main
	.type	main, @function						.type	main, @function
main:								main:
							      >		move.l __stack_start@GOT(%a5),%a0
							      >		addq.l #4,%a0
							      >		cmp.l %sp,%a0
							      >		bls.s .+4
							      >		trap #7
	move.l %a5,-(%sp)						move.l %a5,-(%sp)
	clr.l -(%sp)							clr.l -(%sp)
	move.l overflow@GOT(%a5),%d0					move.l overflow@GOT(%a5),%d0
	move.l %d0,%a0							move.l %d0,%a0
	jsr (%a0)							jsr (%a0)
	addq.l #4,%sp							addq.l #4,%sp
	clr.l %d0							clr.l %d0
	move.l (%sp)+,%a5						move.l (%sp)+,%a5
	rts								rts
	.size	main, .-main						.size	main, .-main
	.ident	"GCC: (GNU) 4.6.1 20120905 (prerelease)"		.ident	"GCC: (GNU) 4.6.1 20120905 (prerelease)"
	.section	.note.GNU-stack,"",@progbits			.section	.note.GNU-stack,"",@progbits


> Be mindful that on older ColdFire Cores, that only had a single A7,
> then the CPU will be pushing the exception frame onto the user
> space stack (so an extra 8 bytes).


In addition to implementing the "conditional trap" instruction patterns for non-68020 processors, I fixed the code to always check before pushing any registers on the stack and before allocating space on the stack for automatic variables.  I didn't pick a "minimum" stack that must remain.  For example, the null function void junk{} generates:

#NO_APP
	.file	"junk.c"
	.text
	.align	2
	.globl	junk
	.type	junk, @function
junk:
	move.l __stack_start@GOT(%a5),%a0
	addq.l #4,%a0
	cmp.l %sp,%a0
	bls.s .+4
	trap #7
	rts
	.size	junk, .-junk
	.ident	"GCC: (GNU) 4.6.1 20120905 (prerelease)"
	.section	.note.GNU-stack,"",@progbits

It only checks that 4 bytes are available.  (To account for a frame pointer?  That's my guess.  I changed 4 to INCOMING_FRAME_SP_OFFSET in the stack checking code.  There is not always a frame pointer, though, like in this case.)  Maybe some minimum value would be a good idea, just to account for the single A7 you describe -- so some minimum trap or O/S call could be handled.  It's easy enough to modify the stack checking code.  Not sure, though, what flags tell the compiler there is only one A7.

Larry Baker
US Geological Survey
650-329-5608
[email protected]

_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.