From patchwork Thu Nov 9 23:48:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Senozhatsky X-Patchwork-Id: 836568 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yY0bt0nQSz9sRg for ; Fri, 10 Nov 2017 11:03:06 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="VkCc6weJ"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3yY0bs6ZMjzDrKJ for ; Fri, 10 Nov 2017 11:03:05 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="VkCc6weJ"; dkim-atps=neutral X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:400e:c00::243; helo=mail-pf0-x243.google.com; envelope-from=sergey.senozhatsky@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="VkCc6weJ"; dkim-atps=neutral Received: from mail-pf0-x243.google.com (mail-pf0-x243.google.com [IPv6:2607:f8b0:400e:c00::243]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3yY0Kp2Cb8zDrKj for ; Fri, 10 Nov 2017 10:50:54 +1100 (AEDT) Received: by mail-pf0-x243.google.com with SMTP id u70so625862pfa.7 for ; Thu, 09 Nov 2017 15:50:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gBEgXOJBzLHOxPJ8KiISypx9SW4dgzTQv6pFfa20/w4=; b=VkCc6weJqwrSRWclAYxQSMLVJIICzRe+5jC8ztEkdmVJ+24CNe/4jHTOsKae1/W3aE aDiDj4I5H98lCPfADB6Bw9N7zzLDFgniry6RmD7e/vnTLWGzxEOOulBMosQbZVxYTvyF vIn4yLXlTYwsnE6gQhw8B9UUPv7X2DNR4hQQLTEaPcQQhcNtNHXykXz0VBeVO2OG6XwW uKrBRV8kOvnsQXWj3QsTOIuVj3IpU8xQHmZ0YuQ5A0vRiT/xeHFukQ4PZgj5p36AyIw7 7/erskcEagNVpE5PIvTWj6YqzHUXdDoGhjQ+KFfsHEdWD0FOJAKzfUqUqvrwoucxQv6Z D9fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gBEgXOJBzLHOxPJ8KiISypx9SW4dgzTQv6pFfa20/w4=; b=HLEPQmKMFa6rvb4GJQKhDnI8m7/Gov4frXCgFgJ/mZi3MicslDqJwtUz7qfY/imWwA wfNJ89IcYZLqjrL4cof9HilFH2CMeQUxGHZPng0a7IAhQ2tyEiHLXOCbFAJgSfFC7pv+ j/C20gAUz6Ufg3LJX/VqCEDYeESvyfCO7GFs3SxfSQ0OtwB9U3hTTFEkVLSiEgx4onKd gAWdhikm3D3tt7W1iDpDbSzMKeb2s4OYIc3qrLDU0HjTH2YetGySBHRJr4rETB35+HXT etSHaJE8UylnyvHEsg0TLfGwjKMEeqoHHGatpGNAOAFl0S26r+cZTmlLxpMwE9R1KNPz mPVw== X-Gm-Message-State: AJaThX7zVFvqAsaaYGlMhjXFwiflgkT4qOu2qnwayMd4YMBIxdLuM1jn 8Je3dGitixHtxHldgIFldzE= X-Google-Smtp-Source: ABhQp+S2+KZagx7Eu7kHnOE5hoy7P1XfkgqeQ1KWNWGDvg5ZeSqb12E8tMQbXRQyXK0PlMigZ1LQ8w== X-Received: by 10.98.17.7 with SMTP id z7mr2205572pfi.206.1510271451668; Thu, 09 Nov 2017 15:50:51 -0800 (PST) Received: from localhost.localdomain ([121.137.63.184]) by smtp.gmail.com with ESMTPSA id t25sm13160477pfh.67.2017.11.09.15.50.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Nov 2017 15:50:51 -0800 (PST) From: Sergey Senozhatsky To: Tony Luck , Fenghua Yu , Helge Deller , Benjamin Herrenschmidt , Paul Mackerras , Michael Ellerman , James Bottomley Subject: [PATCHv4 5/6] symbol lookup: introduce dereference_symbol_descriptor() Date: Fri, 10 Nov 2017 08:48:29 +0900 Message-Id: <20171109234830.5067-6-sergey.senozhatsky@gmail.com> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171109234830.5067-1-sergey.senozhatsky@gmail.com> References: <20171109234830.5067-1-sergey.senozhatsky@gmail.com> X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , linux-ia64@vger.kernel.org, Sergey Senozhatsky , linux-parisc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Jessica Yu , Andrew Morton , linuxppc-dev@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" dereference_symbol_descriptor() invokes appropriate ARCH specific function descriptor dereference callbacks: - dereference_kernel_function_descriptor() if the pointer is a kernel symbol; - dereference_module_function_descriptor() if the pointer is a module symbol. This is the last step needed to make '%pS/%ps' smart enough to handle function descriptor dereference on affected ARCHs and to retire '%pF/%pf'. To refresh it: Some architectures (ia64, ppc64, parisc64) use an indirect pointer for C function pointers - the function pointer points to a function descriptor and we need to dereference it to get the actual function pointer. Function descriptors live in .opd elf section and all affected ARCHs (ia64, ppc64, parisc64) handle it properly for kernel and modules. So we, technically, can decide if the dereference is needed by simply looking at the pointer: if it belongs to .opd section then we need to dereference it. The kernel and modules have their own .opd sections, obviously, that's why we need to split dereference_function_descriptor() and use separate kernel and module dereference arch callbacks. Signed-off-by: Sergey Senozhatsky Signed-off-by: Sergey Senozhatsky Tested-by: Tony Luck #ia64 Tested-by: Santosh Sivaraj #powerpc Tested-by: Helge Deller #parisc64 --- Documentation/printk-formats.txt | 49 ++++++++++++++++------------------------ include/linux/kallsyms.h | 2 ++ kernel/kallsyms.c | 19 ++++++++++++++++ lib/vsprintf.c | 5 ++-- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 361789df51ec..2f17e684b72e 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -50,42 +50,31 @@ Symbols/Function Pointers :: - %pF versatile_init+0x0/0x110 - %pf versatile_init - %pS versatile_init+0x0/0x110 - %pSR versatile_init+0x9/0x110 - (with __builtin_extract_return_addr() translation) - %ps versatile_init - %pB prev_fn_of_versatile_init+0x88/0x88 - -The ``F`` and ``f`` specifiers are for printing function pointers, -for example, f->func, &gettimeofday. They have the same result as -``S`` and ``s`` specifiers. But they do an extra conversion on -ia64, ppc64 and parisc64 architectures where the function pointers -are actually function descriptors. - -The ``S`` and ``s`` specifiers can be used for printing symbols -from direct addresses, for example, __builtin_return_address(0), -(void *)regs->ip. They result in the symbol name with (``S``) or -without (``s``) offsets. If KALLSYMS are disabled then the symbol -address is printed instead. + %pS versatile_init+0x0/0x110 + %ps versatile_init + %pF versatile_init+0x0/0x110 + %pf versatile_init + %pSR versatile_init+0x9/0x110 + (with __builtin_extract_return_addr() translation) + %pB prev_fn_of_versatile_init+0x88/0x88 + +The ``S`` and ``s`` specifiers are used for printing a pointer in symbolic +format. They result in the symbol name with (``S``) or without (``s``) +offsets. If KALLSYMS are disabled then the symbol address is printed instead. + +Note, that the ``F`` and ``f`` specifiers are identical to ``S`` (``s``) +and thus deprecated. We have ``F`` and ``f`` because on ia64, ppc64 and +parisc64 function pointers are indirect and, in fact, are function +descriptors, which require additional dereferencing before we can lookup +the symbol. As of now, ``S`` and ``s`` perform dereferencing on those +platforms (when needed), so ``F`` and ``f`` exist for compatibility +reasons only. The ``B`` specifier results in the symbol name with offsets and should be used when printing stack backtraces. The specifier takes into consideration the effect of compiler optimisations which may occur when tail-call``s are used and marked with the noreturn GCC attribute. -Examples:: - - printk("Going to call: %pF\n", gettimeofday); - printk("Going to call: %pF\n", p->func); - printk("%s: called from %pS\n", __func__, (void *)_RET_IP_); - printk("%s: called from %pS\n", __func__, - (void *)__builtin_return_address(0)); - printk("Faulted at %pS\n", (void *)regs->ip); - printk(" %s%pB\n", (reliable ? "" : "? "), (void *)*stack); - - Kernel Pointers =============== diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 11dd93e42580..73f7e874c3e1 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -16,6 +16,8 @@ struct module; +void *dereference_symbol_descriptor(void *ptr); + #ifdef CONFIG_KALLSYMS /* Lookup the address for a symbol. Returns 0 if not found. */ unsigned long kallsyms_lookup_name(const char *name); diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 1966fe1c2b57..18b3dffc4b84 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -411,6 +411,25 @@ static int __sprint_symbol(char *buffer, unsigned long address, return len; } +void *dereference_symbol_descriptor(void *ptr) +{ +#ifdef HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR + struct module *mod; + + ptr = dereference_kernel_function_descriptor(ptr); + if (is_ksym_addr((unsigned long)ptr)) + return ptr; + + preempt_disable(); + mod = __module_address((unsigned long)ptr); + preempt_enable(); + + if (mod) + ptr = dereference_module_function_descriptor(mod, ptr); +#endif + return ptr; +} + /** * sprint_symbol - Look up a kernel symbol and return it in a text buffer * @buffer: buffer to be stored diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 1746bae94d41..16e2eefb0f79 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -40,7 +40,6 @@ #include "../mm/internal.h" /* For the trace_print_flags arrays */ #include /* for PAGE_SIZE */ -#include /* for dereference_function_descriptor() */ #include /* cpu_to_le16 */ #include @@ -1723,10 +1722,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, switch (*fmt) { case 'F': case 'f': - ptr = dereference_function_descriptor(ptr); - /* Fallthrough */ case 'S': case 's': + ptr = dereference_symbol_descriptor(ptr); + /* Fallthrough */ case 'B': return symbol_string(buf, end, ptr, spec, fmt); case 'R':