[Top] [All Lists]

Re: unwind_stack() and an exception at the last instruction (after the e

To: Dmitry Adamushko <>
Subject: Re: unwind_stack() and an exception at the last instruction (after the epilogue)
From: Thiemo Seufer <>
Date: Wed, 13 Dec 2006 13:52:22 +0000
Cc: Ralf Baechle <>,
In-reply-to: <>
Original-recipient: rfc822;
References: <> <> <> <>
User-agent: Mutt/1.5.13 (2006-08-11)
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.


<Prev in Thread] Current Thread [Next in Thread>