Bug 5967

Summary: gcc bug when profiling nested functions on powerpc
Product: gcc Reporter: edmar
Component: targetAssignee: Alan Modra <amodra>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs
Priority: P3 Keywords: wrong-code
Version: 3.0.2   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:
Attachments: prog.c

Description edmar 2002-03-14 14:16:01 UTC
gcc version:

When generating routine profiling header code, gcc conditionally inserts
a
move register (mr) instruction if the function being compiled
"needs_context".  The mr copies the register of the static chain pointer

to r30 before the call to _mcount, and copies it back after the _mcount
has returned.  However, r30 is not checked to see if it is being used by

the parent function.


How found:

Compiled glibc 2.1.3 using profiling options (with backport patch of
dl-machine.h from glibc 2.2.5).  When __printf_fp()  (a child function
of
printf() that is called when a floating point format is invoked) is
called, a segfault is seen.  This is because __printf_fp() calls a
nested
function named hack_digit().


Example of brokenness:

1001014c <hack_digit.180>:
1001014c:       7c 08 02 a6     mflr    r0
10010150:       3d 80 10 05     lis     r12,4101
10010154:       90 01 00 04     stw     r0,4(r1)
10010158:       38 0c 20 78     addi    r0,r12,8312
1001015c:       7d 7e 5b 78     mr      r30,r11
10010160:       4b ff 9f 21     bl      1000a080 <_mcount>
10010164:       7f cb f3 78     mr      r11,r30
10010168:       94 21 ff e0     stwu    r1,-32(r1)
1001016c:       7c 08 02 a6     mflr    r0
10010170:       93 c1 00 18     stw     r30,24(r1)


Specific code from gcc:

from rs6000.c:

void
output_function_profiler (file, labelno)
  FILE *file;
  int labelno;
{

        ...

      if (current_function_needs_context)
        asm_fprintf (file, "\tmr %s,%s\n",
                     reg_names[30], reg_names[STATIC_CHAIN_REGNUM]);
      fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
      if (current_function_needs_context)
        asm_fprintf (file, "\tmr %s,%s\n",
                     reg_names[STATIC_CHAIN_REGNUM], reg_names[30]);
        ...

Release:
2.95.2 and 3.0.2

Environment:
At least on 2.95.2, and 3.0.2.
Linux PowerPC

How-To-Repeat:
compile with gcc 2.95.2 or gcc-3.0.2 on a Linux PowerPC:
gcc -O2 -p -S prog.c
them look at prog.s and note that r30 is live across the
call to bar(), and bar clobbers r30 (profiling code).
Comment 1 Alan Modra 2002-07-17 19:16:29 UTC
Responsible-Changed-From-To: unassigned->amodra
Responsible-Changed-Why: Fixing it.
Comment 2 Alan Modra 2002-07-17 19:16:29 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Patch submitted for PR 7114 will fix this one.
    http://gcc.gnu.org/ml/gcc-patches/2002-07/msg00857.html
Comment 3 Alan Modra 2002-09-13 16:37:22 UTC
State-Changed-From-To: analyzed->closed
State-Changed-Why: Fixed on mainline and 3.2 branch