记录一个发生在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.