summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-05-22 16:25:24 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-05-22 16:25:24 -0400
commitbaee44464046d3960fe385baffa8d273f2198236 (patch)
treec361e7f932c641a9668adb080102b22a1d7b678c
parente3339150b3c04f50b0abdc4a6d132a6b75b22cb6 (diff)
parentcf314c0fcb625876d8440291af6a21b86abf66f4 (diff)
downloadsystemtap-steved-baee44464046d3960fe385baffa8d273f2198236.tar.gz
systemtap-steved-baee44464046d3960fe385baffa8d273f2198236.tar.xz
systemtap-steved-baee44464046d3960fe385baffa8d273f2198236.zip
Merge commit 'origin/master' into pr6429-comp-unwindsyms
* commit 'origin/master': PR5643: fix .statement(NUM) regression powerpc register+arg access
-rw-r--r--ChangeLog9
-rw-r--r--stapfuncs.5.in8
-rw-r--r--tapset/ppc64/registers.stp239
-rw-r--r--tapsets.cxx9
4 files changed, 265 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 38d28928..4d02db5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-05-22 Wenji Huang <wenji.huang@oracle.com>
+
+ * tapsets.cxx (iterate_over_functions): Fix .statement(NUM) regression.
+
+2008-05-22 Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+
+ * tapset/ppc64/registers.stp: Support powerpc register + arg lookup
+ * stapfuncs.5.in: Add powerpc bits; indicate scope of uarg_* access
+
2008-05-20 Frank Ch. Eigler <fche@elastic.org>
PR 6538
diff --git a/stapfuncs.5.in b/stapfuncs.5.in
index 994b8c06..04e5ea17 100644
--- a/stapfuncs.5.in
+++ b/stapfuncs.5.in
@@ -365,6 +365,11 @@ rip/ip, rsi/si, rsp/sp;
32-bit registers:
eax, ebp, ebx, ecx, edx, edi, edx, eip, esi, esp, flags/eflags, orig_eax;
segment registers: xcs/cs, xss/ss.
+
+For powerpc, the following names are recognized:
+r1, r2... r31, nip, msr, orig_gpr3, ctr, link, xer, ccr, softe, trap,
+dar, dsisr, result;
+
.TP
u_register:long (name:string)
Same as register(name), except that
@@ -447,6 +452,9 @@ The probed function was built with the gcc \-mregparm=n option.
(The i386 kernel is built with \-mregparm=3, so systemtap considers
regparm(3) the default for kernel functions on that architecture.)
+For some architectures, the *_arg functions may reject unusally high
+values of n.
+
.SS QUEUE_STATS
.PP
The queue_stats tapset provides functions that, given notifications of
diff --git a/tapset/ppc64/registers.stp b/tapset/ppc64/registers.stp
new file mode 100644
index 00000000..d3605c05
--- /dev/null
+++ b/tapset/ppc64/registers.stp
@@ -0,0 +1,239 @@
+/* Dwarfless register access for powerpc */
+
+global _reg_offsets, _stp_regs_registered
+
+function _stp_register_regs() {
+ /* Same order as pt_regs */
+ _reg_offsets["r0"] = 0
+ _reg_offsets["r1"] = 8
+ _reg_offsets["r2"] = 16
+ _reg_offsets["r3"] = 24
+ _reg_offsets["r4"] = 32
+ _reg_offsets["r5"] = 40
+ _reg_offsets["r6"] = 48
+ _reg_offsets["r7"] = 56
+ _reg_offsets["r8"] = 64
+ _reg_offsets["r9"] = 72
+ _reg_offsets["r10"] = 80
+ _reg_offsets["r11"] = 88
+ _reg_offsets["r12"] = 96
+ _reg_offsets["r13"] = 104
+ _reg_offsets["r14"] = 112
+ _reg_offsets["r15"] = 120
+ _reg_offsets["r16"] = 128
+ _reg_offsets["r17"] = 136
+ _reg_offsets["r18"] = 144
+ _reg_offsets["r19"] = 152
+ _reg_offsets["r20"] = 160
+ _reg_offsets["r21"] = 168
+ _reg_offsets["r22"] = 176
+ _reg_offsets["r23"] = 184
+ _reg_offsets["r24"] = 192
+ _reg_offsets["r25"] = 200
+ _reg_offsets["r26"] = 208
+ _reg_offsets["r27"] = 216
+ _reg_offsets["r28"] = 224
+ _reg_offsets["r29"] = 232
+ _reg_offsets["r30"] = 240
+ _reg_offsets["r31"] = 248
+ _reg_offsets["nip"] = 256
+ _reg_offsets["msr"] = 264
+ _reg_offsets["orig_gpr3"] = 272
+ _reg_offsets["ctr"] = 280
+ _reg_offsets["link"] = 288
+ _reg_offsets["xer"] = 296
+ _reg_offsets["ccr"] = 304
+ _reg_offsets["softe"] = 312
+ _reg_offsets["trap"] = 320
+ _reg_offsets["dar"] = 328
+ _reg_offsets["dsisr"] = 336
+ _reg_offsets["result"] = 344
+
+ /*
+ * If we ever need to support 32bit powerpc, we can
+ * get to the register offsets by using just a
+ * reg32_offset = _reg_offsets["reg"]/2
+ * or somesuch
+ */
+ _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;
+%}
+
+function _stp_sign_extend32:long (value:long) {
+ if (value & 0x80000000)
+ value |= (0xffffffff << 32)
+ return value
+}
+
+function _stp_probing_32bit_app() %{
+ if (!(CONTEXT->regs))
+ return 0;
+ return (user_mode(CONTEXT->regs) &&
+ test_tsk_thread_flag(current, TIF_32BIT));
+%}
+
+function _stp_register:long (name:string, sign_extend:long) {
+ if (!_stp_regs_registered)
+ _stp_register_regs()
+ offset = _reg_offsets[name]
+ if (offset == 0 && !(name in _reg_offsets)) {
+ error("Unknown register: " . name)
+ return 0
+ }
+ value = _stp_get_register_by_offset(offset)
+ if (_stp_probing_32bit_app()) {
+ 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 n;
+ 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;
+
+ switch (n) {
+ case 1:
+ val = u_register("r3");
+ break;
+ case 2:
+ val = u_register("r4");
+ break;
+ case 3:
+ val = u_register("r5");
+ break;
+ case 4:
+ val = u_register("r6");
+ break;
+ case 5:
+ val = u_register("r7");
+ break;
+ case 6:
+ val = u_register("r8");
+ break;
+ case 7:
+ val = u_register("r9");
+ break;
+ case 8:
+ val = u_register("r10");
+ 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;
+%}
+
+/* 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 (_stp_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() %{
+ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer),
+ "regparm is invalid on powerpc.");
+ CONTEXT->last_error = CONTEXT->error_buffer;
+%}
diff --git a/tapsets.cxx b/tapsets.cxx
index 7207c072..54b951cd 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2527,6 +2527,15 @@ dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, void * arg),
}
}
}
+ else if (q->has_statement_num) // searching all for kernel.statement
+ {
+ for (cu_function_cache_t::iterator it = v->begin(); it != v->end(); it++)
+ {
+ Dwarf_Die die = it->second;
+ rc = (*callback)(& die, data);
+ if (rc != DWARF_CB_OK) break;
+ }
+ }
else // not a wildcard and no match in this CU
{
// do nothing