/usr/share/systemtap/runtime/regs.c is in systemtap-common 2.3-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | /* -*- linux-c -*-
* Functions to access the members of pt_regs struct
* Copyright (C) 2005, 2007 Red Hat Inc.
* Copyright (C) 2005 Intel Corporation.
* Copyright (C) 2007 Quentin Barnes.
*
* 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 _REGS_C_
#define _REGS_C_
#include "regs.h"
#if defined(__KERNEL__)
#include "linux/regs.c"
#elif defined(__DYNINST__)
#include "dyninst/regs.c"
#endif
/* Function arguments */
#define _STP_REGPARM 0x8000
#define _STP_REGPARM_MASK ((_STP_REGPARM) - 1)
/*
* x86_64 and i386 are especially ugly because:
* 1) the pt_reg member names changed as part of the x86 merge. We use
* either the pre-merge name or the post-merge name, as needed.
* 2) -m32 apps on x86_64 look like i386 apps, so we need to support
* those semantics on both i386 and x86_64.
*/
#ifdef __i386__
static long _stp_get_sp(struct pt_regs *regs)
{
if (!user_mode(regs))
return (long) &EREG(sp, regs);
return EREG(sp, regs);
}
#endif /* __i386__ */
#ifdef __x86_64__
static long _stp_get_sp(struct pt_regs *regs)
{
return RREG(sp, regs);
}
/* Ensure that the upper 32 bits of val are a sign-extension of the lower 32. */
static int64_t __stp_sign_extend32(int64_t val)
{
int32_t *val_ptr32 = (int32_t*) &val;
return *val_ptr32;
}
#endif /* __x86_64__ */
#if defined(__i386__) || defined(__x86_64__)
/*
* Use this for i386 kernel and apps, and for 32-bit apps running on x86_64.
* Does arch-specific work for fetching function arg #argnum (1 = first arg).
* nr_regargs is the number of arguments that reside in registers (e.g.,
* 3 for fastcall functions).
* Returns:
* 0 if the arg resides in a register. *val contains its value.
* 1 if the arg resides on the kernel stack. *val contains its address.
* 2 if the arg resides on the user stack. *val contains its address.
* -1 if the arg number is invalid.
* We assume that the regs pointer is valid.
*/
#if defined(__i386__)
#define ERREG(nm, regs) EREG(nm, regs)
#else /* x86_64 */
#define ERREG(nm, regs) RREG(nm, regs)
#endif
static int _stp_get_arg32_by_number(int n, int nr_regargs,
struct pt_regs *regs, long *val)
{
if (nr_regargs < 0)
return -1;
if (n > nr_regargs) {
/*
* The typical case: arg n is on the stack.
* stack[0] = return address
*/
int stack_index = n - nr_regargs;
int32_t *stack = (int32_t*) _stp_get_sp(regs);
*val = (long) &stack[stack_index];
return (user_mode(regs) ? 2 : 1);
} else {
switch (n) {
case 1: *val = (int32_t)(ERREG(ax, regs)); break;
case 2: *val = (int32_t)(ERREG(dx, regs)); break;
case 3: *val = (int32_t)(ERREG(cx, regs)); break;
default:
/* gcc rejects regparm values > 3. */
return -1;
}
return 0;
}
}
#endif /* __i386__ || __x86_64__ */
#ifdef __x86_64__
/* See _stp_get_arg32_by_number(). */
static int _stp_get_arg64_by_number(int n, int nr_regargs,
struct pt_regs *regs, unsigned long *val)
{
if (nr_regargs < 0)
return -1;
if (n > nr_regargs) {
/* arg n is on the stack. stack[0] = return address */
int stack_index = n - nr_regargs;
unsigned long *stack = (unsigned long*) _stp_get_sp(regs);
*val = (unsigned long) &stack[stack_index];
return (user_mode(regs) ? 2 : 1);
} else {
switch (n) {
case 1: *val = RREG(di, regs); break;
case 2: *val = RREG(si, regs); break;
case 3: *val = RREG(dx, regs); break;
case 4: *val = RREG(cx, regs); break;
case 5: *val = regs->r8; break;
case 6: *val = regs->r9; break;
default:
/* gcc rejects regparm values > 6. */
return -1;
}
return 0;
}
}
#endif /* __x86_64__ */
/** @} */
#endif /* _REGS_C_ */
|