diff options
author | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2016-07-11 09:46:08 +0100 |
---|---|---|
committer | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2016-07-11 09:50:41 +0100 |
commit | efbe665c3a2d344b0d64456cf29499ba53c2965a (patch) | |
tree | 2b4f2072c5b1c0ad5c30af13cd8c927a574ddd9b /sysdeps/aarch64 | |
parent | 468700675f7f36d55758c36b1ed902250470e8ec (diff) | |
download | glibc-efbe665c3a2d344b0d64456cf29499ba53c2965a.tar.gz glibc-efbe665c3a2d344b0d64456cf29499ba53c2965a.tar.xz glibc-efbe665c3a2d344b0d64456cf29499ba53c2965a.zip |
[AArch64] Fix libc internal asm profiling code
When glibc is built with --enable-profile, the ENTRY of asm functions includes CALL_MCOUNT for profiling. (matters for binaries static linked against libc_p.a.) CALL_MCOUNT did not save/restore argument registers around the _mcount call so it clobbered them. (it is enough to only save/restore the arguments passed to a given asm function, but that would be too many asm changes so it is simpler to always save all argument registers in this macro.) float args are not saved: mcount does not clobber the float regs and currently no asm function takes float arguments anyway. [BZ #18707] * sysdeps/aarch64/Makefile (CFLAGS-mcount.c): Add -mgeneral-regs-only. * sysdeps/aarch64/sysdep.h (CALL_MCOUNT): Save argument registers.
Diffstat (limited to 'sysdeps/aarch64')
-rw-r--r-- | sysdeps/aarch64/Makefile | 4 | ||||
-rw-r--r-- | sysdeps/aarch64/sysdep.h | 33 |
2 files changed, 35 insertions, 2 deletions
diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile index 06323550e9..562c1373ae 100644 --- a/sysdeps/aarch64/Makefile +++ b/sysdeps/aarch64/Makefile @@ -12,3 +12,7 @@ endif ifeq ($(subdir),csu) gen-as-const-headers += tlsdesc.sym endif + +ifeq ($(subdir),gmon) +CFLAGS-mcount.c += -mgeneral-regs-only +endif diff --git a/sysdeps/aarch64/sysdep.h b/sysdeps/aarch64/sysdep.h index 6b728ec651..e0457593fc 100644 --- a/sysdeps/aarch64/sysdep.h +++ b/sysdeps/aarch64/sysdep.h @@ -66,9 +66,38 @@ /* If compiled for profiling, call `mcount' at the start of each function. */ #ifdef PROF # define CALL_MCOUNT \ - str x30, [sp, #-16]!; \ + str x30, [sp, #-80]!; \ + cfi_adjust_cfa_offset (80); \ + cfi_rel_offset (x30, 0); \ + stp x0, x1, [sp, #16]; \ + cfi_rel_offset (x0, 16); \ + cfi_rel_offset (x1, 24); \ + stp x2, x3, [sp, #32]; \ + cfi_rel_offset (x2, 32); \ + cfi_rel_offset (x3, 40); \ + stp x4, x5, [sp, #48]; \ + cfi_rel_offset (x4, 48); \ + cfi_rel_offset (x5, 56); \ + stp x6, x7, [sp, #64]; \ + cfi_rel_offset (x6, 64); \ + cfi_rel_offset (x7, 72); \ + mov x0, x30; \ bl mcount; \ - ldr x30, [sp], #16 ; + ldp x0, x1, [sp, #16]; \ + cfi_restore (x0); \ + cfi_restore (x1); \ + ldp x2, x3, [sp, #32]; \ + cfi_restore (x2); \ + cfi_restore (x3); \ + ldp x4, x5, [sp, #48]; \ + cfi_restore (x4); \ + cfi_restore (x5); \ + ldp x6, x7, [sp, #64]; \ + cfi_restore (x6); \ + cfi_restore (x7); \ + ldr x30, [sp], #80; \ + cfi_adjust_cfa_offset (-80); \ + cfi_restore (x30); #else # define CALL_MCOUNT /* Do nothing. */ #endif |