i965: Assert array index on access to vec4_visitor's arrays.
[mesa.git] / src / mesa / drivers / dri / common / megadriver_stub.c
1 /*
2 * Copyright © 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <stdio.h>
25 #include "dri_util.h"
26 #include <dlfcn.h>
27 #include "main/macros.h"
28
29 /* We need GNU extensions to dlfcn.h in order to provide backward
30 * compatibility for the older DRI driver loader mechanism. (dladdr,
31 * Dl_info, and RTLD_DEFAULT are only defined when _GNU_SOURCE is
32 * defined.)
33 */
34 #ifdef _GNU_SOURCE
35
36 #define MEGADRIVER_STUB_MAX_EXTENSIONS 10
37 #define LIB_PATH_SUFFIX "_dri.so"
38 #define LIB_PATH_SUFFIX_LENGTH (sizeof(LIB_PATH_SUFFIX)-1)
39
40 /* This is the table of extensions that the loader will dlsym() for.
41 *
42 * Initially it is empty for the megadriver stub, but the library
43 * constructor may initialize it based on the name of the library that
44 * is being loaded.
45 */
46 PUBLIC const __DRIextension *
47 __driDriverExtensions[MEGADRIVER_STUB_MAX_EXTENSIONS] = {
48 NULL
49 };
50
51 /**
52 * This is a constructor function for the megadriver dynamic library.
53 *
54 * When the driver is dlopen'ed, this function will run. It will
55 * search for the name of the foo_dri.so file that was opened using
56 * the dladdr function.
57 *
58 * After finding foo's name, it will call __driDriverGetExtensions_foo
59 * and use the return to update __driDriverExtensions to enable
60 * compatibility with older DRI driver loaders.
61 */
62 __attribute__((constructor)) static void
63 megadriver_stub_init(void)
64 {
65 Dl_info info;
66 char *driver_name;
67 size_t name_len;
68 char *get_extensions_name;
69 const __DRIextension **(*get_extensions)(void);
70 const __DRIextension **extensions;
71 int i;
72
73 /* Call dladdr on __driDriverExtensions. We are really
74 * interested in the returned info.dli_fname so we can
75 * figure out the path name of the library being loaded.
76 */
77 i = dladdr((void*) __driDriverExtensions, &info);
78 if (i == 0)
79 return;
80
81 /* Search for the last '/' character in the path. */
82 driver_name = strrchr(info.dli_fname, '/');
83 if (driver_name != NULL) {
84 /* Skip '/' character */
85 driver_name++;
86 } else {
87 /* Try using the start of the path */
88 driver_name = (char*) info.dli_fname;
89 }
90
91 /* Make sure the path ends with _dri.so */
92 name_len = strlen(driver_name);
93 i = name_len - LIB_PATH_SUFFIX_LENGTH;
94 if (i < 0 || strcmp(driver_name + i, LIB_PATH_SUFFIX) != 0)
95 return;
96
97 /* Duplicate the string so we can modify it.
98 * So far we've been using info.dli_fname.
99 */
100 driver_name = strdup(driver_name);
101 if (!driver_name)
102 return;
103
104 /* The path ends with _dri.so. Chop this part of the
105 * string off. Then we'll have the driver's final name.
106 */
107 driver_name[i] = '\0';
108
109 i = asprintf(&get_extensions_name, "%s_%s",
110 __DRI_DRIVER_GET_EXTENSIONS, driver_name);
111 free(driver_name);
112 if (i == -1)
113 return;
114
115 /* dlsym to get the driver's get extensions function. We
116 * don't have the dlopen handle, so we have to use
117 * RTLD_DEFAULT. It seems unlikely that the symbol will
118 * be found in another library, but this isn't optimal.
119 */
120 get_extensions = dlsym(RTLD_DEFAULT, get_extensions_name);
121 free(get_extensions_name);
122 if (!get_extensions)
123 return;
124
125 /* Use the newer DRI loader entrypoint to find extensions.
126 * We will then expose these extensions via the older
127 * __driDriverExtensions symbol.
128 */
129 extensions = get_extensions();
130
131 /* Copy the extensions into the __driDriverExtensions array
132 * we declared.
133 */
134 for (i = 0; i < ARRAY_SIZE(__driDriverExtensions); i++) {
135 __driDriverExtensions[i] = extensions[i];
136 if (extensions[i] == NULL)
137 break;
138 }
139
140 /* If the driver had more extensions than we reserved, then
141 * bail out.
142 */
143 if (i == ARRAY_SIZE(__driDriverExtensions)) {
144 __driDriverExtensions[0] = NULL;
145 fprintf(stderr, "Megadriver stub did not reserve enough extension "
146 "slots.\n");
147 return;
148 }
149 }
150
151 #endif /* _GNU_SOURCE */
152
153 static const
154 __DRIconfig **stub_error_init_screen(__DRIscreen *psp)
155 {
156 fprintf(stderr, "An updated DRI driver loader (libGL.so or X Server) is "
157 "required for this Mesa driver.\n");
158 return NULL;
159 }
160
161 /**
162 * This is a stub driDriverAPI that is referenced by dri_util.c but should
163 * never be used.
164 */
165 const struct __DriverAPIRec driDriverAPI = {
166 .InitScreen = stub_error_init_screen,
167 };