Search code examples
gcclinkermemory-alignmentobject-files

alignment in user defined sections in gcc


It seems that top level objects in gcc targeting x86 that are >= 32 bytes automatically get 32 byte alignment. This may be nice for performance, but I'm collecting an array of thingies from all my object files in a user-defined section, and the extra alignment gaps play havoc with this array. Is there any way to prevent this object alignment?

To clarify, I have a low-aligned struct, and different object files define data in the form of an array of that struct in a user defined section, with the purpose to make one application wide array. As soon as one of those arrays is >= 32, the object alignment and with that the section alignment is pushed to 32 and when the linker concatenates the separate sections from the object files into the executable, it creates alignment fillers at the module boundaries in that section.


Solution

  • The following program illustrates a possible solution, assuming GCC extensions are acceptable to you:

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    
    #define ALIGNMENT // __attribute__ ((aligned (8))) 
    
    struct A {
        char arr[40];
    } ;
    
    struct A a __attribute__ ((section ("my_data"))) ALIGNMENT = {{'a'}};
    struct A b __attribute__ ((section ("my_data"))) ALIGNMENT = {{'b'}};
    struct A c __attribute__ ((section ("my_data"))) ALIGNMENT = {{'c'}};
    
    int main(int argc, char **argv)
    {
        assert(sizeof(struct A) == 40);
        printf("%c\n",a.arr[0]);
        printf("%c\n",b.arr[0]);
        printf("%c\n",c.arr[0]);
        printf("%lu\n",(unsigned long)(&a));
        printf("%lu\n",(unsigned long)(&b));
        printf("%lu\n",(unsigned long)(&c));
        return 0;
    }
    

    My output is:

    a
    b
    c
    6295616
    6295680
    6295744
    

    Note that in my (64-bit) executable each of the three 40-byte structures is 64-byte aligned.

    Now uncomment // __attribute__ ((aligned (8))), rebuild and rerun. My output then is:

    a
    b
    c
    6295616
    6295656
    6295696
    

    Now the structures are 8-byte aligned, without gaps.