This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] fix bad interaction between -pg and stack realignment on x86


Hello,

On x86 targets, the "force_align_arg_pointer" implementation bits
potentially badly interact with code generated for profiling purposes.

The former's idea is to use one "free" register as the argument pointer
value, set on function entry before the stack pointer is aligned.

Typically, for

   int main (int argc, char * argv [])
   {
     int x = argc;

     return 0;
   }

we get code like (gcc -S -fverbose-asm)

   .globl main
	   .type   main, @function
   main:
	   leal    4(%esp), %ecx   #,               save arg pointer
	   andl    $-16, %esp      #,               align sp

	   pushl   -4(%ecx)        #
	   pushl   %ebp    #                        ...
	   movl    %esp, %ebp      #,               misc details
	   pushl   %ecx    #                        ...
	   subl    $16, %esp       #,

	   movl    (%ecx), %eax    # argc, argc     use arg pointer
	   movl    %eax, -8(%ebp)  # argc, x
	   ...


With -pg, a call to mcount is inserted between the "save" and the
"use", just before the use in the specific case above.

There is nothing to guarantee that mcount won't clobber ecx in the
absolute (no ABI mandate), and there is a clear problem when this happens.

It turns out not to happen on linux and windows, hence not to be
extremely visible, because mcount explicitly preserves the normally
call clobbered regs.

We have seen the problem on at least freebsd and solaris, still, and I
think this is what http://gcc.gnu.org/ml/gcc/2006-12/msg00319.html is
about with DJGPP.

The code below exposes the problem on i386-solaris, where it aborts
when compiled with -pg:

   #define EXPECTED_ARG 0x12345678

   void __attribute__ ((force_align_arg_pointer)) foo (int arg)
   {
     if (arg != EXPECTED_ARG)
       abort ();
   }

   int main (int argc, char *argv[])
   {
     foo (EXPECTED_ARG);
     return 0;
   }

The attached patch is a suggestion to address this by having
x86_function_profiler save/restore the "force_align_arg_pointer"
register as needed, either because the mcount we call might clobber
it, or if it conflicts with PROFILE_COUNT_REGNUM and we are setting
the latter as an mcount argument.

It splits the function into 32 and 64 bits variants for readability
purposes, and turns PROFILE_COUNT_REGISTER into PROFILE_COUNT_REGNUM
to make comparisons against force_align_arg_pointer easier.

Bootstrapped and regression tested for c,c++,objc,ada on
i386-pc-solaris2.10 + for all,ada on x86_64-redhat-linux.

Thanks in advance,

Olivier

	2007-02-26  Olivier Hainque  <hainque@adacore.com>

	gcc/

	* config/i386/i386.h (PROFILE_COUNT_REGISTER): Turn into ...
	(PROFILE_COUNT_REGNUM): New macro.
	(MCOUNT_PRESERVES_ALL_REGS): New macro, tells whether mcount
	preserves all regs.  Default to 1 here, to be redefined by subtarget
	configurations as needed.  
	* config/i386/i386.c (X86_SET_PROFILE_COUNTERS): New local macro,
	always defined.  Conveys whether NO_PROFILE_COUNTERS is defined.
	(x86_function_profiler): Split into ...
	(x86_64_function_profiler): New function, and
	(x86_32_function_profiler): New function.  Save/restore the
	force_align_arg_pointer register when needed.
	* config/i386/sol2.h (MCOUNT_PRESERVES_ALL_REGS): Redefine to 0.

	testsuite/

	* gcc.target/i386/force_align_mcount.c: New case.














Attachment: force_align_mcount.dif
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]