简体   繁体   中英

What compiler/linker options could influence how structs are laid out in memory

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM