Windows CE: Prefetch Aborts, why they are difficult to locate

Prefetch aborts can be difficult to locate and fix.  To understand why, we first need to understand what a prefetch abort is.  A prefetch abort occurs when the CPU runs out of instructions in its pipeline.  But that can also mean that a zero instruction is in the pipeline.

Possible causes of prefetch aborts:

  1. The CPU really can't get instructions to run.  This could indicate a hardware problem.
  2. An uninitialized function pointer.  I have seen this used as a way to indicate a problem, although I can think of better ways to indicate problems.  This can also be a bug in the code.

    void CausePrefetchPointerAbort()
    {
         // declare a function pointer and set it to NULL

         DWORD (* BadFunction)() = NULL;
         // dereference the NULL function pointer (setting the PC to zero
         BadFunction();
    }

    Causes the following debug output:

    Prefetch Abort: Thread=8339d4a8 Proc=81327730 'SDMenu.exe'
    AKY=00000021 PC=00000000(???+0x00000000) RA=00011a58(SDMenu.exe+0x00001a58) BVA=
    00000000 FSR=000004f0

    Notice that the Program Counter (PC) is zero, which should never happen.  But the good news is that the Return Address (RA) is telling us where the code last was.  So this abort message does give us something to go on to find the problem.
  3. Stack overrun, or corrupted stack.

    Writting code to demonstrate this is a challenge becuase the compiler's job is to optimize out code that doesn't do anything.  So the following two functions will cause the prefetch abort.  The reason for the two functions is to trick the compiler into createing the necessary assembly code.

    This set of functions will cause a prefetch abort by corrupting the stack:.

    DWORD SetToZero( DWORD *Param )
    {
         *Param = 0;
         RETAILMSG( 1, (TEXT("Param %X %d"), Param, *Param ));
    }

    void CausePrefetchStackAbort( int Count )
    {
         DWORD *Array;
         int Index;

         RETAILMSG( 1, (TEXT("Start CausePrefetchStackAbort( %d )/n"), Count));

         // set the ponter to the address of index which is on the stack.  I tried to use an array
         // but the compiler put it into global variables instead of the stack.

         Array = &Index;

         // Loop through Count DWORDS and set the data to zero.  This data is on the stack
         // so we are clearing the stack.

         for( Index = 0; Index < Count; Index++ )
         {
             SetToZero( Array );
             Array++;
         }
         RETAILMSG( 1, (TEXT("returning CausePrefetchStackAbort( %d )/n"), Count));
    }

    When it runs, the following abort occurs.  Notice the PC is zero again. Notice that the RETAILMSG at the end of CausePrefetchStackAbort() is displayed, just before the return address is popped off the stack.

    returning CausePrefetchStackAbort( 500 )
    Prefetch Abort: Thread=8339d550 Proc=81327730 ''
    AKY=00000021 PC=00000000(???+0x00000000) RA=00000000(???+0x00000000) BVA=0000000
    0 FSR=000004f0

So the problem with prefetch aborts is that the abort message doesn't alwayus give much to go on to track back to the cause.  When it does, we can use that to find the problem in the code.  I will cover that in a post on Data Aborts soon.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值