summaryrefslogtreecommitdiffstats
path: root/tapset/x86_64
diff options
context:
space:
mode:
authorJim Keniston <jkenisto@us.ibm.com>2008-05-12 12:17:20 -0700
committerJim Keniston <jkenisto@us.ibm.com>2008-05-12 12:17:20 -0700
commitc7fe0041d2132e801f72e158854d54da50fc651d (patch)
tree258d955ef4a1ead4ba1102812d962c9c981d873b /tapset/x86_64
parent8dd6b23de4dd099aa244402192cb3d7be2bda739 (diff)
parentda3fe5fe9641e7c4cc6ae5c4a289ddbc020aca1a (diff)
downloadsystemtap-steved-c7fe0041d2132e801f72e158854d54da50fc651d.tar.gz
systemtap-steved-c7fe0041d2132e801f72e158854d54da50fc651d.tar.xz
systemtap-steved-c7fe0041d2132e801f72e158854d54da50fc651d.zip
Merge commit 'origin/dwarfless'
PR 4311 - Function boundary tracing without debuginfo: Phases 1 and 2
Diffstat (limited to 'tapset/x86_64')
-rw-r--r--tapset/x86_64/registers.stp243
1 files changed, 243 insertions, 0 deletions
diff --git a/tapset/x86_64/registers.stp b/tapset/x86_64/registers.stp
new file mode 100644
index 00000000..a5aba55a
--- /dev/null
+++ b/tapset/x86_64/registers.stp
@@ -0,0 +1,243 @@
+global _reg_offsets, _r32_offsets, _stp_regs_registered
+
+function _stp_register_regs() {
+ /* Same order as pt_regs */
+ _reg_offsets["r15"] = 0
+ _reg_offsets["r14"] = 8
+ _reg_offsets["r13"] = 16
+ _reg_offsets["r12"] = 24
+ _reg_offsets["rbp"] = 32 _reg_offsets["bp"] = 32
+ _reg_offsets["rbx"] = 40 _reg_offsets["bx"] = 40
+ _reg_offsets["r11"] = 48
+ _reg_offsets["r10"] = 56
+ _reg_offsets["r9"] = 64
+ _reg_offsets["r8"] = 72
+ _reg_offsets["rax"] = 80 _reg_offsets["ax"] = 80
+ _reg_offsets["rcx"] = 88 _reg_offsets["cx"] = 88
+ _reg_offsets["rdx"] = 96 _reg_offsets["dx"] = 96
+ _reg_offsets["rsi"] = 104 _reg_offsets["si"] = 104
+ _reg_offsets["rdi"] = 112 _reg_offsets["di"] = 112
+ _reg_offsets["orig_rax"] = 120 _reg_offsets["orig_ax"] = 120
+ _reg_offsets["rip"] = 128 _reg_offsets["ip"] = 128
+ _reg_offsets["xcs"] = 136 _reg_offsets["cs"] = 136
+ _reg_offsets["eflags"] = 144 _reg_offsets["flags"] = 144
+ _reg_offsets["rsp"] = 152 _reg_offsets["sp"] = 152
+ _reg_offsets["xss"] = 160 _reg_offsets["ss"] = 160
+
+ _r32_offsets["ebp"] = 32
+ _r32_offsets["ebx"] = 40
+ _r32_offsets["eax"] = 80
+ _r32_offsets["ecx"] = 88
+ _r32_offsets["edx"] = 96
+ _r32_offsets["esi"] = 104
+ _r32_offsets["edi"] = 112
+ _r32_offsets["orig_eax"] = 120
+ _r32_offsets["eip"] = 128
+ _r32_offsets["esp"] = 152
+
+ _stp_regs_registered = 1
+}
+
+function _stp_get_register_by_offset:long (offset:long) %{
+ long value;
+ memcpy(&value, ((char *)CONTEXT->regs) + THIS->offset, sizeof(value));
+ THIS->__retvalue = value;
+%}
+
+/*
+ * _stp_sign_extend32() is callable from a script function.
+ * __stp_sign_extend32() (in regs.c) is callable from a C function.
+ */
+function _stp_sign_extend32:long (value:long) %{
+ THIS->__retvalue = __stp_sign_extend32(THIS->value);
+%}
+
+function _stp_register:long (name:string, sign_extend:long) {
+ reg32 = 0
+ if (!_stp_regs_registered)
+ _stp_register_regs()
+ offset = _reg_offsets[name]
+ if (offset == 0 && !(name in _reg_offsets)) {
+ offset = _r32_offsets[name]
+ if (offset == 0 && !(name in _r32_offsets)) {
+ error("Unknown register: " . name)
+ return 0
+ }
+ reg32 = 1
+ }
+ value = _stp_get_register_by_offset(offset)
+ if (reg32) {
+ if (sign_extend)
+ value = _stp_sign_extend32(value)
+ else
+ value &= 0xffffffff
+ }
+ return value
+}
+
+/* Return the named register value as a signed value. */
+function register:long (name:string) {
+ return _stp_register(name, 1)
+}
+
+/*
+ * Return the named register value as an unsigned value. Specifically,
+ * don't sign-extend the register value when promoting it to 64 bits.
+ */
+function u_register:long (name:string) {
+ return _stp_register(name, 0)
+}
+
+/*
+ * Return the value of function arg #argnum (1=first arg).
+ * If truncate=1, mask off the top 32 bits.
+ * If sign_extend=1 and (truncate=1 or the probepoint we've hit is in a
+ * 32-bit app), sign-extend the 32-bit value.
+ */
+function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) %{
+ long val;
+ int result, n, nr_regargs;
+ size_t argsz = sizeof(long);
+
+ THIS->__retvalue = 0;
+ if (!CONTEXT->regs) {
+ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "cannot access function args in this context");
+ CONTEXT->last_error = CONTEXT->error_buffer;
+ return;
+ }
+ if (THIS->argnum < 1)
+ goto bad_argnum;
+ n = (int) THIS->argnum;
+ nr_regargs = _stp_get_regparm(CONTEXT->regparm, CONTEXT->regs);
+ if (_stp_probing_32bit_app(CONTEXT->regs)) {
+ argsz = sizeof(int);
+ result = _stp_get_arg32_by_number(n, nr_regargs, CONTEXT->regs,
+ &val);
+ } else
+ result = _stp_get_arg64_by_number(n, nr_regargs, CONTEXT->regs,
+ &val);
+ switch (result) {
+ case 0:
+ /* Arg is in register. */
+ break;
+ case 1:
+ /* Arg is on kernel stack. */
+ val = kread((long *) val);
+ break;
+ case 2:
+ {
+ /* Arg is on user stack. */
+ const char __user *vaddr = (const char __user*) val;
+ if (_stp_copy_from_user((char*)&val, vaddr, argsz) != 0) {
+ /* Stack page not resident. */
+ _stp_warn("cannot access arg(%d) "
+ "at user stack address %p\n", n, vaddr);
+ THIS->__retvalue = 0;
+ return;
+ }
+ break;
+ }
+ default:
+ goto bad_argnum;
+ }
+ if (THIS->truncate || argsz == sizeof(int)) {
+ if (THIS->sign_extend)
+ THIS->__retvalue = (int64_t) __stp_sign_extend32(val);
+ else
+ /* High bits may be garbage. */
+ THIS->__retvalue = (int64_t) (val & 0xffffffff);
+ } else
+ THIS->__retvalue = (int64_t) val;
+ return;
+
+bad_argnum:
+ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "cannot access arg(%lld)", THIS->argnum);
+ CONTEXT->last_error = CONTEXT->error_buffer;
+ return;
+
+ if (0) {
+deref_fault: /* branched to from deref() */
+ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "kernel fault at %#lx accessing arg(%lld)", val,
+ THIS->argnum);
+ CONTEXT->last_error = CONTEXT->error_buffer;
+ }
+%}
+
+function probing_32bit_app() %{
+ THIS->__retvalue = _stp_probing_32bit_app(CONTEXT->regs);
+%}
+
+/* Return the value of function arg #argnum (1=first arg) as a signed int. */
+function int_arg:long (argnum:long) {
+ return _stp_arg(argnum, 1, 1)
+}
+
+/* Return the value of function arg #argnum (1=first arg) as an unsigned int. */
+function uint_arg:long (argnum:long) {
+ return _stp_arg(argnum, 0, 1)
+}
+
+function long_arg:long (argnum:long) {
+ return _stp_arg(argnum, 1, 0)
+}
+
+function ulong_arg:long (argnum:long) {
+ return _stp_arg(argnum, 0, 0)
+}
+
+function longlong_arg:long (argnum:long) {
+ if (probing_32bit_app()) {
+ lowbits = _stp_arg(argnum, 0, 1)
+ highbits = _stp_arg(argnum+1, 0, 1)
+ return ((highbits << 32) | lowbits)
+ } else
+ return _stp_arg(argnum, 0, 0)
+}
+
+function ulonglong_arg:long (argnum:long) {
+ return longlong_arg(argnum)
+}
+
+function pointer_arg:long (argnum:long) {
+ return _stp_arg(argnum, 0, 0)
+}
+
+function s32_arg:long (argnum:long) {
+ return int_arg(argnum)
+}
+
+function u32_arg:long (argnum:long) {
+ return uint_arg(argnum)
+}
+
+function s64_arg:long (argnum:long) {
+ return longlong_arg(argnum)
+}
+
+function u64_arg:long (argnum:long) {
+ return ulonglong_arg(argnum)
+}
+
+function asmlinkage() {
+}
+
+function fastcall() {
+}
+
+function regparm(n) %{
+ if (_stp_probing_32bit_app(CONTEXT->regs) &&
+ (THIS->n < 0 || THIS->n > 3)) {
+ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "For -m32 programs, "
+ "regparm value must be in the range 0-3.");
+ CONTEXT->last_error = CONTEXT->error_buffer;
+ } else if (THIS->n < 0 || THIS->n > 6) {
+ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "For x86_64, regparm value must be in the range 0-6.");
+ CONTEXT->last_error = CONTEXT->error_buffer;
+ } else
+ CONTEXT->regparm = _STP_REGPARM | (int) n;
+%}