SIGBUS:BUS_ADRERR for stack access violation in memcpy

来源:互联网 发布:数据冗余导致的问题 编辑:程序博客网 时间:2024/04/30 02:59

记录一个发生在copy constructor中的SIGBUS:BUS_ADRERR的trouble shooting,涉及三个点

1. In memcpy again

2. SIGBUS:BUS_ADRERR for stack access

3. copy constructor

[SYMPTOM]

Crash log:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/release-keys'
Revision: '0'
pid: 18768, tid: 18768, name: mediaserver  >>> /system/bin/mediaserver <<<
signal 7 (SIGBUS), code 2 (BUS_ADRERR), fault addr bee7c000
    r0 bee7bff4  r1 b528fe38  r2 00020000  r3 00000000
    r4 b5272008  r5 00000027  r6 bee5e3f0  r7 b6f38208
    r8 b746d8e0  r9 00000000  sl b52903c0  fp bee9ea2c
    ip 0000007a  sp bee5e3d8  lr 000005fc  pc b6f0a090  cpsr 20000010
    d0  0000000000000000  d1  0000000000000000
    d2  0000000000000000  d3  0000000000000000
    d4  0000000000000000  d5  0000000000000000
    d6  0000000000000000  d7  0000000000000000
    d8  0000000000000000  d9  0000000000000000
    d10 0000000000000000  d11 0000000000000000
    d12 0000000000000000  d13 0000000000000000
    d14 0000000000000000  d15 0000000000000000
    d16 78694d6f69647541  d17 6b63617274207265
    d18 303030307830203a  d19 726f460a33303030
    d20 460a31203a74616d  d21 7a697320656d6172
    d22 65500a0a34203a65  d23 657320676e69646e
    d24 3fa1a82d39a2df40  d25 bfa1a82d486375ce
    d26 4045400000000000  d27 401ed2a028000000
    d28 3ff0000000000000  d29 3fab54ec5f25c8d8
    d30 3cc2892746984074  d31 4000000000000000
    scr 20000011

backtrace:
    #00  pc 0001d090  /system/lib/libc.so (memcpy+272)

stack:
         bee5e398  0000001c  
         bee5e39c  bee9e474  [heap]
         bee5e3a0  b6f38208  
         bee5e3a4  bee9e5e4  [heap]
         bee5e3a8  00000001  
         bee5e3ac  00000000  
         bee5e3b0  bee9ea2c  [heap]
         bee5e3b4  b6efab95  /system/lib/libc.so (malloc+12)
         bee5e3b8  bee9e490  [heap]
         bee5e3bc  b6dd79a5  /system/lib/libutils.so (android::SharedBuffer::alloc(unsigned int)+12)
         bee5e3c0  bee5e3e8  [heap]
         bee5e3c4  b6dd7e5b  /system/lib/libutils.so
         bee5e3c8  b732b680  [heap]
         bee5e3cc  bee5e3e8  [heap]
         bee5e3d0  df0027ad  
         bee5e3d4  00000000  
    #00  bee5e3d8  00000001  
         bee5e3dc  00000000  
         bee5e3e0  b6e616c3  /system/lib/libaudioflinger.so (android::AudioFlinger::MixerThread::dumpInternals(int, android::Vector<android::String16> const&)+250)
         bee5e3e4  bee5e474  [heap]
         bee5e3e8  b746d8e0  [heap]
         bee5e3ec  0126ffb0  
         bee5e3f0  032602c4  
         bee5e3f4  0090028a  
         bee5e3f8  fbe8fd7e  
         bee5e3fc  00000000  
         bee5e400  00000000  
         bee5e404  00000000  
         bee5e408  00000000  
         bee5e40c  00000000  
         bee5e410  00000000  
         bee5e414  00000000  

