[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#283127: Server crash probably on huge pixmap allocation



retitle 283127 xserver-xfree86: [ati/radeon] SEGV in fbBlt() during large pixmap allocation on unknown chipset (0x5964) rev 1 (RV280 [Radeon 9200 SE])
tag 283127 = upstream help
thanks

On Sun, Dec 19, 2004 at 05:22:55PM +0200, Sami Liedes wrote:
> I've tried to start the server in 3 different ways:
> 
> 1. As a normal user using the command "X"
> 2. As a normal user using the command "startx $(which x-terminal-emulator)"
> 3. As root using the command "startx $(which x-terminal-emulator)"
> 
> Of these, #1 and #3 crash when I run the gv client, #2 doesn't (after
> a few tries, anyway; #1 and #3 seem to crash always).
> 
> #3 indeed produces a core file in /etc/X11/, after which it goes into
> some kind of an endless loop (after printing "When reporting a server
> crash..."), eating all CPU it gets and unable to be killed even with
> -KILL. #1 doesn't go into an endless loop, but doesn't produce a core
> file either.

Given where you're seeing the SEGV, that there is any difference in the
above baffles me.

> Unfortunately gdb doesn't seem able to give useful information:
[...]
> However I tried to attach to a running X process and was able to get
> the following backtrace (running the crash-provoking client
> immediately after issuing the first 'cont' command):
[...]
> Program received signal SIGSEGV, Segmentation fault.
> 0x0853ba9a in fbBlt (srcLine=0x23f2762c, srcStride=21641, srcX=0, 
>     dstLine=0xbffff4fc, dstStride=21641, dstX=0, width=692512, height=0, 
>     alu=3, pm=16777215, bpp=32, reverse=0, upsidedown=0) at fbblt.c:180
> 180	fbblt.c: No such file or directory.
> 	in fbblt.c
> (gdb) bt
> #0  0x0853ba9a in fbBlt (srcLine=0x23f2762c, srcStride=21641, srcX=0, 
>     dstLine=0xbffff4fc, dstStride=21641, dstX=0, width=692512, height=0, 
>     alu=3, pm=16777215, bpp=32, reverse=0, upsidedown=0) at fbblt.c:180
[...]
> (gdb) bt full
> #0  0x0853ba9a in fbBlt (srcLine=0x23f2762c, srcStride=21641, srcX=0, 
>     dstLine=0xbffff4fc, dstStride=21641, dstX=0, width=692512, height=0, 
>     alu=3, pm=16777215, bpp=32, reverse=0, upsidedown=0) at fbblt.c:180
> 	src = (FbBits *) 0x23f1240c
> 	dst = (FbBits *) 0xbffea2d8
> 	leftShift = 0
> 	rightShift = 0
> 	startmask = 0
> 	endmask = 0
> 	bits = 0
> 	bits1 = 0
> 	n = 21640
> 	nmiddle = 21641
> 	destInvarient = 0
> 	startbyte = 0
> 	endbyte = 0
> 	_ca1 = 0
> 	_cx1 = 4278190080
> 	_ca2 = 16777215
> 	_cx2 = 0
[...]
> Hope this information helps. If there's still something I can do to
> gather more information, I'll be happy to.

Excellent.  Thank you very much for this detailed followup!

