Discussion:
[uClinux-dev] __stack_start for ColdFire uClinux
Larry Baker
2012-09-26 02:49:17 UTC
Permalink
I have been chasing what I suspect are stack overflows in NTP. I spotted mention of that there was a gcc option, -fstack-check-symbol=__stack_start, for run-time stack checking on uClinux. I tried that, but it caused an internal compiler error. My development environment is the Sourcery (now Mentor Graphics) CodeBench Lite for ColdFire uClinux SDK. I modified their GCC source to add support for -fstack-limit-symbol. Unfortunately, using the __stack_start symbol to detect stack overflow does not seem to be working out. For my test uClinux executable, stack-overflow.c:

#include <stdio.h>

void overflow( int i ) {

/* Allocate automatic array j[256] so stack limit checking works. */

int j[256];

/* Stack limit checking tests only whether the stack is large enough for */
/* the initial stack allocation: saved registers and automatic variables. */
/* Stack limit checking does not test for stack overflow in the body of a */
/* function. That is what happens when j[] is not present. When j[] is */
/* too large, the program will abnormally terminate on its own (illegal */
/* instruction trap?). j[256] works. */

i++;
printf( "i = %i\n", i );
overflow( i );

}

int main() {

overflow( 0 );

return 0;

}

the stack is allocated 4K (0x1000). When I hacked the .s file to print out the stack pointer and __stack start, it shows that there is more than 4K between the value in the stack pointer and __stack_start:

%sp = 0x405f3ee4
__stack_start = 0x405f08b4

That is not what I was expecting.

Can someone shed some light on why %sp is not roughly __stack_start + 0x1000?

__stack_start is defined in the linker script from the Sourcery SDK, m68k-uclinux/lib/elf2flt.ld, right after .bss and before .junk:

.bss : {
. = ALIGN(0x4) ;
_sbss = ALIGN(0x4) ;
__bss_start = . ;
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.scommon)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.bss*)
*(.gnu.linkonce.b*)
*(COMMON)
. = ALIGN(0x10) ;
_ebss = . ;
_end = . ;
end = . ;
} > flatmem

.stack : {
. = ALIGN(0x4);
__stack_start = .;
}

.junk 0 : { *(.rel*) *(.rela*) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }

Is stack: in the wrong place?

Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov
Greg Ungerer
2012-09-26 12:48:17 UTC
Permalink
Hi Larry,
Post by Larry Baker
#include <stdio.h>
void overflow( int i ) {
/* Allocate automatic array j[256] so stack limit checking works. */
int j[256];
/* Stack limit checking tests only whether the stack is large enough for */
/* the initial stack allocation: saved registers and automatic variables. */
/* Stack limit checking does not test for stack overflow in the body of a */
/* function. That is what happens when j[] is not present. When j[] is */
/* too large, the program will abnormally terminate on its own (illegal */
/* instruction trap?). j[256] works. */
i++;
printf( "i = %i\n", i );
overflow( i );
}
int main() {
overflow( 0 );
return 0;
}
the stack is allocated 4K (0x1000).
How are you setting the app stack size?
Post by Larry Baker
%sp = 0x405f3ee4
__stack_start = 0x405f08b4
That is not what I was expecting.
Can someone shed some light on why %sp is not roughly __stack_start + 0x1000?
.bss : {
. = ALIGN(0x4) ;
_sbss = ALIGN(0x4) ;
__bss_start = . ;
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.scommon)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.bss*)
*(.gnu.linkonce.b*)
*(COMMON)
. = ALIGN(0x10) ;
_ebss = . ;
_end = . ;
end = . ;
} > flatmem
.stack : {
. = ALIGN(0x4);
__stack_start = .;
}
This is a little deceptive, and not completely accurate in general.

If you look at what binfmt_flat.c does when loading a flat format file
you will see that that point is labeled the start of the "brk" region.
When allocating the memory for the process (text, data, stack) we may
get a larger region than requested(1). We use the extra space if we get
it, and that will push the stack further away from the end of the data
region if we do. This is probably what you are seeing. A little trace
in binfmt_flat.c will let you see the exact regions and addresses you
are getting on process start.

(1) Page aligning or buddy allocator rounding means we may get a bit
more, or even potentially a lot more.

Regards
Greg


------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg at snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close, FAX: +61 7 3891 3630
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
Larry Baker
2012-09-26 20:25:04 UTC
Permalink
Greg,
Post by Greg Ungerer
Hi Larry,
Post by Larry Baker
#include <stdio.h>
void overflow( int i ) {
/* Allocate automatic array j[256] so stack limit checking works. */
int j[256];
/* Stack limit checking tests only whether the stack is large enough for */
/* the initial stack allocation: saved registers and automatic variables. */
/* Stack limit checking does not test for stack overflow in the body of a */
/* function. That is what happens when j[] is not present. When j[] is */
/* too large, the program will abnormally terminate on its own (illegal */
/* instruction trap?). j[256] works. */
i++;
printf( "i = %i\n", i );
overflow( i );
}
int main() {
overflow( 0 );
return 0;
}
the stack is allocated 4K (0x1000).
How are you setting the app stack size?
I take the default. I build two images: one with and one without -fstack-limit-symbol=__stack_start:

# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-gcc -mcpu=5208 -fomit-frame-pointer -fno-common -fno-builtin -fno-dwarf2-cfi-asm -msep-data -o no-check-stack-overflow stack-overflow.c

# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-gcc -mcpu=5208 -fomit-frame-pointer -fno-common -fno-builtin -fno-dwarf2-cfi-asm -msep-data -fstack-limit-symbol=__stack_start -o check-stack-overflow stack-overflow.c

The executable says the stack size is 0x1000:

# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-flthdr -p check-stack-overflow
check-stack-overflow
Magic: bFLT
Rev: 4
Build Date: Wed Sep 26 11:54:28 2012
Entry: 0x44
Data Start: 0x3c60
Data End: 0x44e4
BSS End: 0x6590
Stack Size: 0x1000
Reloc Start: 0x44e4
Reloc Count: 0x29
Flags: 0x2 ( Has-PIC-GOT )
Post by Greg Ungerer
Post by Larry Baker
%sp = 0x405f3ee4
__stack_start = 0x405f08b4
That is not what I was expecting.
This is a little deceptive, and not completely accurate in general.
If you look at what binfmt_flat.c does when loading a flat format file
you will see that that point is labeled the start of the "brk" region.
When allocating the memory for the process (text, data, stack) we may
get a larger region than requested(1). We use the extra space if we get
it, and that will push the stack further away from the end of the data
region if we do. This is probably what you are seeing.
If this were the case, __stack_start would still be an accurate value for detecting stack overrun. I see signs of stack overrun before the stack check trips. When I force a trap (trap #7), I get no messages from the O/S on the console, and the shell prompt reappears. (Should I see something? Is there a kernel build option I should enable?) When I run my stack checking test program with j[32], the hardware watchdog timer trips. I'll have to hack the .s file some more to print out __stack_start and %sp when this happens. Perhaps the stack check for j[32] (128 bytes) passes, but the printf library routine is using more stack and is actually causing the system failure.

There should be nothing but stack between __stack_start and the end of the region, where the initial %sp points, correct? If not, I can't use __stack_start as a sentinel.
Post by Greg Ungerer
A little trace
in binfmt_flat.c will let you see the exact regions and addresses you
are getting on process start.
(1) Page aligning or buddy allocator rounding means we may get a bit
more, or even potentially a lot more.
Regards
Greg
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg at snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close, FAX: +61 7 3891 3630
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.uclinux.org/pipermail/uclinux-dev/attachments/20120926/da5cbde0/attachment.html>
Larry Baker
2012-09-27 00:08:57 UTC
Permalink
Greg,

I hacked the .s file for my stack check test program.
# cat stack-overflow.c#include <stdio.h>
void overflow( int i ) {
/* Allocate automatic array j[256] so stack limit checking works. */
int j[256];
/* Stack limit checking tests only whether the stack is large enough for */
/* the initial stack allocation: saved registers and automatic variables. */
/* Stack limit checking does not test for stack overflow in the body of a */
/* function. That is what happens when j[] is not present. When j[] is */
/* too large, the program will abnormally terminate on its own (illegal */
/* instruction trap?). j[256] works. */
i++;
printf( "i = %i\n", i );
overflow( i );
}
int main() {
overflow( 0 );
return 0;
}
# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-gcc -mcpu=5208 -fomit-frame-pointer -fno-common -fno-builtin -fno-dwarf2-cfi-asm -msep-data -fstack-limit-symbol=__stack_start -S -o stack-overflow.s stack-overflow.c
# cat stack-overflow.s
#NO_APP
.file "stack-overflow.c"
.section .rodata
.string "i = %i\n"
.text
.align 2
.globl overflow
move.l __stack_start at GOT(%a5),%a0
lea (1028,%a0),%a0
cmp.l %sp,%a0
bls.s .+4
trap #7
lea (-1024,%sp),%sp
move.l %a5,-(%sp)
addq.l #1,1032(%sp)
move.l .LC0 at GOT(%a5),%d0
move.l 1032(%sp),-(%sp)
move.l %d0,-(%sp)
move.l printf at GOT(%a5),%d0
move.l %d0,%a0
jsr (%a0)
addq.l #8,%sp
move.l 1032(%sp),-(%sp)
move.l overflow at GOT(%a5),%d0
move.l %d0,%a0
jsr (%a0)
addq.l #4,%sp
move.l (%sp)+,%a5
lea (1024,%sp),%sp
rts
.size overflow, .-overflow
.align 2
.globl main
move.l __stack_start at GOT(%a5),%a0
addq.l #4,%a0
cmp.l %sp,%a0
bls.s .+4
trap #7
move.l %a5,-(%sp)
clr.l -(%sp)
move.l overflow at GOT(%a5),%d0
move.l %d0,%a0
jsr (%a0)
addq.l #4,%sp
clr.l %d0
move.l (%sp)+,%a5
rts
.size main, .-main
.ident "GCC: (GNU) 4.6.1 20120905 (patched)"
.section .note.GNU-stack,"", at progbits
# cat stack-overflow.s
#NO_APP
.file "stack-overflow.c"
.section .rodata
.string "i = %i\n"
.string "__stack_start = %p\n"
.string "%%sp = %p\n"
.text
.align 2
.globl overflow
move.l __stack_start at GOT(%a5),%a0
lea (1028,%a0),%a0
cmp.l %sp,%a0
bls.s .+4
trap #7
lea (-1024,%sp),%sp
move.l %a5,-(%sp)
addq.l #1,1032(%sp)
move.l .LC0 at GOT(%a5),%d0
move.l 1032(%sp),-(%sp)
move.l %d0,-(%sp)
move.l printf at GOT(%a5),%d0
move.l %d0,%a0
jsr (%a0)
addq.l #8,%sp
move.l %sp,-(%sp)
move.l .LC2 at GOT(%a5),-(%sp)
move.l printf at GOT(%a5),%a0
jsr (%a0)
addq.l #8,%sp
move.l 1032(%sp),-(%sp)
move.l overflow at GOT(%a5),%d0
move.l %d0,%a0
jsr (%a0)
addq.l #4,%sp
move.l (%sp)+,%a5
lea (1024,%sp),%sp
rts
.size overflow, .-overflow
.align 2
.globl main
move.l __stack_start at GOT(%a5),%a0
addq.l #4,%a0
cmp.l %sp,%a0
bls.s .+4
trap #7
move.l %a5,-(%sp)
move.l __stack_start at GOT(%a5),-(%sp)
move.l .LC1 at GOT(%a5),-(%sp)
move.l printf at GOT(%a5),%a0
jsr (%a0)
addq.l #8,%sp
move.l %sp,-(%sp)
move.l .LC2 at GOT(%a5),-(%sp)
move.l printf at GOT(%a5),%a0
jsr (%a0)
addq.l #8,%sp
clr.l -(%sp)
move.l overflow at GOT(%a5),%d0
move.l %d0,%a0
jsr (%a0)
addq.l #4,%sp
clr.l %d0
move.l (%sp)+,%a5
rts
.size main, .-main
.ident "GCC: (GNU) 4.6.1 20120905 (patched)"
.section .note.GNU-stack,"", at progbits
# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-gcc -mcpu=5208 -fomit-frame-pointer -fno-common -fno-builtin -fno-dwarf2-cfi-asm -msep-data -fstack-limit-symbol=__stack_start -o check-stack-overflow stack-overflow.s
/ # /usr/bin/check-stack-overflow
__stack_start = 0x406148b4
%sp = 0x40617ee4
i = 1
%sp = 0x40617ad8
i = 2
%sp = 0x406176cc
i = 3
%sp = 0x406172c0
i = 4
%sp = 0x40616eb4
i = 5
%sp = 0x40616aa8
i = 6
%s
Watchdog Timer Reset
There must be code between __stack_start and the initial stack pointer. Yes? binfmt_flat.c knows all? By the way, where is binfmt_flat.c?

I'm on vacation for five days. I'll pick this up again when I get back.

Thanks,

Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.uclinux.org/pipermail/uclinux-dev/attachments/20120926/08614361/attachment.html>
Greg Ungerer
2012-09-27 13:16:20 UTC
Permalink
Hi Larry,
Post by Larry Baker
I hacked the .s file for my stack check test program.
I haven't had a minute to look over the code yet. Will get back to
you on that.


[snip]
Post by Larry Baker
There must be code between __stack_start and the initial stack pointer. Yes?
No code in that region. Possibly data, though typically not.
Post by Larry Baker
binfmt_flat.c knows all? By the way, where is binfmt_flat.c?
That is the kernel's FLAT file loader. See linux/fs/binfmt_flat.c

Regards
Greg



------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg at snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close, FAX: +61 7 3891 3630
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
Greg Ungerer
2012-09-27 06:57:54 UTC
Permalink
Hi Larry,
Post by Larry Baker
Post by Greg Ungerer
Post by Larry Baker
#include <stdio.h>
void overflow( int i ) {
/* Allocate automatic array j[256] so stack limit checking works. */
int j[256];
/* Stack limit checking tests only whether the stack is large enough for */
/* the initial stack allocation: saved registers and automatic variables. */
/* Stack limit checking does not test for stack overflow in the body of a */
/* function. That is what happens when j[] is not present. When j[] is */
/* too large, the program will abnormally terminate on its own (illegal */
/* instruction trap?). j[256] works. */
i++;
printf( "i = %i\n", i );
overflow( i );
}
int main() {
overflow( 0 );
return 0;
}
the stack is allocated 4K (0x1000).
How are you setting the app stack size?
# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-gcc -mcpu=5208 -fomit-frame-pointer -fno-common -fno-builtin -fno-dwarf2-cfi-asm -msep-data -o no-check-stack-overflow stack-overflow.c
# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-gcc -mcpu=5208 -fomit-frame-pointer -fno-common -fno-builtin -fno-dwarf2-cfi-asm -msep-data -fstack-limit-symbol=__stack_start -o check-stack-overflow stack-overflow.c
# toolchains/freescale-coldfire-2011.09-patched/bin/m68k-uclinux-flthdr -p check-stack-overflow
check-stack-overflow
Magic: bFLT
Rev: 4
Build Date: Wed Sep 26 11:54:28 2012
Entry: 0x44
Data Start: 0x3c60
Data End: 0x44e4
BSS End: 0x6590
Stack Size: 0x1000
Reloc Start: 0x44e4
Reloc Count: 0x29
Flags: 0x2 ( Has-PIC-GOT )
Post by Greg Ungerer
Post by Larry Baker
%sp = 0x405f3ee4
__stack_start = 0x405f08b4
That is not what I was expecting.
This is a little deceptive, and not completely accurate in general.
If you look at what binfmt_flat.c does when loading a flat format file
you will see that that point is labeled the start of the "brk" region.
When allocating the memory for the process (text, data, stack) we may
get a larger region than requested(1). We use the extra space if we get
it, and that will push the stack further away from the end of the data
region if we do. This is probably what you are seeing.
If this were the case, __stack_start would still be an accurate value for detecting stack overrun. I see signs of stack overrun before the stack check trips. When I force a trap (trap #7), I get no messages from the O/S on the console, and the shell prompt reappears. (Should I see something?
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.
Post by Larry Baker
Is there a kernel build option I should enable?) When I run my stack checking test program with j[32], the hardware watchdog timer trips. I'll have to hack the .s file some more to print out __stack_start and %sp when this happens. Perhaps the stack check for j[32] (128 bytes) passes, but the printf library routine is using more stack and is actually causing the system failure.
There is no special kernel options to support this currently.
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?

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).
Post by Larry Baker
There should be nothing but stack between __stack_start and the end of the region, where the initial %sp points, correct? If not, I can't use __stack_start as a sentinel.
Normally there isn't. In the past it has been possible to use the brk
system call and use the "spare" space. But in practice I don't think
anybody ever used this support much.

