[Mesa-dev] [Mesa-stable] [PATCH v2] dri megadriver_stub: provide compatibility with older DRI loader
Ian Romanick
idr at freedesktop.org
Fri Dec 6 19:58:24 PST 2013
On 12/06/2013 07:54 PM, Matt Turner wrote:
> On Fri, Dec 6, 2013 at 7:11 PM, Jordan Justen <jordan.l.justen at intel.com> wrote:
>> To help the transition period when DRI loaders are being updated
>> to support the newer __driDriverExtensions_foo mechanism,
>> we populate __DRIextension with the extensions returned
>> by __driDriverExtensions_foo during a library contructor
>> function.
>>
>> We find the driver foo's name by using the dladdr function
>> which gives the path of the dynamic library's name that
>> was being loaded.
>>
>> v2:
>> * dladdr on public symbol __driDriverExtensions rather
>> than static megadriver_stub_init.
>> * Incorporate fixes and suggestions from Keith
>>
>> Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
>> Cc: "10.0" <mesa-stable at lists.freedesktop.org>
>> ---
>> src/mesa/drivers/dri/common/megadriver_stub.c | 125 ++++++++++++++++++++++++++
>> 1 file changed, 125 insertions(+)
>>
>> diff --git a/src/mesa/drivers/dri/common/megadriver_stub.c b/src/mesa/drivers/dri/common/megadriver_stub.c
>> index 6bf5d73..cb1078d 100644
>> --- a/src/mesa/drivers/dri/common/megadriver_stub.c
>> +++ b/src/mesa/drivers/dri/common/megadriver_stub.c
>> @@ -23,6 +23,131 @@
>>
>> #include <stdio.h>
>> #include "dri_util.h"
>> +#include <dlfcn.h>
>> +#include "main/macros.h"
>> +
>> +/* The extensions that allow the megadriver stub to provide backward
>> + * compatibility for the older DRI driver loader require GNU
>> + * extensions from dlfcn.h.
>> + */
>> +#ifdef _GNU_SOURCE
>
> More specifically, what extension do we use?
>
>> +#define MEGADRIVER_STUB_MAX_EXTENSIONS 10
>> +#define LIB_PATH_SUFFIX "_dri.so"
>> +#define LIB_PATH_SUFFIX_LENGTH (sizeof(LIB_PATH_SUFFIX)-1)
>> +
>> +/* This is the table of extensions that the loader will dlsym() for.
>> + *
>> + * Initially it is empty for the megadriver stub, but the library
>> + * contructor may initialize it based on the name of the library that
>
> constructor
>
>> + * is being loaded.
>> + */
>> +PUBLIC const __DRIextension *
>> +__driDriverExtensions[MEGADRIVER_STUB_MAX_EXTENSIONS] = {
>> + NULL
>> +};
>> +
>> +/**
>> + * This is a contructor function for the megadriver dynamic library.
>
> constructor
>
>> + *
>> + * When the driver is dlopen'ed, this function will run. It will
>> + * search for the name of the foo_dri.so file that was opened using
>> + * the dladdr function.
>> + *
>> + * After finding foo's name, it will call __driDriverGetExtensions_foo
>> + * and use the return to update __driDriverExtensions to enable
>> + * compatibility with older DRI driver loaders.
>> + */
>> +__attribute__((constructor)) static void
>> +megadriver_stub_init(void)
>> +{
>> + Dl_info info;
>> + char *driver_name;
>> + size_t name_len;
>> + char *get_extensions_name;
>> + const __DRIextension **(*get_extensions)(void);
>> + const __DRIextension **extensions;
>> + int i;
>> +
>> + /* Call dladdr on __driDriverExtensions. We are really
>> + * interested in the returned info.dli_fname so we can
>> + * figure out the path name of the library being loaded.
>> + */
>> + i = dladdr((void*) __driDriverExtensions, &info);
>> + if (i == 0)
>> + return;
>> +
>> + /* Search for the last '/' character in the path. */
>> + driver_name = strrchr(info.dli_fname, '/');
>> + if (driver_name != NULL) {
>> + /* Skip '/' character */
>> + driver_name++;
>> + } else {
>> + /* Try using the start of the path */
>> + driver_name = (char*) info.dli_fname;
>> + }
>> +
>> + /* Make sure the path ends with _dri.so */
>> + name_len = strlen(driver_name);
>> + i = name_len - LIB_PATH_SUFFIX_LENGTH;
>> + if (i < 0 || strcmp(driver_name + i, LIB_PATH_SUFFIX) != 0)
>> + return;
>> +
>> + /* Duplicate the string so we can modify it.
>> + * So far we've been using info.dli_fname.
>> + */
>> + driver_name = strdup(driver_name);
>> + if (!driver_name)
>> + return;
>> +
>> + /* The path ends with _dri.so. Chop this part of the
>> + * string off. Then we'll have the driver's final name.
>> + */
>> + driver_name[i] = '\0';
>> +
>> + i = asprintf(&get_extensions_name, "%s_%s",
>> + __DRI_DRIVER_GET_EXTENSIONS, driver_name);
>> + free(driver_name);
>> + if (i == -1)
>> + return;
>> +
>> + /* dlsym to get the driver's get extensions function. We
>> + * don't have the dlopen handle, so we have to use
>> + * RTLD_DEFAULT. It seems unlikely that the symbol will
>> + * be found in another library, but this isn't optimal.
>> + */
>> + get_extensions = dlsym(RTLD_DEFAULT, get_extensions_name);
>> + free(get_extensions_name);
>> + if (!get_extensions)
>> + return;
>> +
>> + /* Use the newer DRI loader entrypoint to find extensions.
>> + * We will then expose these extensions via the older
>> + * __driDriverExtensions symbol.
>> + */
>> + extensions = get_extensions();
>> +
>> + /* Copy the extensions into the __driDriverExtensions array
>> + * we declared.
>> + */
>> + for (i = 0; i < ARRAY_SIZE(__driDriverExtensions); i++) {
>> + __driDriverExtensions[i] = extensions[i];
>> + if (extensions[i] == NULL)
>> + break;
>> + }
>> +
>> + /* If the driver had more extensions than we reserved, then
>> + * bail out.
>> + */
>> + if (i == ARRAY_SIZE(__driDriverExtensions)) {
>> + __driDriverExtensions[0] = NULL;
>> + fprintf(stderr, "Megadriver stub did not reserve enough extension "
>> + "slots.\n");
>> + return;
>> + }
>> +}
>> +
>> +#endif // #ifdef _GNU_SOURCE
>
> C++-style comment.
This part gets build using C99, right? If so, that should be fine.
> Very cool. Have a
>
> Reviewed-by: Matt Turner <mattst88 at gmail.com>
> _______________________________________________
> mesa-stable mailing list
> mesa-stable at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-stable
More information about the mesa-dev
mailing list