diff options
author | Brian Nguyen <brnguyen@nvidia.com> | 2014-01-23 20:14:03 -0800 |
---|---|---|
committer | brnguyen <brnguyen@nvidia.com> | 2014-01-23 20:28:50 -0800 |
commit | a0221d1ad6b9d62b0e5d6a95e60e475fd61f4e22 (patch) | |
tree | c322997ff6d097f54a4ec8fda3fe0c1645da884a /tests | |
parent | 7ff53ca956abc2cc7cf25880b6c3a6c19d1985fc (diff) |
Build libGLX_patchentry.so for future entrypoint patching unit test
This test DSO patches glVertex3fv() at runtime to increment a global
variable, __glXSawVertex3fv. This will be used by a future
"testglxpatchentry" unit test to verify that basic entrypoint patching
works as expected on platforms that support it.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/GLX_dummy/GLX_dummy.c | 142 | ||||
-rw-r--r-- | tests/GLX_dummy/Makefile.am | 11 |
2 files changed, 150 insertions, 3 deletions
diff --git a/tests/GLX_dummy/GLX_dummy.c b/tests/GLX_dummy/GLX_dummy.c index d4f0f6c..6f6d74c 100644 --- a/tests/GLX_dummy/GLX_dummy.c +++ b/tests/GLX_dummy/GLX_dummy.c @@ -468,6 +468,144 @@ static void dummySetDispatchIndex (const GLubyte *procName, int ind } } +#if defined(PATCH_ENTRYPOINTS) +PUBLIC int __glXSawVertex3fv; + +static void patch_x86_64_tls(char *entry, + int stubSize) +{ +#if defined(__x86_64__) + char *pSawVertex3fv = (char *)&__glXSawVertex3fv; + int *p; + char tmpl[] = { + 0x8b, 0x05, 0x0, 0x0, 0x0, 0x0, // mov 0x0(%rip), %eax + 0x83, 0xc0, 0x01, // add $0x1, %eax + 0x89, 0x05, 0x0, 0x0, 0x0, 0x0, // mov %eax, 0x0(%rip) + 0xc3, // ret + }; + + STATIC_ASSERT(sizeof(int) == 0x4); + + if (stubSize < sizeof(tmpl)) { + return; + } + + p = (int *)&tmpl[2]; + *p = (int)(pSawVertex3fv - (entry + 6)); + + p = (int *)&tmpl[11]; + *p = (int)(pSawVertex3fv - (entry + 15)); + + memcpy(entry, tmpl, sizeof(tmpl)); +#else + assert(0); // Should not be calling this +#endif +} + +static void patch_x86_tls(char *entry, + int stubSize) +{ +#if defined(__i386__) + char *pSawVertex3fv = (char *)&__glXSawVertex3fv; + int *p; + char tmpl[] = { + 0xa1, 0x0, 0x0, 0x0, 0x0, // mov 0x0, %eax + 0x83, 0xc0, 0x01, // add $0x1, %eax + 0xa3, 0x0, 0x0, 0x0, 0x0, // mov %eax, 0x0 + 0xc3 // ret + }; + + STATIC_ASSERT(sizeof(int) == 0x4); + + if (stubSize < sizeof(tmpl)) { + return; + } + + p = (int *)&tmpl[1]; + *p = (int)(pSawVertex3fv - (entry + 5)); + + p = (int *)&tmpl[9]; + *p = (int)(pSawVertex3fv - (entry + 13)); + + memcpy(entry, tmpl, sizeof(tmpl)); + + // Jump to an intermediate location + __asm__( + "\tjmp 0f\n" + "\t0:\n" + ); +#else + assert(0); // Should not be calling this +#endif +} + +static int dummyStubType; +static int dummyStubSize; +static int dummyStubGeneration; +static char *dummyVertex3fvAddrs[3]; + +static GLboolean dummyInitiatePatch(int type, + int stubSize, + int stubGeneration, + GLboolean *needOffsets) +{ + assert(needOffsets); + switch (type) { + case __GLDISPATCH_STUB_X86_64_TLS: + case __GLDISPATCH_STUB_X86_TLS: + dummyStubType = type; + dummyStubSize = stubSize; + dummyStubGeneration = stubGeneration; + *needOffsets = GL_TRUE; + return GL_TRUE; + default: + *needOffsets = GL_FALSE; + return GL_FALSE; + } +} + +/* Only interested in glVertex3fv() for testing purposes. */ +static void dummyGetOffsetHook( + void *(*lookupStubOffset)(const char *funcName) +) +{ + char **pNewAddr; + + // Seek to the first empty entry + for (pNewAddr = dummyVertex3fvAddrs; + *pNewAddr; pNewAddr++) { + } + + assert((pNewAddr - dummyVertex3fvAddrs) < 3); + + *pNewAddr = (char *)lookupStubOffset("Vertex3fv"); +} + +static void dummyFinalizePatch(void) +{ + char **pAddr; + for (pAddr = dummyVertex3fvAddrs; *pAddr; pAddr++) { + switch (dummyStubType) { + case __GLDISPATCH_STUB_X86_64_TLS: + patch_x86_64_tls(*pAddr, dummyStubSize); + break; + case __GLDISPATCH_STUB_X86_TLS: + patch_x86_tls(*pAddr, dummyStubSize); + break; + default: + assert(0); + } + } +} + +static const __GLdispatchPatchCallbacks dummyPatchCallbacks = +{ + .initiatePatch = dummyInitiatePatch, + .getOffsetHook = dummyGetOffsetHook, + .finalizePatch = dummyFinalizePatch +}; +#endif // defined(PATCH_ENTRYPOINTS) + static const __GLXapiImports dummyImports = { /* Entry points */ @@ -511,7 +649,11 @@ static const __GLXapiImports dummyImports = .getProcAddress = dummyGetProcAddress, .getDispatchAddress = dummyGetDispatchAddress, .setDispatchIndex = dummySetDispatchIndex, +#if defined(PATCH_ENTRYPOINTS) + .patchCallbacks = &dummyPatchCallbacks, +#else .patchCallbacks = NULL, +#endif } }; diff --git a/tests/GLX_dummy/Makefile.am b/tests/GLX_dummy/Makefile.am index d667aaf..54f984c 100644 --- a/tests/GLX_dummy/Makefile.am +++ b/tests/GLX_dummy/Makefile.am @@ -1,5 +1,5 @@ noinst_HEADERS = GLX_dummy.h -lib_LTLIBRARIES = libGLX_dummy.la +lib_LTLIBRARIES = libGLX_dummy.la libGLX_patchentry.la check-local: libGLX_dummy_copy @@ -10,13 +10,18 @@ libGLX_dummy_copy : libGLX_dummy.la cp .libs/libGLX_dummy.so.0.0.0 .libs/libGLX_dummy_0.so.0 cp .libs/libGLX_dummy.so.0.0.0 .libs/libGLX_dummy_1.so.0 - -libGLX_dummy_la_CFLAGS = \ +COMMON_CFLAGS = \ -I$(top_srcdir)/src/GLX \ -I$(top_srcdir)/src/GLdispatch \ -I$(top_srcdir)/src/util \ -I$(top_srcdir)/src/util/trace \ -I$(top_srcdir)/include \ -Wno-error=unused-function + +libGLX_dummy_la_CFLAGS = $(COMMON_CFLAGS) libGLX_dummy_la_SOURCES = GLX_dummy.c libGLX_dummy_la_LIBADD = $(top_builddir)/src/util/trace/libtrace.la + +libGLX_patchentry_la_CFLAGS = $(COMMON_CFLAGS) -DPATCH_ENTRYPOINTS +libGLX_patchentry_la_SOURCES = GLX_dummy.c +libGLX_patchentry_la_LIBADD = $(top_builddir)/src/util/trace/libtrace.la |