Dmitry Adamushko wrote:
> >Was this example generated by a real world compiler? (Which one?)
>
> [adamushkad@cplx219]/>mips-linux-uclibc-gcc -v
> Reading specs from
> /vobs/linux/tools/mips/gcc-3.4.2/bin/../lib/gcc/mips-linux-uclibc/3.4.2/specs
> Configured with:
> /vobs/linux/tools/buildroot/toolchain_build_mips/gcc-3.4.2/configure
> --prefix=/vobs/linux/tools/buildroot/build_mips/staging_dir
> --build=i386-pc-linux-gnu
> --host=i386-pc-linux-gnu
> --target=mips-linux-uclibc
> --enable-languages=c,c++
> --enable-shared
> --disable-__cxa_atexit
> --enable-target-optspace
> -with-gnu-ld
> --disable-nls
> --enable-multilib
> Thread model: posix
>
> gcc version 3.4.2
I figure it doesn't create such an zero access as shown in the example.
> >I'm inclined to claim the example is broken WRT ABI rules since it
> >doesn't enclose the whole user code in the prologue/epilogue bracket.
> >
>
> It's o32. So it explicitly requires that when the prologue and
> epilogue have been used in the function, all the user code must be
> place in between, right?
That's basically the definition of "prologue" and "epilogue".
> In this light, the unlike(ofs == 0) in unwind_stack() aims at catching
> cases when <sp> is wrong (if addiu sp,sp,OFFSET is normally the very
> first instruction)
Technically it is probably ok, since the o32 ABI covers only PIC code,
while the kernel is non-PIC.
> ok, here is an example from kernel/sched.o (the same compiler).
>
> 00000098 <enqueue_task>:
> 98: 8c820018 lw v0,24(a0) <----- before the
> prologue
> 9c: 27bdfff8 addiu sp,sp,-8
> a0: afbe0000 sw s8,0(sp)
> a4: 000210c0 sll v0,v0,0x3
> a8: 00a21021 addu v0,a1,v0
> ac: 24420018 addiu v0,v0,24
> b0: 8c460004 lw a2,4(v0)
> b4: 24830020 addiu v1,a0,32
> b8: ac430004 sw v1,4(v0)
> bc: ac820020 sw v0,32(a0)
> c0: ac660004 sw a2,4(v1)
> c4: acc30000 sw v1,0(a2)
> c8: 8c860018 lw a2,24(a0)
> cc: 24a70004 addiu a3,a1,4
> d0: 03a0f021 move s8,sp
> d4: 00061142 srl v0,a2,0x5
> d8: 00021080 sll v0,v0,0x2
> dc: 00e23821 addu a3,a3,v0
> e0: 8ce30000 lw v1,0(a3)
> e4: 30c6001f andi a2,a2,0x1f
> e8: 24020001 li v0,1
> ec: 00c21004 sllv v0,v0,a2
> f0: 00621825 or v1,v1,v0
> f4: ace30000 sw v1,0(a3)
> f8: 8ca20000 lw v0,0(a1)
> fc: 03c0e821 move sp,s8
> 100: 8fbe0000 lw s8,0(sp)
> 104: 24420001 addiu v0,v0,1
> 108: 27bd0008 addiu sp,sp,8
> 10c: aca20000 sw v0,0(a1)
> 110: 03e00008 jr ra
> 114: ac850028 sw a1,40(a0) <------------
> after the epilogue
It looks rather broken, given that the stack frame is only used to
pointlessly push s8 around. The compiler should have optimized it away.
> As I can see, normally this compiler places "addiu sp,sp,FRAME_SIZE"
> at the branch delay slot of "jr ra" but e.g. enqueue_task() (example
> above) and request_task() are exceptions. btw, the very first
> instruction is also placed before the epilogue.
>
> Are there any configure options that might have caused such a
> behaviour [hmmm... e.g. gcc was configured with --ignore-abi-rulles :]
> ? Although, I don't think this would be an option-dependent case.
Well, breakage happens from time to time in gcc. To cover such cases
it would be nice to have a more robust stack unwinder, but that's easier
said than done.
Thiemo
|