QOpenGL widget-based app crashing

Bug #1490956 reported by Gerry Boland
16
This bug affects 3 people
Affects Status Importance Assigned to Milestone
libhybris (Ubuntu)
Confirmed
Undecided
Simon Fels
qtubuntu (Ubuntu)
Triaged
High
Gerry Boland

Bug Description

tsdgeos has this crash with a game of his: http://paste.ubuntu.com/12244384/

Revision history for this message
Albert Astals Cid (aacid) wrote :

In case you're interested at reproducing the code can be found at git://anongit.kde.org/blinken

It compiles fine on the phone after you install the dependencies.

Also if you need help testing something do not hesitate to ask.

Gerry Boland (gerboland)
Changed in qtubuntu:
importance: Undecided → High
status: New → Triaged
Revision history for this message
Gerry Boland (gerboland) wrote :

Crash only occurs on the phone, not desktop. This tends to be the usual backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
(gdb) bt
#0 0x00000000 in ?? ()
#1 0xb6b6af64 in glGenTextures (this=<optimized out>, textures=0x2815d8, n=1) at opengl/qopengltexturehelper_p.h:508
#2 create (this=0x2815c8) at opengl/qopengltexture.cpp:169
#3 QOpenGLTexture::setFormat (this=this@entry=0x281bb0, format=format@entry=QOpenGLTexture::RGBAFormat)
    at opengl/qopengltexture.cpp:1923
#4 0xb6b70b46 in QOpenGLTexture::setData (this=this@entry=0x281bb0, image=..., genMipMaps=QOpenGLTexture::GenerateMipMaps)
    at opengl/qopengltexture.cpp:2669
#5 0xb6b70c66 in QOpenGLTexture::QOpenGLTexture (this=0x281bb0, image=..., genMipMaps=<optimized out>)
    at opengl/qopengltexture.cpp:1707
#6 0x0000b480 in ?? ()

Qt has a non-trivial way of wrapping GL calls to abstract away API differences where possible. It starts in QOpenGLTextureHelper, which on creation, resolves symbols for the usual GL calls:
http://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/opengl/qopengltexturehelper.cpp?id=69196b38c481610ef30bfe8ce8e7ba6826729ab8#n182
Here GenTextures is a function pointer:
    GenTextures = ::glGenTextures;
which should be set the address of the actual call. It is via this GenTextures that Qt then works.

But when I try to debug this assignment, I get confusing results:

(gdb) p GenTextures
$3 = (void (*)(GLsizei, GLuint *)) 0xffffffff
(gdb) p glGenTextures
Cannot take address of method glGenTextures.
(gdb) p ::glGenTextures
$4 = {<text gnu-indirect-function variable, no debug info>} 0xb6536384 <glGenTextures>

This debug is definitely taken after the variable should be assigned. But this makes no sense.

Revision history for this message
Gerry Boland (gerboland) wrote :

Easy way to reproduce problem is to install qtbase5-examples and run

/usr/lib/arm-linux-gnueabihf/qt5/examples/opengl/cube/cube --desktop_file_hint=dialer-app

Revision history for this message
Gerry Boland (gerboland) wrote :

Digging into hybris, glGenTextures is generated by

#define GLES2_IDLOAD(sym) \
 __asm__ (".type " #sym ", %gnu_indirect_function"); \
typeof(sym) * sym ## _dispatch (void) __asm__ (#sym);\
typeof(sym) * sym ## _dispatch (void) \
{ \
 return (void *) android_dlsym(_libglesv2, #sym); \
}

which a function that when first called overwrites it's plt entry with new address. Subsequent calls jump directly at the target function in the android library.

Qt is saving a pointer to this function, before it is ever called. Might be a problem, /me goes to learn about PLT entries

Revision history for this message
Gerry Boland (gerboland) wrote :

Confirmed that ::glGenTextures is resolving to 0x0 for Qt, meaning GenTextures is also null, and so QOpenGLTextureHelper::glGenTextures calls a null function, and crash.

Revision history for this message
Gerry Boland (gerboland) wrote :

nm -D /usr/lib/arm-linux-gnueabihf/libhybris-egl/libGLESv2.so.2 | grep glGenTex
00002384 i glGenTextures

the symbol is in the library, but is indirect function.

LD_DEBUG=all ./cube --desktop_file_hint=dialer-app 2>&1 | grep glGenTex
      8196: symbol=glGenTextures; lookup in file=./cube [0]
      8196: symbol=glGenTextures; lookup in file=/usr/lib/arm-linux-gnueabihf/libQt5Widgets.so.5 [0]
      8196: symbol=glGenTextures; lookup in file=/usr/lib/arm-linux-gnueabihf/libQt5Gui.so.5 [0]
      8196: symbol=glGenTextures; lookup in file=/usr/lib/arm-linux-gnueabihf/libQt5Core.so.5 [0]
      8196: symbol=glGenTextures; lookup in file=/usr/lib/arm-linux-gnueabihf/libhybris-egl/libGLESv2.so.2 [0]
      8196: binding file /usr/lib/arm-linux-gnueabihf/libQt5Gui.so.5 [0] to /usr/lib/arm-linux-gnueabihf/libhybris-egl/libGLESv2.so.2 [0]: normal symbol `glGenTextures'

it appears that the runtime linker finds the symbol in the correct library.

Revision history for this message
Gerry Boland (gerboland) wrote :

Investigating libhybris, I see no evidence for it resolving the symbol incorrectly. Enabling debug & trace modes, and patching it to print each resolved symbol and its address, I see

glGetIntegerv, (nil)
glGenTextures, (nil)
glBindTexture, (nil)
glTexImage2D, (nil)
glTexSubImage2D, (nil)
glDeleteTextures, (nil)
glGetBooleanv, (nil)
glTexParameteri, (nil)
glActiveTexture, (nil)
glPixelStorei, (nil)
glGetTexParameteriv, (nil)
glGetTexParameterfv, (nil)
glTexParameteriv, (nil)
glTexParameterfv, (nil)
glCompressedTexSubImage2D, (nil)
glCompressedTexImage2D, (nil)
glGenerateMipmap, (nil)
HYBRIS constructed!!
glGetString, 0xb6cdfd34
glCreateProgram, 0xb6cde208
glCreateShader, 0xb6cde220
glShaderSource, 0xb6cde7d8
glCompileShader, 0xb6cde1a4
glGetShaderiv, 0xb6cde560
glAttachShader, 0xb6cde024
glLinkProgram, 0xb6cde724
glGetProgramiv, 0xb6cde524
glUseProgram, 0xb6cdea58
glGenTextures, 0xb6cde440
// from here, Qt prints:
Helper: glGenTextures 0x0 0x0 <- should print same address as hybris just returned above
"glTexImage3D" true
"glTexSubImage3D" true
"glCompressedTexImage3D" true
"glCompressedTexSubImage3D" true
glGenTextures 0xdf9250 0x0
Segmentation fault (core dumped)

I had a slight concern that the log shows the first time glGenTextures symbols is asked for, the glesv2 hybris constructor had not completed, so the symbol returned is 0. But the %gnu_indirect_function extension should only replace a non-null address. So above output indicates hybris is acting correctly.

Revision history for this message
Pat McGowan (pat-mcgowan) wrote :

@simon mind having a look when you can

Changed in libhybris (Ubuntu):
assignee: nobody → Simon Fels (morphis)
Changed in qtubuntu:
assignee: nobody → Gerry Boland (gerboland)
Revision history for this message
Gerry Boland (gerboland) wrote :

I suspect https://github.com/libhybris/libhybris/issues/315 is exactly this issue.

Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in libhybris (Ubuntu):
status: New → Confirmed
Michał Sawicz (saviq)
affects: qtubuntu → qtubuntu (Ubuntu)
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.