summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBrian Nguyen <brnguyen@nvidia.com>2014-01-23 20:14:03 -0800
committerbrnguyen <brnguyen@nvidia.com>2014-01-23 20:28:50 -0800
commita0221d1ad6b9d62b0e5d6a95e60e475fd61f4e22 (patch)
treec322997ff6d097f54a4ec8fda3fe0c1645da884a /tests
parent7ff53ca956abc2cc7cf25880b6c3a6c19d1985fc (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.c142
-rw-r--r--tests/GLX_dummy/Makefile.am11
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