From patchwork Thu Apr 14 20:19:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 109731 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 68381A0509; Thu, 14 Apr 2022 22:19:45 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 429464067C; Thu, 14 Apr 2022 22:19:45 +0200 (CEST) Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com [209.85.216.49]) by mails.dpdk.org (Postfix) with ESMTP id 4393C4003C for ; Thu, 14 Apr 2022 22:19:44 +0200 (CEST) Received: by mail-pj1-f49.google.com with SMTP id z6-20020a17090a398600b001cb9fca3210so6743502pjb.1 for ; Thu, 14 Apr 2022 13:19:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wl9pFBSE9Kcn+jkh87Nb4V7iQ/yBDfSeWKxuNmMWGEA=; b=ygPX7TSgnQQoHEuCYMNZnOrdt/D/WJ3GxBh30IpSTPwARtRasUI7+eGJPLIw3XK5sk R50N379/dh7+f1dZPCiLrryoP7ICxQjcjvgTZzxiub+ravIZmLN6aGll3v+izG+W5bed +GVatxPn8quPejoI0A1CTnFJTj6bOiY48JUOPQVsDwL+vHKe3ZgfKdFZeyaFS0J1rSp1 BS6Q411PrR2t38KO4qtjCmcBMRoSJEr+/aVDTG7Qer4ZsY8m4TbUZSQtGrms3WqnnTbA YFq92Dg/16hBsg0rboMwp9haYZw+fosDIOJss2ZVhiegOOXwTkL2EGLIIh9e8Pt4hoKJ 5zaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wl9pFBSE9Kcn+jkh87Nb4V7iQ/yBDfSeWKxuNmMWGEA=; b=UMVqun3pEtLGBHEJ5s3+1/MPghN80+56NDTaZiFp8oQZ26ox0PK0dkY44sygE0DUV8 HTMg8lgxNhu+06cYwrpLoOLMsxCjVbGAjfik93ER4CdMwx/uEZ/zVLrgIxHgexdMSZSs lEle/ausoHxnqhV6c5zffoJxzvOdqJvh7uhUSY0GOu1SG7mcELTzXI5qmHoaR5yX4fnK g3Ghfx4YKrZ66BKErsec5mRWSoRficP3oJQOgDN7aGLGLdN4y5SUFvfnup94GsAo0PTH 92qi3IYqC9vph+zG0TMmSz1P+YSLHPqzubyo2GfF9KEJgeRwM2BzMhHhWLy2IHXNmvFT fOHA== X-Gm-Message-State: AOAM532zpOGXAy8dgHz+v6Yjx6qHlrkFVMQcYGJjBygSB9gGje5Oo2RI KAvId+Srgg7Uw4K2eYpDhh5Q8S6gNamX8g== X-Google-Smtp-Source: ABdhPJzPi7Dg4ie7Z9OdWG/IybqOE6UsLeF7TwB5xapB4+FB4vG427NuHYSULxrixnE4iT1RUtKmEw== X-Received: by 2002:a17:902:ec92:b0:158:71e5:fcda with SMTP id x18-20020a170902ec9200b0015871e5fcdamr19135797plg.143.1649967582895; Thu, 14 Apr 2022 13:19:42 -0700 (PDT) Received: from hermes.local (204-195-112-199.wavecable.com. [204.195.112.199]) by smtp.gmail.com with ESMTPSA id u206-20020a6279d7000000b00505fdc42bf9sm694927pfc.101.2022.04.14.13.19.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Apr 2022 13:19:42 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger , =?utf-8?q?Morten_Br?= =?utf-8?q?=C3=B8rup?= , Bruce Richardson Subject: [PATCH v4] rte_dump_stack: make in async signal safe Date: Thu, 14 Apr 2022 13:19:40 -0700 Message-Id: <20220414201940.266711-1-stephen@networkplumber.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220129011039.264377-1-stephen@networkplumber.org> References: <20220129011039.264377-1-stephen@networkplumber.org> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org rte_dump_stack() needs to be usable in situations when a bug is encountered and from signal handlers (such as SEGV). Glibc backtrace_symbols() calls malloc which makes it dangerous in a signal handler that is handling errors that maybe due to memory corruption. Additionally, rte_log() is unsafe because syslog() is not signal safe; printf() is also documented as not being safe. This version formats message and uses writev for each line in a manner similar to what glibc version of backtrace_symbols_fd() does. The FreeBSD version of backtrace_symbols_fd() is not signal safe. Sample output: 0: ./build/app/dpdk-testpmd (rte_dump_stack+0x2b) [560a6e9c002b] 1: ./build/app/dpdk-testpmd (main+0xad) [560a6decd5ad] 2: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xcd) [7fd43d3e27fd] 3: ./build/app/dpdk-testpmd (_start+0x2a) [560a6e83628a] Bugzilla ID: 929 Acked-by: Morten Brørup Signed-off-by: Stephen Hemminger Reviewed-by: David Marchand --- v4 - fix whitespace report from checkpatch v3 - merge previous two patches into one common Linux/FreeBSD code. - rewrite the code to not use functions which are not documented to be signal safe. lib/eal/freebsd/eal_debug.c | 43 ------------- lib/eal/freebsd/meson.build | 1 - lib/eal/include/rte_debug.h | 2 +- lib/eal/linux/eal_debug.c | 38 ----------- lib/eal/linux/meson.build | 1 - lib/eal/unix/eal_debug.c | 123 ++++++++++++++++++++++++++++++++++++ lib/eal/unix/meson.build | 1 + 7 files changed, 125 insertions(+), 84 deletions(-) delete mode 100644 lib/eal/freebsd/eal_debug.c delete mode 100644 lib/eal/linux/eal_debug.c create mode 100644 lib/eal/unix/eal_debug.c diff --git a/lib/eal/freebsd/eal_debug.c b/lib/eal/freebsd/eal_debug.c deleted file mode 100644 index 64dab4e0da24..000000000000 --- a/lib/eal/freebsd/eal_debug.c +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifdef RTE_BACKTRACE -#include -#endif -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define BACKTRACE_SIZE 256 - -/* dump the stack of the calling core */ -void rte_dump_stack(void) -{ -#ifdef RTE_BACKTRACE - void *func[BACKTRACE_SIZE]; - char **symb = NULL; - int size; - - size = backtrace(func, BACKTRACE_SIZE); - symb = backtrace_symbols(func, size); - - if (symb == NULL) - return; - - while (size > 0) { - rte_log(RTE_LOG_ERR, RTE_LOGTYPE_EAL, - "%d: [%s]\n", size, symb[size - 1]); - size --; - } - - free(symb); -#endif /* RTE_BACKTRACE */ -} diff --git a/lib/eal/freebsd/meson.build b/lib/eal/freebsd/meson.build index 398ceab71d03..85cca5a096ca 100644 --- a/lib/eal/freebsd/meson.build +++ b/lib/eal/freebsd/meson.build @@ -7,7 +7,6 @@ sources += files( 'eal.c', 'eal_alarm.c', 'eal_cpuflags.c', - 'eal_debug.c', 'eal_dev.c', 'eal_hugepage_info.c', 'eal_interrupts.c', diff --git a/lib/eal/include/rte_debug.h b/lib/eal/include/rte_debug.h index c4bc71ce28f5..2c4b94a7c9bf 100644 --- a/lib/eal/include/rte_debug.h +++ b/lib/eal/include/rte_debug.h @@ -22,7 +22,7 @@ extern "C" { #endif /** - * Dump the stack of the calling core to the console. + * Dump the stack of the calling core to the standard error. */ void rte_dump_stack(void); diff --git a/lib/eal/linux/eal_debug.c b/lib/eal/linux/eal_debug.c deleted file mode 100644 index b0ecf5a9dcde..000000000000 --- a/lib/eal/linux/eal_debug.c +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifdef RTE_BACKTRACE -#include -#endif -#include -#include - -#include -#include - -#define BACKTRACE_SIZE 256 - -/* dump the stack of the calling core */ -void rte_dump_stack(void) -{ -#ifdef RTE_BACKTRACE - void *func[BACKTRACE_SIZE]; - char **symb = NULL; - int size; - - size = backtrace(func, BACKTRACE_SIZE); - symb = backtrace_symbols(func, size); - - if (symb == NULL) - return; - - while (size > 0) { - rte_log(RTE_LOG_ERR, RTE_LOGTYPE_EAL, - "%d: [%s]\n", size, symb[size - 1]); - size --; - } - - free(symb); -#endif /* RTE_BACKTRACE */ -} diff --git a/lib/eal/linux/meson.build b/lib/eal/linux/meson.build index 65f2ac6b4798..3cccfa36c0a4 100644 --- a/lib/eal/linux/meson.build +++ b/lib/eal/linux/meson.build @@ -7,7 +7,6 @@ sources += files( 'eal.c', 'eal_alarm.c', 'eal_cpuflags.c', - 'eal_debug.c', 'eal_dev.c', 'eal_hugepage_info.c', 'eal_interrupts.c', diff --git a/lib/eal/unix/eal_debug.c b/lib/eal/unix/eal_debug.c new file mode 100644 index 000000000000..dea7372af2f8 --- /dev/null +++ b/lib/eal/unix/eal_debug.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#include + + +#ifdef RTE_BACKTRACE + +#include +#include +#include +#include +#include + +#define BACKTRACE_SIZE 256 + +/* + * Convert number to string and return start of string. + * Note: string does not start at beginning of buffer. + */ +static char *safe_itoa(long val, char *buf, size_t len, unsigned int radix) +{ + char *bp = buf + len; + static const char hexdigit[] = "0123456789abcdef"; + + *--bp = '\0'; /* Null terminate the string */ + do { + /* if buffer is not big enough, then truncate */ + if (bp == buf) + return bp; + + *--bp = hexdigit[val % radix]; + val /= radix; + } while (val != 0); + + return bp; +} + + +/* Dump the stack of the calling core + * + * To be safe in signal handler requires limiting what functions are + * used in this code since may be called from inside libc or + * when malloc poll is corrupt. + * + * Most of libc is therefore not safe, include RTE_LOG (calls syslog); + * backtrace_symbols (calls malloc), etc. + */ +void rte_dump_stack(void) +{ + void *func[BACKTRACE_SIZE]; + Dl_info info; + char buf1[8], buf2[32], buf3[32], buf4[32]; + struct iovec iov[10]; + int i, size; + + size = backtrace(func, BACKTRACE_SIZE); + + for (i = 0; i < size; i++) { + struct iovec *io = iov; + char *str; + uintptr_t base; + long offset; + void *pc = func[i]; + +/* Macro to put string onto set of iovecs + * cast is to suppress warnings about lose of const qualifier + */ +#define PUSH_IOV(io, str) { \ + (io)->iov_base = (char *)(uintptr_t)str; \ + (io)->iov_len = strlen(str); \ + ++io; } + + /* output stack frame number */ + str = safe_itoa(i, buf1, sizeof(buf1), 10); + PUSH_IOV(io, str); /* iov[0] */ + PUSH_IOV(io, ": "); /* iov[1] */ + + /* Lookup the symbol information */ + if (dladdr(pc, &info) == 0) { + PUSH_IOV(io, "?? ["); + } else { + const char *fname; + + if (info.dli_fname && *info.dli_fname) + fname = info.dli_fname; + else + fname = "(vdso)"; + PUSH_IOV(io, fname); /* iov[2] */ + PUSH_IOV(io, " ("); /* iov[3] */ + + if (info.dli_saddr != NULL) { + PUSH_IOV(io, info.dli_sname); /* iov[4] */ + base = (uintptr_t)info.dli_saddr; + } else { + str = safe_itoa((unsigned long)info.dli_fbase, + buf3, sizeof(buf3), 16); + PUSH_IOV(io, str); + base = (uintptr_t)info.dli_fbase; + } + + PUSH_IOV(io, "+0x"); /* iov[5] */ + + offset = (uintptr_t)pc - base; + str = safe_itoa(offset, buf4, sizeof(buf4), 16); + PUSH_IOV(io, str); /* iov[6] */ + + PUSH_IOV(io, ") ["); /* iov[7] */ + } + + str = safe_itoa((unsigned long)pc, buf2, sizeof(buf2), 16); + PUSH_IOV(io, str); /* iov[8] */ + PUSH_IOV(io, "]\n"); /* iov[9] */ + + if (writev(STDERR_FILENO, iov, io - iov) < 0) + break; + } +} +#else +/* stub if not enabled */ +void rte_dump_stack(void) { } +#endif /* RTE_BACKTRACE */ diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build index 781505ca9061..cc7d67dd321d 100644 --- a/lib/eal/unix/meson.build +++ b/lib/eal/unix/meson.build @@ -2,6 +2,7 @@ # Copyright(c) 2020 Dmitry Kozlyuk sources += files( + 'eal_debug.c', 'eal_file.c', 'eal_filesystem.c', 'eal_firmware.c',