// conversions tapset // Copyright (C) 2005-2007 Red Hat Inc. // Copyright (C) 2007 Intel Corporation. // // 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. function kernel_string:string (addr:long) %{ /* pure */ char *destination = THIS->__retvalue; deref_string (destination, THIS->addr, MAXSTRINGLEN); if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", (void *) (uintptr_t) THIS->addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} function kernel_string_n:string (addr:long, n:long) %{ /* pure */ char *destination = THIS->__retvalue; long len = THIS->n + 1; len = (len > MAXSTRINGLEN) ? MAXSTRINGLEN : len; deref_string (destination, THIS->addr, len); if (0) { deref_fault: /* branched to from deref_string() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel string copy fault at 0x%p", (void *) (uintptr_t) THIS->addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} function kernel_long:long (addr:long) %{ /* pure */ THIS->__retvalue = kread((long *) (intptr_t) THIS->addr); if (0) { deref_fault: /* branched to from deref() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel long copy fault at 0x%p", (void *) (uintptr_t) THIS->addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} function kernel_int:long (addr:long) %{ /* pure */ THIS->__retvalue = kread((int *) (intptr_t) THIS->addr); if (0) { deref_fault: /* branched to from deref() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel int copy fault at 0x%p", (void *) (uintptr_t) THIS->addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} function kernel_short:long (addr:long) %{ /* pure */ THIS->__retvalue = kread((short *) (intptr_t) THIS->addr); if (0) { deref_fault: /* branched to from deref() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel short copy fault at 0x%p", (void *) (uintptr_t) THIS->addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} function kernel_char:long (addr:long) %{ /* pure */ THIS->__retvalue = kread((char *) (intptr_t) THIS->addr); if (0) { deref_fault: /* branched to from deref() */ snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "kernel char copy fault at 0x%p", (void *) (uintptr_t) THIS->addr); CONTEXT->last_error = CONTEXT->error_buffer; } %} // On rare cases when userspace data is not accessible, // this function returns "" function user_string:string (addr:long) { return user_string2 (addr, "") } function user_string2:string (addr:long, err_msg:string) %{ /* pure */ if (_stp_strncpy_from_user (THIS->__retvalue, (const char __user*) (uintptr_t) THIS->addr, MAXSTRINGLEN) < 0) strlcpy (THIS->__retvalue, THIS->err_msg, MAXSTRINGLEN); %} function user_string_warn:string (addr:long) %{ /* pure */ long rc = _stp_strncpy_from_user (THIS->__retvalue, (const char __user*) (uintptr_t) THIS->addr, MAXSTRINGLEN); if (rc < 0) { // NB: using error_buffer to get local space for the warning, but we're // not aborting, so leave last_error alone. snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), "user string copy fault %ld at %p", rc, (void *) (uintptr_t) THIS->addr); _stp_warn(CONTEXT->error_buffer); strlcpy (THIS->__retvalue, "", MAXSTRINGLEN); } %} function user_string_quoted:string (addr:long) %{ /* pure */ if (THIS->addr == 0) strlcpy (THIS->__retvalue, "NULL", MAXSTRINGLEN); else /* XXX: stp_text_str uses sleepy __get_user() => unsafe ?! */ _stp_text_str(THIS->__retvalue, (char *)(uintptr_t)THIS->addr, MAXSTRINGLEN, 1, 1); %}