Regards
Greg


------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg at snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close FAX: +61 7 3217 5323
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
Larry Baker
2012-10-03 00:45:30 UTC
Permalink
Greg,
Post by Greg Ungerer
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.
Post by Greg Ungerer
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
Post by Greg Ungerer
move.l __stack_start at 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 at GOT(%a5),%d0 move.l .LC0 at GOT(%a5),%d0
move.l 408(%sp),-(%sp) move.l 408(%sp),-(%sp)
move.l %d0,-(%sp) move.l %d0,-(%sp)
move.l printf at GOT(%a5),%d0 move.l printf at 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 at GOT(%a5),%d0 move.l overflow at 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
Post by Greg Ungerer
move.l __stack_start at 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 at GOT(%a5),%d0 move.l overflow at 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,"", at progbits .section .note.GNU-stack,"", at progbits
Post by Greg Ungerer
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 at 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,"", at 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
baker at usgs.gov

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.uclinux.org/pipermail/uclinux-dev/attachments/20121002/c09dd89d/attachment.html>
Greg Ungerer
2012-10-03 07:00:37 UTC
Permalink
Hi Larry,
Post by Larry Baker
Post by Greg Ungerer
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.
Issuing a trap #7 will just cause the kernel to send a SIGILL signal to the
process. If it is not caugth it will probably cause process termination.
(All software traps, except 0, do this on ColdFire).
Post by Larry Baker
Post by Greg Ungerer
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.
Ok, better than nothing I guess.
Post by Larry Baker
Post by Greg Ungerer
move.l __stack_start at GOT(%a5),%a0
lea (404,%a0),%a0
cmp.l %sp,%a0
bls.s .+4
trap #7
It would be pretty easy to just add a whole bunch of debug trace in
the kernel when you get this - just for debugging purposes of course.
Probably makes no sense for a user space process to catch the SIGILL
in this case. You are out of stack and drastic action is needed.


