Re: default alignment

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 06/15/2015 08:38 AM, Pawel Por wrote:
Hi,

Assume the following C program.

void main ( void )
{
   int var;
}

Does gcc guarantee that "var" will be aligned on 4-byte boundary on
x86 (32/64) architectures ?

Presumably you're interested in the default alignment of
the stack in general and not just in the case above where,
as others have said, the variable may not even exist.

The default stack alignment depends how main is called to
begin with, and on the options main is compiled with. On
Linux with glibc and the default compiler options, the stack
is 16-byte aligned on both x86_64 (as required by the ABI)
and on i386 (even though the ABI requires only 4-byte
alignment). On 64-bit x86_64, GCC simply assumes 16-byte
alignment and doesn't do anything special to make it so.
On i386 and on 32-bit x86_64 GCC explicitly aligns the
stack at the beginning of main to a 16-byte boundary. You
can see this by disassembling main (look for the
"and $0xfffffff0, %esp" instruction in main's prologue).

This means that if on a 32-bit x86 target main were to be
compiled with the -mpreferred-stack-boundary=2 option and
called with a stack that's not 16-byte aligned then stack
allocated objects would be misaligned. You can see this by
compiling and running the program below on i386.

Another caveat to keep in mind is that while GCC may align
the stack once, in main, it doesn't do so in every function.
A program that consists of object files generated by different
compilers (or written in assembly) that don't maintain the
same alignment may find its stack misaligned when functions
defined in those object files make calls into functions
compiled by GCC.

Martin

$ cat t.c && gcc -O2 -Wall -m32 -mpreferred-stack-boundary=2 -nostdlib t.c && ./a.out; echo $?
  void _start (void) {
    asm ("subl  $0x1, %esp\n" /* misalign the stack */
         "call  main\n"
         "movl  %eax, %ebx\n"
         "movl  $1, %eax\n"   /* call _Exit */
         "int   $0x80\n");
  }

  int __attribute__ ((weak)) foo (void *p) {
    return (long)p & 15;
  }

  int main (void) {
    int var;
    return foo (&var);
  }
  7




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux