Sindbad~EG File Manager
/* -*- linux-c -*-
* function for preparing registers for dyninst-based uprobes
* Copyright (C) 2012-2019 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
* Public License (GPL); either version 2, or (at your option) any
* later version.
*/
#ifndef _UPROBES_REGS_DYNINST_C_
#define _UPROBES_REGS_DYNINST_C_
int
enter_dyninst_uprobe_partial_regs(uint64_t index, unsigned long first_reg, ...)
{
static struct pt_regs regs = {};
va_list varegs;
va_start(varegs, first_reg);
#if defined(__powerpc__) || defined(__powerpc64__)
// Dyninst BPatch_funcCallExpr only supports register parms
#define MAX_REG 32
for (unsigned long r = first_reg;
r < MAX_REG && r < first_reg + 6; ++r)
pt_regs_store_register((®s), r,
va_arg(varegs, unsigned long));
#elif defined(__aarch64__)
#define MAX_REG 32
for (unsigned long r = first_reg;
r < MAX_REG && r < first_reg + 6; ++r) {
if (r == 31)
regs.sp = va_arg(varegs, unsigned long);
else
regs.regs[r] = va_arg(varegs, unsigned long);
}
#endif
#undef MAX_REG
// The last chunk of saved registers is r30/r31/ip
if (first_reg == 30) {
SET_REG_IP((®s), va_arg(varegs, unsigned long));
va_end(varegs);
return enter_dyninst_uprobe(index, ®s);
}
else {
va_end(varegs);
return 0;
}
}
int
enter_dyninst_uprobe_regs(uint64_t index, unsigned long nregs, ...)
{
struct pt_regs regs = {};
va_list varegs;
va_start(varegs, nregs);
#ifdef __i386__
// XXX Dyninst currently has a bug where it's only passing a 32-bit
// index, which means nregs gets stuffed into the upper bits of index,
// and the varegs are all off by one. Hacking it into shape for now...
if (index > UINT32_MAX) {
SET_REG_IP((®s), nregs);
nregs = index >> 32;
index &= UINT32_MAX;
} else
#endif
if (likely(nregs > 0))
SET_REG_IP((®s), va_arg(varegs, unsigned long));
#if defined(__i386__) || defined(__x86_64__)
/* NB: x86 pt_regs_store_register() expects literal register numbers to
* paste as CPP tokens, so unfortunately this has to be unrolled. */
#define SET_REG(n) if (likely(n < nregs - 1)) \
pt_regs_store_register((®s), n, \
va_arg(varegs, unsigned long))
SET_REG(0);
SET_REG(1);
SET_REG(2);
SET_REG(3);
SET_REG(4);
SET_REG(5);
SET_REG(6);
SET_REG(7);
#if defined(__x86_64__)
SET_REG(8);
SET_REG(9);
SET_REG(10);
SET_REG(11);
SET_REG(12);
SET_REG(13);
SET_REG(14);
SET_REG(15);
#endif
#undef SET_REG
#else
#if defined(__powerpc__) || defined(__powerpc64__)
#define MAX_REG 32
for (unsigned long r = 0; r < MAX_REG && r < nregs - 1; ++r)
pt_regs_store_register((®s), r,
va_arg(varegs, unsigned long));
#elif defined(__aarch64__)
#define MAX_REG 32
for (unsigned long r = 0; r < MAX_REG && r < nregs - 1; ++r)
regs.regs[r] = va_arg(varegs, unsigned long);
#else
#error "Unknown architecture!"
#endif
#undef MAX_REG
#endif
va_end(varegs);
return enter_dyninst_uprobe(index, ®s);
}
#endif /* _UPROBES_REGS_DYNINST_C_ */
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists