module: 'SoundPlugin' on Mac OS.

John M McIntosh johnmci at
Wed Jan 10 05:05:25 UTC 2007

Ok, thank you for the information, mind it seems we are copying the  
list, plus 5 others so it's quite a crowd.
However given the interest in ensuring sound recording works, I'll  

In looking at the dump, mind I did look at assembler dumps for IBM  
mainframes for a living in years past so doing this just brings back  
old memories
versus being difficult,  I see the following  (Hah, assuming I'm not  
being a bit careless here) anyway...

0x000ce510 <Stream_setFormat+576>:	bl	0xcd260 <Buffer_new>
0x000ce514 <Stream_setFormat+580>:	lwz	r5,4(r31)
0x000ce518 <Stream_setFormat+584>:	mr	r4,r31
0x000ce51c <Stream_setFormat+588>:	stw	r3,28(r31)
0x000ce520 <Stream_setFormat+592>:	mr	r8,r29
0x000ce524 <Stream_setFormat+596>:	lwz	r7,4(r3)   <---- death strikes  
0x000ce528 <Stream_setFormat+600>:	lwz	r6,20(r31)
0x000ce52c <Stream_setFormat+604>:	lis	r31,16
0x000ce530 <Stream_setFormat+608>:	addi	r3,r31,1592
0x000ce534 <Stream_setFormat+612>:	bl	0xcd1b0 <dprintf>

I believe we take r3 which is r3: 0x0000000000000000 and attempt to  
index by 4
and get a read failure  KERN_PROTECTION_FAILURE (0x0002) at 0x00000004

I believe the C code is
   s->buffer= Buffer_new((s->direction ? DeviceFrameSize :  
SqueakFrameSize) * nChannels * frameCount * 2);

   dprintf("stream %p[%d] sound buffer size %d/%d (%d)\n", s, s- 
 >direction, s->imgBufSize, s->buffer->size, frameCount);

The short answer is frameCount is 0x000000007fffffff, and we build a  
bogus number to attempt to allocate memory with,
which fails, which then sets s->buffer to zero, and we die  
referencing s->buffer->size, which is the software bug.

Now lets look at the proof:

For non-debug Ian has #ifdefined the dprintf as:

  inline void dprintf(const char *fmt, ...) {}

interestingly enough the compiler still wants to pass the parms to a  
null routine, but the issue is when we do the
s->buffer->size  because s->buffer is zero and we die when we  
deference to access ->size

Now why would s->buffer be nil?

Buffer *Buffer_new(int size)
   Buffer *b= (Buffer *)malloc(sizeof(Buffer));
   if (!b)
     return 0;
   if (!(b->data= (char *)malloc(size)))
       return 0;
   b->size=  size;
   b->avail= 0;
   b->iptr=  0;
   b->optr=  0;
   return b;

We pass in size, and allocate the Buffer structure, if that fails we  
return zero, then we allocate size for the data, if that fails, then  
we would return 0.

I believe
r3 is  s->buffer   0x0000000000000000
r4 is  s  0x0000000000411920
r5 is  s->direction  0x0000000000000001
r6 would be s->imgBufSize we don't assign it before crash
r7 would be s->buffer->size but we crash calculating that
r8 is frameCount      ->>>>>>>>>>   0x000000007fffffff   Bad evil  thing

typedef struct Stream
   AudioDeviceID		 id;			// associated with this stream
   int			 direction;		// 1nput/0utput
   int			 sampleRate;		// Squeak frames per second
   int			 channels;		// channels per Squeak frame
   int			 devBufSize;		// bytes per device buffer
   int			 imgBufSize;		// bytes per Squeak buffer
   int			 cvtBufSize;		// bytes per converter buffer
   Buffer		*buffer;		// fifo
   AudioConverterRef	 converter;		// frame format converter
   int			 semaphore;		// ping me!
   u_int64_t		 timestamp;		// nominal buffer tail time (uSecs)

I see that we call Stream_setFormat via

  int sound_StartRecording(int samplesPerSec, int stereo, int semaIndex)
   Stream *s= 0;

   dprintf("snd_StartRecording rate: %d stereo: %d semaIndex: %d\n",
	   samplesPerSec, stereo, semaIndex);

   if (input)	// there might be a change of sample rate

   if ((s= Stream_new(1)))	// 1nput
       // approximate the frameCount that output uses for the same  
sample rate
       int frameCount= 5288 * samplesPerSec / 44100;
       if ((  Stream_setFormat(s, frameCount, samplesPerSec, stereo))
	  && Stream_startSema(s, semaIndex))

I'm wonder here if you have a integer overflow situation calculating  
frameCount base on your passed in samplesPerSec.

Thus you should check the values you are passing into the start sound  
primitive, it's likely a stack dump at this point
would show the variables btw.

Thread 0 crashed with PPC Thread State 64:
   srr0: 0x00000000000ce3c4 srr1:  
0x000000000000f030                        vrsave: 0x0000000000000000
     cr: 0x24024444          xer: 0x0000000000000004   lr:  
0x00000000000ce3b4  ctr: 0x0000000000000001
     r0: 0x0000000000000000   r1: 0x00000000bfffc9c0   r2:  
0x00000000000ce3b4   r3: 0x0000000000000000
     r4: 0x0000000000411920   r5: 0x0000000000000001   r6:  
0x00000000ffffffff   r7: 0x0000000000000007
     r8: 0x000000007fffffff   r9: 0x00000000a0001fac  r10:  
0x000000000000000d  r11: 0x0000000044024442
    r12: 0x000000009000660c  r13: 0x0000000000122c70  r14:  
0x00000000bfffcc00  r15: 0x00000000a321c4f8
    r16: 0x000000000041cca0  r17: 0x00000000bfffd0e0  r18:  
0x000000004a4d4d32  r19: 0x000000004a4d4d32
    r20: 0x000000000041ce90  r21: 0x00000000ffffd96e  r22:  
0x0000000000000000  r23: 0x0000000000001340
    r24: 0x0000000000122c70  r25: 0x0000000000100000  r26:  
0x0000000000000001  r27: 0x00000000000014a8
    r28: 0x0000000000100000  r29: 0x000000007fffffff  r30:  
0x0000000000000001  r31: 0x0000000000411920

On Jan 9, 2007, at 6:58 AM, efimov wrote:

> Hello, John.
> I guess the problem is in the byte order.
> I took the same Squeak VM 3.8.14b7 (3.8.14b7),
> the same image, but the results were different on a PowerPC Mac
> and on an Intel Mac.
> On PowerPC G4  (1.2) - VM crashed after push rec button in
> RecordingControlsMorph.
> On Intel Core Solo - everything is ok, not sure about sound
> (i worked remote), but the VM did not crash.

John M. McIntosh <johnmci at>
Corporate Smalltalk Consulting Ltd.

More information about the Squeak-dev mailing list