From a0fbee404b2d23aab6b544075628eb38e837d738 Mon Sep 17 00:00:00 2001 From: Honggyu Kim Date: Wed, 12 Feb 2020 11:39:37 +0900 Subject: [PATCH] aarch64: Save and restore VFP registers on update_mem_regions() It seems to overwrite aarch64 VFP registers while recording args in string format. Here is the test program and the preparation. $ cat float.c #include float float_add(float a, float b) { return a + b; } int main(int argc, char *argv[]) { double c; c = float_add(-0.1, 0.2); fprintf(stderr, "%lf\n", c); return c > 0; } $ gcc -pg float.c $ uftrace -A fprintf@arg2 -F main a.out 0.100000 # DURATION TID FUNCTION [ 1047] | main() { 1.198 us [ 1047] | float_add(); 95.104 us [ 1047] | fprintf(0xaaaab814ca48); 109.843 us [ 1047] | } /* main */ However, the return value of 'float_add' is overwritten by some garbage value if uftrace records a function in string format. $ uftrace -A fprintf@arg2/s -F main a.out 121362470815289747852695694937146665636545397707008516 ... 912.000000 # DURATION TID FUNCTION [ 1058] | main() { 1.250 us [ 1058] | float_add(); 1.278 ms [ 1058] | fprintf("%lf\n"); 1.292 ms [ 1058] | } /* main */ This patch protects the context by saving d0-d7 registers before calling it, and it makes the result correct. Signed-off-by: Honggyu Kim --- arch/aarch64/mcount-arch.h | 2 ++ arch/aarch64/mcount-support.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arch/aarch64/mcount-arch.h b/arch/aarch64/mcount-arch.h index 7afe65527..69efe521f 100644 --- a/arch/aarch64/mcount-arch.h +++ b/arch/aarch64/mcount-arch.h @@ -26,7 +26,9 @@ struct mcount_regs { #define ARCH_MAX_REG_ARGS 8 #define ARCH_MAX_FLOAT_REGS 8 +#define HAVE_MCOUNT_ARCH_CONTEXT struct mcount_arch_context { + double d[ARCH_MAX_FLOAT_REGS]; }; #define ARCH_PLT0_SIZE 32 diff --git a/arch/aarch64/mcount-support.c b/arch/aarch64/mcount-support.c index cd0531d18..b68e9107a 100644 --- a/arch/aarch64/mcount-support.c +++ b/arch/aarch64/mcount-support.c @@ -193,3 +193,27 @@ unsigned long mcount_arch_plthook_addr(struct plthook_data *pd, int idx) sym = &pd->dsymtab.sym[0]; return sym->addr - ARCH_PLT0_SIZE; } + +void mcount_save_arch_context(struct mcount_arch_context *ctx) +{ + asm volatile ("str d0, %0\n" : "=m" (ctx->d[0])); + asm volatile ("str d1, %0\n" : "=m" (ctx->d[1])); + asm volatile ("str d2, %0\n" : "=m" (ctx->d[2])); + asm volatile ("str d3, %0\n" : "=m" (ctx->d[3])); + asm volatile ("str d4, %0\n" : "=m" (ctx->d[4])); + asm volatile ("str d5, %0\n" : "=m" (ctx->d[5])); + asm volatile ("str d6, %0\n" : "=m" (ctx->d[6])); + asm volatile ("str d7, %0\n" : "=m" (ctx->d[7])); +} + +void mcount_restore_arch_context(struct mcount_arch_context *ctx) +{ + asm volatile ("ldr d0, %0\n" :: "m" (ctx->d[0])); + asm volatile ("ldr d1, %0\n" :: "m" (ctx->d[1])); + asm volatile ("ldr d2, %0\n" :: "m" (ctx->d[2])); + asm volatile ("ldr d3, %0\n" :: "m" (ctx->d[3])); + asm volatile ("ldr d4, %0\n" :: "m" (ctx->d[4])); + asm volatile ("ldr d5, %0\n" :: "m" (ctx->d[5])); + asm volatile ("ldr d6, %0\n" :: "m" (ctx->d[6])); + asm volatile ("ldr d7, %0\n" :: "m" (ctx->d[7])); +}