我正在开发一个基本的演示应用程序(kmscube)来通过DRM和GBM API进行渲染。我的应用程序使用libgbm的TI变体(mesa通用缓冲区管理)。 TI提供source,GNU autotools files和build environment(Yocto)来编译它。我在他们的环境中编译了GBM,它运行得很好。
我不想使用Yocto,所以我将源代码移动到我自己的构建系统(buildroot)并编译它。一切都正确编译(使用相同的autotools文件),但是当它运行时,我调用gbm_surface_create
时会出现分段错误。我尽可能调试,发现程序进入gbm库但在return gbm->surface_create(gbm, width, height, format, flags);
上失败
在不同环境中编译时,导致库运行方式不同的原因。是否有一些我可能遗漏的非常重要的编译器或链接器标志?
这是图形应用程序中的代码(在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;
这是创建设备的调用堆栈(在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;
}
(继续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);
}
以下是抛出分段错误的代码(在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);
}