memory near r0:
    bee7bfd4 00000000 00000000 00000000 00000000  
    bee7bfe4 00000000 00000000 00000000 00000000  
    bee7bff4 00000000 00000000 00000000 ffffffff  
    bee7c004 ffffffff ffffffff ffffffff ffffffff  
    bee7c014 ffffffff ffffffff ffffffff ffffffff  
    bee7c024 ffffffff ffffffff ffffffff ffffffff  
    bee7c034 ffffffff ffffffff ffffffff ffffffff  
    bee7c044 ffffffff ffffffff ffffffff ffffffff  
    bee7c054 ffffffff ffffffff ffffffff ffffffff  
    bee7c064 ffffffff ffffffff ffffffff ffffffff  
    bee7c074 ffffffff ffffffff ffffffff ffffffff  
    bee7c084 ffffffff ffffffff ffffffff ffffffff  
    bee7c094 ffffffff ffffffff ffffffff ffffffff  
    bee7c0a4 ffffffff ffffffff ffffffff ffffffff  
    bee7c0b4 ffffffff ffffffff ffffffff ffffffff  
    bee7c0c4 ffffffff ffffffff ffffffff ffffffff  

memory near r1:
    b528fe18 00000000 00000000 00000000 00000000  
    b528fe28 00000000 00000000 00000000 00000000  
    b528fe38 00000000 00000000 00000000 00000000  
    b528fe48 00000000 00000000 00000000 00000000  

[ANALYSIS]
From assembly code of memcpy, we can get the info of stack use.
Dump of assembler code for function memcpy:
   0x0001cf80 <+0>: movr12, r0
   0x0001cf84 <+4>: cmpr2, #4
   0x0001cf88 <+8>: blt0x1d10c <memcpy+396>
   0x0001cf8c <+12>: cmpr2, #16
   0x0001cf90 <+16>: blt0x1d0f0 <memcpy+368>
   0x0001cf94 <+20>: cmpr2, #32
   0x0001cf98 <+24>: blt0x1d0dc <memcpy+348>
   0x0001cf9c <+28>: cmpr2, #64; 0x40
   0x0001cfa0 <+32>: blt0x1d0cc <memcpy+332>
   0x0001cfa4 <+36>: stmfdsp!, {r0}
   0x0001cfa8 <+40>: lsrr12, r2, #6
   0x0001cfac <+44>: cmpr12, #10
   0x0001cfb0 <+48>: ble0x1d0a8 <memcpy+296>
   0x0001cfb4 <+52>: push{r9, r10, lr}
   0x0001cfb8 <+56>: cmpr12, #64; 0x40
   0x0001cfbc <+60>: ble0x1d068 <memcpy+232>
   0x0001cfc0 <+64>: addlr, r0, #1024; 0x400
   0x0001cfc4 <+68>: addr9, r1, #640; 0x280
   0x0001cfc8 <+72>: sublr, lr, r9
   0x0001cfcc <+76>: lsllr, lr, #21
   0x0001cfd0 <+80>: lsrlr, lr, #21
   0x0001cfd4 <+84>: addlr, lr, #640; 0x280

   0x0001d014 <+148>: vld1.32{d0-d3}, [r1]!
   0x0001d018 <+152>: vld1.32{d4-d7}, [r1]!
   0x0001d01c <+156>: ldrr3, [r10]
   0x0001d020 <+160>: subsr9, r9, #1
   0x0001d024 <+164>: vst1.32{d0-d3}, [r0]!
   0x0001d028 <+168>: vst1.32{d4-d7}, [r0]!
   0x0001d02c <+172>: addr10, r10, #64; 0x40
   0x0001d030 <+176>: bne0x1d010 <memcpy+144>
   0x0001d034 <+180>: cmpr12, #0
   0x0001d038 <+184>: beq0x1d0a0 <memcpy+288>
   0x0001d03c <+188>: cmpr12, #8192; 0x2000
   0x0001d040 <+192>: blt0x1d080 <memcpy+256>
   0x0001d044 <+196>: vld1.32{d0-d3}, [r1]!
   0x0001d048 <+200>: vld1.32{d4-d7}, [r1]!
   0x0001d04c <+204>: pld[r10]
   0x0001d050 <+208>: subsr12, r12, #1
   0x0001d054 <+212>: vst1.32{d0-d3}, [r0]!
   0x0001d058 <+216>: vst1.32{d4-d7}, [r0]!
   0x0001d05c <+220>: addr10, r10, #64; 0x40
   0x0001d060 <+224>: bne0x1d044 <memcpy+196>
   0x0001d064 <+228>: b0x1d0a0 <memcpy+288>
   0x0001d068 <+232>: movlr, #640; 0x280
   0x0001d06c <+236>: addr10, r1, #640; 0x280
   0x0001d070 <+240>: bicr10, r10, #63; 0x3f
   0x0001d074 <+244>: subr12, r12, #10
   0x0001d078 <+248>: ldrr3, [r10, #-64]; 0x40
   0x0001d07c <+252>: nop{0}
   0x0001d080 <+256>: vld1.32{d0-d3}, [r1]!
   0x0001d084 <+260>: vld1.32{d4-d7}, [r1]!
   0x0001d088 <+264>: ldrr3, [r10]
   0x0001d08c <+268>: subsr12, r12, #1
 =>0x0001d090 <+272>: vst1.32{d0-d3}, [r0]!  <= crash here!!
   0x0001d094 <+276>: vst1.32{d4-d7}, [r0]!

The registers saved on stack by memcpy list as follows.
    #00  bee5e3d8  00000001  r9
         bee5e3dc  00000000  r10
         bee5e3e0  b6e616c3  lr 
         bee5e3e4  bee5e474  r0

From {r9, r10, LR} saved by memcpy on the stack, we can deduce the caller is 
android::AudioFlinger::MixerThread::dumpInternals(int, android::Vector<android::String16> const&) 

From Instructions near memcpy call in android::AudioFlinger::MixerThread::dumpInternals 
   0x0003a6a8 <+224>: ldr.wr1, [r4, #620]; 0x26c    ------- r4: this pointer
   0x0003a6ac <+228>:     sub.w    r0, r6, #260          ; 0x104
   0x0003a6b0 <+232>:    mov.w  r2, #131072         ; 0x20000
   0x0003a6b4 <+236>:    sub.w    r6, r6, #392          ; 0x188
   0x0003a6b8 <+240>:    str           r1, [sp, #136]      ; 0x88
   0x0003a6ba <+242>:    add.w   r1, r4, #624          ; 0x270
 =>0x0003a6be <+246>:    blx          0x2e590  ---- memcpy-1
   0x0003a6c2 <+250>:     add.w   r12, sp, #20
   0x0003a6c2 <+250>:     add.w   r12, sp, #20
   0x0003a6c6 <+254>:     add.w   r0, r12, #131072                ; 0x20000
   0x0003a6ca <+258>:     add.w   r2, r4, #131072   ; 0x20000
   0x0003a6ce <+262>:    add.w   r1, r2, #624          ; 0x270
   0x0003a6d2 <+266>:    adds      r0, #120                ; 0x78
   0x0003a6d4 <+268>:    mov.w  r2, #131072         ; 0x20000
   0x0003a6d8 <+272>:    add.w   r4, r4, #262144   ; 0x40000
   0x0003a6dc <+276>:    blx          0x2e590  ---- memcpy-2
   0x0003a6e0 <+280>:    add        r0, sp, #20
   0x0003a6e2 <+282>:    mov       r1, r5
   0x0003a6e4 <+284>:    bl            0x494b8 <android::FastMixerDumpState::dump(int)>

can get the real call stack 
#00  pc 0001d090  /system/lib/libc.so (memcpy+272)
#01  pc 0003a6be  /system/lib/libaudioflinger.so

and memcpy(r0, r1, r2) arguments
R0 = R6_cur + 0x188 – 0x104 = 0xbee5e3f0 + 0x188 – 0x104 = 0xBEE5E474
The saved value can be found on stack above the saved lr register.
    #00  bee5e3d8  00000001  
         bee5e3dc  00000000  
         bee5e3e0  b6e616c3  /system/lib/libaudioflinger.so (android::AudioFlinger::MixerThread::dumpInternals(int, android::Vector<android::String16> const&)+250)
         bee5e3e4  bee5e474  [heap]
         bee5e3e8  b746d8e0  [heap]
R1 = r4_cur + 0x270 = 0xB5272278
R2 = 0x20000

The crash occurs in moving data to destination process at page boundary 0xbee7c000.
The SIGBUS::BUS_ADRERR means to access a Nonexistent physical address. Nonexistent physical address for that part of stack linear space.
For access violation of heap, it offen leads to SIGSEGV:SEGV_MAPERR.

R0 : 0xbee5e474 ---> 0xbee7bff4  
R1 : 0xB5272278  ---> 0xb528fe38

Examing source of AudioFlinger::MixerThread::dumpInternals, find crash occurs in FastMixerDumpState's default copy constructor.
void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args) @ audioFlinger/Threads.cpp
{
    const size_t SIZE = 256;
    char buffer[SIZE];
    String8 result;

    PlaybackThread::dumpInternals(fd, args);

    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
    result.append(buffer);
    write(fd, result.string(), result.size());

    // Make a non-atomic copy of fast mixer dump state so it won't change underneath us
    FastMixerDumpState copy = mFastMixerDumpState;
    copy.dump(fd);
    ….
}

memcpy-1 copies the mFastMixerDumpState.mMonotonicNs to the mMonotonicNs of ‘local object’ copy on the stack, and
memcpy-2 copies the mFastMixerDumpState. mLoadNs to copy.mLoadNs.
the size of each array is 0x20000.

See struct FastMixerDumpState, it is realy realy too big(with size more than 0x40000).
struct FastMixerDumpState {         // @ FastMixer.h
    FastMixerDumpState();
    /*virtual*/ ~FastMixerDumpState();

    void dump(int fd);          // should only be called on a stable copy, not the original

    FastMixerState::Command mCommand;   // current command
    uint32_t mWriteSequence;    // incremented before and after each write()
    uint32_t mFramesWritten;    // total number of frames written successfully
    uint32_t mNumTracks;        // total number of active fast tracks
    uint32_t mWriteErrors;      // total number of write() errors
    uint32_t mUnderruns;        // total number of underruns
    uint32_t mOverruns;         // total number of overruns
    uint32_t mSampleRate;
    size_t   mFrameCount;
    struct timespec mMeasuredWarmupTs;  // measured warmup time
    uint32_t mWarmupCycles;     // number of loop cycles required to warmup
    uint32_t mTrackMask;        // mask of active tracks
    FastTrackDump   mTracks[FastMixerState::kMaxFastTracks];

#ifdef FAST_MIXER_STATISTICS
    // Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency.
    // kSamplingN is the size of the sampling frame, and must be a power of 2 <= 0x8000.
    static const uint32_t kSamplingN = 0x8000;
    // The bounds define the interval of valid samples, and are represented as follows:
    //      newest open (excluded) endpoint   = lower 16 bits of bounds, modulo N
    //      oldest closed (included) endpoint = upper 16 bits of bounds, modulo N
    // Number of valid samples is newest - oldest.
    uint32_t mBounds;                   // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
    // The elements in the *Ns arrays are in units of nanoseconds <= 3999999999.
    uint32_t mMonotonicNs[kSamplingN];  // delta monotonic (wall clock) time
    uint32_t mLoadNs[kSamplingN];       // delta CPU load in time
#ifdef CPU_FREQUENCY_STATISTICS
    uint32_t mCpukHz[kSamplingN];       // absolute CPU clock frequency in kHz, bits 0-3 are CPU#
#endif
#endif
};

So, the access is out of the range of stack.

[Ref Solution]
Do not make a so big object on the stack.
Use operator new to allocate the FastMixerDumpState object on the heap to avoid stack access violation.

0 0
原创粉丝点击