[snip]
Post by Larry Baker
Post by Greg Ungerer
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).
#NO_APP
.file"junk.c"
.text
.align2
.globljunk
move.l __stack_start at GOT(%a5),%a0
addq.l #4,%a0
cmp.l %sp,%a0
bls.s .+4
trap #7
rts
.sizejunk, .-junk
.ident"GCC: (GNU) 4.6.1 20120905 (prerelease)"
.section.note.GNU-stack,"", at 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.
There is no need to tell the compiler, it doesn't really care. That is
only something that the Operating System cares about. User processes are
completely oblivious to the implementation of exception frames - and
that is what you want.

On your example junk function above, if you are running that on a
ColdFire with a single A7 then when you hit "trap #7" the CPU will
push the 8 bytes of the exception frame onto the current user stack,
and then switch to supervisor mode (ie enter the kernel). On most
other CPU types, and ColdFires that have separate supervisor and user
A7 registers, the CPU will switch to supervisor mode, switch to using
the kernels A7 and then push the 8 bytes of exception frame.

You would have to be unlucky to be 8 bytes short, that is why I said
to just be mindfull of this happening.

Regards
Greg
--
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg at snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close FAX: +61 7 3217 5323
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
Larry Baker
2012-10-03 21:38:49 UTC
Permalink
Greg,

On 3 Oct 2012, at 12:00 AM, Greg Ungerer wrote:

For stack checking to be useful, I need two things: 1) it has to detect the (preferably impending) occurrence of a stack overflow, and 2) it has to give notice that it has occurred.

For task 2), I'm trying to figure out how to enable the typical Linux behavior, such as a tty message "Illegal instruction (core dumped)", and/or register dumps on the tty or in /var/log/messages.
Post by Greg Ungerer
Post by Larry Baker
I use trap #7 because the conditional trap instructions use trap vector #7.
Issuing a trap #7 will just cause the kernel to send a SIGILL signal to the
process. If it is not caugth it will probably cause process termination.
(All software traps, except 0, do this on ColdFire).
So far I found where the vectored interrupts are setup in arch/m68k/kernel/vectors.c. trap #7 (VEC_TRAP7, I assume) is routed to ENTRY(trap) in arch/m68k/kernel/entry_mm.S, which then calls trap_c() in arch/m68k/kernel/traps.c. traps_c decides to signal SIGILL(ILL_ILLTRAP) and calls force_sig_info() in kernel/signal.c. That's as far as I've gotten. I think maybe kernel/exec.c is where I should look next for what notification options there are.
Post by Greg Ungerer
Post by Larry Baker
move.l __stack_start at GOT(%a5),%a0
lea (404,%a0),%a0
cmp.l %sp,%a0
bls.s .+4
trap #7
It would be pretty easy to just add a whole bunch of debug trace in
the kernel when you get this - just for debugging purposes of course.
Probably makes no sense for a user space process to catch the SIGILL
in this case. You are out of stack and drastic action is needed.
I'm still looking for the conditions it takes to have something like show_registers() in arch/m68k/kernel/traps.c called when the trap occurs.
Post by Greg Ungerer
Post by Larry Baker
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).
[snip]
Post by Greg Ungerer
Post by Larry Baker
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.
There is no need to tell the compiler, it doesn't really care. That is
only something that the Operating System cares about. User processes are
completely oblivious to the implementation of exception frames - and
that is what you want.
Just to be completely safe (picky, I know). I guess gcc -mcpu could be used to figure out whether there is a separate interrupt stack.
Post by Greg Ungerer
On your example junk function above, if you are running that on a
ColdFire with a single A7 then when you hit "trap #7" the CPU will
push the 8 bytes of the exception frame onto the current user stack,
and then switch to supervisor mode (ie enter the kernel). On most
other CPU types, and ColdFires that have separate supervisor and user
A7 registers, the CPU will switch to supervisor mode, switch to using
the kernels A7 and then push the 8 bytes of exception frame.
I assume the same is true for interrupts: the single A7 has to be able to at least hold the current PC and PSW. Another good reason to make sure the stack has at least 8 bytes.
Post by Greg Ungerer
You would have to be unlucky to be 8 bytes short, that is why I said
to just be mindfull of this happening.
Agreed.

As for task 1), I've been working my way through fs/binfmt_flat.c. I found load_flat_binary() handles the "main" executable; load_flat_shared_library() handles libraries. They both call load_flat_file() to do most of the work. From what I can tell so far, the initial memory layout of the "main" executable is:

<--- memp + memp_size (physical memory address)
unused (space for bss, stack, environment variables, command-line arguments)
shared library table (allocated)
relocation table (read from executable, released after relocations are done)
data (read from executable)
text (read from executable)
<--- memp (physical memory address)

After relocation (ready for execution), the memory layout is:

<--- memp + memp_size (physical memory address)
environment variables
command-line arguments
argv[]
<--- initial sp
stack
<--- memp + memp_size - stack_len (physical memory address)
brk
<--- start_brk (physical memory address)
<--- __STACK_START
<--- datapos + data_len + bss_len (physical memory address)
bss
<--- datapos + data_len (physical memory address)
data
<--- datapos (physical memory address)
text
<--- memp/textpos (physical memory address)

The crux of my problem seems to be that __STACK_START is not really the "top" of the stack. There is an area identified as BRK that can be overwritten before the stack check logic trips. I do not know what it is used for or what can happen if it gets clobbered.

binfmt_flat.c honors a header flag, FLAT_FLAG_KTRACE, to print out the executable layout. I'll try to figure out how to enable that.
Post by Greg Ungerer
Regards
Greg
--
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg at snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close FAX: +61 7 3217 5323
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.uclinux.org/pipermail/uclinux-dev/attachments/20121003/a2251263/attachment.html>
Geert Uytterhoeven
2012-10-04 05:00:14 UTC
Permalink
Post by Larry Baker
Post by Greg Ungerer
It would be pretty easy to just add a whole bunch of debug trace in
the kernel when you get this - just for debugging purposes of course.
Probably makes no sense for a user space process to catch the SIGILL
in this case. You are out of stack and drastic action is needed.
I'm still looking for the conditions it takes to have something like
show_registers() in arch/m68k/kernel/traps.c called when the trap occurs.
The registers are only printed for exceptions caused in kernel mode.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Larry Baker
2012-10-04 05:15:31 UTC
Permalink
Geert,
Post by Geert Uytterhoeven
Post by Larry Baker
I'm still looking for the conditions it takes to have something like
show_registers() in arch/m68k/kernel/traps.c called when the trap occurs.
The registers are only printed for exceptions caused in kernel mode.
Is this a difference between uClinux and Linux?

