none
Data abort exception accessing user buffer in stream driver (WEC7, SMP enabled platform) RRS feed

  • Question

  • OK, this one looks pretty strange. Basically the problem is I'm geting a somewhat strange data abort exception in my serial driver inside COM_Read().

    The client app does something simple like this:

     

     

    BYTE buffer[ 256 ]; // On stack
    
    DWORD read;
    
    while (<condition>)
    
    {
    
     if (ReadFile(hCOM, buffer, 256, &read, NULL) && (read > 0))
    
     {
    
       // Do something
    
     }
    
    }
    

     

     

    And inside the serial driver:

     

    ULONG
    COM_Read(
     HANDLE hCommOpen, //@parm [IN]  HANDLE returned by COM_Open 
     PUCHAR pBuffer, //@parm [IN,OUT] Pointer to valid memory.  
     ULONG Count) //@parm [IN]  Size in bytes of pTargetBuffer.
    {
    
      < Input params validation>
      < Some timeout calcs >
    
      // Read the data whatever available in the internal receive buffer
      readBytes = InternalUartRead(pBuffer, Count);
    
      <etc>
    }

     Now the problem is once in a while (usually ~5-30min of quite intensive serial comms) I'm getting a Data abort exception with the bad address (BVA) being exactly the beginning of "pBuffer" passed from the user. This happens on the very first byte copied from the internal buffer to "pBuffer". Tracking down exception address to the .COD assembly file shows the folowing instruction:

     

     

    strb        r3,[r4],#1

     

    where r4 contains the address of  "pBuffer" passed down from the app. I'm pulling my hair trying to find something wrong with that and I just can't! The address looks absolutely fine and then again it hapens aftrer thousands of successfull writes to the same exactly buffer/address during previous RedaFile() calls from the app. Any ideas guys?

     

     


    Wednesday, July 6, 2011 9:30 AM

Answers

  • Have you tried to commit the stack before pass to ReadFile?
    For example

    while (<condition>)

    {
    buffer[0] = 0;
    if (ReadFile(hCOM, buffer, 256, &read, NULL) && (read > 0))

    {
    ...

    Wednesday, July 6, 2011 7:58 PM

All replies

  • Nothing comes immediately to mind.  A few questions:

    1) Is the abort a regular data abort, or a stack abort?  I'm assuming the former.

    2) Is your serial driver running as a user mode or kernel mode driver?

    3) Does the abort happen on the same thread as the original application thread (synchronous with ReadFile), or is it on another thread?

     


    Dean Ramsier eMVP BSQUARE Corporation
    Wednesday, July 6, 2011 12:48 PM
  • Have you tried to commit the stack before pass to ReadFile?
    For example

    while (<condition>)

    {
    buffer[0] = 0;
    if (ReadFile(hCOM, buffer, 256, &read, NULL) && (read > 0))

    {
    ...

    Wednesday, July 6, 2011 7:58 PM
  • Thank you guys. I'll try the commit trick bit later. Do you think this might be a cache related problem? 

     

    Dean's questions:

     


    1) The exception looks like a regular one. Added the dump below.

    2) Kernel mode (SHK attrs in the .bib).

    3) Async abort. Always happens when active VM is a different process and different thread.

     

    ReadFile caller thread:

    hThread=41h, dwThreadId=25200A2h as returned by GetCurrentThread() and GetCurrentThreadId()

     

    Exception:

    PID:00400003 TID:0081002A Exception 'Data Abort' (4): Thread-Id=0081002a(pth=c0817270), Proc-Id=00400002(pprc=823e65d8) 'NK.EXE'
    , VM-active=03b10016(pprc=c084f4d0) 'explorer.exe'
    PID:00400003 TID:0081002A PC=ef62d7d8(serial_drv.dll+0x0001d7d8) RA=d1236eb8(???+0xd1236eb8) SP=d13cfdc4, BVA=00052e94
    PID:00400003 TID:0081002A

     

    BVA address is the buffer ptr passed to COM_Read()

     

     



    Thursday, July 7, 2011 8:20 AM
  • Oh my, looks like I have cache issues! Commiting the buffer seems to make a ton of difference. The exception doesn't appear any more but shouldn't be there at all in the first place... gotta dig the low level OAL caching stuff.

    Thank you guys.

    Thursday, July 7, 2011 10:27 AM
  • User mode stack is demand committing and you allocate a large pool (256 bytes) so there is a better chance the buffer may cross the page boundary. i.e. part or all of the memory for buffer is not yet committed.
    As your driver is in kernel mode but the buffer address still in user mode, so when accessing this address, a page fault will be generated.
    Normally, kernel can recover this stack page fault gracefully, but committing a user stack (untrusted stack) in kernel mode is likely to expose more risk, and kernel just fail it.
    Instead of the workaround by committing the page before passed, you can use LockPages the buffer when entering the COM_Read and UnlockPages it before return.
    To commit the user buffer in driver explicitly.
    Thursday, July 7, 2011 11:35 PM