or1k: Fix clobbering of _mcount argument if fPIC is enabled
commit1bac7d31a1276f06bfa6cd3fae775b0ad7fec164
authorStafford Horne <shorne@gmail.com>
Mon, 8 Nov 2021 22:10:12 +0000 (9 07:10 +0900)
committerStafford Horne <shorne@gmail.com>
Fri, 12 Nov 2021 22:58:00 +0000 (13 07:58 +0900)
tree36043c0912cc342774dee5f34623dcf563471e97
parent4d2d5565a0953eaa829d10006baf007cf33bab89
or1k: Fix clobbering of _mcount argument if fPIC is enabled

Recently we changed the PROFILE_HOOK _mcount call to pass in the link
register as an argument.  This actually does not work when the _mcount
call uses a PLT because the GOT register setup code ends up getting
inserted before the PROFILE_HOOK and clobbers the link register
argument.

These glibc tests are failing:
  gmon/tst-gmon-pie-gprof
  gmon/tst-gmon-static-gprof

This patch fixes this by saving the instruction that stores the Link
Register to the _mcount argument and then inserts the GOT register setup
instructions after that.

For example:

main.c:

    extern int e;

    int f2(int a) {
      return a + e;
    }

    int f1(int a) {
      return f2 (a + a);
    }

    int main(int argc, char ** argv) {
      return f1 (argc);
    }

Compiled:

    or1k-smh-linux-gnu-gcc -Wall -c -O2 -fPIC -pg -S main.c

Before Fix:

    main:
        l.addi  r1, r1, -16
        l.sw    8(r1), r2
        l.sw    0(r1), r16
        l.addi  r2, r1, 16   # Keeping FP, but not needed
        l.sw    4(r1), r18
        l.sw    12(r1), r9
        l.jal   8            # GOT Setup clobbers r9 (Link Register)
         l.movhi        r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4)
        l.ori   r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0)
        l.add   r16, r16, r9
        l.or    r18, r3, r3
        l.or    r3, r9, r9    # This is not the original LR
        l.jal   plt(_mcount)
         l.nop

        l.jal   plt(f1)
         l.or    r3, r18, r18
        l.lwz   r9, 12(r1)
        l.lwz   r16, 0(r1)
        l.lwz   r18, 4(r1)
        l.lwz   r2, 8(r1)
        l.jr    r9
         l.addi  r1, r1, 16

After the fix:

    main:
        l.addi  r1, r1, -12
        l.sw    0(r1), r16
        l.sw    4(r1), r18
        l.sw    8(r1), r9
        l.or    r18, r3, r3
        l.or    r3, r9, r9    # We now have r9 (LR) set early
        l.jal   8             # Clobbers r9 (Link Register)
         l.movhi        r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4)
        l.ori   r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0)
        l.add   r16, r16, r9
        l.jal   plt(_mcount)
         l.nop

        l.jal   plt(f1)
         l.or    r3, r18, r18
        l.lwz   r9, 8(r1)
        l.lwz   r16, 0(r1)
        l.lwz   r18, 4(r1)
        l.jr    r9
         l.addi  r1, r1, 12

Fixes: 308531d148a ("or1k: Add return address argument to _mcount call")

gcc/ChangeLog:
* config/or1k/or1k-protos.h (or1k_profile_hook): New function.
* config/or1k/or1k.h (PROFILE_HOOK): Change macro to reference
new function or1k_profile_hook.
* config/or1k/or1k.c (struct machine_function): Add new field
set_mcount_arg_insn.
(or1k_profile_hook): New function.
(or1k_init_pic_reg): Update to inject pic rtx after _mcount arg
when profiling.
(or1k_frame_pointer_required): Frame pointer no longer needed
when profiling.
gcc/config/or1k/or1k-protos.h
gcc/config/or1k/or1k.c
gcc/config/or1k/or1k.h