Let's have a look at that fbBlt function.  This is a long paste.  I have
some comments inlined after line number 180, and then at the very end.

    40	void
    41	fbBlt (FbBits   *srcLine,
    42	       FbStride	srcStride,
    43	       int	srcX,
    44	       
    45	       FbBits   *dstLine,
    46	       FbStride dstStride,
    47	       int	dstX,
    48	       
    49	       int	width, 
    50	       int	height,
    51	       
    52	       int	alu,
    53	       FbBits	pm,
    54	       int	bpp,
    55	       
    56	       Bool	reverse,
    57	       Bool	upsidedown)
    58	{
    59	    FbBits  *src, *dst;
    60	    int	    leftShift, rightShift;
    61	    FbBits  startmask, endmask;
    62	    FbBits  bits, bits1;
    63	    int	    n, nmiddle;
    64	    Bool    destInvarient;
    65	    int	    startbyte, endbyte;
    66	    FbDeclareMergeRop ();
    67	
    68	#ifdef FB_24BIT
    69	    if (bpp == 24 && !FbCheck24Pix (pm))
    70	    {
    71		fbBlt24 (srcLine, srcStride, srcX, dstLine, dstStride, dstX,
    72			 width, height, alu, pm, reverse, upsidedown);
    73		return;
    74	    }
    75	#endif
    76	    FbInitializeMergeRop(alu, pm);
    77	    destInvarient = FbDestInvarientMergeRop();
    78	    if (upsidedown)
    79	    {
    80		srcLine += (height - 1) * (srcStride);
    81		dstLine += (height - 1) * (dstStride);
    82		srcStride = -srcStride;
    83		dstStride = -dstStride;
    84	    }
    85	    FbMaskBitsBytes (dstX, width, destInvarient, startmask, startbyte,
    86			     nmiddle, endmask, endbyte);
    87	    if (reverse)
    88	    {
    89		srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1;
    90		dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1;
    91		srcX = (srcX + width - 1) & FB_MASK;
    92		dstX = (dstX + width - 1) & FB_MASK;
    93	    }
    94	    else
    95	    {
    96		srcLine += srcX >> FB_SHIFT;
    97		dstLine += dstX >> FB_SHIFT;
    98		srcX &= FB_MASK;
    99		dstX &= FB_MASK;
   100	    }
   101	    if (srcX == dstX)
   102	    {
   103		while (height--)
   104		{
   105		    src = srcLine;
   106		    srcLine += srcStride;
   107		    dst = dstLine;
   108		    dstLine += dstStride;
   109		    if (reverse)
   110		    {
   111			if (endmask)
   112			{
   113			    bits = *--src;
   114			    --dst;
   115			    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
   116			}
   117			n = nmiddle;
   118			if (destInvarient)
   119			{
   120			    while (n--)
   121				*--dst = FbDoDestInvarientMergeRop(*--src);
   122			}
   123			else
   124			{
   125			    while (n--)
   126			    {
   127				bits = *--src;
   128				--dst;
   129				*dst = FbDoMergeRop (bits, *dst);
   130			    }
   131			}
   132			if (startmask)
   133			{
   134			    bits = *--src;
   135			    --dst;
   136			    FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
   137			}
   138		    }
   139		    else
   140		    {
   141			if (startmask)
   142			{
   143			    bits = *src++;
   144			    FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
   145			    dst++;
   146			}
   147			n = nmiddle;
   148			if (destInvarient)
   149			{
   150	#if 0
   151			    /*
   152			     * This provides some speedup on screen->screen blts
   153			     * over the PCI bus, usually about 10%.  But fb
   154			     * isn't usually used for this operation...
   155			     */
   156			    if (_ca2 + 1 == 0 && _cx2 == 0)
   157			    {
   158				FbBits	t1, t2, t3, t4;
   159				while (n >= 4)
   160				{
   161				    t1 = *src++;
   162				    t2 = *src++;
   163				    t3 = *src++;
   164				    t4 = *src++;
   165				    *dst++ = t1;
   166				    *dst++ = t2;
   167				    *dst++ = t3;
   168				    *dst++ = t4;
   169				    n -= 4;
   170				}
   171			    }
   172	#endif
   173			    while (n--)
   174				*dst++ = FbDoDestInvarientMergeRop(*src++);
   175			}
   176			else
   177			{
   178			    while (n--)
   179			    {
   180				bits = *src++;

Here's where we SEGVd.

Looks like we walked off the end of the src FbBits array.

> 	src = (FbBits *) 0x23f1240c

The actual problem is probably higher up in the call stack, but I am
distressed that I see no assert()s in this code, which relies so heavily on
externally-supplied values, and which ends up at the bottom of tall call
stacks.

If this code were commented, I might better understand what "n" and
"nmiddle" are.  :-/

> 	n = 21640
> 	nmiddle = 21641

It strikes me as suspicious that the SEGV occurs when n has just been
decremented below value of nmiddle.  But since I do not understand the
code, I don't know if that is significant.

   181				*dst = FbDoMergeRop (bits, *dst);
   182				dst++;
   183			    }
   184			}
   185			if (endmask)
   186			{
   187			    bits = *src;
   188			    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
   189			}
   190		    }
   191		}
   192	    }
   193	    else
   194	    {
   195		if (srcX > dstX)
   196		{
   197		    leftShift = srcX - dstX;
   198		    rightShift = FB_UNIT - leftShift;
   199		}
   200		else
   201		{
   202		    rightShift = dstX - srcX;
   203		    leftShift = FB_UNIT - rightShift;
   204		}
   205		while (height--)
   206		{
   207		    src = srcLine;
   208		    srcLine += srcStride;
   209		    dst = dstLine;
   210		    dstLine += dstStride;
   211		    
   212		    bits1 = 0;
   213		    if (reverse)
   214		    {
   215			if (srcX < dstX)
   216			    bits1 = *--src;
   217			if (endmask)
   218			{
   219			    bits = FbScrRight(bits1, rightShift); 
   220			    if (FbScrRight(endmask, leftShift))
   221			    {
   222				bits1 = *--src;
   223				bits |= FbScrLeft(bits1, leftShift);
   224			    }
   225			    --dst;
   226			    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
   227			}
   228			n = nmiddle;
   229			if (destInvarient)
   230			{
   231			    while (n--)
   232			    {
   233				bits = FbScrRight(bits1, rightShift); 
   234				bits1 = *--src;
   235				bits |= FbScrLeft(bits1, leftShift);
   236				--dst;
   237				*dst = FbDoDestInvarientMergeRop(bits);
   238			    }
   239			}
   240			else
   241			{
   242			    while (n--)
   243			    {
   244				bits = FbScrRight(bits1, rightShift); 
   245				bits1 = *--src;
   246				bits |= FbScrLeft(bits1, leftShift);
   247				--dst;
   248				*dst = FbDoMergeRop(bits, *dst);
   249			    }
   250			}
   251			if (startmask)
   252			{
   253			    bits = FbScrRight(bits1, rightShift); 
   254			    if (FbScrRight(startmask, leftShift))
   255			    {
   256				bits1 = *--src;
   257				bits |= FbScrLeft(bits1, leftShift);
   258			    }
   259			    --dst;
   260			    FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
   261			}
   262		    }
   263		    else
   264		    {
   265			if (srcX > dstX)
   266			    bits1 = *src++;
   267			if (startmask)
   268			{
   269			    bits = FbScrLeft(bits1, leftShift); 
   270			    bits1 = *src++;
   271			    bits |= FbScrRight(bits1, rightShift);
   272			    FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
   273			    dst++;
   274			}
   275			n = nmiddle;
   276			if (destInvarient)
   277			{
   278			    while (n--)
   279			    {
   280				bits = FbScrLeft(bits1, leftShift); 
   281				bits1 = *src++;
   282				bits |= FbScrRight(bits1, rightShift);
   283				*dst = FbDoDestInvarientMergeRop(bits);
   284				dst++;
   285			    }
   286			}
   287			else
   288			{
   289			    while (n--)
   290			    {
   291				bits = FbScrLeft(bits1, leftShift); 
   292				bits1 = *src++;
   293				bits |= FbScrRight(bits1, rightShift);
   294				*dst = FbDoMergeRop(bits, *dst);
   295				dst++;
   296			    }
   297			}
   298			if (endmask)
   299			{
   300			    bits = FbScrLeft(bits1, leftShift); 
   301			    if (FbScrLeft(endmask, rightShift))
   302			    {
   303				bits1 = *src;
   304				bits |= FbScrRight(bits1, rightShift);
   305			    }
   306			    FbDoRightMaskByteMergeRop (dst, bits, endbyte, endmask);
   307			}
   308		    }
   309		}
   310	    }
   311	}

I don't have time to dig into this further right at the moment, but if
someone would like to help chase this down, that would be great.

-- 
G. Branden Robinson                |     You don't just decide to break
Debian GNU/Linux                   |     Kubrick's code of silence and then
branden@debian.org                 |     get drawn away from it to a
http://people.debian.org/~branden/ |     discussion about cough medicine.

Attachment: signature.asc
Description: Digital signature


Reply to: