Summary: I am trying to figure out what settings in my compiler would change how stucts are setup in memory
Details: I have two versions of the same library file (libgbm.so), one provided as a pre-built binary and one compiled on my own machine. One works correctly and one throws a segmentation fault. It appears that my compiler is handing my data structures differently than the pre-compiled version.
I have provided a trimmed-down version of the code (see associated structs at bottom). Basically, it loads a shared library and calls the create_device()
function. That returns a data structure ( gbm_device
) with a bunch of function pointers.
gbm_create_device(int fd)
{
struct gbm_device *gbm = NULL;
void *module;
const struct gbm_backend *backend = NULL
module = dlopen("/usr/lib/gbm/gbm_pvr.so", RTLD_NOW | RTLD_GLOBAL);
backend = dlsym(module, "gbm_backend");
gbm = backend->create_device(fd);
gbm->surface_create(gbm, width, height, format, flags);
}
This is where the code runs differently. When using the precompiled library, GDB shows the next step after gbm->surface_create
as
0xb6beb5d0 in ?? () from /usr/lib/gbm/gbm_pvr.so
When using my locally-compiled version, GDB shows the next step as
0xb6c414a4 in ?? () from /usr/lib/gbm/gbm_pvr.so
I don't have the debug symbols for gbm_pvr.so (proprietary library), but the code is obviously stepping into two different functions (at least the last 3 digits of the memory address should be the same).
The only thing that I can think of is that there are some compiler/linker setting that I missed which change how the gbm_device
structure is laid out in memory, thus messing up all of the pointers it gets.
Here are the associate structs
struct gbm_device {
/* Hack to make a gbm_device detectable by its first element. */
struct gbm_device *(*dummy)(int);
int fd;
const char *name;
unsigned int refcount;
struct stat stat;
void (*destroy)(struct gbm_device *gbm);
int (*is_format_supported)(struct gbm_device *gbm,
uint32_t format,
uint32_t usage);
struct gbm_bo *(*bo_create)(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
uint32_t usage);
struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type,
void *buffer, uint32_t usage);
int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data);
int (*bo_get_fd)(struct gbm_bo *bo);
void (*bo_destroy)(struct gbm_bo *bo);
struct gbm_surface *(*surface_create)(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags);
struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface);
void (*surface_release_buffer)(struct gbm_surface *surface,
struct gbm_bo *bo);
int (*surface_has_free_buffers)(struct gbm_surface *surface);
void (*surface_destroy)(struct gbm_surface *surface);
};
And
struct gbm_backend {
const char *backend_name;
struct gbm_device *(*create_device)(int fd);
};
I don't think the difference in code offsets within the page is evidence of a difference in struct layout. The code layout can easily change due to differences in compiler, assembler, and linker versions and optimization settings.
It is possible that the shared object simply uses a different definition of the struct. With the definitions you posted, you would have to use something like #pragma pack
to create a different layout, and this seems unlikely to be the cause.
EDIT I missed the struct stat
member. This is really a no-no because it changes size depending on the value of _FILE_OFFSET_BITS
(like ino_t
and off_t
). Portable code should not use these types (and time_t
) in public header files.
I figured out the problem.
My build environment was automatically adding the following compiler flags. Removing these fixed the problem.
-D_LARGEFILE_SOURCE
-D_LARGEFILE64_SOURCE
-D_FILE_OFFSET_BITS=64
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.