I have worked on bugs in IBM's J9 JVM on ARM Linux (MontaVista 2.4 kernel) which resulted in register and stack dumps of user code (the JVM) to the console and /var/log/messages for access violations (illegal instruction fetch). Like you say, I originally thought those must have been kernel traps. But, they were not followed by an Oops. I tracked down the kernel code that was printing the messages and convinced myself that the fault was actually occurring in user mode, not kernel mode -- which made much more sense for a JVM.
Post by Geert Uytterhoeven
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov
Geert Uytterhoeven
2012-10-04 06:18:45 UTC
Permalink
Hi Larry,
Post by Larry Baker
Post by Geert Uytterhoeven
Post by Larry Baker
I'm still looking for the conditions it takes to have something like
show_registers() in arch/m68k/kernel/traps.c called when the trap occurs.
The registers are only printed for exceptions caused in kernel mode.
Is this a difference between uClinux and Linux?
I have worked on bugs in IBM's J9 JVM on ARM Linux (MontaVista 2.4 kernel) which resulted in register and stack dumps of user code (the JVM) to the console and /var/log/messages for access violations (illegal instruction fetch). Like you say, I originally thought those must have been kernel traps. But, they were not followed by an Oops. I tracked down the kernel code that was printing the messages and convinced myself that the fault was actually occurring in user mode, not kernel mode -- which made much more sense for a JVM.
Typically, you do not want to spam the kernel log for exceptions in user mode,
as this may allow a DoS attack.

It may be useful for debugging, though.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Larry Baker
2012-10-04 06:33:57 UTC
Permalink
Geert,
Post by Geert Uytterhoeven
Post by Larry Baker
I'm still looking for the conditions it takes to have something like
show_registers() in arch/m68k/kernel/traps.c called when the trap occurs.
The registers are only printed for exceptions caused in kernel mode.
if (sig_kernel_coredump(signr)) {
if (print_fatal_signals)
print_fatal_signal(regs, info->si_signo);
/*
* If it was able to dump core, this kills all
* other threads in the group and synchronizes with
* their demise. If we lost the race with another
* thread getting here, it set group_exit_code
* first and our do_group_exit call below will use
* that value and ignore the one we pass it.
*/
do_coredump(info->si_signo, info->si_signo, regs);
}
print-fatal-signals=
[KNL] debug: print fatal signals
If enabled, warn about various signal handling
related application anomalies: too many signals,
too many POSIX.1 timers, fatal signals causing a
coredump - etc.
If you hit the warning due to signal overflow,
you might want to try "ulimit -i unlimited".
default: off.
Tomorrow I will find out if this will produce what I am looking for.
Post by Geert Uytterhoeven
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov
Larry Baker
2012-10-04 20:05:56 UTC
Permalink
/ # echo 1 >/proc/sys/kernel/print-fatal-signals
/ # trap
trap/82: potentially unexpected fatal signal 4.
Format 04 Vector: 009c PC: 4052812e Status: 0000 Not tainted
ORIG_D0: ffffffff D0: 405285c8 A2: 40529f64 A1: 405284dc
A0: 40528128 D5: 40528524 D4: 00000000
D3: 00000000 D2: 00000001 D1: 0000002f
USP: 40529f10
FYI. The messages do not get sent to /var/log/messages. I don't know why. That would be more useful.

I am still puzzled, though, why uClinux is silent when a program is aborted when it receives an unhandled fatal signal. Mainline Linux (really the shell?) prints out a message like
[root at atompc sdk]# ./SIGILL
Illegal instruction
(SIGILL.c is the example program from http://en.wikipedia.org/wiki/SIGILL.) After a reboot of uClinux, I get nothing
/ # SIGILL
/ # echo 1 >/proc/sys/kernel/print-fatal-signals
/ # SIGILL
SIGILL/79: potentially unexpected fatal signal 4.
Format 04 Vector: 002c PC: 4052e544 Status: 0000 Not tainted
ORIG_D0: ffffffff D0: 4052e544 A2: 4052ff60 A1: 4052e4ec
A0: 4052e544 D5: 4052e524 D4: 00000000
D3: 00000000 D2: 00000001 D1: 0000002f
USP: 4052ff04
Is this a uClinux thing? Or, a BusyBox (my uClinux shell) thing?

Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov
Larry Baker
2012-10-05 18:38:32 UTC
Permalink
Post by Larry Baker
I am still puzzled, though, why uClinux is silent when a program is aborted when it receives an unhandled fatal signal. Mainline Linux (really the shell?) prints out a message like
[root at atompc sdk]# ./SIGILL
Illegal instruction
(SIGILL.c is the example program from http://en.wikipedia.org/wiki/SIGILL.) After a reboot of uClinux, I get nothing
/ # SIGILL
/ # echo 1 >/proc/sys/kernel/print-fatal-signals
/ # SIGILL
SIGILL/79: potentially unexpected fatal signal 4.
Format 04 Vector: 002c PC: 4052e544 Status: 0000 Not tainted
ORIG_D0: ffffffff D0: 4052e544 A2: 4052ff60 A1: 4052e4ec
A0: 4052e544 D5: 4052e524 D4: 00000000
D3: 00000000 D2: 00000001 D1: 0000002f
USP: 4052ff04
Is this a uClinux thing? Or, a BusyBox (my uClinux shell) thing?
I'll answer my own question.

It is the shell that prints out the "Illegal instruction" message. I found the code in bash that does that and added it to the BusyBox hush shell. The SDK I use has a rather old BusyBox, 1.13.3. The hush shell is in busybox-1.13.3/shell/hush.c. checkjobs() waits for all child processes -- there is no distinction made between job control jobs and non-job control jobs like there is in bash. There is already code there that can be (hand) enabled to be verbose about what happens to a job. Enabling that also makes hush very chatty. So, I added an #else clause for the #if DEBUG_JOBS conditional code in checkjobs() to mimic bash's behavior. Here's the patch for busybox-1.13.3:

--- busybox-1.13.3/shell/hush.c
+++ busybox-1.13.3-patched/shell/hush.c
@@ -1720,2 +1720,13 @@
childpid, WEXITSTATUS(status));
Post by Larry Baker
+#else
+ if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status)) {
+ int sig = WTERMSIG (status);
+ if ((sig != SIGINT) && (sig != SIGPIPE)) {
+ char *s = strsignal (sig);
+ if ( s != NULL )
+ fprintf (stderr, "%s\n", s);
+ else
+ fprintf (stderr, "Unknown signal: %d\n", sig);
+ }
+ }
#endif
/ # trap
Illegal instruction
/ # SIGILL
Illegal instruction
Now I can go back and find out where the applications I use are failing. I suspect stack overflows, which my implementation of gcc -stack-check-symbol=__stack_start for non-68020 (e.g., ColdFire) processors can catch now.

Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.uclinux.org/pipermail/uclinux-dev/attachments/20121005/bb89dcc9/attachment.html>
Larry Baker
2012-10-03 22:06:56 UTC
Permalink
Greg,

