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 arm64 */ /* TODO: handle 32-bit access of registers */ @__private30 global _reg_offsets[37], _r32_offsets[31] probe init { /* Same order as pt_regs */ _reg_offsets["x0"] = 0 _reg_offsets["x1"] = 8 _reg_offsets["x2"] = 16 _reg_offsets["x3"] = 24 _reg_offsets["x4"] = 32 _reg_offsets["x5"] = 40 _reg_offsets["x6"] = 48 _reg_offsets["x7"] = 56 _reg_offsets["x8"] = 64 _reg_offsets["x9"] = 72 _reg_offsets["x10"] = 80 _reg_offsets["x11"] = 88 _reg_offsets["x12"] = 96 _reg_offsets["x13"] = 104 _reg_offsets["x14"] = 112 _reg_offsets["x15"] = 120 _reg_offsets["x16"] = 128 _reg_offsets["x17"] = 136 _reg_offsets["x18"] = 144 _reg_offsets["x19"] = 152 _reg_offsets["x20"] = 160 _reg_offsets["x21"] = 168 _reg_offsets["x22"] = 176 _reg_offsets["x23"] = 184 _reg_offsets["x24"] = 192 _reg_offsets["x25"] = 200 _reg_offsets["x26"] = 208 _reg_offsets["x27"] = 216 _reg_offsets["x28"] = 224 _reg_offsets["x29"] = 232 _reg_offsets["fp"] = 232 _reg_offsets["x30"] = 240 _reg_offsets["lr"] = 240 _reg_offsets["sp"] = 248 _reg_offsets["pc"] = 256 _reg_offsets["pstate"] = 264 _reg_offsets["orig_x0"] = 272 _r32_offsets["w0"] = 0 _r32_offsets["w1"] = 8 _r32_offsets["w2"] = 16 _r32_offsets["w3"] = 24 _r32_offsets["w4"] = 32 _r32_offsets["w5"] = 40 _r32_offsets["w6"] = 48 _r32_offsets["w7"] = 56 _r32_offsets["w8"] = 64 _r32_offsets["w9"] = 72 _r32_offsets["w10"] = 80 _r32_offsets["w11"] = 88 _r32_offsets["w12"] = 96 _r32_offsets["w13"] = 104 _r32_offsets["w14"] = 112 _r32_offsets["w15"] = 120 _r32_offsets["w16"] = 128 _r32_offsets["w17"] = 136 _r32_offsets["w18"] = 144 _r32_offsets["w19"] = 152 _r32_offsets["w20"] = 160 _r32_offsets["w21"] = 168 _r32_offsets["w22"] = 176 _r32_offsets["w23"] = 184 _r32_offsets["w24"] = 192 _r32_offsets["w25"] = 200 _r32_offsets["w26"] = 208 _r32_offsets["w27"] = 216 _r32_offsets["w28"] = 224 _r32_offsets["w29"] = 232 _r32_offsets["w30"] = 240 } 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 } function _stp_get_register_by_offset:long (offset:long) %{ /* pure */ long value; struct pt_regs *regs; if (CONTEXT->sregs) regs = CONTEXT->sregs; else 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", (long long)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) { reg32 = 0 assert(registers_valid(), "cannot access CPU registers in this context") offset = _reg_offsets[name] if (offset == 0 && !(name in _reg_offsets)) { offset = _r32_offsets[name] if (offset == 0 && !(name in _r32_offsets)) { assert(0, "Unknown register: " . name) } reg32 = 1; } value = _stp_get_register_by_offset(offset) if (reg32 || 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. * TODO: 32-bit arm code has different calling conventions than arm64 */ function _stp_arg:long (argnum:long, sign_extend:long, truncate:long) { val = 0 assert(!(argnum < 1 || argnum > 8), sprintf("Cannot access arg(%d)", argnum)) if (argnum == 1) val = u_register("x0") else if (argnum == 2) val = u_register("x1") else if (argnum == 3) val = u_register("x2") else if (argnum == 4) val = u_register("x3") else if (argnum == 5) val = u_register("x4") else if (argnum == 6) val = u_register("x5") else if (argnum == 7) val = u_register("x6") else if (argnum == 8) val = u_register("x7") if (truncate) { if (sign_extend) val = _stp_sign_extend32(val) else /* High bits may be garbage. */ val = (val & 0xffffffff); } return val; } /* * Return a pointer to an argument given its offset in pt_regs. */ function _stp_offset_to_argptr:long (offset:long) %{ struct pt_regs *regs = CONTEXT->sregs; if (!regs) { snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "cannot access function args in this context"); CONTEXT->last_error = CONTEXT->error_buffer; 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", (long long)STAP_ARG_offset); CONTEXT->last_error = CONTEXT->error_buffer; return; } STAP_RETVALUE = (unsigned long)(((char *)regs) + STAP_ARG_offset); %} /* * Return a pointer to function argument #argnum (1=first arg). */ function _stp_get_argptr:long (argnum:long) { off = 0 assert(!(argnum < 1 || argnum > 8), sprintf("Cannot access arg(%d)", argnum)) if (argnum == 1) off = _reg_offsets["x0"] else if (argnum == 2) off = _reg_offsets["x1"] else if (argnum == 3) off = _reg_offsets["x2"] else if (argnum == 4) off = _reg_offsets["x3"] else if (argnum == 5) off = _reg_offsets["x4"] else if (argnum == 6) off = _reg_offsets["x5"] else if (argnum == 7) off = _reg_offsets["x6"] else if (argnum == 8) off = _reg_offsets["x7"] return _stp_offset_to_argptr(off) } /* 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) } /* Set the value of function arg #argnum (1=first arg) as a signed int. */ function set_int_arg:long (argnum:long, value:long) { return set_kernel_int(_stp_get_argptr(argnum), value) } /* Return the value of function arg #argnum (1=first arg) as an unsigned int. */ function set_uint_arg:long (argnum:long, value:long) { return set_int_arg(argnum, value) } function set_long_arg:long (argnum:long, value:long) { return set_kernel_long(_stp_get_argptr(argnum), value) } function set_ulong_arg:long (argnum:long, value:long) { return set_long_arg(argnum, value) } function set_longlong_arg:long (argnum:long, value:long) { if (probing_32bit_app()) { highbits = value >> 32 lowbits = value & 0xffffffff set_u32_arg(argnum, lowbits) set_u32_arg(argnum+1, highbits) } else set_long_arg(argnum, value) } function set_ulonglong_arg:long (argnum:long, value:long) { return set_longlong_arg(argnum, value) } function set_pointer_arg:long (argnum:long, value:long) { return set_kernel_pointer(_stp_get_argptr(argnum), value) } function set_s32_arg:long (argnum:long, value:long) { return set_int_arg(argnum, value) } function set_u32_arg:long (argnum:long, value:long) { return set_uint_arg(argnum, value) } function set_s64_arg:long (argnum:long, value:long) { return set_longlong_arg(argnum, value) } function set_u64_arg:long (argnum:long, value:long) { return set_ulonglong_arg(argnum, value) } function asmlinkage() %{ /* pure */ %} function fastcall() %{ /* pure */ %} function regparm(n:long) %{ snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "regparm is invalid on arm64."); CONTEXT->last_error = CONTEXT->error_buffer; %}