asda?‰PNG  IHDR ? f ??C1 sRGB ??é gAMA ±? üa pHYs ? ??o¨d GIDATx^íüL”÷e÷Y?a?("Bh?_ò???¢§?q5k?*:t0A-o??¥]VkJ¢M??f?±8\k2íll£1]q?ù???T /* Dwarfless register access for mips */ global _reg_offsets, _stp_regs_registered function _stp_register_regs() { offset_acx = 0 %( CONFIG_64BIT == "y" %? /* n32/n64 registers naming scheme */ /* Same order as struct pt_regs */ _reg_offsets["zero"] = 0 _reg_offsets["at"] = 8 _reg_offsets["v0"] = 16 _reg_offsets["v1"] = 24 _reg_offsets["a0"] = 32 _reg_offsets["a1"] = 40 _reg_offsets["a2"] = 48 _reg_offsets["a3"] = 56 _reg_offsets["a4"] = 64 _reg_offsets["a5"] = 72 _reg_offsets["a6"] = 80 _reg_offsets["a7"] = 88 _reg_offsets["t0"] = 96 _reg_offsets["t1"] = 104 _reg_offsets["t2"] = 112 _reg_offsets["t3"] = 120 _reg_offsets["s0"] = 128 _reg_offsets["s1"] = 136 _reg_offsets["s2"] = 144 _reg_offsets["s3"] = 152 _reg_offsets["s4"] = 160 _reg_offsets["s5"] = 168 _reg_offsets["s6"] = 176 _reg_offsets["s7"] = 184 _reg_offsets["t8"] = 192 _reg_offsets["t9"] = 200 _reg_offsets["k0"] = 208 _reg_offsets["k1"] = 216 _reg_offsets["gp"] = 224 _reg_offsets["sp"] = 232 _reg_offsets["s8"] = 240 _reg_offsets["fp"] = 240 _reg_offsets["ra"] = 248 _reg_offsets["status"] = 256 _reg_offsets["hi"] = 264 _reg_offsets["lo"] = 272 %( CONFIG_CPU_HAS_SMARTMIPS == "y" %? _reg_offsets["acx"] = 280 offset_acx = 8 %) _reg_offsets["badvaddr"] = 280 + offset_acx _reg_offsets["cause"] = 288 + offset_acx _reg_offsets["epc"] = 296 + offset_acx /* no cp0_tcstatus register for now */ %( CONFIG_CPU_CAVIUM_OCTEON == "y" %? _reg_offsets["mpl0"] = 304 + offset_acx _reg_offsets["mpl1"] = 310 + offset_acx _reg_offsets["mpl2"] = 318 + offset_acx _reg_offsets["mtp0"] = 316 + offset_acx _reg_offsets["mtp1"] = 324 + offset_acx _reg_offsets["mtp2"] = 330 + offset_acx %) %: /* o32 registers naming scheme */ /* Same order as struct pt_regs */ _reg_offsets["zero"] = 24 _reg_offsets["at"] = 28 _reg_offsets["v0"] = 32 _reg_offsets["v1"] = 36 _reg_offsets["a0"] = 40 _reg_offsets["a1"] = 44 _reg_offsets["a2"] = 48 _reg_offsets["a3"] = 52 _reg_offsets["t0"] = 56 _reg_offsets["t1"] = 60 _reg_offsets["t2"] = 64 _reg_offsets["t3"] = 68 _reg_offsets["t4"] = 72 _reg_offsets["t5"] = 76 _reg_offsets["t6"] = 80 _reg_offsets["t7"] = 84 _reg_offsets["s0"] = 88 _reg_offsets["s1"] = 92 _reg_offsets["s2"] = 96 _reg_offsets["s3"] = 100 _reg_offsets["s4"] = 104 _reg_offsets["s5"] = 108 _reg_offsets["s6"] = 112 _reg_offsets["s7"] = 116 _reg_offsets["t8"] = 120 _reg_offsets["t9"] = 124 _reg_offsets["k0"] = 128 _reg_offsets["k1"] = 132 _reg_offsets["gp"] = 136 _reg_offsets["sp"] = 140 _reg_offsets["s8"] = 144 _reg_offsets["fp"] = 144 _reg_offsets["ra"] = 148 _reg_offsets["status"] = 152 _reg_offsets["hi"] = 156 _reg_offsets["lo"] = 160 %( CONFIG_CPU_HAS_SMARTMIPS == "y" %? _reg_offsets["acx"] = 164 offset_acx = 4 %) _reg_offsets["badvaddr"] = 164 + offset_acx _reg_offsets["cause"] = 168 + offset_acx _reg_offsets["epc"] = 172 + offset_acx /* no cp0_tcstatus register for now */ /* no mpl and mtp registers for now */ %) _stp_regs_registered = 1 } function probing_app_with_32bit_regs() %{ /* pure */ struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : NULL ); STAP_RETVALUE = _stp_probing_app_with_32bit_regs(regs); %} function _stp_get_register_by_offset:long (offset:long) %{ /* pure */ long value; struct pt_regs *regs; regs = (CONTEXT->user_mode_p ? CONTEXT->uregs : CONTEXT->kregs); if (!regs) { CONTEXT->last_error = "No registers available in this context"; return; } if (STAP_ARG_offset < 0 || STAP_ARG_offset > sizeof(struct pt_regs) - sizeof(long)) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "Bad register offset: %lld", STAP_ARG_offset); CONTEXT->last_error = CONTEXT->error_buffer; return; } memcpy(&value, ((char *)regs) + STAP_ARG_offset, sizeof(value)); STAP_RETVALUE = value; %} function _stp_sign_extend32:long (value:long) { if (value & 0x80000000) value |= (0xffffffff << 32) return value } function _stp_register:long (name:string, sign_extend:long) { if (!registers_valid()) { error("cannot access CPU registers in this context") return 0 } 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) %( CONFIG_64BIT == "y" %? if (probing_app_with_32bit_regs()) { %) if (sign_extend) value = _stp_sign_extend32(value) else value &= 0xffffffff %( CONFIG_64BIT == "y" %? } %) 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) } /* Dwarfless register access for mips */ %{ // These functions are largely lifted from arch/mips/include/ptrace.h. static inline unsigned long _stp_kernel_stack_pointer(struct pt_regs *regs) { return regs->regs[31]; } /** * _stp_regs_within_kernel_stack() - check the address in the stack * @regs: pt_regs which contains kernel stack pointer. * @addr: address which is checked. * * _stp_regs_within_kernel_stack() checks @addr is within the kernel stack page(s). * If @addr is within the kernel stack, it returns true. If not, returns false. */ static inline int _stp_regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) { return ((addr & ~(THREAD_SIZE - 1)) == (_stp_kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); } /* * _stp_regs_get_kernel_stack_nth_addr() - get address of the Nth entry of the stack * @regs: pt_regs which contains kernel stack pointer. * @n: stack entry number. * * _stp_regs_get_kernel_stack_nth_addr() returns the address of the @n * th entry of the kernel stack which is specified by @regs. If the @n * th entry is NOT in the kernel stack, this returns 0. */ long * _stp_regs_get_kernel_stack_nth_addr(struct pt_regs *regs, unsigned int n) { long *addr = (unsigned long *)_stp_kernel_stack_pointer(regs); addr += n; if (_stp_regs_within_kernel_stack(regs, (unsigned long)addr)) return addr; else return 0; } %} function _stp_get_stack_nth:long (n:long) %{ /* pure */ __label__ deref_fault; unsigned int n = (unsigned int)STAP_ARG_n; struct pt_regs *regs; long *addr; STAP_RETVALUE = 0; if (CONTEXT->user_mode_p) { // This function only handles kernel arguments off the stack. snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access function args in this context"); CONTEXT->last_error = CONTEXT->error_buffer; return; } regs = CONTEXT->kregs; if (!regs) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access function args in this context"); CONTEXT->last_error = CONTEXT->error_buffer; return; } /* Get the address of the nth item on the stack. */ addr = _stp_regs_get_kernel_stack_nth_addr(regs, n); if (addr == NULL) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access stack arg(%d)", n); CONTEXT->last_error = CONTEXT->error_buffer; return; } STAP_RETVALUE = kread(addr); return; deref_fault: /* branched to from kread() */ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel fault at %#lx accessing stack arg(%d)", (unsigned long)addr, n); CONTEXT->last_error = CONTEXT->error_buffer; %} /* * 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) { val = 0 if (argnum < 1 || argnum > 8) { error(sprintf("Cannot access arg(%d)", argnum)) return 0 } if (argnum == 1) val = u_register("a0") else if (argnum == 2) val = u_register("a1") else if (argnum == 3) val = u_register("a2") else if (argnum == 4) val = u_register("a3") %( CONFIG_64BIT == "y" %? else if (argnum == 5) val = u_register("a4") else if (argnum == 6) val = u_register("a5") else if (argnum == 7) val = u_register("a6") else if (argnum == 8) val = u_register("a7") %: else val = _stp_get_stack_nth(argnum - 5) %) if (truncate) { if (sign_extend) val = _stp_sign_extend32(val) else /* High bits may be garbage. */ val = (val & 0xffffffff); } return val; } function probing_32bit_app:long() %{ /* pure */ STAP_RETVALUE = (CONTEXT->user_mode_p && _stp_is_compat_task()); %} function arch_bytes:long() %{ /* pure */ STAP_RETVALUE = sizeof(long); %} function uarch_bytes:long() { assert(user_mode(), "requires user mode") return probing_32bit_app() ? 4 : 8 } /* 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_app_with_32bit_regs()) { 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() %{ /* pure */ %} function fastcall() %{ /* pure */ %} function regparm() %{ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "regparm is invalid on mips."); CONTEXT->last_error = CONTEXT->error_buffer; %}