As far as my task 2) to properly detect stack overflow, I think the source of my problem is that the __stack_start symbol is not correctly defined.

I found the flthdr -k option to enable the FLAT_FLAG_KTRACE flag for printing the executable layout.
# toolchains/freescale-coldfire-2011.09/bin/m68k-uclinux-flthdr check-stack-overflow
check-stack-overflow
Magic: bFLT
Rev: 4
Build Date: Wed Sep 26 16:52:43 2012
Entry: 0x44
Data Start: 0x3ca0
Data End: 0x4544
BSS End: 0x65f0
Stack Size: 0x1000
Reloc Start: 0x4544
Reloc Count: 0x29
Flags: 0x12 ( Has-PIC-GOT Kernel-Traced-Load )
When I run the program, I can see that the stack overflow checking is not preventing the stack from getting clobbered. The stack overruns into the BSS, causing the hardware watchdog timer to trip.
/ # check-stack-overflow
BINFMT_FLAT: Loading file: /usr/bin/check-stack-overflow
Mapping is 4063c000, Entry point is 44, data_start is 3ca0
Load /usr/bin/check-stack-overflow: TEXT=4063c040-4063fca0 DATA=40608004-406088a8 BSS=406088a8-4060a954
__stack_start = 0x406088b4
%sp = 0x4060beec
i = 1
%sp = 0x4060bae0
i = 2
%sp = 0x4060b6d4
i = 3
%sp = 0x4060b2c8
i = 4
%sp = 0x4060aebc
i = 5
%sp = 0x4060aab0
i = 6
%sp
Watchdog Timer Reset
__stack_start (0x406088b4) is clearly wrong; it should have a value greater than the end of the BSS section (0x4060a954).
# toolchains/freescale-coldfire-2011.09/bin/m68k-uclinux-objdump -t check-stack-overflow.gdb
check-stack-overflow.gdb: file format elf32-m68k
00000000 w *UND* 00000000 __deregister_frame_info
00000000 w *UND* 00000000 __h_errno_location
00000000 w *UND* 00000000 __pthread_initialize_minimal
00000000 w *UND* 00000000 __register_frame_info
00000000 w *UND* 00000000 _Jv_RegisterClasses
00000000 l *ABS* 00000000 EBITS
00000000 l *ABS* 00000000 EQUAL
00000000 l *ABS* 00000000 have_current_got
00000000 l *ABS* 00000000 have_current_got
00000000 l *ABS* 00000000 NIL
00000000 l *ABS* 00000000 NOOP
[snip]
ffffffff l *ABS* 00000000 LESS
ffffffff l *ABS* 00000000 QUIET_NaN
ffffffff l *ABS* 00000000 UNKNOWN
ffffffff l *ABS* 00000000 UNKNOWN
00000000 l df *ABS* 00000000 __C_ctype_b.c
00000000 l df *ABS* 00000000 __errno_location.c
00000000 l df *ABS* 00000000 __uClibc_main.c
[snip]
00000000 l df *ABS* 00000000 write.c
00004510 g *ABS* 00000000 _edata
00000000 l d .text 00000000 .text
00000004 g .text 00000000 _stext
00000004 g F .text 00000000 _start
[snip]
00003be0 l F .text 00000000 __do_global_ctors_aux
00003c0e l F .text 00000000 call___do_global_ctors_aux
00003c1c l O .text 00000000 __JCR_END__
00003c1c l O .text 00000000 __JCR_LIST__
00003c20 g F .text 00000000 _init
00003c34 g F .text 00000000 _fini
00003c60 g .text 00000000 _etext
00003c60 g .data 00000000 __data_start
00003c60 g .data 00000000 _sdata
00003c60 g .data 00000000 _ssro_size
00003c60 g .data 00000000 _ssrw_size
00003c60 g .data 00000000 data_start
00003c60 l O .data 00000000 _GLOBAL_OFFSET_TABLE_
00003c60 l d .data 00000000 .data
[snip]
00004500 l .data 00000000 __fini_array_end
00004500 l .data 00000000 __fini_array_start
00004500 l .data 00000000 __init_array_end
00004500 l .data 00000000 __init_array_start
00004500 l .data 00000000 __preinit_array_end
00004500 l .data 00000000 __preinit_array_start
00004500 l O .eh_frame 00000000 __EH_FRAME_BEGIN__
00004500 l O .eh_frame 00000000 __FRAME_END__
00004500 l d .eh_frame 00000000 .eh_frame
00004504 g .bss 00000000 __bss_start
00004504 g .bss 00000000 _sbss
00004504 l O .bss 00000001 completed.4562
00004504 l d .bss 00000000 .bss
00004506 l O .bss 00000004 dtor_idx.4564
0000450a l O .bss 00000018 object.4577
00004524 g O .bss 00000004 _stdio_openlist_del_count
00004528 g O .bss 00000004 _stdio_openlist_use_count
0000452c l O .bss 00002000 _fixed_buffers
0000652c l O .bss 0000000a _bss_custom_printf_spec
00006538 l O .bss 00000004 __rtld_fini
0000653c l O .bss 00000004 __app_fini
00006540 g O .bss 00000004 __pagesize
00006544 w O .bss 00000004 environ
00006544 g O .bss 00000004 __environ
00006548 g O .bss 00000004 __libc_stack_end
0000654c l O .bss 00000004 been_there_done_that.3075
00006550 l O .bss 00000004 __exit_cleanup
00006554 w O .bss 00000004 _h_errno
00006554 g O .bss 00000004 h_errno
00006558 w O .bss 00000004 _errno
00006558 g O .bss 00000004 errno
0000655c l O .bss 00000028 _custom_printf_arginfo
00006584 g O .bss 00000028 .hidden _custom_printf_handler
000065b0 g .bss 00000000 _ebss
000065b0 g .bss 00000000 _end
000065b0 g .bss 00000000 end
00004510 g .comment 00000000 __stack_start
00000000 l d .comment 00000000 .comment
00000000 l d .debug_abbrev 00000000 .debug_abbrev
00000000 l d .debug_aranges 00000000 .debug_aranges
00000000 l d .debug_frame 00000000 .debug_frame
00000000 l d .debug_info 00000000 .debug_info
00000000 l d .debug_line 00000000 .debug_line
00000000 l d .debug_loc 00000000 .debug_loc
00000000 l d .debug_ranges 00000000 .debug_ranges
00000000 l d .debug_str 00000000 .debug_str
I don't know the ld scripting language. I will try to figure out how to define __start_stack to have the same value as, for example, .bss _end.

In the mean time, I'll try using _end instead of __stack_start for the stack limit symbol.

Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.uclinux.org/pipermail/uclinux-dev/attachments/20121003/06edbe00/attachment.html>
Larry Baker
2012-10-04 01:16:29 UTC
Permalink
Greg,
Post by Larry Baker
In the mean time, I'll try using _end instead of __stack_start for the stack limit symbol.
gcc -fstack-limit-symbol=_end works.
Post by Larry Baker
I don't know the ld scripting language. I will try to figure out how to define __start_stack to have the same value as, for example, .bss _end.
Here's a patch that corrects the definition of __stack_start in elf2flt.ld.in:

--- elf2flt-orig/elf2flt.ld.in
+++ elf2flt/elf2flt.ld.in
@@ -172,3 +172,3 @@
@SYMBOL_PREFIX at _stack_start = .;
- }
+ } > flatmem

With the patch, gcc -fstack-limit-symbol=__stack_start works. Please have the people that maintain elf2flt take a look at it.

That is, the stack check trips and the program exits without clobbering the stack. It is silent, though -- there is no indication that SIGILL occurred. I still haven't figured out how to enable a message and/or register dump when this happens.

Larry Baker
US Geological Survey
650-329-5608
baker at usgs.gov
Greg Ungerer
2012-10-04 02:34:25 UTC
Permalink
Hi Larry,
Post by Larry Baker
Post by Larry Baker
In the mean time, I'll try using _end instead of __stack_start for the stack limit symbol.
gcc -fstack-limit-symbol=_end works.
Post by Larry Baker
I don't know the ld scripting language. I will try to figure out how to define __start_stack to have the same value as, for example, .bss _end.
--- elf2flt-orig/elf2flt.ld.in
+++ elf2flt/elf2flt.ld.in
@@ -172,3 +172,3 @@
@SYMBOL_PREFIX at _stack_start = .;
- }
+ } > flatmem
Yep, that would be it.
Post by Larry Baker
With the patch, gcc -fstack-limit-symbol=__stack_start works. Please have the people that maintain elf2flt take a look at it.
That would be me. I have pushed that fix into the CVS.
Thanks.

Regards
Greg
--
------------------------------------------------------------------------
Greg Ungerer -- Principal Engineer EMAIL: gerg at snapgear.com
SnapGear Group, McAfee PHONE: +61 7 3435 2888
8 Gardner Close, FAX: +61 7 3891 3630
Milton, QLD, 4064, Australia WEB: http://www.SnapGear.com
Loading...