1

I am working on a basic demo application (kmscube) to do rendering via the DRM and GBM APIs. My application uses the TI variation of libgbm (mesa generic buffer management). TI provides the source, GNU autotools files, and a build environment (Yocto) to compile it. I compiled GBM in their environment and it works perfectly.

I did not want to use Yocto, so I moved the source into my own build system (buildroot) and compiled it. Everything compiles correctly (using the same autotools files), but when it runs, I get a segmentation fault when I call gbm_surface_create. I debugged as far as I could and found that the program steps into the gbm library but fails on return gbm->surface_create(gbm, width, height, format, flags);

What would cause a library to run differently when compiled in different environments. Are there some really important compiler or linker flags that I could be missing?

This is the code from the graphics application (in kmscube.c)

gbm.dev = gbm_create_device(drm.fd);

gbm.surface = gbm_surface_create(gbm.dev,
                                  drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay,
                                  drm_fmt_to_gbm_fmt(drm.format[DISP_ID]),
                                  GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!gbm.surface) {
   printf("failed to create gbm surface\n");
   return -1;
}

return 0;

This is the call stack that creates the device ( in gbm.c)

GBM_EXPORT struct gbm_device *
gbm_create_device(int fd)
{
   struct gbm_device *gbm = NULL;
   struct stat buf;

   if (fd < 0 || fstat(fd, &buf) < 0 || !S_ISCHR(buf.st_mode)) {
      fprintf(stderr, "gbm_create_device: invalid fd: %d\n", fd);
      return NULL;  
   }

   if (device_num == 0)
      memset(devices, 0, sizeof devices);

   gbm = _gbm_create_device(fd);
   if (gbm == NULL)
      return NULL;

   gbm->dummy = gbm_create_device;
   gbm->stat = buf;
   gbm->refcount = 1;

   if (device_num < ARRAY_SIZE(devices)-1)
      devices[device_num++] = gbm;

   return gbm;
}

(continued in backend.c)

struct gbm_device *
_gbm_create_device(int fd)
{
   const struct gbm_backend *backend = NULL;
   struct gbm_device *dev = NULL;
   int i;
   const char *b;

   b = getenv("GBM_BACKEND");
   if (b)
      backend = load_backend(b);

   if (backend)
      dev = backend->create_device(fd);

   for (i = 0; i < ARRAY_SIZE(backends) && dev == NULL; ++i) {
      backend = load_backend(backends[i]);
      if (backend == NULL)
         continue;
      fprintf(stderr, "found valid GBM backend : %s\n", backends[i]);
      dev = backend->create_device(fd);
   }

   return dev;
}

static const void *
load_backend(const char *name)
{
   char path[PATH_MAX];
   void *module;
   const char *entrypoint = "gbm_backend";

   if (name[0] != '/')
      snprintf(path, sizeof path, MODULEDIR "/%s", name);
   else
      snprintf(path, sizeof path, "%s", name);

   module = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
   if (!module) {
      fprintf(stderr, "failed to load module: %s\n", dlerror());
      return NULL;
   }
   else {
      fprintf(stderr, "loaded module : %s\n", name);
   }

   return dlsym(module, entrypoint);
}

And here is the code that throws a segmentation fault (in gbm.c)

GBM_EXPORT struct gbm_surface *
gbm_surface_create(struct gbm_device *gbm,
                   uint32_t width, uint32_t height,
                   uint32_t format, uint32_t flags)
{
   return gbm->surface_create(gbm, width, height, format, flags);
}
FelixSFD
  • 6,052
  • 10
  • 43
  • 117
user8908459
  • 537
  • 5
  • 24

0 Answers0