On linux don't take address of glX/egl symbols

* The application could export a public glXSwapBuffers symbol that is its own
  function pointer, and &glXSwapBuffers looking up that symbol will get it,
  instead of our entry point. Follow the GL function scheme of still exporting a
  small stub with the proper name, but forwarding to an internal suffixed symbol
  that won't be overloaded.
This commit is contained in:
baldurk
2018-09-25 11:01:25 +01:00
parent 73ec1e1d37
commit 081d283575
3 changed files with 175 additions and 54 deletions
+3 -4
View File
@@ -185,10 +185,9 @@ void CGLHook::RegisterHooks()
LibraryHooks::RegisterLibraryHook("libGL.dylib", NULL);
// register CGL hooks
#define CGL_REGISTER(func) \
LibraryHooks::RegisterFunctionHook("OpenGL", \
FunctionHook(STRINGIZE(func), (void **)&CGL.func, \
(void *)&GL_EXPORT_NAME(CGLFlushDrawable)));
#define CGL_REGISTER(func) \
LibraryHooks::RegisterFunctionHook( \
"OpenGL", FunctionHook(STRINGIZE(func), (void **)&CGL.func, (void *)&GL_EXPORT_NAME(func)));
CGL_HOOKED_SYMBOLS(CGL_REGISTER)
#undef CGL_REGISTER
}
+83 -23
View File
@@ -74,7 +74,7 @@ public:
} eglhook;
HOOK_EXPORT EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display)
HOOK_EXPORT EGLDisplay EGLAPIENTRY eglGetDisplay_renderdoc_hooked(EGLNativeDisplayType display)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -91,8 +91,10 @@ HOOK_EXPORT EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display)
return EGL.GetDisplay(display);
}
HOOK_EXPORT EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config,
EGLContext shareContext, EGLint const *attribList)
HOOK_EXPORT EGLContext EGLAPIENTRY eglCreateContext_renderdoc_hooked(EGLDisplay display,
EGLConfig config,
EGLContext shareContext,
EGLint const *attribList)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -200,7 +202,7 @@ HOOK_EXPORT EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfi
return ret;
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglDestroyContext_renderdoc_hooked(EGLDisplay dpy, EGLContext ctx)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -220,9 +222,10 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext
return EGL.DestroyContext(dpy, ctx);
}
HOOK_EXPORT EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLNativeWindowType win,
const EGLint *attrib_list)
HOOK_EXPORT EGLSurface EGLAPIENTRY eglCreateWindowSurface_renderdoc_hooked(EGLDisplay dpy,
EGLConfig config,
EGLNativeWindowType win,
const EGLint *attrib_list)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -244,8 +247,9 @@ HOOK_EXPORT EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLCon
return ret;
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface draw,
EGLSurface read, EGLContext ctx)
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglMakeCurrent_renderdoc_hooked(EGLDisplay display,
EGLSurface draw, EGLSurface read,
EGLContext ctx)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -320,7 +324,7 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface
return ret;
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffers_renderdoc_hooked(EGLDisplay dpy, EGLSurface surface)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -339,8 +343,10 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface sur
return EGL.SwapBuffers(dpy, surface);
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x,
EGLint y, EGLint width, EGLint height)
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglPostSubBufferNV_renderdoc_hooked(EGLDisplay dpy,
EGLSurface surface, EGLint x,
EGLint y, EGLint width,
EGLint height)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -359,7 +365,8 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface
return EGL.PostSubBufferNV(dpy, surface, x, y, width, height);
}
HOOK_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *func)
HOOK_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY
eglGetProcAddress_renderdoc_hooked(const char *func)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -381,17 +388,19 @@ HOOK_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddre
// return our egl hooks
if(!strcmp(func, "eglCreateContext"))
return (__eglMustCastToProperFunctionPointerType)&eglCreateContext;
return (__eglMustCastToProperFunctionPointerType)&eglCreateContext_renderdoc_hooked;
if(!strcmp(func, "eglGetDisplay"))
return (__eglMustCastToProperFunctionPointerType)&eglGetDisplay;
return (__eglMustCastToProperFunctionPointerType)&eglGetDisplay_renderdoc_hooked;
if(!strcmp(func, "eglDestroyContext"))
return (__eglMustCastToProperFunctionPointerType)&eglDestroyContext;
return (__eglMustCastToProperFunctionPointerType)&eglDestroyContext_renderdoc_hooked;
if(!strcmp(func, "eglMakeCurrent"))
return (__eglMustCastToProperFunctionPointerType)&eglMakeCurrent;
return (__eglMustCastToProperFunctionPointerType)&eglMakeCurrent_renderdoc_hooked;
if(!strcmp(func, "eglSwapBuffers"))
return (__eglMustCastToProperFunctionPointerType)&eglSwapBuffers;
return (__eglMustCastToProperFunctionPointerType)&eglSwapBuffers_renderdoc_hooked;
if(!strcmp(func, "eglPostSubBufferNV"))
return (__eglMustCastToProperFunctionPointerType)&eglPostSubBufferNV;
return (__eglMustCastToProperFunctionPointerType)&eglPostSubBufferNV_renderdoc_hooked;
if(!strcmp(func, "eglGetProcAddress"))
return (__eglMustCastToProperFunctionPointerType)&eglGetProcAddress_renderdoc_hooked;
// any other egl functions are safe to pass through unchanged
if(!strncmp(func, "egl", 3))
@@ -401,6 +410,57 @@ HOOK_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddre
return (__eglMustCastToProperFunctionPointerType)HookedGetProcAddress(func, (void *)realFunc);
}
// on posix systems, someone might declare a global variable with the same name as a function. When
// doing this, it might mean that our code for "&eglSwapBuffers" looking up that global symbol will
// instead find the location fo the function pointer instead of our hook function. For this reason
// we always refer to the _renderdoc_hooked name, but we still must export the functions under their
// real names and just forward to the hook implementation.
HOOK_EXPORT EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display)
{
return eglGetDisplay_renderdoc_hooked(display);
}
HOOK_EXPORT EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config,
EGLContext shareContext, EGLint const *attribList)
{
return eglCreateContext_renderdoc_hooked(display, config, shareContext, attribList);
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
return eglDestroyContext_renderdoc_hooked(dpy, ctx);
}
HOOK_EXPORT EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLNativeWindowType win,
const EGLint *attrib_list)
{
return eglCreateWindowSurface_renderdoc_hooked(dpy, config, win, attrib_list);
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface draw,
EGLSurface read, EGLContext ctx)
{
return eglMakeCurrent_renderdoc_hooked(display, draw, read, ctx);
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
return eglSwapBuffers_renderdoc_hooked(dpy, surface);
}
HOOK_EXPORT EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x,
EGLint y, EGLint width, EGLint height)
{
return eglPostSubBufferNV_renderdoc_hooked(dpy, surface, x, y, width, height);
}
HOOK_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *func)
{
return eglGetProcAddress_renderdoc_hooked(func);
}
// on posix systems we need to export the whole of the EGL API, since we will have redirected any
// dlopen() for libEGL.so to ourselves, and dlsym() for any of these entry points must return a
// valid function. We don't need to intercept them, so we just pass it along
@@ -602,10 +662,10 @@ void EGLHook::RegisterHooks()
#endif
// register EGL hooks
#define EGL_REGISTER(func, isext) \
LibraryHooks::RegisterFunctionHook( \
"libEGL" LIBSUFFIX, \
FunctionHook("egl" STRINGIZE(func), (void **)&EGL.func, (void *)&CONCAT(egl, func)));
#define EGL_REGISTER(func, isext) \
LibraryHooks::RegisterFunctionHook( \
"libEGL" LIBSUFFIX, FunctionHook("egl" STRINGIZE(func), (void **)&EGL.func, \
(void *)&CONCAT(egl, CONCAT(func, _renderdoc_hooked))));
EGL_HOOKED_SYMBOLS(EGL_REGISTER)
#undef EGL_REGISTER
}
+89 -27
View File
@@ -93,8 +93,8 @@ public:
std::map<XID, XID> m_GLXWindowMap;
} glxhook;
HOOK_EXPORT GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList,
Bool direct)
HOOK_EXPORT GLXContext glXCreateContext_renderdoc_hooked(Display *dpy, XVisualInfo *vis,
GLXContext shareList, Bool direct)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -146,7 +146,7 @@ HOOK_EXPORT GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXConte
return ret;
}
HOOK_EXPORT void glXDestroyContext(Display *dpy, GLXContext ctx)
HOOK_EXPORT void glXDestroyContext_renderdoc_hooked(Display *dpy, GLXContext ctx)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -165,9 +165,9 @@ HOOK_EXPORT void glXDestroyContext(Display *dpy, GLXContext ctx)
GLX.glXDestroyContext(dpy, ctx);
}
HOOK_EXPORT GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
GLXContext shareList, Bool direct,
const int *attribList)
HOOK_EXPORT GLXContext glXCreateContextAttribsARB_renderdoc_hooked(Display *dpy, GLXFBConfig config,
GLXContext shareList, Bool direct,
const int *attribList)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -289,7 +289,7 @@ HOOK_EXPORT GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig conf
return ret;
}
HOOK_EXPORT Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
HOOK_EXPORT Bool glXMakeCurrent_renderdoc_hooked(Display *dpy, GLXDrawable drawable, GLXContext ctx)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -356,8 +356,8 @@ HOOK_EXPORT Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext c
return ret;
}
HOOK_EXPORT Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read,
GLXContext ctx)
HOOK_EXPORT Bool glXMakeContextCurrent_renderdoc_hooked(Display *dpy, GLXDrawable draw,
GLXDrawable read, GLXContext ctx)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -423,7 +423,7 @@ HOOK_EXPORT Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawab
return ret;
}
HOOK_EXPORT void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
HOOK_EXPORT void glXSwapBuffers_renderdoc_hooked(Display *dpy, GLXDrawable drawable)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -440,8 +440,8 @@ HOOK_EXPORT void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
GLX.glXSwapBuffers(dpy, drawable);
}
HOOK_EXPORT GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window win,
const int *attribList)
HOOK_EXPORT GLXWindow glXCreateWindow_renderdoc_hooked(Display *dpy, GLXFBConfig config, Window win,
const int *attribList)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -461,7 +461,7 @@ HOOK_EXPORT GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window w
return ret;
}
HOOK_EXPORT void glXDestroyWindow(Display *dpy, GLXWindow window)
HOOK_EXPORT void glXDestroyWindow_renderdoc_hooked(Display *dpy, GLXWindow window)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -479,7 +479,7 @@ HOOK_EXPORT void glXDestroyWindow(Display *dpy, GLXWindow window)
return GLX.glXDestroyWindow(dpy, window);
}
HOOK_EXPORT __GLXextFuncPtr glXGetProcAddress(const GLubyte *f)
HOOK_EXPORT __GLXextFuncPtr glXGetProcAddress_renderdoc_hooked(const GLubyte *f)
{
if(RenderDoc::Inst().IsReplayApp())
{
@@ -503,27 +503,27 @@ HOOK_EXPORT __GLXextFuncPtr glXGetProcAddress(const GLubyte *f)
// return our glX hooks
if(!strcmp(func, "glXCreateContext"))
return (__GLXextFuncPtr)&glXCreateContext;
return (__GLXextFuncPtr)&glXCreateContext_renderdoc_hooked;
if(!strcmp(func, "glXDestroyContext"))
return (__GLXextFuncPtr)&glXDestroyContext;
return (__GLXextFuncPtr)&glXDestroyContext_renderdoc_hooked;
if(!strcmp(func, "glXCreateContextAttribsARB"))
return (__GLXextFuncPtr)&glXCreateContextAttribsARB;
return (__GLXextFuncPtr)&glXCreateContextAttribsARB_renderdoc_hooked;
if(!strcmp(func, "glXMakeCurrent"))
return (__GLXextFuncPtr)&glXMakeCurrent;
return (__GLXextFuncPtr)&glXMakeCurrent_renderdoc_hooked;
if(!strcmp(func, "glXMakeContextCurrent"))
return (__GLXextFuncPtr)&glXMakeContextCurrent;
return (__GLXextFuncPtr)&glXMakeContextCurrent_renderdoc_hooked;
if(!strcmp(func, "glXSwapBuffers"))
return (__GLXextFuncPtr)&glXSwapBuffers;
return (__GLXextFuncPtr)&glXSwapBuffers_renderdoc_hooked;
if(!strcmp(func, "glXCreateWindow"))
return (__GLXextFuncPtr)&glXCreateWindow;
return (__GLXextFuncPtr)&glXCreateWindow_renderdoc_hooked;
if(!strcmp(func, "glXDestroyWindow"))
return (__GLXextFuncPtr)&glXDestroyWindow;
return (__GLXextFuncPtr)&glXDestroyWindow_renderdoc_hooked;
if(!strcmp(func, "glXGetProcAddress"))
return (__GLXextFuncPtr)&glXGetProcAddress;
return (__GLXextFuncPtr)&glXGetProcAddress_renderdoc_hooked;
if(!strcmp(func, "glXGetProcAddressARB"))
return (__GLXextFuncPtr)&glXGetProcAddressARB;
return (__GLXextFuncPtr)&glXGetProcAddress_renderdoc_hooked;
// any other egl functions are safe to pass through unchanged
// any other GLX functions are safe to pass through unchanged
if(!strncmp(func, "glX", 3))
return realFunc;
@@ -531,9 +531,70 @@ HOOK_EXPORT __GLXextFuncPtr glXGetProcAddress(const GLubyte *f)
return (__GLXextFuncPtr)HookedGetProcAddress(func, (void *)realFunc);
}
HOOK_EXPORT __GLXextFuncPtr glXGetProcAddressARB_renderdoc_hooked(const GLubyte *f)
{
return glXGetProcAddress_renderdoc_hooked(f);
}
// on posix systems, someone might declare a global variable with the same name as a function. When
// doing this, it might mean that our code for "&glXSwapBuffers" looking up that global symbol will
// instead find the location fo the function pointer instead of our hook function. For this reason
// we always refer to the _renderdoc_hooked name, but we still must export the functions under their
// real names and just forward to the hook implementation.
HOOK_EXPORT GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList,
Bool direct)
{
return glXCreateContext_renderdoc_hooked(dpy, vis, shareList, direct);
}
HOOK_EXPORT void glXDestroyContext(Display *dpy, GLXContext ctx)
{
return glXDestroyContext_renderdoc_hooked(dpy, ctx);
}
HOOK_EXPORT GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
GLXContext shareList, Bool direct,
const int *attribList)
{
return glXCreateContextAttribsARB_renderdoc_hooked(dpy, config, shareList, direct, attribList);
}
HOOK_EXPORT Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
{
return glXMakeCurrent_renderdoc_hooked(dpy, drawable, ctx);
}
HOOK_EXPORT Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read,
GLXContext ctx)
{
return glXMakeContextCurrent_renderdoc_hooked(dpy, draw, read, ctx);
}
HOOK_EXPORT void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
{
return glXSwapBuffers_renderdoc_hooked(dpy, drawable);
}
HOOK_EXPORT GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window win,
const int *attribList)
{
return glXCreateWindow_renderdoc_hooked(dpy, config, win, attribList);
}
HOOK_EXPORT void glXDestroyWindow(Display *dpy, GLXWindow window)
{
return glXDestroyWindow_renderdoc_hooked(dpy, window);
}
HOOK_EXPORT __GLXextFuncPtr glXGetProcAddress(const GLubyte *f)
{
return glXGetProcAddress_renderdoc_hooked(f);
}
HOOK_EXPORT __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *f)
{
return glXGetProcAddress(f);
return glXGetProcAddressARB_renderdoc_hooked(f);
}
// on posix systems we need to export the whole of the GLX API, since we will have redirected any
@@ -695,7 +756,8 @@ void GLXHook::RegisterHooks()
// register EGL hooks
#define GLX_REGISTER(func) \
LibraryHooks::RegisterFunctionHook( \
"libGL.so", FunctionHook(STRINGIZE(func), (void **)&GLX.func, (void *)&func));
"libGL.so", \
FunctionHook(STRINGIZE(func), (void **)&GLX.func, (void *)&CONCAT(func, _renderdoc_hooked)));
GLX_HOOKED_SYMBOLS(GLX_REGISTER)
#undef GLX_REGISTER
}