Skip to content

Commit

Permalink
aarch64: Save and restore VFP registers on update_mem_regions()
Browse files Browse the repository at this point in the history
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 <stdio.h>

  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 <honggyu.kp@gmail.com>
  • Loading branch information
honggyukim committed Feb 12, 2020
1 parent 5e422c0 commit a0fbee4
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
2 changes: 2 additions & 0 deletions arch/aarch64/mcount-arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions arch/aarch64/mcount-support.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]));
}

0 comments on commit a0fbee4

Please sign in to comment.