From patchwork Thu Nov 9 23:59:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451869 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B97AD38FB1; Fri, 10 Nov 2023 00:00:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QhzGPgQM" Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4558E44A4; Thu, 9 Nov 2023 16:00:19 -0800 (PST) Received: by mail-pg1-x52c.google.com with SMTP id 41be03b00d2f7-5a9bf4fbd3fso1210418a12.1; Thu, 09 Nov 2023 16:00:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574419; x=1700179219; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=s26PP4ZDsM0R9c6L05wqU22qp26lYxGgumYeBt3IcPk=; b=QhzGPgQMi46JFIGAL1E1foEvEniu8U/jJhiNMbehb60avWy5Zp5m3LVJZEuU1LlEAP aNyWvgBWZrgkfTLJcEGNy77G5kjxrd27AvpVdLLJtg3I7a92aOxVJJ39iN/UwGVoh9Jf Dw95Kjs0igsCCEErS0RhoX/T3N8ueeJHHt+D5HlKA7HEP7QxUl+7rZsWaXe4Dhd03lE9 WwcGgmPR7qQoDG6zADMlbFl8JtYhubm4gjM7e0CFmCNIEq+msc6Ir1+pUwRfZ8dPROcK ekA9w9E6Unv0iR+DKOo40E4fQmQvwLmge81GRehjgpJZ44E0/4NSecIO3uxdgFmkv07X /uFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574419; x=1700179219; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=s26PP4ZDsM0R9c6L05wqU22qp26lYxGgumYeBt3IcPk=; b=WiVCTUl2zL6tAVOXoFO7YRh9lyeTFXsbR0NUBMQPzC7KAnF1Q4ZavhRz4FrgW2cbcF ZiOJLgdVSa68hJuzyxBzRazuj3M+auxVWEYWOO+cb542btSPD5qbDylx8FqteQPnamV+ ml+7cVizO832OTk54pCRGl8M4sW7I6w/fjsEfm+09U0/KFLcAIv65ONE6v7o6JjbQOR3 5ogZZPKZEgWF4jkQiOvDblV1bQSTRMNTdXSDLe7+aGyEXNLznlR8YJ0COKelLTUSVg20 QWJ2jHy4Lr6P9g/hqxjp125rwSrj3G5Ws6IoTo7q+WhIZdTjf2Cp5sVwf/QuAG/ooVlQ oT3w== X-Gm-Message-State: AOJu0YzWL84Wi4/9OCGpEMgCojfqZHpDz6hNTuo+/kb9fz0OO54oxFp4 aBlPWL9ag8BUgyMSETYZllIU7ScP8Po= X-Google-Smtp-Source: AGHT+IHHnB+o3wtlhsc5Pg6XZ5hiEHujvSdyi7qq+Tz5AvknsajtKxTo1tPTlLQ40kEzsUxhbvt8aw== X-Received: by 2002:a17:90b:1bcc:b0:27d:7ebe:2e8 with SMTP id oa12-20020a17090b1bcc00b0027d7ebe02e8mr3543803pjb.9.1699574417184; Thu, 09 Nov 2023 16:00:17 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:16 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 01/52] perf annotate: Pass "-l" option to objdump conditionally Date: Thu, 9 Nov 2023 15:59:20 -0800 Message-ID: <20231110000012.3538610-2-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The "-l" option is to print line numbers in the objdump output. perf annotate TUI only can show the line numbers later but it causes big slow downs for the kernel binary. Similarly, showing source code also takes a long time and it already has an option to control it. $ time objdump ... -d -S -C vmlinux > /dev/null real 0m3.474s user 0m3.047s sys 0m0.428s $ time objdump ... -d -l -C vmlinux > /dev/null real 0m1.796s user 0m1.459s sys 0m0.338s $ time objdump ... -d -C vmlinux > /dev/null real 0m0.051s user 0m0.036s sys 0m0.016s As it's not needed for data type profiling, let's make it conditional so that it can skip the unnecessary work. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 9b68b8e3791c..118195c787b9 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2144,12 +2144,13 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) err = asprintf(&command, "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 - " -l -d %s %s %s %c%s%c %s%s -C \"$1\"", + " %s -d %s %s %s %c%s%c %s%s -C \"$1\"", opts->objdump_path ?: "objdump", opts->disassembler_style ? "-M " : "", opts->disassembler_style ?: "", map__rip_2objdump(map, sym->start), map__rip_2objdump(map, sym->end), + opts->show_linenr ? "-l" : "", opts->show_asm_raw ? "" : "--no-show-raw-insn", opts->annotate_src ? "-S" : "", opts->prefix ? "--prefix " : "", From patchwork Thu Nov 9 23:59:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451870 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 139EA38FBE; Fri, 10 Nov 2023 00:00:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ephkuhv9" Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8888344B8; Thu, 9 Nov 2023 16:00:19 -0800 (PST) Received: by mail-pg1-x52c.google.com with SMTP id 41be03b00d2f7-5bd6ac9833fso1120837a12.0; Thu, 09 Nov 2023 16:00:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574419; x=1700179219; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=Ey94DP/uelsbEgibz5QQXMU4gKyXrxF4jUDbY06eM9k=; b=Ephkuhv9YJ3flFd8uODkLImjUCiSTuItkx30J5PVBrnptk03z24GLYisdYEYXS953w SZsqr0hVWtPxbZ7kUrNo3SvVHwmj6qHSkeLjbAlUo5ZY0GM4b7RZqWn8HZELF71KTWC7 lwr9qeW87FN2q3f4j6/H9j+YN5e1eQIscjOIxEL5fy4W1M9fulucSDzM/FTPDN8J8w5k yYeLCMwNAXTi2Kd+jHXBGBIdiGpz2/Rwkd1Dsb1m1SIfkLE77Msr4xSgJv5L+r+rJgKT 1YDXUSSuQH17ldyeBxHwN+bb7VMAGBsSCRYMlVJaRn5BOe7prC4aD7aNB3343o9kLZzf UTsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574419; x=1700179219; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Ey94DP/uelsbEgibz5QQXMU4gKyXrxF4jUDbY06eM9k=; b=uwmWVb8S1RxyiTZvlEatkp6oAZJ1GJUVu92gdrf1X2On9M18OEOR9rRs67CBR5rsma 5v9ianRYtvZ3AntdvktFEnN272MwtmK6nTbA4Lg+835qZWNOkPVlT26Bh74idEdpI8TC MD2tdw2RuQoLY2ELpIPF9zDv+dUqG3ALsHap/8a/3n/WWrG2nAIwY1cz32T1Ng4otIsU JGYue1osHSa3kraglJdvmA5d5AQekpNPcRWjwV7ZWoBW8Ey5yzhlvLL+sVZPDpy5ZSmQ KDmd0nePTqVCBjEoNlpeYbqgVrxv+llRZrRDCZaaHeFIpTu0n9ZucLEvFpNxuvJgjS5v bmpw== X-Gm-Message-State: AOJu0Ywe8yiBnvCpW4ueOBEJsZ4QVgG0QOsU06Bd13L4mPuMU/jPNoGw CJgDl4LwdGVKwYo8xO92Xw0= X-Google-Smtp-Source: AGHT+IHXWtCX2mhFjyGobqMA7A87aXao3MRvg4Ed5XHGcG3lOAOTrWMfM0jz0XLmBzBfDwCv1WDy+Q== X-Received: by 2002:a05:6a20:441a:b0:16b:f3b1:c040 with SMTP id ce26-20020a056a20441a00b0016bf3b1c040mr8149334pzb.38.1699574418918; Thu, 09 Nov 2023 16:00:18 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:18 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org, Huacai Chen , WANG Rui Subject: [PATCH 02/52] perf annotate: Move raw_comment and raw_func_start Date: Thu, 9 Nov 2023 15:59:21 -0800 Message-ID: <20231110000012.3538610-3-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Thoese two fields are used only for the jump_ops, so move them into the union to save some bytes. Also add jump__delete() callback not to free the fields as they didn't allocate new strings. Cc: Huacai Chen Cc: WANG Rui Signed-off-by: Namhyung Kim --- .../perf/arch/loongarch/annotate/instructions.c | 6 +++--- tools/perf/util/annotate.c | 17 +++++++++++++---- tools/perf/util/annotate.h | 6 ++++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/tools/perf/arch/loongarch/annotate/instructions.c b/tools/perf/arch/loongarch/annotate/instructions.c index 98e19c5366ac..21cc7e4149f7 100644 --- a/tools/perf/arch/loongarch/annotate/instructions.c +++ b/tools/perf/arch/loongarch/annotate/instructions.c @@ -61,10 +61,10 @@ static int loongarch_jump__parse(struct arch *arch, struct ins_operands *ops, st const char *c = strchr(ops->raw, '#'); u64 start, end; - ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char); - ops->raw_func_start = strchr(ops->raw, '<'); + ops->jump.raw_comment = strchr(ops->raw, arch->objdump.comment_char); + ops->jump.raw_func_start = strchr(ops->raw, '<'); - if (ops->raw_func_start && c > ops->raw_func_start) + if (ops->jump.raw_func_start && c > ops->jump.raw_func_start) c = NULL; if (c++ != NULL) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 118195c787b9..3364edf30f50 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -340,10 +340,10 @@ bool ins__is_call(const struct ins *ins) */ static inline const char *validate_comma(const char *c, struct ins_operands *ops) { - if (ops->raw_comment && c > ops->raw_comment) + if (ops->jump.raw_comment && c > ops->jump.raw_comment) return NULL; - if (ops->raw_func_start && c > ops->raw_func_start) + if (ops->jump.raw_func_start && c > ops->jump.raw_func_start) return NULL; return c; @@ -359,8 +359,8 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s const char *c = strchr(ops->raw, ','); u64 start, end; - ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char); - ops->raw_func_start = strchr(ops->raw, '<'); + ops->jump.raw_comment = strchr(ops->raw, arch->objdump.comment_char); + ops->jump.raw_func_start = strchr(ops->raw, '<'); c = validate_comma(c, ops); @@ -462,7 +462,16 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size, ops->target.offset); } +static void jump__delete(struct ins_operands *ops __maybe_unused) +{ + /* + * The ops->jump.raw_comment and ops->jump.raw_func_start belong to the + * raw string, don't free them. + */ +} + static struct ins_ops jump_ops = { + .free = jump__delete, .parse = jump__parse, .scnprintf = jump__scnprintf, }; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index de59c1aff08e..bc8b95e8b1be 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -31,8 +31,6 @@ struct ins { struct ins_operands { char *raw; - char *raw_comment; - char *raw_func_start; struct { char *raw; char *name; @@ -52,6 +50,10 @@ struct ins_operands { struct ins ins; struct ins_operands *ops; } locked; + struct { + char *raw_comment; + char *raw_func_start; + } jump; }; }; From patchwork Thu Nov 9 23:59:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451871 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D075638FB1; Fri, 10 Nov 2023 00:00:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZAKVfq6k" Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5DBB6420B; Thu, 9 Nov 2023 16:00:21 -0800 (PST) Received: by mail-pf1-x431.google.com with SMTP id d2e1a72fcca58-6b44befac59so2029072b3a.0; Thu, 09 Nov 2023 16:00:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574421; x=1700179221; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=Ohn4+jphevtQjEHJsPa6nw1ndYUCUTA0xB3bWWY8ZxA=; b=ZAKVfq6kx8SI+oirL5u7gFjp/qILkDXAeM9ZJRtq5AaXoEIxU/PclY+kb6cYXMY3EK DcgBHq4i+MLTaCt15YMp7tTrjH/VYclrI2hqsrjuqCJRjDLGFG92xVqgZ6tnzu5Bberd YlvdSmmW18e1OhhX+GMRLhNkbnoji6XQJQC3RD21UkOVJbnOxA7QDBLgpZjMRyTtEcrR UVT2nb4YHcOeSS0MfIwL2WkDvRudCF+kCz5oTt19BEuNFtNf+NQ9ZX7ipYDA5umnPN50 y5Smnt2A17zkyHm5BcxZUHxRTXGs+G4mnyerwY9QrOpN4X3VOaSfxDN+DP0QMUN7OhOu mS7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574421; x=1700179221; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Ohn4+jphevtQjEHJsPa6nw1ndYUCUTA0xB3bWWY8ZxA=; b=E5tYWnC02QWYvIs2qU7wuN5PzYgza7fw2xdEpRy0gcW3U/KkOrcVqLZ6TXfLGAY8Br vTpJl3962RtpURBThkrmonnlXLRXt3pRUDieSGJ+kKLyg1AvTTFkbTAEEtnYvSeCTmVF ncOHoygc8wyEq9Xdof3qCqrWKiiENGWPbRvKRQp091VvFX/lXGuX94jEud4VixflIs/+ rzmIa7rPBorddVVefkJpOZSxlnMPcvTK1c1RolbXwpyRYxKZjFpsAv8bZQjQt/E+ChVJ MUYNWivnG8ALWB9Xb+cPMLuwVxdkJnzEV3flgNDd1jaeU98bZFYQXVfmKfNb82L0GkIB smQw== X-Gm-Message-State: AOJu0Ywm2SQ1OW7Yf6yYe/3Yq1mK9gNF37l+fxu8+zb6eYdibpnbzadu ngNpbIBhMsyLyhsKvdSxQxA= X-Google-Smtp-Source: AGHT+IFe4IKBEneDjcK+fClglxOUqCTJXhiazz2fwJwEQ9EIE9cURli9ecN0TcG3PDVVefhqzjLIDA== X-Received: by 2002:a17:90b:1b04:b0:27d:1369:515e with SMTP id nu4-20020a17090b1b0400b0027d1369515emr1079689pjb.22.1699574420611; Thu, 09 Nov 2023 16:00:20 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:20 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 03/52] perf tools: Add util/debuginfo.[ch] files Date: Thu, 9 Nov 2023 15:59:22 -0800 Message-ID: <20231110000012.3538610-4-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Split debuginfo data structure and related functions into a separate file so that it can be used other than the probe-finder. Cc: Masami Hiramatsu Signed-off-by: Namhyung Kim --- tools/perf/util/Build | 1 + tools/perf/util/debuginfo.c | 205 +++++++++++++++++++++++++++++++++ tools/perf/util/debuginfo.h | 64 ++++++++++ tools/perf/util/probe-finder.c | 193 +------------------------------ tools/perf/util/probe-finder.h | 19 +-- 5 files changed, 272 insertions(+), 210 deletions(-) create mode 100644 tools/perf/util/debuginfo.c create mode 100644 tools/perf/util/debuginfo.h diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 96058f949ec9..73e3f194f949 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -195,6 +195,7 @@ endif perf-$(CONFIG_DWARF) += probe-finder.o perf-$(CONFIG_DWARF) += dwarf-aux.o perf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_DWARF) += debuginfo.o perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o diff --git a/tools/perf/util/debuginfo.c b/tools/perf/util/debuginfo.c new file mode 100644 index 000000000000..19acf4775d35 --- /dev/null +++ b/tools/perf/util/debuginfo.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * DWARF debug information handling code. Copied from probe-finder.c. + * + * Written by Masami Hiramatsu + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "build-id.h" +#include "dso.h" +#include "debug.h" +#include "debuginfo.h" +#include "symbol.h" + +#ifdef HAVE_DEBUGINFOD_SUPPORT +#include +#endif + +/* Dwarf FL wrappers */ +static char *debuginfo_path; /* Currently dummy */ + +static const Dwfl_Callbacks offline_callbacks = { + .find_debuginfo = dwfl_standard_find_debuginfo, + .debuginfo_path = &debuginfo_path, + + .section_address = dwfl_offline_section_address, + + /* We use this table for core files too. */ + .find_elf = dwfl_build_id_find_elf, +}; + +/* Get a Dwarf from offline image */ +static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, + const char *path) +{ + GElf_Addr dummy; + int fd; + + fd = open(path, O_RDONLY); + if (fd < 0) + return fd; + + dbg->dwfl = dwfl_begin(&offline_callbacks); + if (!dbg->dwfl) + goto error; + + dwfl_report_begin(dbg->dwfl); + dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); + if (!dbg->mod) + goto error; + + dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); + if (!dbg->dbg) + goto error; + + dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy); + + dwfl_report_end(dbg->dwfl, NULL, NULL); + + return 0; +error: + if (dbg->dwfl) + dwfl_end(dbg->dwfl); + else + close(fd); + memset(dbg, 0, sizeof(*dbg)); + + return -ENOENT; +} + +static struct debuginfo *__debuginfo__new(const char *path) +{ + struct debuginfo *dbg = zalloc(sizeof(*dbg)); + if (!dbg) + return NULL; + + if (debuginfo__init_offline_dwarf(dbg, path) < 0) + zfree(&dbg); + if (dbg) + pr_debug("Open Debuginfo file: %s\n", path); + return dbg; +} + +enum dso_binary_type distro_dwarf_types[] = { + DSO_BINARY_TYPE__FEDORA_DEBUGINFO, + DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, + DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, + DSO_BINARY_TYPE__BUILDID_DEBUGINFO, + DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO, + DSO_BINARY_TYPE__NOT_FOUND, +}; + +struct debuginfo *debuginfo__new(const char *path) +{ + enum dso_binary_type *type; + char buf[PATH_MAX], nil = '\0'; + struct dso *dso; + struct debuginfo *dinfo = NULL; + struct build_id bid; + + /* Try to open distro debuginfo files */ + dso = dso__new(path); + if (!dso) + goto out; + + /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */ + if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0) + dso__set_build_id(dso, &bid); + + for (type = distro_dwarf_types; + !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; + type++) { + if (dso__read_binary_type_filename(dso, *type, &nil, + buf, PATH_MAX) < 0) + continue; + dinfo = __debuginfo__new(buf); + } + dso__put(dso); + +out: + /* if failed to open all distro debuginfo, open given binary */ + return dinfo ? : __debuginfo__new(path); +} + +void debuginfo__delete(struct debuginfo *dbg) +{ + if (dbg) { + if (dbg->dwfl) + dwfl_end(dbg->dwfl); + free(dbg); + } +} + +/* For the kernel module, we need a special code to get a DIE */ +int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, + bool adjust_offset) +{ + int n, i; + Elf32_Word shndx; + Elf_Scn *scn; + Elf *elf; + GElf_Shdr mem, *shdr; + const char *p; + + elf = dwfl_module_getelf(dbg->mod, &dbg->bias); + if (!elf) + return -EINVAL; + + /* Get the number of relocations */ + n = dwfl_module_relocations(dbg->mod); + if (n < 0) + return -ENOENT; + /* Search the relocation related .text section */ + for (i = 0; i < n; i++) { + p = dwfl_module_relocation_info(dbg->mod, i, &shndx); + if (strcmp(p, ".text") == 0) { + /* OK, get the section header */ + scn = elf_getscn(elf, shndx); + if (!scn) + return -ENOENT; + shdr = gelf_getshdr(scn, &mem); + if (!shdr) + return -ENOENT; + *offs = shdr->sh_addr; + if (adjust_offset) + *offs -= shdr->sh_offset; + } + } + return 0; +} + +#ifdef HAVE_DEBUGINFOD_SUPPORT +int get_source_from_debuginfod(const char *raw_path, + const char *sbuild_id, char **new_path) +{ + debuginfod_client *c = debuginfod_begin(); + const char *p = raw_path; + int fd; + + if (!c) + return -ENOMEM; + + fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id, + 0, p, new_path); + pr_debug("Search %s from debuginfod -> %d\n", p, fd); + if (fd >= 0) + close(fd); + debuginfod_end(c); + if (fd < 0) { + pr_debug("Failed to find %s in debuginfod (%s)\n", + raw_path, sbuild_id); + return -ENOENT; + } + pr_debug("Got a source %s\n", *new_path); + + return 0; +} +#endif /* HAVE_DEBUGINFOD_SUPPORT */ diff --git a/tools/perf/util/debuginfo.h b/tools/perf/util/debuginfo.h new file mode 100644 index 000000000000..4d65b8c605fc --- /dev/null +++ b/tools/perf/util/debuginfo.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _PERF_DEBUGINFO_H +#define _PERF_DEBUGINFO_H + +#include +#include + +#ifdef HAVE_DWARF_SUPPORT + +#include "dwarf-aux.h" + +/* debug information structure */ +struct debuginfo { + Dwarf *dbg; + Dwfl_Module *mod; + Dwfl *dwfl; + Dwarf_Addr bias; + const unsigned char *build_id; +}; + +/* This also tries to open distro debuginfo */ +struct debuginfo *debuginfo__new(const char *path); +void debuginfo__delete(struct debuginfo *dbg); + +int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, + bool adjust_offset); + +#else /* HAVE_DWARF_SUPPORT */ + +/* dummy debug information structure */ +struct debuginfo { +}; + +static inline struct debuginfo *debuginfo__new(const char *path __maybe_unused) +{ + return NULL; +} + +static inline void debuginfo__delete(struct debuginfo *dbg __maybe_unused) +{ +} + +static inline int debuginfo__get_text_offset(struct debuginfo *dbg __maybe_unused, + Dwarf_Addr *offs __maybe_unused, + bool adjust_offset __maybe_unused) +{ + return -EINVAL; +} + +#endif /* HAVE_DWARF_SUPPORT */ + +#ifdef HAVE_DEBUGINFOD_SUPPORT +int get_source_from_debuginfod(const char *raw_path, const char *sbuild_id, + char **new_path); +#else /* HAVE_DEBUGINFOD_SUPPORT */ +static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused, + const char *sbuild_id __maybe_unused, + char **new_path __maybe_unused) +{ + return -ENOTSUP; +} +#endif /* HAVE_DEBUGINFOD_SUPPORT */ + +#endif /* _PERF_DEBUGINFO_H */ diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index f171360b0ef4..8d3dd85f9ff4 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -23,6 +23,7 @@ #include "event.h" #include "dso.h" #include "debug.h" +#include "debuginfo.h" #include "intlist.h" #include "strbuf.h" #include "strlist.h" @@ -31,128 +32,9 @@ #include "probe-file.h" #include "string2.h" -#ifdef HAVE_DEBUGINFOD_SUPPORT -#include -#endif - /* Kprobe tracer basic type is up to u64 */ #define MAX_BASIC_TYPE_BITS 64 -/* Dwarf FL wrappers */ -static char *debuginfo_path; /* Currently dummy */ - -static const Dwfl_Callbacks offline_callbacks = { - .find_debuginfo = dwfl_standard_find_debuginfo, - .debuginfo_path = &debuginfo_path, - - .section_address = dwfl_offline_section_address, - - /* We use this table for core files too. */ - .find_elf = dwfl_build_id_find_elf, -}; - -/* Get a Dwarf from offline image */ -static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, - const char *path) -{ - GElf_Addr dummy; - int fd; - - fd = open(path, O_RDONLY); - if (fd < 0) - return fd; - - dbg->dwfl = dwfl_begin(&offline_callbacks); - if (!dbg->dwfl) - goto error; - - dwfl_report_begin(dbg->dwfl); - dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); - if (!dbg->mod) - goto error; - - dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); - if (!dbg->dbg) - goto error; - - dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy); - - dwfl_report_end(dbg->dwfl, NULL, NULL); - - return 0; -error: - if (dbg->dwfl) - dwfl_end(dbg->dwfl); - else - close(fd); - memset(dbg, 0, sizeof(*dbg)); - - return -ENOENT; -} - -static struct debuginfo *__debuginfo__new(const char *path) -{ - struct debuginfo *dbg = zalloc(sizeof(*dbg)); - if (!dbg) - return NULL; - - if (debuginfo__init_offline_dwarf(dbg, path) < 0) - zfree(&dbg); - if (dbg) - pr_debug("Open Debuginfo file: %s\n", path); - return dbg; -} - -enum dso_binary_type distro_dwarf_types[] = { - DSO_BINARY_TYPE__FEDORA_DEBUGINFO, - DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, - DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, - DSO_BINARY_TYPE__BUILDID_DEBUGINFO, - DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO, - DSO_BINARY_TYPE__NOT_FOUND, -}; - -struct debuginfo *debuginfo__new(const char *path) -{ - enum dso_binary_type *type; - char buf[PATH_MAX], nil = '\0'; - struct dso *dso; - struct debuginfo *dinfo = NULL; - struct build_id bid; - - /* Try to open distro debuginfo files */ - dso = dso__new(path); - if (!dso) - goto out; - - /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */ - if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0) - dso__set_build_id(dso, &bid); - - for (type = distro_dwarf_types; - !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; - type++) { - if (dso__read_binary_type_filename(dso, *type, &nil, - buf, PATH_MAX) < 0) - continue; - dinfo = __debuginfo__new(buf); - } - dso__put(dso); - -out: - /* if failed to open all distro debuginfo, open given binary */ - return dinfo ? : __debuginfo__new(path); -} - -void debuginfo__delete(struct debuginfo *dbg) -{ - if (dbg) { - if (dbg->dwfl) - dwfl_end(dbg->dwfl); - free(dbg); - } -} - /* * Probe finder related functions */ @@ -1677,44 +1559,6 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, return (ret < 0) ? ret : af.nvls; } -/* For the kernel module, we need a special code to get a DIE */ -int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, - bool adjust_offset) -{ - int n, i; - Elf32_Word shndx; - Elf_Scn *scn; - Elf *elf; - GElf_Shdr mem, *shdr; - const char *p; - - elf = dwfl_module_getelf(dbg->mod, &dbg->bias); - if (!elf) - return -EINVAL; - - /* Get the number of relocations */ - n = dwfl_module_relocations(dbg->mod); - if (n < 0) - return -ENOENT; - /* Search the relocation related .text section */ - for (i = 0; i < n; i++) { - p = dwfl_module_relocation_info(dbg->mod, i, &shndx); - if (strcmp(p, ".text") == 0) { - /* OK, get the section header */ - scn = elf_getscn(elf, shndx); - if (!scn) - return -ENOENT; - shdr = gelf_getshdr(scn, &mem); - if (!shdr) - return -ENOENT; - *offs = shdr->sh_addr; - if (adjust_offset) - *offs -= shdr->sh_offset; - } - } - return 0; -} - /* Reverse search */ int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, struct perf_probe_point *ppt) @@ -2009,41 +1853,6 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) return (ret < 0) ? ret : lf.found; } -#ifdef HAVE_DEBUGINFOD_SUPPORT -/* debuginfod doesn't require the comp_dir but buildid is required */ -static int get_source_from_debuginfod(const char *raw_path, - const char *sbuild_id, char **new_path) -{ - debuginfod_client *c = debuginfod_begin(); - const char *p = raw_path; - int fd; - - if (!c) - return -ENOMEM; - - fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id, - 0, p, new_path); - pr_debug("Search %s from debuginfod -> %d\n", p, fd); - if (fd >= 0) - close(fd); - debuginfod_end(c); - if (fd < 0) { - pr_debug("Failed to find %s in debuginfod (%s)\n", - raw_path, sbuild_id); - return -ENOENT; - } - pr_debug("Got a source %s\n", *new_path); - - return 0; -} -#else -static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused, - const char *sbuild_id __maybe_unused, - char **new_path __maybe_unused) -{ - return -ENOTSUP; -} -#endif /* * Find a src file from a DWARF tag path. Prepend optional source path prefix * and chop off leading directories that do not exist. Result is passed back as diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 8bc1c80d3c1c..3add5ff516e1 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -24,21 +24,7 @@ static inline int is_c_varname(const char *name) #ifdef HAVE_DWARF_SUPPORT #include "dwarf-aux.h" - -/* TODO: export debuginfo data structure even if no dwarf support */ - -/* debug information structure */ -struct debuginfo { - Dwarf *dbg; - Dwfl_Module *mod; - Dwfl *dwfl; - Dwarf_Addr bias; - const unsigned char *build_id; -}; - -/* This also tries to open distro debuginfo */ -struct debuginfo *debuginfo__new(const char *path); -void debuginfo__delete(struct debuginfo *dbg); +#include "debuginfo.h" /* Find probe_trace_events specified by perf_probe_event from debuginfo */ int debuginfo__find_trace_events(struct debuginfo *dbg, @@ -49,9 +35,6 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, struct perf_probe_point *ppt); -int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, - bool adjust_offset); - /* Find a line range */ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); From patchwork Thu Nov 9 23:59:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451872 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 300F93984B; Fri, 10 Nov 2023 00:00:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="CbLFzvPC" Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D2E4544BE; Thu, 9 Nov 2023 16:00:22 -0800 (PST) Received: by mail-pj1-x1030.google.com with SMTP id 98e67ed59e1d1-27ff7fe7fbcso1299554a91.1; Thu, 09 Nov 2023 16:00:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574422; x=1700179222; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=YFMOX8SX01fXKILUSbNGFFOegaedr50GlhEgN7HfJ3c=; b=CbLFzvPC358cS0wOpDSrPGATDH0xnqTgZD0dqsUDQcOfBytmiDL3raJOWTRUicod6X wHXzk4NuiM6GcCK0clPzu1SlkG9oBJC2uU2VyA2Av0SCs20VUpwRn0PsdxgfOmJcwhMX Hy4sGGo1FRdoS2hcbnfLAYNh7kOiVuV0dE1+2rWb/AirRrud7TtxZFJl/W9czdrSo+qU zfW/B1WQ2cNe7ykTb3SKrAx8GYadAMvQX4rbU9Ua+LBlTGsVj+RkVwdmAXhnW/2I4tbP H6GxQ+oFJOGr/i8FTkIhnhCgSGnbbBKNCnzPRtgQ8vSLwO3tEYHh0j+61Q620hlGxmut G11w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574422; x=1700179222; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=YFMOX8SX01fXKILUSbNGFFOegaedr50GlhEgN7HfJ3c=; b=f7iO/DpGZppY8pXBqHJ84jmT2CH1Eco5OznaId5G8jIogTIyN5kAFmmEXqtceDp8+z UmLV8/pYOZ4/QGwjdGM7tGI4MQMIMGYmBKorWDf5iomyGypxEkhG1NslQgs4lskPpnwq YiTb8LCUAkohWx8CHaKGyIS6WFDXQbZ+B93GeFA/XjufAiTIpzNQobFzWn9v1FW1Crkr eOye93utTxw5GIGbjZpoR/+3ZewG9h+tW9VIF2Vp37dJi5Dqao28phStJE18g42R+pWE 9xOMyJ34saxxlW6LQHLCe4B17RF566MjrPO599NAvFQNKQnh9adFn1Y0Iu96qWVgeH22 xc6A== X-Gm-Message-State: AOJu0YxVEsgW+mMGEhdmYkSoU86vnSsMK5KAEaGa26k6BlRhafUOUGPA K2u4vAdmlI5RbKUO5CIYRqA= X-Google-Smtp-Source: AGHT+IGSNjWc3MbyvDO+qDwwjc7N06wOn2WivEP4MkJBt3rpiL3aUf/iaPdEzzYU/Ta+kPiT01PkDQ== X-Received: by 2002:a17:90a:e7c7:b0:281:3fb:6df1 with SMTP id kb7-20020a17090ae7c700b0028103fb6df1mr3301226pjb.46.1699574422245; Thu, 09 Nov 2023 16:00:22 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:21 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 04/52] perf dwarf-aux: Fix die_get_typename() for void * Date: Thu, 9 Nov 2023 15:59:23 -0800 Message-ID: <20231110000012.3538610-5-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The die_get_typename() is to return a C-like type name from DWARF debug entry and it follows data type if the target entry is a pointer type. But I found void pointers don't have the type attribte to follow and then the function returns an error for that case. This results in a broken type string for void pointer types. For example, the following type entries are pointer types. <1><48c>: Abbrev Number: 4 (DW_TAG_pointer_type) <48d> DW_AT_byte_size : 8 <48d> DW_AT_type : <0x481> <1><491>: Abbrev Number: 211 (DW_TAG_pointer_type) <493> DW_AT_byte_size : 8 <1><494>: Abbrev Number: 4 (DW_TAG_pointer_type) <495> DW_AT_byte_size : 8 <495> DW_AT_type : <0x49e> The first one at offset 48c and the third one at offset 494 have type information. Then they are pointer types for the referenced types. But the second one at offset 491 doesn't have the type attribute. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 2941d88f2199..4849c3bbfd95 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1090,7 +1090,14 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) return strbuf_addf(buf, "%s%s", tmp, name ?: ""); } ret = die_get_typename(&type, buf); - return ret ? ret : strbuf_addstr(buf, tmp); + if (ret < 0) { + /* void pointer has no type attribute */ + if (tag == DW_TAG_pointer_type && ret == -ENOENT) + return strbuf_addf(buf, "void*"); + + return ret; + } + return strbuf_addstr(buf, tmp); } /** From patchwork Thu Nov 9 23:59:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451873 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40A6A39851; Fri, 10 Nov 2023 00:00:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AjF20uFK" Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C7E1B4689; Thu, 9 Nov 2023 16:00:24 -0800 (PST) Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-6bb4abb8100so1390619b3a.2; Thu, 09 Nov 2023 16:00:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574424; x=1700179224; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=gBFPY4pW04M2sgJecsy3kFli8IglhnnPsjX6xiP+Dlg=; b=AjF20uFKQi1cHWGqvw1DKTEmQ5rTmfFuJjUR2OWT2Y+2IYSFbXwkA2pWIbrknqOemL 1caI36D22RZr2TCDWojbPe61NtCz764bLpxXBNaD5TyQH5qPft66jbBXZgmXNBerdrn4 xX1AlHUeUygAfK9CLJdKNCOGfu9Ba1QWc1WmqF3+Si8XUBztGk9EQXdjsZFjYauRetea v5fGo+r6EUQtJPYZcHQN71ayLPwJd/K6N3EUaiWHo6koNzkyDVAUtmpVQJPnO4diD1/1 PAQ0yrATm2jGBMhm8g23ryWDrjWcmCSW6XbMhwLrYE7/UGq7B/LlWNKHJ6P6kegDKbft J8CA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574424; x=1700179224; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=gBFPY4pW04M2sgJecsy3kFli8IglhnnPsjX6xiP+Dlg=; b=IDxo4JQgeh4f56EzBWYKBVB2p0eMxc6VqfYRPhInmeXLhSBlYMWqPggtQLAqJ6Wbid dfBgb1bBiXK4I2prFsYP3wb2ptl8JzcOprHY1rJRynuAfb6oH9jqbwOht4mLyQjd0S9f MxrQooEPpbqm5+Z4mf/rjD/yCe0VEASvDSlJb94pMYvuzpPN1BeXBbRWHkVhQQPN3lgO qXdRm4fJN+BNfvXTGyLjJxq9rwakg/9lF4382fC1CJ/4CizXDhTeMCyIEVx5i8FzYiwq SV2Vf4kZio/CNnIirQLB+Os1Fy2J0UbDBrCCdyIdhAsRG1+7zBjlr6QBwytwBkBx+wFK L2SQ== X-Gm-Message-State: AOJu0Yylx352mBaN86SZq/h2M3jcgn7meIUdGQNiztNyH+xD/Euq31Jp rWYjKtPnK+TPK9HvntRaMvY= X-Google-Smtp-Source: AGHT+IGh5xp75WCSAqGUum6l9xwGOp3SEtjtW8b9M3Z96gpo14k1fTr8mUXAKHiQIx0W+urxCOggFw== X-Received: by 2002:a05:6a20:9143:b0:182:11b2:b982 with SMTP id x3-20020a056a20914300b0018211b2b982mr6536454pzc.27.1699574424018; Thu, 09 Nov 2023 16:00:24 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:23 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 05/52] perf dwarf-aux: Move #ifdef code to the header file Date: Thu, 9 Nov 2023 15:59:24 -0800 Message-ID: <20231110000012.3538610-6-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 It's a usual convention that the conditional code is handled in a header file. As I'm planning to add some more of them, let's move the current code to the header first. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 7 ------- tools/perf/util/dwarf-aux.h | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 4849c3bbfd95..adef2635587d 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1245,13 +1245,6 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) out: return ret; } -#else -int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, - Dwarf_Die *vr_die __maybe_unused, - struct strbuf *buf __maybe_unused) -{ - return -ENOTSUP; -} #endif /* diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index 7ec8bc1083bb..4f5d0211ee4f 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -121,7 +121,6 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf); /* Get the name and type of given variable DIE, stored as "type\tname" */ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf); -int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); /* Check if target program is compiled with optimization */ bool die_is_optimized_target(Dwarf_Die *cu_die); @@ -130,4 +129,20 @@ bool die_is_optimized_target(Dwarf_Die *cu_die); void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die, Dwarf_Addr *entrypc); -#endif +#ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT + +/* Get byte offset range of given variable DIE */ +int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); + +#else /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ + +static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, + Dwarf_Die *vr_die __maybe_unused, + struct strbuf *buf __maybe_unused) +{ + return -ENOTSUP; +} + +#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ + +#endif /* _DWARF_AUX_H */ From patchwork Thu Nov 9 23:59:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451874 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1FF139843; Fri, 10 Nov 2023 00:00:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jT9icGVX" Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2B3454693; Thu, 9 Nov 2023 16:00:26 -0800 (PST) Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1cc316ccc38so12752135ad.1; Thu, 09 Nov 2023 16:00:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574425; x=1700179225; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=MVwEgWJomgfw297GtG9OF7+0iUeurVYuT1rqsW67QX0=; b=jT9icGVXK2F8It0gtLH//nJbw5IUDqeNUg48nF4zmk4TUiezseWg0YqvDoUiU3kzH5 DS9mBRtr5UjY060aO2vV67E5Q2uK9EgsDsNOZXJrL7t3PMgumLAIkrbuPrsyfzfp2BS6 MNuCDfJumf/kQYfckP38Hjcs+ULxCu/7W7PMxnDkQjsZY/4/nPhH/finCj8OYcYB8acn kMC/wlkGiLXitMrNio18JutvMgKi3H70WWnYwuwnCebs9DfVTdN8pwQKTtnIWXqhOSv0 yzVDr8CtqJ9fPFttiSzOYs4eqSCrXLpVuSmXY000nU2JaKfMchHZB0/5AqoORJXx8ulD VhFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574425; x=1700179225; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=MVwEgWJomgfw297GtG9OF7+0iUeurVYuT1rqsW67QX0=; b=sls7f1vIkojZzMreQLOtlThQITd2cJQqZLlhxTMVpsYRs+6c6Az8JmvxMWrX8CB4DE HneLMgyA87emyYXjb3cjXHf+7hbFQZ12llV2aDUSWrT9dFJprtl8nd9EjclwuxgnEjKs jlHs0YXX9wG0dpHUXxsph9ZAa+jd46dLoHGJIAeIB4QIy5CjOElWY5RR4Jhzh/7AmDi9 bgb0Tui/rRq0Z3KyYuVcB2TkRNvHvXvXnxfF9vlRf+le4o8nZQbondkVmUDZbikLn/+i adXvaYNIyVYtvYS+q8lfepJgl6MGR1Ml5EAN/u7Ej1kFgxlAlF/gJlxWlflWMHTwpFs4 k2wA== X-Gm-Message-State: AOJu0YzAXopfdOhcdii+LCtV7FHG7pZqDFCRODwjmGOIT5IVikvGEdoL PEy2cdrif9FeZyG4D8euawRsh9CgsUk= X-Google-Smtp-Source: AGHT+IHa3NPlEkQxndKeHMB+SCA3CAVMa9ywBwXCn4vWfuYRoUSshom/VddDCJBuWbdJNlYkYYWC9g== X-Received: by 2002:a17:90b:4c47:b0:27d:4f1f:47f5 with SMTP id np7-20020a17090b4c4700b0027d4f1f47f5mr3352933pjb.23.1699574425414; Thu, 09 Nov 2023 16:00:25 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:24 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 06/52] perf dwarf-aux: Add die_get_scopes() helper Date: Thu, 9 Nov 2023 15:59:25 -0800 Message-ID: <20231110000012.3538610-7-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The die_get_scopes() would return the number of enclosing DIEs for the given address and it fills an array of DIEs like dwarf_getscopes(). But it doesn't follow the abstract origin of inlined functions as we want information of the concrete instance. This is needed to check the location of parameters and local variables properly. Users can check the origin separately if needed. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 53 +++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 3 +++ 2 files changed, 56 insertions(+) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index adef2635587d..10aa32334d6f 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1425,3 +1425,56 @@ void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die, *entrypc = postprologue_addr; } + +/* Internal parameters for __die_find_scope_cb() */ +struct find_scope_data { + /* Target instruction address */ + Dwarf_Addr pc; + /* Number of scopes found [output] */ + int nr; + /* Array of scopes found, 0 for the outermost one. [output] */ + Dwarf_Die *scopes; +}; + +static int __die_find_scope_cb(Dwarf_Die *die_mem, void *arg) +{ + struct find_scope_data *data = arg; + + if (dwarf_haspc(die_mem, data->pc)) { + Dwarf_Die *tmp; + + tmp = realloc(data->scopes, (data->nr + 1) * sizeof(*tmp)); + if (tmp == NULL) + return DIE_FIND_CB_END; + + memcpy(tmp + data->nr, die_mem, sizeof(*die_mem)); + data->scopes = tmp; + data->nr++; + return DIE_FIND_CB_CHILD; + } + return DIE_FIND_CB_SIBLING; +} + +/** + * die_get_scopes - Return a list of scopes including the address + * @cu_die: a compile unit DIE + * @pc: the address to find + * @scopes: the array of DIEs for scopes (result) + * + * This function does the same as the dwarf_getscopes() but doesn't follow + * the origins of inlined functions. It returns the number of scopes saved + * in the @scopes argument. The outer scope will be saved first (index 0) and + * the last one is the innermost scope at the @pc. + */ +int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes) +{ + struct find_scope_data data = { + .pc = pc, + }; + Dwarf_Die die_mem; + + die_find_child(cu_die, __die_find_scope_cb, &data, &die_mem); + + *scopes = data.scopes; + return data.nr; +} diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index 4f5d0211ee4f..f9d765f80fb0 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -129,6 +129,9 @@ bool die_is_optimized_target(Dwarf_Die *cu_die); void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die, Dwarf_Addr *entrypc); +/* Get the list of including scopes */ +int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes); + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT /* Get byte offset range of given variable DIE */ From patchwork Thu Nov 9 23:59:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451875 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E21E239849; Fri, 10 Nov 2023 00:00:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mBStWFfd" Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 860FB46A0; Thu, 9 Nov 2023 16:00:27 -0800 (PST) Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-5aa481d53e5so1188714a12.1; Thu, 09 Nov 2023 16:00:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574427; x=1700179227; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=UzNWsgJvVG83qkttBUZAr2wiEePWD6gXUY5o4BwenZA=; b=mBStWFfdtzHeDoEpJSikIejM6kx1p3v/0EnIKnUojEekQns4UA7+ZZevb5bbIKZ3uq ypofpOtLlV12mlP7lYZNC+VRu5BglnHEOiAV4jj4j3tSYNyBieP6vJ0iVC4OcI/uMlhU zD07gTRAzApk6Iap+/yrEgj5vwv1GPXDQffXJuWs/QMgh8eGQbX+CCFUYRuNec4NBScp koCNjWvy1jRkIYTZAzLaMOIlbRFsSLPtrnRHOVjFlvsHzcMeeJFWZKe/vSQy2g4zKAAE ObS4Dg2dFwMHz84drQ6XcOadQ4k1pCDBU7dSUtZn1IQ3GSvz6wCQGFAQ4tuUzT13Tepw aOQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574427; x=1700179227; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=UzNWsgJvVG83qkttBUZAr2wiEePWD6gXUY5o4BwenZA=; b=w6FA0TSfELayeMJSF0uajYujf6fXhSfyrheqYANVNkaVgMeA+9oxwwEjswAHl6hbez hsC4EeUKly0uO9DT1z6A3B843t56OGOpgUXuzwOSxrQ6OCzFSscKz/9QtF6BfYmN7lBz f92yUeYHtKmhV0TD1h+nwwat5RJiQtuYRrC2XOJoWdYN0RBnWf3wx7uZUZcrLtGJR8HI SN9AHKcGTSjJ49nEog08gnNKP5ZBRZ13ZvLA4rFm6rgX6ASe6mWVSHFxpNL5znWw2AJl hlnJgnoN1qeHPhG7EhRLFU/QSLtwEwML5KtMJkEqFddFTwo/GBoeNSjqLikGSdnkfMa/ lB6g== X-Gm-Message-State: AOJu0YzLcgIduxSZehmpVY8wpKzVAsW5+v8Up5OXLubOqtOY0oecmIYC HkQs94CHNS1PNS+fhAjaHaA= X-Google-Smtp-Source: AGHT+IH2aDlDHclMvlGvih/W2kJW293m1dOuZdnt+k6rsCs/9CfN1lwITe+WXWC7SyG4MIPXLfwjuw== X-Received: by 2002:a17:90b:3b83:b0:280:52a3:711e with SMTP id pc3-20020a17090b3b8300b0028052a3711emr3317822pjb.47.1699574426927; Thu, 09 Nov 2023 16:00:26 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:26 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 07/52] perf dwarf-aux: Add die_find_variable_by_reg() helper Date: Thu, 9 Nov 2023 15:59:26 -0800 Message-ID: <20231110000012.3538610-8-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The die_find_variable_by_reg() will search for a variable or a parameter sub-DIE in the given scope DIE where the location matches to the given register. For the simpliest and most common case, memory access usually happens with a base register and an offset to the field so the register would hold a pointer in a variable or function parameter. Then we can find one if it has a location expression at the (instruction) address. So this function only handles such a simple case for now. In this case, the expression would have a DW_OP_regN operation where N < 32. If the register index (N) is greater than or equal to 32, DW_OP_regx operation with an operand which saves the value for the N would be used. It would reject expressions with more operations. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 67 +++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 12 +++++++ 2 files changed, 79 insertions(+) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 10aa32334d6f..652e6e7368a2 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1245,6 +1245,73 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) out: return ret; } + +/* Interval parameters for __die_find_var_reg_cb() */ +struct find_var_data { + /* Target instruction address */ + Dwarf_Addr pc; + /* Target register */ + unsigned reg; +}; + +/* Max number of registers DW_OP_regN supports */ +#define DWARF_OP_DIRECT_REGS 32 + +/* Only checks direct child DIEs in the given scope. */ +static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) +{ + struct find_var_data *data = arg; + int tag = dwarf_tag(die_mem); + ptrdiff_t off = 0; + Dwarf_Attribute attr; + Dwarf_Addr base, start, end; + Dwarf_Op *ops; + size_t nops; + + if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter) + return DIE_FIND_CB_SIBLING; + + if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) + return DIE_FIND_CB_SIBLING; + + while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) { + /* Assuming the location list is sorted by address */ + if (end < data->pc) + continue; + if (start > data->pc) + break; + + /* Only match with a simple case */ + if (data->reg < DWARF_OP_DIRECT_REGS) { + if (ops->atom == (DW_OP_reg0 + data->reg) && nops == 1) + return DIE_FIND_CB_END; + } else { + if (ops->atom == DW_OP_regx && ops->number == data->reg && + nops == 1) + return DIE_FIND_CB_END; + } + } + return DIE_FIND_CB_SIBLING; +} + +/** + * die_find_variable_by_reg - Find a variable saved in a register + * @sc_die: a scope DIE + * @pc: the program address to find + * @reg: the register number to find + * @die_mem: a buffer to save the resulting DIE + * + * Find the variable DIE accessed by the given register. + */ +Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg, + Dwarf_Die *die_mem) +{ + struct find_var_data data = { + .pc = pc, + .reg = reg, + }; + return die_find_child(sc_die, __die_find_var_reg_cb, &data, die_mem); +} #endif /* diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index f9d765f80fb0..b6f430730bd1 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -137,6 +137,10 @@ int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes); /* Get byte offset range of given variable DIE */ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); +/* Find a variable saved in the 'reg' at given address */ +Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg, + Dwarf_Die *die_mem); + #else /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, @@ -146,6 +150,14 @@ static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, return -ENOTSUP; } +static inline Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die __maybe_unused, + Dwarf_Addr pc __maybe_unused, + int reg __maybe_unused, + Dwarf_Die *die_mem __maybe_unused) +{ + return NULL; +} + #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ #endif /* _DWARF_AUX_H */ From patchwork Thu Nov 9 23:59:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451876 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 636BB39843; Fri, 10 Nov 2023 00:00:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UCdg3e68" Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0FA1346AD; Thu, 9 Nov 2023 16:00:29 -0800 (PST) Received: by mail-pj1-x1033.google.com with SMTP id 98e67ed59e1d1-2809fb0027cso1296222a91.2; Thu, 09 Nov 2023 16:00:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574428; x=1700179228; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=S9f6IvIGwymLkdOL1VpLPLvQfPskawajHqhT5uorupU=; b=UCdg3e68NYEq57mahG9/zkSU9YMBeP7Fcu0gDadBbRx5BmblawvIJvbMJBhGF1BVay 6RBPvTPYdQDb1uKDQ4SVuAzO+Y7Uyew2MFhhNNQ9OKfe5pvlB4zliIhSgNVq8rR+ZXAB 6/q7X3IPYbmac4H96Oz+gcuhzYopqDr7CjcyrfCzFMzXP79Fs8PFQwZDdUAeMrpKuu/O 4Tt+uJPzkhkYV/A+kTaNk+1ABR93SAypDNIVsgPL4jiLmCt24PvzjAU/8CH8OmWPW1c1 f8IdxaFTffyuWkrdsZEh6TprrjWlYKpeDUSAV3wbi3Uis4/vg3uf7is/CHiYH5ceZvxD 9asw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574428; x=1700179228; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=S9f6IvIGwymLkdOL1VpLPLvQfPskawajHqhT5uorupU=; b=vesNb6W5MHdj91ovOuLx4mXO1Shx9mNjF4PHl+YoBdurvJMU5DBn1P4A6j6Zm+twX/ TJTo6r04h7cYbJ4+1lpP/4WkKMspzZfRbxXwx8VI58GXlLNNw62tLr2h/aYD32zjnlM3 LYAYeZToYw5Hcsqp8QbGIlg3BEpoiipNNsAWvgeqaQP2NvBz2kVpjuxk3kNIFNXR5XSp d7ndYrhqp4Um3bfMhZoZlNgu1fVo/3TkjjccX/qR95S6RDT24Ju9F6ziwhB3BbZd5EO+ OEVuRhftIlyJ/Ken4u1dzvIwfk+wxpxq2HsvS+UCkwhZfCORiTEnUCKUR8wjim8uwJl8 9/Hw== X-Gm-Message-State: AOJu0Yz3KcSRvtZh6TNC7HTNwHr0MGG/nlDbJ/5io+uaYIn97YsI7XeQ EvDk6P3axYMaJi1GQ8qgrmo= X-Google-Smtp-Source: AGHT+IF1NAQhLh0Co6ml9PpkL9EAkduXrR3OwA0e3PBB9zj5VsdjZpAJI29AnNpmoYHl2M2vtwtUaA== X-Received: by 2002:a17:90b:4f88:b0:27d:75f2:a3ee with SMTP id qe8-20020a17090b4f8800b0027d75f2a3eemr3118306pjb.10.1699574428251; Thu, 09 Nov 2023 16:00:28 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:27 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 08/52] perf build: Add feature check for dwarf_getcfi() Date: Thu, 9 Nov 2023 15:59:27 -0800 Message-ID: <20231110000012.3538610-9-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The dwarf_getcfi() is available on libdw 0.142+. Instead of just checking the version number, it'd be nice to have a config item to check the feature at build time. Suggested-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim Acked-by: Masami Hiramatsu (Google) --- tools/build/Makefile.feature | 1 + tools/build/feature/Makefile | 4 ++++ tools/build/feature/test-dwarf_getcfi.c | 9 +++++++++ 3 files changed, 14 insertions(+) create mode 100644 tools/build/feature/test-dwarf_getcfi.c diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 934e2777a2db..64df118376df 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -32,6 +32,7 @@ FEATURE_TESTS_BASIC := \ backtrace \ dwarf \ dwarf_getlocations \ + dwarf_getcfi \ eventfd \ fortify-source \ get_current_dir_name \ diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index dad79ede4e0a..37722e509eb9 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -7,6 +7,7 @@ FILES= \ test-bionic.bin \ test-dwarf.bin \ test-dwarf_getlocations.bin \ + test-dwarf_getcfi.bin \ test-eventfd.bin \ test-fortify-source.bin \ test-get_current_dir_name.bin \ @@ -154,6 +155,9 @@ endif $(OUTPUT)test-dwarf_getlocations.bin: $(BUILD) $(DWARFLIBS) +$(OUTPUT)test-dwarf_getcfi.bin: + $(BUILD) $(DWARFLIBS) + $(OUTPUT)test-libelf-getphdrnum.bin: $(BUILD) -lelf diff --git a/tools/build/feature/test-dwarf_getcfi.c b/tools/build/feature/test-dwarf_getcfi.c new file mode 100644 index 000000000000..50e7d7cb7bdf --- /dev/null +++ b/tools/build/feature/test-dwarf_getcfi.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +int main(void) +{ + Dwarf *dwarf = NULL; + return dwarf_getcfi(dwarf) == NULL; +} From patchwork Thu Nov 9 23:59:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451877 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CBF3039851; Fri, 10 Nov 2023 00:00:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fc+0U4Gy" Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E23246B2; Thu, 9 Nov 2023 16:00:30 -0800 (PST) Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-28023eadc70so1291767a91.2; Thu, 09 Nov 2023 16:00:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574430; x=1700179230; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=+X4K8d8Dew6reLn4C0dstRYrhu2d/Re9BWl7Yzp4hOo=; b=fc+0U4Gy18sRK/DkuJub7OLhE5u9XNZ9Y+wievEjZg8ShRmRC50Rpw3/o0YO/SuLK8 WHm4i7vw2FEkCQDnDx3LxTdnp4yS10p2GuFycCK8kwMKJcpdrNXqKsbvOaGfORLjwrN7 uU4JNfPpuKTeP+5fy6Mo/p9n8JA2zC8e2OAN6ERwl4+Ij7B3vWNGOC0XrbJVqNYntrDp bY0hRK2aJBi2wRSNkN0ixByHQgq3UvZ48uuzyglHZ/CMOWYDbzJbSYG59wSMkMqo4Eqr Z35a/FTmuvcMejv5w1FCJrD+4qNBAAYve7keLNNTstJZ4dp8x4PvQAssJAweIheY/1So qF9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574430; x=1700179230; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+X4K8d8Dew6reLn4C0dstRYrhu2d/Re9BWl7Yzp4hOo=; b=Xb55HhLdCEexIoXSXF7phdpjvy9tfXkxrJybItYVH8ULWrNGiRYiNq0kUfFav04aPv awLVRZqKLgZFCsLyJ0MUoL4H32Vq7tJ8FKKBL4lLzsg2DiMTL2/ebqtJk32umwY91+dd pCMU/xAK0Xni4SO/vyKxholVUBA71OptPXsvJNOoB25kJfxMObptc0kIjWSP3XVj3kdp 3db2seZ+944CT+VNMEtWc+FzhVzTQuufL6DYU/2v28tjljVMRTikRvPh2ZqcFHVNzkz9 1gqlO8jx1SMnijeVstPgkWqrJAnqP84VfY4sbsQUCP+VVIdx841rv1xOrW9zbtO9C8BI vAZA== X-Gm-Message-State: AOJu0YyjBzOFKoOIEGN2e3H8GwEBW3FkynBZ4L+8ESGF0YOaY80Zfjz+ BUEN26SGd9m3JbrThGsIFVc= X-Google-Smtp-Source: AGHT+IFuj0VFdBbVA2ARzozLQpDa3u3jgJF4Egr2pmAoU4tq/yDacLFFrbHVbVYvgHfRIEfm9YXbaA== X-Received: by 2002:a17:90b:33c3:b0:27d:839:52ae with SMTP id lk3-20020a17090b33c300b0027d083952aemr3235984pjb.32.1699574429713; Thu, 09 Nov 2023 16:00:29 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:29 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 09/52] perf probe: Convert to check dwarf_getcfi feature Date: Thu, 9 Nov 2023 15:59:28 -0800 Message-ID: <20231110000012.3538610-10-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Now it has a feature check for the dwarf_getcfi(), use it and convert the code to check HAVE_DWARF_CFI_SUPPORT definition. Suggested-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim Acked-by: Masami Hiramatsu (Google) --- tools/perf/Makefile.config | 5 +++++ tools/perf/util/probe-finder.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 8b6cffbc4858..aa55850fbc21 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -476,6 +476,11 @@ else else CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT endif # dwarf_getlocations + ifneq ($(feature-dwarf_getcfi), 1) + msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.142); + else + CFLAGS += -DHAVE_DWARF_CFI_SUPPORT + endif # dwarf_getcfi endif # Dwarf support endif # libelf support endif # NO_LIBELF diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 8d3dd85f9ff4..c8923375e30d 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -604,7 +604,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); if (ret <= 0 || nops == 0) { pf->fb_ops = NULL; -#if _ELFUTILS_PREREQ(0, 142) +#ifdef HAVE_DWARF_CFI_SUPPORT } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) { if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 && @@ -615,7 +615,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) free(frame); return -ENOENT; } -#endif +#endif /* HAVE_DWARF_CFI_SUPPORT */ } /* Call finder's callback handler */ @@ -1140,7 +1140,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg, pf->machine = ehdr.e_machine; -#if _ELFUTILS_PREREQ(0, 142) +#ifdef HAVE_DWARF_CFI_SUPPORT do { GElf_Shdr shdr; @@ -1150,7 +1150,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg, pf->cfi_dbg = dwarf_getcfi(dbg->dbg); } while (0); -#endif +#endif /* HAVE_DWARF_CFI_SUPPORT */ ret = debuginfo__find_probe_location(dbg, pf); return ret; From patchwork Thu Nov 9 23:59:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451878 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2309139843; Fri, 10 Nov 2023 00:00:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dLSYgAne" Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B9427478B; Thu, 9 Nov 2023 16:00:31 -0800 (PST) Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-2800c221af2so1336728a91.0; Thu, 09 Nov 2023 16:00:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574431; x=1700179231; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=vPHuNFbXr+S2SlRfwyzwCgcZDXra7FMzxpczsBE4C70=; b=dLSYgAnec/6gwcZcg2fylFEiVFJVb3f4CLu69amQk/OsmAM8+V2oJu+gWwTWbZ9/eh heAGc9pr1KEU/YGX6H8BVSiAjxWMQhVLYZLstR1uSNv9JHkhbvfUfVFOZOeWLfoX3c58 +RueHVXZ+X4BnqlYRkSyiLXKZ53SN5Hgya0tByVgoqajBMWKoRZmG+wEL/ADA5zY4H1B HkObPu2WNyd7ayajfpSXljR8Y1v6Y8OqLiCIstpPisjxaX4oQJMh6l+8fm1oQ+nKFvyT c2/wbeLSIyauh6aYCbc8sswySJOBaIVVTdzwTx/ynkwMJBhpj6A+WEVHU6OzfXwoaTQb MIoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574431; x=1700179231; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=vPHuNFbXr+S2SlRfwyzwCgcZDXra7FMzxpczsBE4C70=; b=DIsJSrBc286raVIU/cJdcM6CRcYoT7WsJhLH6TCtHPIVWkPt4mdzZRTjebMELvgpt4 dzGeUsRhXx3A8XOoh0eiW7RfD5PGNUHY2WNuuOHk3rFLLFm7FCBi8bV9D/WnnKs9hDDu g2h4Er04P7NgR9Sjj5O8GOoqCvFq3Adu7D9y5uHHFP+guEsPtKT5dtkfEvHdmtnzo9oU sXNEbAXlOOzZvbiMYkDSIkZENaOXvOTvie42oHDk5q2JUCsgeTvXRdPsneC9JpyJeHGt yIYmA/I+/7ND0cjsA/Y74OXJysBKqfOkfzjVdXtQKKCjWi+b4ypVowVX75m5wcK/V99r mC1A== X-Gm-Message-State: AOJu0YxEv+9pgM2kZ82yABMW4yTNse1bTguINCni04tqCbDgiMS82WvL Wb8qDooj4hrLrEdnTLovDc0= X-Google-Smtp-Source: AGHT+IEHCy9hCDuslZKjaVVpbYLJc/ESmSsfVCGnOyGHAZwSRi8tOQcyBoJiJiRNBshvVPo7RpnEYw== X-Received: by 2002:a17:90b:3908:b0:281:12b4:21c2 with SMTP id ob8-20020a17090b390800b0028112b421c2mr3344854pjb.26.1699574431018; Thu, 09 Nov 2023 16:00:31 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:30 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 10/52] perf dwarf-aux: Factor out die_get_typename_from_type() Date: Thu, 9 Nov 2023 15:59:29 -0800 Message-ID: <20231110000012.3538610-11-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The die_get_typename_from_type() is to get the name of the given DIE in C-style type name. The difference from the die_get_typename() is that it does not retrieve the DW_AT_type and use the given DIE directly. This will be used when users know the type DIE already. Cc: Masami Hiramatsu Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 38 ++++++++++++++++++++++++++----------- tools/perf/util/dwarf-aux.h | 3 +++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 652e6e7368a2..4bdcd3dea28f 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1051,32 +1051,28 @@ Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, } /** - * die_get_typename - Get the name of given variable DIE - * @vr_die: a variable DIE + * die_get_typename_from_type - Get the name of given type DIE + * @type_die: a type DIE * @buf: a strbuf for result type name * - * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded. + * Get the name of @type_die and stores it to @buf. Return 0 if succeeded. * and Return -ENOENT if failed to find type name. * Note that the result will stores typedef name if possible, and stores * "*(function_type)" if the type is a function pointer. */ -int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) +int die_get_typename_from_type(Dwarf_Die *type_die, struct strbuf *buf) { - Dwarf_Die type; int tag, ret; const char *tmp = ""; - if (__die_get_real_type(vr_die, &type) == NULL) - return -ENOENT; - - tag = dwarf_tag(&type); + tag = dwarf_tag(type_die); if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type) tmp = "*"; else if (tag == DW_TAG_subroutine_type) { /* Function pointer */ return strbuf_add(buf, "(function_type)", 15); } else { - const char *name = dwarf_diename(&type); + const char *name = dwarf_diename(type_die); if (tag == DW_TAG_union_type) tmp = "union "; @@ -1089,7 +1085,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) /* Write a base name */ return strbuf_addf(buf, "%s%s", tmp, name ?: ""); } - ret = die_get_typename(&type, buf); + ret = die_get_typename(type_die, buf); if (ret < 0) { /* void pointer has no type attribute */ if (tag == DW_TAG_pointer_type && ret == -ENOENT) @@ -1100,6 +1096,26 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) return strbuf_addstr(buf, tmp); } +/** + * die_get_typename - Get the name of given variable DIE + * @vr_die: a variable DIE + * @buf: a strbuf for result type name + * + * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded. + * and Return -ENOENT if failed to find type name. + * Note that the result will stores typedef name if possible, and stores + * "*(function_type)" if the type is a function pointer. + */ +int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) +{ + Dwarf_Die type; + + if (__die_get_real_type(vr_die, &type) == NULL) + return -ENOENT; + + return die_get_typename_from_type(&type, buf); +} + /** * die_get_varname - Get the name and type of given variable DIE * @vr_die: a variable DIE diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index b6f430730bd1..f9763d3b7572 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -116,6 +116,9 @@ Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name, Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, Dwarf_Die *die_mem); +/* Get the name of given type DIE */ +int die_get_typename_from_type(Dwarf_Die *type_die, struct strbuf *buf); + /* Get the name of given variable DIE */ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf); From patchwork Thu Nov 9 23:59:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451879 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9FBEE39851; Fri, 10 Nov 2023 00:00:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nCXC+dv8" Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03CC2479A; Thu, 9 Nov 2023 16:00:32 -0800 (PST) Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-2802e5ae23bso1362833a91.2; Thu, 09 Nov 2023 16:00:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574432; x=1700179232; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=JsFJzlGzUeWGTriQqSvj7eYER8wcSmZ2Yq/gVw4ZyQA=; b=nCXC+dv8dUNB9LBnBeq8kVF9FgkAbVha+Qg+rqDaEgNdQOny9wcoACAntOSWxJUmJI YMYOPzBIoP46dLZhdOexDXocR9TmnBcE1YhqT6kh6OpVPDdB2VBMAcDl+RD6vQFRi4rZ w19pxt0ktM4/lwXVVjClJxFCkSJNxjl/vIaWRcR6jXGg4OH7GU3wmJ7e5jiZv7Jf8Fj0 H4uWlLVQNMCfZhO1do7df3fLQCfS8oX91lbZRTRYCrswMwkl4wHprn8tBdSo16iavOP7 wprLXtBWJRCuVP4EVdlepmVIozqe7kW4r2+VqUzdENjgJbEkGXx/SELkobJXl0cuX/HB 3+Hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574432; x=1700179232; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=JsFJzlGzUeWGTriQqSvj7eYER8wcSmZ2Yq/gVw4ZyQA=; b=DFYao75r2FGK60kT3aAq9kEK4JneoKUmJ/UR79hF1JaB5CzHAS1UgOE8RfuyliDzXO slcYb7BTJcMf0z1RcZ3mfmqN3BxBZxKaGypx5mYCBbqygbjDmp+Xkegg5pHjNdp/vai2 BscsXQvIMZK+qmhYoyQA6M1TM2+EByHuMoQy7gpZSHFN+EkwY/0yk0CXIxx1C8L2UoEU wXP25ii5CZMlOCpTzQ9qbam8loUKQn+PytClPfu8gGlKm6GqFFRcbBRURUx4udFNDfmy 11yV4+Y0TzXw+AsEBWgsTNDEsct1G5ZT0EZW4THQ81mIAiVUd1wvbCE9bqg69eCjetho ZlXg== X-Gm-Message-State: AOJu0YwnYFkfigwJuth6lNR3SdmqxmxcIEjVF6XtOjT78ojY6PurhugU 9EnspjLfD02LLOGy9bmtfRc= X-Google-Smtp-Source: AGHT+IFirRse62PG8X2PJJ1HHbgaFZizcHsEsgMZ5W8b42eEn1+qWYNVjSPs2XtCCV39UNCtWrdQDg== X-Received: by 2002:a17:90b:4c10:b0:280:c0:9d3f with SMTP id na16-20020a17090b4c1000b0028000c09d3fmr3410142pjb.34.1699574432339; Thu, 09 Nov 2023 16:00:32 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:32 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 11/52] perf dwarf-regs: Add get_dwarf_regnum() Date: Thu, 9 Nov 2023 15:59:30 -0800 Message-ID: <20231110000012.3538610-12-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The get_dwarf_regnum() returns a DWARF register number from a register name string according to the psABI. Also add two pseudo encodings of DWARF_REG_PC which is a register that are used by PC-relative addressing and DWARF_REG_FB which is a frame base register. They need to be handled in a special way. Cc: Masami Hiramatsu Signed-off-by: Namhyung Kim --- tools/perf/arch/x86/util/dwarf-regs.c | 38 +++++++++++++++++++++++++++ tools/perf/util/dwarf-regs.c | 34 ++++++++++++++++++++++++ tools/perf/util/include/dwarf-regs.h | 19 ++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c index 530934805710..399c4a0a29d8 100644 --- a/tools/perf/arch/x86/util/dwarf-regs.c +++ b/tools/perf/arch/x86/util/dwarf-regs.c @@ -113,3 +113,41 @@ int regs_query_register_offset(const char *name) return roff->offset; return -EINVAL; } + +struct dwarf_regs_idx { + const char *name; + int idx; +}; + +static const struct dwarf_regs_idx x86_regidx_table[] = { + { "rax", 0 }, { "eax", 0 }, { "ax", 0 }, { "al", 0 }, + { "rdx", 1 }, { "edx", 1 }, { "dx", 1 }, { "dl", 1 }, + { "rcx", 2 }, { "ecx", 2 }, { "cx", 2 }, { "cl", 2 }, + { "rbx", 3 }, { "edx", 3 }, { "bx", 3 }, { "bl", 3 }, + { "rsi", 4 }, { "esi", 4 }, { "si", 4 }, { "sil", 4 }, + { "rdi", 5 }, { "edi", 5 }, { "di", 5 }, { "dil", 5 }, + { "rbp", 6 }, { "ebp", 6 }, { "bp", 6 }, { "bpl", 6 }, + { "rsp", 7 }, { "esp", 7 }, { "sp", 7 }, { "spl", 7 }, + { "r8", 8 }, { "r8d", 8 }, { "r8w", 8 }, { "r8b", 8 }, + { "r9", 9 }, { "r9d", 9 }, { "r9w", 9 }, { "r9b", 9 }, + { "r10", 10 }, { "r10d", 10 }, { "r10w", 10 }, { "r10b", 10 }, + { "r11", 11 }, { "r11d", 11 }, { "r11w", 11 }, { "r11b", 11 }, + { "r12", 12 }, { "r12d", 12 }, { "r12w", 12 }, { "r12b", 12 }, + { "r13", 13 }, { "r13d", 13 }, { "r13w", 13 }, { "r13b", 13 }, + { "r14", 14 }, { "r14d", 14 }, { "r14w", 14 }, { "r14b", 14 }, + { "r15", 15 }, { "r15d", 15 }, { "r15w", 15 }, { "r15b", 15 }, + { "rip", DWARF_REG_PC }, +}; + +int get_arch_regnum(const char *name) +{ + unsigned int i; + + if (*name != '%') + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(x86_regidx_table); i++) + if (!strcmp(x86_regidx_table[i].name, name + 1)) + return x86_regidx_table[i].idx; + return -ENOENT; +} diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c index 69cfaa5953bf..5b7f86c0063f 100644 --- a/tools/perf/util/dwarf-regs.c +++ b/tools/perf/util/dwarf-regs.c @@ -5,9 +5,12 @@ * Written by: Masami Hiramatsu */ +#include +#include #include #include #include +#include #include #ifndef EM_AARCH64 @@ -68,3 +71,34 @@ const char *get_dwarf_regstr(unsigned int n, unsigned int machine) } return NULL; } + +__weak int get_arch_regnum(const char *name __maybe_unused) +{ + return -ENOTSUP; +} + +/* Return DWARF register number from architecture register name */ +int get_dwarf_regnum(const char *name, unsigned int machine) +{ + char *regname = strdup(name); + int reg = -1; + char *p; + + if (regname == NULL) + return -EINVAL; + + /* For convenience, remove trailing characters */ + p = strpbrk(regname, " ,)"); + if (p) + *p = '\0'; + + switch (machine) { + case EM_NONE: /* Generic arch - use host arch */ + reg = get_arch_regnum(regname); + break; + default: + pr_err("ELF MACHINE %x is not supported.\n", machine); + } + free(regname); + return reg; +} diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h index 7d99a084e82d..01fb25a1150a 100644 --- a/tools/perf/util/include/dwarf-regs.h +++ b/tools/perf/util/include/dwarf-regs.h @@ -2,6 +2,9 @@ #ifndef _PERF_DWARF_REGS_H_ #define _PERF_DWARF_REGS_H_ +#define DWARF_REG_PC 0xd3af9c /* random number */ +#define DWARF_REG_FB 0xd3affb /* random number */ + #ifdef HAVE_DWARF_SUPPORT const char *get_arch_regstr(unsigned int n); /* @@ -10,6 +13,22 @@ const char *get_arch_regstr(unsigned int n); * machine: ELF machine signature (EM_*) */ const char *get_dwarf_regstr(unsigned int n, unsigned int machine); + +int get_arch_regnum(const char *name); +/* + * get_dwarf_regnum - Returns DWARF regnum from register name + * name: architecture register name + * machine: ELF machine signature (EM_*) + */ +int get_dwarf_regnum(const char *name, unsigned int machine); + +#else /* HAVE_DWARF_SUPPORT */ + +static inline int get_dwarf_regnum(const char *name __maybe_unused, + unsigned int machine __maybe_unused) +{ + return -1; +} #endif #ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET From patchwork Thu Nov 9 23:59:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451880 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2F1B39843; Fri, 10 Nov 2023 00:00:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mku3WDu9" Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7331F47AB; Thu, 9 Nov 2023 16:00:34 -0800 (PST) Received: by mail-pj1-x1031.google.com with SMTP id 98e67ed59e1d1-2801d7f46f9so1287108a91.3; Thu, 09 Nov 2023 16:00:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574434; x=1700179234; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=sHXzUGxx4mCEF+9mvo8Xi+4AaAQfbNuc3owYmpUKBQk=; b=mku3WDu9vlFXHxwV1ztxciomeaHBHgZxQc8vA8e00PRTQSj2QxsDNCm+eeNEVpXGCn YvN39QT4hV6ZAB6PiNvK8Ia/UxY7u4KFJse1+0IFQjV0CLQAatrQeMlBrkI1/Pg/rIb/ ZtJmc7E8GfK7PjpoXN4hBhb/CGcLA8LV6PLEeLBtnV8o5j4HCF7TpIkDH/4UPocRr7eU WeXeaVWVegny0UYklXuIe4ky+zKAomPw0k3MrcGSZVoeYzumW688G74lQuTO5vOhJsEZ rDSHPhs2Vo2d2j3P94INDAFex/XDEnQcEEhKzvnfvSrcQd+WQ4kFXFkvwszsk0W16ks+ e8ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574434; x=1700179234; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=sHXzUGxx4mCEF+9mvo8Xi+4AaAQfbNuc3owYmpUKBQk=; b=QoIWSaRJJWwmKMhk88AlQvb7+ync9yrdgUKvan93BkexRy20zolZF3f58sFwqwoH0f 8WABd9lEibpJezLnynT9mn8bCyPuwmqUddNzJZIQVxIIwaz+XKF6eS/d1ezDQx5X0nCp mt2uxtWIt/B0VviKZzP8gUTFHaoHT52/it2XSZOHCrf62HZeXjhzZE06cqJtuBLTtcp6 6T+bqKPLAI9f+dfhSmxm6njyLdjUGiHDwI4TiTtqyqgrLyGuYtQlR6Unm5rBlrGBdAkK R7SVHYMLH6TrMUgwcKrWSkXJSwwEvSO4cuJQ8dbIbvVZqea3g008kd8SDB4m31E50LYv aj+Q== X-Gm-Message-State: AOJu0YyivUpDvHQdmTyzNL6E6fsDKKVCmwPKbsyrjaB3e4YjzptTTwqN Xg4bs9pmkWqUseW/hP2ON20= X-Google-Smtp-Source: AGHT+IHZMumz2bIcIndJTegPtVEfNK8r94bkNhISmA7Ny4g7zgzkQ5qn6SJ/4kwnkvsvZ/2AEHJu0w== X-Received: by 2002:a17:90b:4a05:b0:27c:fafd:f785 with SMTP id kk5-20020a17090b4a0500b0027cfafdf785mr3220907pjb.47.1699574433737; Thu, 09 Nov 2023 16:00:33 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:33 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 12/52] perf annotate-data: Add find_data_type() Date: Thu, 9 Nov 2023 15:59:31 -0800 Message-ID: <20231110000012.3538610-13-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The find_data_type() is to get a data type from the memory access at the given address (IP) using a register and an offset. It requires DWARF debug info in the DSO and searches the list of variables and function parameters in the scope. In a pseudo code, it does basically the following: find_data_type(dso, ip, reg, offset) { pc = map__rip_2objdump(ip); CU = dwarf_addrdie(dso->dwarf, pc); scopes = die_get_scopes(CU, pc); for_each_scope(S, scopes) { V = die_find_variable_by_reg(S, pc, reg); if (V && V.type == pointer_type) { T = die_get_real_type(V); if (offset < T.size) return T; } } return NULL; } Signed-off-by: Namhyung Kim --- tools/perf/util/Build | 1 + tools/perf/util/annotate-data.c | 163 ++++++++++++++++++++++++++++++++ tools/perf/util/annotate-data.h | 40 ++++++++ 3 files changed, 204 insertions(+) create mode 100644 tools/perf/util/annotate-data.c create mode 100644 tools/perf/util/annotate-data.h diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 73e3f194f949..5cf000302080 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -196,6 +196,7 @@ perf-$(CONFIG_DWARF) += probe-finder.o perf-$(CONFIG_DWARF) += dwarf-aux.o perf-$(CONFIG_DWARF) += dwarf-regs.o perf-$(CONFIG_DWARF) += debuginfo.o +perf-$(CONFIG_DWARF) += annotate-data.o perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c new file mode 100644 index 000000000000..98c42dff2645 --- /dev/null +++ b/tools/perf/util/annotate-data.c @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Convert sample address to data type using DWARF debug info. + * + * Written by Namhyung Kim + */ + +#include +#include + +#include "annotate-data.h" +#include "debuginfo.h" +#include "debug.h" +#include "dso.h" +#include "map.h" +#include "map_symbol.h" +#include "strbuf.h" +#include "symbol.h" + +static bool find_cu_die(struct debuginfo *di, u64 pc, Dwarf_Die *cu_die) +{ + Dwarf_Off off, next_off; + size_t header_size; + + if (dwarf_addrdie(di->dbg, pc, cu_die) != NULL) + return cu_die; + + /* + * There are some kernels don't have full aranges and contain only a few + * aranges entries. Fallback to iterate all CU entries in .debug_info + * in case it's missing. + */ + off = 0; + while (dwarf_nextcu(di->dbg, off, &next_off, &header_size, + NULL, NULL, NULL) == 0) { + if (dwarf_offdie(di->dbg, off + header_size, cu_die) && + dwarf_haspc(cu_die, pc)) + return true; + + off = next_off; + } + return false; +} + +/* The type info will be saved in @type_die */ +static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) +{ + Dwarf_Word size; + + /* Get the type of the variable */ + if (die_get_real_type(var_die, type_die) == NULL) { + pr_debug("variable has no type\n"); + return -1; + } + + /* + * It expects a pointer type for a memory access. + * Convert to a real type it points to. + */ + if (dwarf_tag(type_die) != DW_TAG_pointer_type || + die_get_real_type(type_die, type_die) == NULL) { + pr_debug("no pointer or no type\n"); + return -1; + } + + /* Get the size of the actual type */ + if (dwarf_aggregate_size(type_die, &size) < 0) { + pr_debug("type size is unknown\n"); + return -1; + } + + /* Minimal sanity check */ + if ((unsigned)offset >= size) { + pr_debug("offset: %d is bigger than size: %lu\n", offset, size); + return -1; + } + + return 0; +} + +/* The result will be saved in @type_die */ +static int find_data_type_die(struct debuginfo *di, u64 pc, + int reg, int offset, Dwarf_Die *type_die) +{ + Dwarf_Die cu_die, var_die; + Dwarf_Die *scopes = NULL; + int ret = -1; + int i, nr_scopes; + + /* Get a compile_unit for this address */ + if (!find_cu_die(di, pc, &cu_die)) { + pr_debug("cannot find CU for address %lx\n", pc); + return -1; + } + + /* Get a list of nested scopes - i.e. (inlined) functions and blocks. */ + nr_scopes = die_get_scopes(&cu_die, pc, &scopes); + + /* Search from the inner-most scope to the outer */ + for (i = nr_scopes - 1; i >= 0; i--) { + /* Look up variables/parameters in this scope */ + if (!die_find_variable_by_reg(&scopes[i], pc, reg, &var_die)) + continue; + + /* Found a variable, see if it's correct */ + ret = check_variable(&var_die, type_die, offset); + break; + } + + free(scopes); + return ret; +} + +/** + * find_data_type - Return a data type at the location + * @ms: map and symbol at the location + * @ip: instruction address of the memory access + * @reg: register that holds the base address + * @offset: offset from the base address + * + * This functions searches the debug information of the binary to get the data + * type it accesses. The exact location is expressed by (ip, reg, offset). + * It return %NULL if not found. + */ +struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, + int reg, int offset) +{ + struct annotated_data_type *result = NULL; + struct dso *dso = ms->map->dso; + struct debuginfo *di; + Dwarf_Die type_die; + struct strbuf sb; + u64 pc; + + di = debuginfo__new(dso->long_name); + if (di == NULL) { + pr_debug("cannot get the debug info\n"); + return NULL; + } + + /* + * IP is a relative instruction address from the start of the map, as + * it can be randomized/relocated, it needs to translate to PC which is + * a file address for DWARF processing. + */ + pc = map__rip_2objdump(ms->map, ip); + if (find_data_type_die(di, pc, reg, offset, &type_die) < 0) + goto out; + + result = zalloc(sizeof(*result)); + if (result == NULL) + goto out; + + strbuf_init(&sb, 32); + if (die_get_typename_from_type(&type_die, &sb) < 0) + strbuf_add(&sb, "(unknown type)", 14); + + result->type_name = strbuf_detach(&sb, NULL); + +out: + debuginfo__delete(di); + return result; +} diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h new file mode 100644 index 000000000000..633147f78ca5 --- /dev/null +++ b/tools/perf/util/annotate-data.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _PERF_ANNOTATE_DATA_H +#define _PERF_ANNOTATE_DATA_H + +#include +#include +#include + +struct map_symbol; + +/** + * struct annotated_data_type - Data type to profile + * @type_name: Name of the data type + * @type_size: Size of the data type + * + * This represents a data type accessed by samples in the profile data. + */ +struct annotated_data_type { + char *type_name; + int type_size; +}; + +#ifdef HAVE_DWARF_SUPPORT + +/* Returns data type at the location (ip, reg, offset) */ +struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, + int reg, int offset); + +#else /* HAVE_DWARF_SUPPORT */ + +static inline struct annotated_data_type * +find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused, + int reg __maybe_unused, int offset __maybe_unused) +{ + return NULL; +} + +#endif /* HAVE_DWARF_SUPPORT */ + +#endif /* _PERF_ANNOTATE_DATA_H */ From patchwork Thu Nov 9 23:59:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451881 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34BC538FB1; Fri, 10 Nov 2023 00:00:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aLU/hF3g" Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B737947AF; Thu, 9 Nov 2023 16:00:35 -0800 (PST) Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1cc0d0a0355so12902865ad.3; Thu, 09 Nov 2023 16:00:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574435; x=1700179235; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=jaiH4xsSZSVG8THDe6PHcB4BM1fDj8obKYS0yTWnTRI=; b=aLU/hF3gvS2hIWmde2Z4wunowb4Tq8OU+ZrzzLl4Sui/dHUtfNdQS2z+OTQB+/RBGb y9JHBysdaD3CeyUJKMFFHmNKbU4QoKRXT//VfpfixHzAqMjdHO+DRXgEtazRihRBa2r2 ohoZ5WXvqDw3U7IHrs+0Bt3Cis/XTMXdA9RcGj2yvOrmZqCKSWiJD6CqqFz/KceK9W2l vuXrRhb9KflFO+Oc7iLDeC4rnS8GyiI+2PQudkGWP0L32LGccgYfGcJBTzBSHbkuHtPJ /mzb5Ziey+VtsAgx/zChicOa6NBXHFKVrKVpqOuDw8Nfpc09OuMR1WJP8XyRxUtKfDh4 254g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574435; x=1700179235; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=jaiH4xsSZSVG8THDe6PHcB4BM1fDj8obKYS0yTWnTRI=; b=jo1AdJOe84lY8n9m/qyy8akEqyo66aOdqKqA1VVm+klZ+pNaX7gk1gTJcghhKdwanq ZJt9m7AumdOjwac8EWySGtguSM+KDjq6+MaWXHv5DcLz4bh4yfUXuL/r9nSTTTCVRpOV ZbVOUsurYgjAJt2BDqf5xKE6qHiNqw5LnlbgfmvvDEApX7LtrRsoTPV74WOCWlfMmUuL gBGEq1wuNEVKfP3gLpEtU8Zz573QdTgVhicBQkFAz922bHyR1aqu8Ys1IZzPiaLECNo8 Req0BRyo4inGITv9Qnc5IEM7dh0DaQWwoTpAVwoDtetu35Gzn7Y3hf6QvsAV6osDWf9s bmag== X-Gm-Message-State: AOJu0YyyM6hPn+VigBDMTS1hgaWYMGzsqDbX5m1nDndMsooYoYYvXiST 7P7p7dv9AEW+bBIrYgGgrxg= X-Google-Smtp-Source: AGHT+IE0XA8K5dSTw3b6gY61NwzmzfZAG7YIO/thoeigAZowevsG/ocGEmnyBL4rChn705UpMZ6NRg== X-Received: by 2002:a17:90b:1e4d:b0:27d:b488:92ee with SMTP id pi13-20020a17090b1e4d00b0027db48892eemr3201230pjb.2.1699574435138; Thu, 09 Nov 2023 16:00:35 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:34 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 13/52] perf annotate-data: Add dso->data_types tree Date: Thu, 9 Nov 2023 15:59:32 -0800 Message-ID: <20231110000012.3538610-14-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To aggregate accesses to the same data type, add 'data_types' tree in DSO to maintain data types and find it by name and size. It might have different data types that happen to have the same name. So it also compares the size of the type. Even if it doesn't 100% guarantee, it'd reduce the possiblility of mis-handling of such conflicts. And I don't think it's common to have different types with the same name. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 95 +++++++++++++++++++++++++++++---- tools/perf/util/annotate-data.h | 9 ++++ tools/perf/util/dso.c | 4 ++ tools/perf/util/dso.h | 2 + 4 files changed, 100 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 98c42dff2645..475cc30b33e1 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -17,6 +17,76 @@ #include "strbuf.h" #include "symbol.h" +/* + * Compare type name and size to maintain them in a tree. + * I'm not sure if DWARF would have information of a single type in many + * different places (compilation units). If not, it could compare the + * offset of the type entry in the .debug_info section. + */ +static int data_type_cmp(const void *_key, const struct rb_node *node) +{ + const struct annotated_data_type *key = _key; + struct annotated_data_type *type; + + type = rb_entry(node, struct annotated_data_type, node); + + if (key->type_size != type->type_size) + return key->type_size - type->type_size; + return strcmp(key->type_name, type->type_name); +} + +static bool data_type_less(struct rb_node *node_a, const struct rb_node *node_b) +{ + struct annotated_data_type *a, *b; + + a = rb_entry(node_a, struct annotated_data_type, node); + b = rb_entry(node_b, struct annotated_data_type, node); + + if (a->type_size != b->type_size) + return a->type_size < b->type_size; + return strcmp(a->type_name, b->type_name) < 0; +} + +static struct annotated_data_type *dso__findnew_data_type(struct dso *dso, + Dwarf_Die *type_die) +{ + struct annotated_data_type *result = NULL; + struct annotated_data_type key; + struct rb_node *node; + struct strbuf sb; + char *type_name; + Dwarf_Word size; + + strbuf_init(&sb, 32); + if (die_get_typename_from_type(type_die, &sb) < 0) + strbuf_add(&sb, "(unknown type)", 14); + type_name = strbuf_detach(&sb, NULL); + dwarf_aggregate_size(type_die, &size); + + /* Check existing nodes in dso->data_types tree */ + key.type_name = type_name; + key.type_size = size; + node = rb_find(&key, &dso->data_types, data_type_cmp); + if (node) { + result = rb_entry(node, struct annotated_data_type, node); + free(type_name); + return result; + } + + /* If not, add a new one */ + result = zalloc(sizeof(*result)); + if (result == NULL) { + free(type_name); + return NULL; + } + + result->type_name = type_name; + result->type_size = size; + + rb_add(&result->node, &dso->data_types, data_type_less); + return result; +} + static bool find_cu_die(struct debuginfo *di, u64 pc, Dwarf_Die *cu_die) { Dwarf_Off off, next_off; @@ -129,7 +199,6 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, struct dso *dso = ms->map->dso; struct debuginfo *di; Dwarf_Die type_die; - struct strbuf sb; u64 pc; di = debuginfo__new(dso->long_name); @@ -147,17 +216,23 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, if (find_data_type_die(di, pc, reg, offset, &type_die) < 0) goto out; - result = zalloc(sizeof(*result)); - if (result == NULL) - goto out; - - strbuf_init(&sb, 32); - if (die_get_typename_from_type(&type_die, &sb) < 0) - strbuf_add(&sb, "(unknown type)", 14); - - result->type_name = strbuf_detach(&sb, NULL); + result = dso__findnew_data_type(dso, &type_die); out: debuginfo__delete(di); return result; } + +void annotated_data_type__tree_delete(struct rb_root *root) +{ + struct annotated_data_type *pos; + + while (!RB_EMPTY_ROOT(root)) { + struct rb_node *node = rb_first(root); + + rb_erase(node, root); + pos = rb_entry(node, struct annotated_data_type, node); + free(pos->type_name); + free(pos); + } +} diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 633147f78ca5..ab9f187bd7f1 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -4,6 +4,7 @@ #include #include +#include #include struct map_symbol; @@ -16,6 +17,7 @@ struct map_symbol; * This represents a data type accessed by samples in the profile data. */ struct annotated_data_type { + struct rb_node node; char *type_name; int type_size; }; @@ -26,6 +28,9 @@ struct annotated_data_type { struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, int reg, int offset); +/* Release all data type information in the tree */ +void annotated_data_type__tree_delete(struct rb_root *root); + #else /* HAVE_DWARF_SUPPORT */ static inline struct annotated_data_type * @@ -35,6 +40,10 @@ find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused, return NULL; } +static inline void annotated_data_type__tree_delete(struct rb_root *root __maybe_unused) +{ +} + #endif /* HAVE_DWARF_SUPPORT */ #endif /* _PERF_ANNOTATE_DATA_H */ diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 1f629b6fb7cf..22fd5fa806ed 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -31,6 +31,7 @@ #include "debug.h" #include "string2.h" #include "vdso.h" +#include "annotate-data.h" static const char * const debuglink_paths[] = { "%.0s%s", @@ -1327,6 +1328,7 @@ struct dso *dso__new_id(const char *name, struct dso_id *id) dso->data.cache = RB_ROOT; dso->inlined_nodes = RB_ROOT_CACHED; dso->srclines = RB_ROOT_CACHED; + dso->data_types = RB_ROOT; dso->data.fd = -1; dso->data.status = DSO_DATA_STATUS_UNKNOWN; dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; @@ -1370,6 +1372,8 @@ void dso__delete(struct dso *dso) symbols__delete(&dso->symbols); dso->symbol_names_len = 0; zfree(&dso->symbol_names); + annotated_data_type__tree_delete(&dso->data_types); + if (dso->short_name_allocated) { zfree((char **)&dso->short_name); dso->short_name_allocated = false; diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 3759de8c2267..ce9f3849a773 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -154,6 +154,8 @@ struct dso { size_t symbol_names_len; struct rb_root_cached inlined_nodes; struct rb_root_cached srclines; + struct rb_root data_types; + struct { u64 addr; struct symbol *symbol; From patchwork Thu Nov 9 23:59:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451882 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8ED8139843; Fri, 10 Nov 2023 00:00:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HxYFUZ5T" Received: from mail-pg1-x531.google.com (mail-pg1-x531.google.com [IPv6:2607:f8b0:4864:20::531]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2460A47B9; Thu, 9 Nov 2023 16:00:37 -0800 (PST) Received: by mail-pg1-x531.google.com with SMTP id 41be03b00d2f7-5bcfc508d14so1196413a12.3; Thu, 09 Nov 2023 16:00:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574436; x=1700179236; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=bvKZfgb9TPzKC/D8JQqUC0o12NYPt/G4JoRXa7PKCNk=; b=HxYFUZ5TZorUYGDTkALP8XuYJIic15+yB4YnFv8Nets1et9ioyl7j3zz7ePQX2n+gX PqBkdVhGOw9DxaEXUkLHFrE/QlXb9CrhP4YJiBWTNrTK73uzrtfMOVDOoKx8JEEyhpil 6W4DgkO96PJy2uOAa/k6WE5qgC/xvzWiAFJPxb6eqSqlhBbSf87VR/DWqLuj8MSbUIWo pSNUamsWhS5oHcO5nJxyssgUyjwqbSGKiP7wOvegE8lBD37j4kLJt9kdDHAh4NoxFqRg OZ7aWUlRj70lN/y6NzQ7k/3YEe5xF9Xspp3kUCWo7781ewbX8vNq0hmdjgvhQ2sKPrTp CPfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574436; x=1700179236; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bvKZfgb9TPzKC/D8JQqUC0o12NYPt/G4JoRXa7PKCNk=; b=oG3E8eF131ADKwA7uvcYevNHaKT40J3+mE7krcsaXOy5seLsACZ07LLL1znEKORvji /5xtmGk5iQ5RV9vHP5khnZ5NxZLx+cglxHmK4i47uVige9JugdZ0S+qN3IgX8HuxEdW8 63TwN4zcRVmDrzqhweNbjyu5xITTJ1rGKr4V3lZ/X7buzCTm4n//ShUghT4kU7fPBGa2 WsUT340HD/KrqgJotBZJhOYNSu84U1Y7b2JI/eBc2ijwPdqw8e/7FSRLrPimZeqji1cv 9nGVPIhDPi843XEW8TR3Lp6SxQMiNQx7uEY5LAJpMkBpFNDrHv+RxmkJ1UzZyslcAPpW +3tA== X-Gm-Message-State: AOJu0YzT3dzchK5Q3xNi0Jw8UQHrXj/8vg0YRDmjUb06B9bv2bYp9H4o 0lq3QpalCQMim7vTsT/F0i8= X-Google-Smtp-Source: AGHT+IGGw5+FjGvov4deH0597Hqz6bPE/R28i03Bp6d1L4KHkwqLmd7PycY/kw9a4GFmJqqNYnbt/g== X-Received: by 2002:a05:6a20:8e10:b0:183:c7ea:bb52 with SMTP id y16-20020a056a208e1000b00183c7eabb52mr7616275pzj.30.1699574436444; Thu, 09 Nov 2023 16:00:36 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:36 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 14/52] perf annotate: Factor out evsel__get_arch() Date: Thu, 9 Nov 2023 15:59:33 -0800 Message-ID: <20231110000012.3538610-15-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The evsel__get_arch() is to get architecture info from the environ. It'll be used by other places later so let's factor it out. Also add arch__is() to check the arch info by name. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 44 +++++++++++++++++++++++++++----------- tools/perf/util/annotate.h | 2 ++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 3364edf30f50..83e0996992af 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -804,6 +804,11 @@ static struct arch *arch__find(const char *name) return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp); } +bool arch__is(struct arch *arch, const char *name) +{ + return !strcmp(arch->name, name); +} + static struct annotated_source *annotated_source__new(void) { struct annotated_source *src = zalloc(sizeof(*src)); @@ -2340,15 +2345,8 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel) annotation__calc_percent(notes, evsel, symbol__size(sym)); } -int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, - struct annotation_options *options, struct arch **parch) +static int evsel__get_arch(struct evsel *evsel, struct arch **parch) { - struct symbol *sym = ms->sym; - struct annotation *notes = symbol__annotation(sym); - struct annotate_args args = { - .evsel = evsel, - .options = options, - }; struct perf_env *env = evsel__env(evsel); const char *arch_name = perf_env__arch(env); struct arch *arch; @@ -2357,23 +2355,43 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, if (!arch_name) return errno; - args.arch = arch = arch__find(arch_name); + *parch = arch = arch__find(arch_name); if (arch == NULL) { pr_err("%s: unsupported arch %s\n", __func__, arch_name); return ENOTSUP; } - if (parch) - *parch = arch; - if (arch->init) { err = arch->init(arch, env ? env->cpuid : NULL); if (err) { - pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name); + pr_err("%s: failed to initialize %s arch priv area\n", + __func__, arch->name); return err; } } + return 0; +} + +int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, + struct annotation_options *options, struct arch **parch) +{ + struct symbol *sym = ms->sym; + struct annotation *notes = symbol__annotation(sym); + struct annotate_args args = { + .evsel = evsel, + .options = options, + }; + struct arch *arch = NULL; + int err; + + err = evsel__get_arch(evsel, &arch); + if (err < 0) + return err; + + if (parch) + *parch = arch; + args.arch = arch; args.ms = *ms; if (notes->options && notes->options->full_addr) notes->start = map__objdump_2mem(ms->map, ms->sym->start); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index bc8b95e8b1be..e8b0173f5f00 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -59,6 +59,8 @@ struct ins_operands { struct arch; +bool arch__is(struct arch *arch, const char *name); + struct ins_ops { void (*free)(struct ins_operands *ops); int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms); From patchwork Thu Nov 9 23:59:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451883 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 250FD14290; Fri, 10 Nov 2023 00:00:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="huE+tmGr" Received: from mail-pg1-x534.google.com (mail-pg1-x534.google.com [IPv6:2607:f8b0:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 813CC49CF; Thu, 9 Nov 2023 16:00:38 -0800 (PST) Received: by mail-pg1-x534.google.com with SMTP id 41be03b00d2f7-5bd85b1939aso1097043a12.2; Thu, 09 Nov 2023 16:00:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574438; x=1700179238; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=kl6qkwzmCb2Fb09U1AXlxKbKREoLSgao7N8IelzAMBg=; b=huE+tmGrENZq27PQZHbDXKv6PKMPRIOtN7Xqxmp0hx2BqD3mneWnaoPNo3K2fTc+BE QmIrJKTqku7Sg43Do4ltYgF+JZPgsqGNMBUTYAYsqXEj83zx0zRejw0M54eA/cB278da ZMKdTcOkwyd0yt87axOzKIVTWxBSM1u9tY7BwoCzS/P1YMZJbafHIz47kQODVhXWa2bu a9WLOLn+4Z7/wH7lA1TfVziWgnQy3oK6/Dkt9Espw9xEkr3SrohWX8YH/peTRiOzWytN vwmDMHM8JS2S+5FDUcC8i1QAaB8UBCvhSo0eCujORsX/iDttStGN5RUEY0anxeFDRMem XU1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574438; x=1700179238; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=kl6qkwzmCb2Fb09U1AXlxKbKREoLSgao7N8IelzAMBg=; b=lVmljx6hu8aS8p0W/xqj3/hzSB5Cd8XH3z32JYG58kJ/tsWtPPrqQA7te7UPyKqhX8 0W4LB8hYquNHvR/a5sSLcAMD0lPsdzpNka4PMFIwX5XrMQ+B3ZzGGOiU72xi9C98R1iU td9e7gcxTuO0pd/DyxcubFolyD7DV+r28JyyTvBl+/u4yKVHooh/oGEf0Hy6/C4NyySJ B0zbaXXoBnfTskLE6U50jKCuMO5ekP6eO4uJiR5g2yC9S5FCeW6NvBfZBQJZzbsBJRKV 54y2+iT0xTQHNw57VR8bydYH2866aepxF2Ex8wO5AGWhwK502Bq0lRMEZ/cPPLn77L0Y Al5A== X-Gm-Message-State: AOJu0YyRiV5c68eBD7SHdFoiyebVUrnm96k13rBUA7wVkI3sQ0uwCWaF DUXpdL5f08mxpncfCZMazXw= X-Google-Smtp-Source: AGHT+IEl6Kg+Ce9xdTunRkPSVE+zc/L7j9/ec6svm1a9xENy5X2o+woa+hJIZpauMbUzihB8rs8FVQ== X-Received: by 2002:a17:90a:4888:b0:280:1df1:cbc7 with SMTP id b8-20020a17090a488800b002801df1cbc7mr3334799pjh.19.1699574437858; Thu, 09 Nov 2023 16:00:37 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:37 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 15/52] perf annotate: Check if operand has multiple regs Date: Thu, 9 Nov 2023 15:59:34 -0800 Message-ID: <20231110000012.3538610-16-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 It needs to check all possible information in an instruction. Let's add a field indicating if the operand has multiple registers. I'll be used to search type information like in an array access on x86 like: mov 0x10(%rax,%rbx,8), %rcx ------------- here Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 36 ++++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 83e0996992af..9e297adc8c59 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -85,6 +85,8 @@ struct arch { struct { char comment_char; char skip_functions_char; + char register_char; + char memory_ref_char; } objdump; }; @@ -188,6 +190,8 @@ static struct arch architectures[] = { .insn_suffix = "bwlq", .objdump = { .comment_char = '#', + .register_char = '%', + .memory_ref_char = '(', }, }, { @@ -566,6 +570,34 @@ static struct ins_ops lock_ops = { .scnprintf = lock__scnprintf, }; +/* + * Check if the operand has more than one registers like x86 SIB addressing: + * 0x1234(%rax, %rbx, 8) + * + * But it doesn't care segment selectors like %gs:0x5678(%rcx), so just check + * the input string after 'memory_ref_char' if exists. + */ +static bool check_multi_regs(struct arch *arch, const char *op) +{ + int count = 0; + + if (arch->objdump.register_char == 0) + return false; + + if (arch->objdump.memory_ref_char) { + op = strchr(op, arch->objdump.memory_ref_char); + if (op == NULL) + return false; + } + + while ((op = strchr(op, arch->objdump.register_char)) != NULL) { + count++; + op++; + } + + return count > 1; +} + static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused) { char *s = strchr(ops->raw, ','), *target, *comment, prev; @@ -593,6 +625,8 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_sy if (ops->source.raw == NULL) return -1; + ops->source.multi_regs = check_multi_regs(arch, ops->source.raw); + target = skip_spaces(++s); comment = strchr(s, arch->objdump.comment_char); @@ -613,6 +647,8 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_sy if (ops->target.raw == NULL) goto out_free_source; + ops->target.multi_regs = check_multi_regs(arch, ops->target.raw); + if (comment == NULL) return 0; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index e8b0173f5f00..4ebc6407c68a 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -39,12 +39,14 @@ struct ins_operands { s64 offset; bool offset_avail; bool outside; + bool multi_regs; } target; union { struct { char *raw; char *name; u64 addr; + bool multi_regs; } source; struct { struct ins ins; From patchwork Thu Nov 9 23:59:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451884 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 55AAA39843; Fri, 10 Nov 2023 00:00:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="epgO4grc" Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00A5A49D9; Thu, 9 Nov 2023 16:00:39 -0800 (PST) Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-6be0277c05bso1416748b3a.0; Thu, 09 Nov 2023 16:00:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574439; x=1700179239; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=Yak7ZiK/orMJhPDQBjUATJ5nSnN4xhs60FDmugSdC0Y=; b=epgO4grcPCC0a815L1IXE8TZG4vtfnBNKBZNayuZNaTwwnUgwVYCLCI93K8zIxWW/h V7f8OtYXh664+D8NW1ET7tLT5uDD57OQEZkjCsquTNsfy7D5sxv82g/aHbTxeGfLSJq2 xxcchVFAY2H3AwDEPFVI1fToWmWRBt48P7sP4R1JHOUDu5Ao2Sw7aEHsCr60QSm70ATv Oti+XumD0b4kG4MuHPSCWoxBHY1PjBw199BecboeiBvUNjMQ3chUBOtPYzm+U1BMA8Rb DxDXuBp9Rivu3QPrm7uLGGPIyqT2kgGwrKOxU0vMzRNHvU2xLTJPmM1hNQkcieXlYvK0 GAlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574439; x=1700179239; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Yak7ZiK/orMJhPDQBjUATJ5nSnN4xhs60FDmugSdC0Y=; b=cYn5IZqQ1VFH/HSiZgOfszMXrFNWIYRPr0dIwJSvzlMn7oHOx3TZfgbIcGTl+IY3ln jUUQi+v/T2y2iedulLPkyOGJ1SBts+BfZ1ECTk/NU3ztJUfsN+nEinrA6ewQV5peeiTJ +SX+SF8I6ofa7hfm6R1vbqgfiM+Bu1Jg6xcoU7Tml0Z4QYc0yBdF2VD/n8PdYvvBIXvV 547EbOAlgzteekJpGQCPhtCEl/yEmhAh7fZInW5p5aDvmEzD3yhm9dwdpFwqRAw1ixIl kVDaZJzTxRvyixIc+YhmetL+RMaOkIwakV/Fs7vO2FSgS3zkCiYv3ZP3G0b+9kMskGsG wHDQ== X-Gm-Message-State: AOJu0YyMrjj5i9tCk7j9p3RUXrc3RxDrTFbe2o0RJZn0BJFu0Tpqy1Tq pdwj9Jz85aOXW9eEv/BjsSA= X-Google-Smtp-Source: AGHT+IHOnFmfzVnnX1rpOFEixG0qlHI9krjG5m81PSquo/G5LrU/uwO6UeBHn/iO+psTLRUHxwDLmA== X-Received: by 2002:a05:6a21:187:b0:161:28e0:9abd with SMTP id le7-20020a056a21018700b0016128e09abdmr8060198pzb.16.1699574439336; Thu, 09 Nov 2023 16:00:39 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:38 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 16/52] perf annotate: Add annotate_get_insn_location() Date: Thu, 9 Nov 2023 15:59:35 -0800 Message-ID: <20231110000012.3538610-17-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The annotate_get_insn_location() is to get the detailed information of instruction locations like registers and offset. It has source and target operands locations in an array. Each operand can have a register and an offset. The offset is meaningful when mem_ref flag is set. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 107 +++++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 36 +++++++++++++ 2 files changed, 143 insertions(+) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 9e297adc8c59..f0c89552087d 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -31,6 +31,7 @@ #include "bpf-utils.h" #include "block-range.h" #include "string2.h" +#include "dwarf-regs.h" #include "util/event.h" #include "util/sharded_mutex.h" #include "arch/common.h" @@ -3522,3 +3523,109 @@ int annotate_check_args(struct annotation_options *args) } return 0; } + +/* + * Get register number and access offset from the given instruction. + * It assumes AT&T x86 asm format like OFFSET(REG). Maybe it needs + * to revisit the format when it handles different architecture. + * Fills @reg and @offset when return 0. + */ +static int extract_reg_offset(struct arch *arch, const char *str, + struct annotated_op_loc *op_loc) +{ + char *p; + char *regname; + + if (arch->objdump.register_char == 0) + return -1; + + /* + * It should start from offset, but it's possible to skip 0 + * in the asm. So 0(%rax) should be same as (%rax). + * + * However, it also start with a segment select register like + * %gs:0x18(%rbx). In that case it should skip the part. + */ + if (*str == arch->objdump.register_char) { + while (*str && !isdigit(*str) && + *str != arch->objdump.memory_ref_char) + str++; + } + + op_loc->offset = strtol(str, &p, 0); + + p = strchr(p, arch->objdump.register_char); + if (p == NULL) + return -1; + + regname = strdup(p); + if (regname == NULL) + return -1; + + op_loc->reg = get_dwarf_regnum(regname, 0); + free(regname); + return 0; +} + +/** + * annotate_get_insn_location - Get location of instruction + * @arch: the architecture info + * @dl: the target instruction + * @loc: a buffer to save the data + * + * Get detailed location info (register and offset) in the instruction. + * It needs both source and target operand and whether it accesses a + * memory location. The offset field is meaningful only when the + * corresponding mem flag is set. + * + * Some examples on x86: + * + * mov (%rax), %rcx # src_reg = rax, src_mem = 1, src_offset = 0 + * # dst_reg = rcx, dst_mem = 0 + * + * mov 0x18, %r8 # src_reg = -1, dst_reg = r8 + */ +int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, + struct annotated_insn_loc *loc) +{ + struct ins_operands *ops; + struct annotated_op_loc *op_loc; + int i; + + if (!strcmp(dl->ins.name, "lock")) + ops = dl->ops.locked.ops; + else + ops = &dl->ops; + + if (ops == NULL) + return -1; + + memset(loc, 0, sizeof(*loc)); + + for_each_insn_op_loc(loc, i, op_loc) { + const char *insn_str = ops->source.raw; + + if (i == INSN_OP_TARGET) + insn_str = ops->target.raw; + + /* Invalidate the register by default */ + op_loc->reg = -1; + + if (insn_str == NULL) + continue; + + if (strchr(insn_str, arch->objdump.memory_ref_char)) { + op_loc->mem_ref = true; + extract_reg_offset(arch, insn_str, op_loc); + } else { + char *s = strdup(insn_str); + + if (s) { + op_loc->reg = get_dwarf_regnum(s, 0); + free(s); + } + } + } + + return 0; +} diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 4ebc6407c68a..10eefecf49c4 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -445,4 +445,40 @@ int annotate_parse_percent_type(const struct option *opt, const char *_str, int annotate_check_args(struct annotation_options *args); +/** + * struct annotated_op_loc - Location info of instruction operand + * @reg: Register in the operand + * @offset: Memory access offset in the operand + * @mem_ref: Whether the operand accesses memory + */ +struct annotated_op_loc { + int reg; + int offset; + bool mem_ref; +}; + +enum annotated_insn_ops { + INSN_OP_SOURCE = 0, + INSN_OP_TARGET = 1, + + INSN_OP_MAX, +}; + +/** + * struct annotated_insn_loc - Location info of instruction + * @ops: Array of location info for source and target operands + */ +struct annotated_insn_loc { + struct annotated_op_loc ops[INSN_OP_MAX]; +}; + +#define for_each_insn_op_loc(insn_loc, i, op_loc) \ + for (i = INSN_OP_SOURCE, op_loc = &(insn_loc)->ops[i]; \ + i < INSN_OP_MAX; \ + i++, op_loc++) + +/* Get detailed location info in the instruction */ +int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, + struct annotated_insn_loc *loc); + #endif /* __PERF_ANNOTATE_H */ From patchwork Thu Nov 9 23:59:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451885 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD4D314290; Fri, 10 Nov 2023 00:00:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="T8A+2BvS" Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BE3D49F2; Thu, 9 Nov 2023 16:00:41 -0800 (PST) Received: by mail-pj1-x1033.google.com with SMTP id 98e67ed59e1d1-2809414efa9so1374609a91.1; Thu, 09 Nov 2023 16:00:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574441; x=1700179241; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=mWaJqhvBxoi7J2eAsBrbo6D+bveraN1II1Qf4G2yQhQ=; b=T8A+2BvSqJDGq3/J6//XCLN+CFW9DkBCZhGzZxNdUdAUGzoD0mMNqQhxE051ogGkB+ WutjLVHyFMdoAN0NjJhgHNcVP3BGW+te93Z1hQL2THfOm0NL9zXtHNcDunH2Nn1morU2 /m1KKhSl70RvBJVNJE9eMXavO4oyKmQmUh2+ZAXro6BJxBQGHNCdvxo4zGbQN+ATQ++v CdGjup9fFyhRVpBH/prLPG7k6YPcqWO9sd7PxQ5EJXl8a7TE+rIRc87HwTG550MeQcMx nMShZN21b/QCrX6Up3/kSxUaD63JGDcZrLjhO6SHcT1RIEXpO9HmUDVfakaLgxQqsOrb EFKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574441; x=1700179241; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=mWaJqhvBxoi7J2eAsBrbo6D+bveraN1II1Qf4G2yQhQ=; b=L3AVkSZ2IfM9eX6ZiVijfWPhMflZA7ihtRiN4mERE7IoD+X6BURMhglzQnVDB3oINH 7vYpl72lu3Ii4p2BVqMACR6GFBqXxXHOjKTM7GKtDSGTLyhtLcIMojRYOmQzoa7lDr69 5PZPbsp+Fe1rvGuHTYDPm3CAIqLWioT3ASVBkb+PYAlkHyiFoyVLq3cqJpSoVdzb8Qni w0lNTWSjp0PVrs32ZyBPnPquU+DzCZ74QgeAPXE5K+9MPlzC2tDX1rK74dUyFXJgoFWH DlOeQzTKlJS56JDbeJfSuWdHk8PfcKtdELkvGvC2XUQJingnby0jhI3IZExJtpMT/s+A Jgjg== X-Gm-Message-State: AOJu0YzhGsWzQKYu5Tb93rHKF0dj+eggq/01awLnhLdw+BSygjDipsgK e+FKMnYXrxmlacHX9Izl/q4= X-Google-Smtp-Source: AGHT+IEaSPKnPWXbekCEG6WprIPDnyGu0sJhPrEKmU0oNGqnlyjFqH8YvOy0pQ5PGLU8quUnxGVLrA== X-Received: by 2002:a17:90b:314e:b0:280:39f2:2f12 with SMTP id ip14-20020a17090b314e00b0028039f22f12mr3388244pjb.26.1699574440731; Thu, 09 Nov 2023 16:00:40 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:40 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 17/52] perf annotate: Implement hist_entry__get_data_type() Date: Thu, 9 Nov 2023 15:59:36 -0800 Message-ID: <20231110000012.3538610-18-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 It's the function to find out the type info from the given sample data and will be called from the hist_entry sort logic when 'type' sort key is used. It first calls objdump to disassemble the instructions and figure out information about memory access at the location. Maybe we can do it better by analyzing the instruction directly, but I'll leave it for later work. The memory access is determined by checking instruction operands to have "(" and then extract register name and offset. It'll return NULL if no data type is found. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 85 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 4 ++ 2 files changed, 89 insertions(+) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index f0c89552087d..c08686b91861 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -25,6 +25,7 @@ #include "units.h" #include "debug.h" #include "annotate.h" +#include "annotate-data.h" #include "evsel.h" #include "evlist.h" #include "bpf-event.h" @@ -3629,3 +3630,87 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, return 0; } + +static void symbol__ensure_annotate(struct map_symbol *ms, struct evsel *evsel) +{ + struct disasm_line *dl, *tmp_dl; + struct annotation *notes; + + notes = symbol__annotation(ms->sym); + if (!list_empty(¬es->src->source)) + return; + + if (symbol__annotate(ms, evsel, notes->options, NULL) < 0) + return; + + /* remove non-insn disasm lines for simplicity */ + list_for_each_entry_safe(dl, tmp_dl, ¬es->src->source, al.node) { + if (dl->al.offset == -1) { + list_del(&dl->al.node); + free(dl); + } + } +} + +static struct disasm_line *find_disasm_line(struct symbol *sym, u64 ip) +{ + struct disasm_line *dl; + struct annotation *notes; + + notes = symbol__annotation(sym); + + list_for_each_entry(dl, ¬es->src->source, al.node) { + if (sym->start + dl->al.offset == ip) + return dl; + } + return NULL; +} + +/** + * hist_entry__get_data_type - find data type for given hist entry + * @he: hist entry + * + * This function first annotates the instruction at @he->ip and extracts + * register and offset info from it. Then it searches the DWARF debug + * info to get a variable and type information using the address, register, + * and offset. + */ +struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) +{ + struct map_symbol *ms = &he->ms; + struct evsel *evsel = hists_to_evsel(he->hists); + struct arch *arch; + struct disasm_line *dl; + struct annotated_insn_loc loc; + struct annotated_op_loc *op_loc; + u64 ip = he->ip; + int i; + + if (ms->map == NULL || ms->sym == NULL) + return NULL; + + if (evsel__get_arch(evsel, &arch) < 0) + return NULL; + + /* Make sure it runs objdump to get disasm of the function */ + symbol__ensure_annotate(ms, evsel); + + /* + * Get a disasm to extract the location from the insn. + * This is too slow... + */ + dl = find_disasm_line(ms->sym, ip); + if (dl == NULL) + return NULL; + + if (annotate_get_insn_location(arch, dl, &loc) < 0) + return NULL; + + for_each_insn_op_loc(&loc, i, op_loc) { + if (!op_loc->mem_ref) + continue; + + return find_data_type(ms, ip, op_loc->reg, op_loc->offset); + } + return NULL; +} diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 10eefecf49c4..06281a50ecf6 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -23,6 +23,7 @@ struct option; struct perf_sample; struct evsel; struct symbol; +struct annotated_data_type; struct ins { const char *name; @@ -481,4 +482,7 @@ struct annotated_insn_loc { int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, struct annotated_insn_loc *loc); +/* Returns a data type from the sample instruction (if any) */ +struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he); + #endif /* __PERF_ANNOTATE_H */ From patchwork Thu Nov 9 23:59:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451886 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A24479C3; Fri, 10 Nov 2023 00:00:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZjhkiPhs" Received: from mail-pl1-x632.google.com (mail-pl1-x632.google.com [IPv6:2607:f8b0:4864:20::632]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C94114C06; Thu, 9 Nov 2023 16:00:42 -0800 (PST) Received: by mail-pl1-x632.google.com with SMTP id d9443c01a7336-1cc37fb1310so12618705ad.1; Thu, 09 Nov 2023 16:00:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574442; x=1700179242; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=hXLxCqlf5n/qGCc38OHpbFSGlVUS7JYGwpo/0dfoHnw=; b=ZjhkiPhsBgb/eM8CYz4uidGdm41senxyeojOwtVV6S61p3GUCZuGt+sVTpvmhP114y upFHxBZedhVOtX6iMbOiyFnXwcBLGH+YrdxOn/wkHNp4eF3BmrwQP1tgQplQ4OIUpypl ry2p4daj3tyAtHj1U86OV7xmWJ7MOi3jdNDUezI7KJVACxJ9pLKUUBAJ9KTLPjp+fi3L D0DFgeT2AFswcEeDQfYcLhsgyZa3kCEu0CvtkRj0D0NZRQOTXr/sll0+QF6luiiMeK2+ NuU3qHiOAYBO6dWtDpjOS84JoSUJI9dPAB2r6Jifx9qPVOy2pAMqb5Z9bXk/ld5K2H9q XM9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574442; x=1700179242; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=hXLxCqlf5n/qGCc38OHpbFSGlVUS7JYGwpo/0dfoHnw=; b=IwLvmckZLxJ3PcClPOap7G0px8PxYpScIPT/UC1DrdpRsIYl+tG6cacNJLuraojqor lDbvbm8kXw2RbU+Lla2YeWk3/TvfeHz8/3WbC8b+EuKY13FBVj9JVBA7eDXVG9V2VJF0 SR35Im6dpaSMTe3pOSRA2lgadzUb4FwWu86wqGkPIGyNvAL3xz5bAZkE99YVjvsgnWCS E2onjb3iM9wpezttpftWR/+H2ycpT8XjuEGfhBtIHuBrmEILz+BvgeTjpd5jpQCJpKms 7pc/+4Ru4al+cSH9QIIXObl3Rcrv7APm1IXfsblGl3a75PmWzNfmIG3yUfh682OOAi9a g8+g== X-Gm-Message-State: AOJu0Yxpy9PUUSbjOK1oMlOE7N8nKPfHAWt1aM38FvgCbv8NlrBpMwm1 GFCMXJXVWAzaGvMu810uiiE= X-Google-Smtp-Source: AGHT+IE16tVXtAfG+JAkRRQbICcGiKDpJUVAfqRLG851iGqVR8Ue7V3A3rwDhdd36iRyTcv+m9YncQ== X-Received: by 2002:a17:90a:b96:b0:280:3911:adfe with SMTP id 22-20020a17090a0b9600b002803911adfemr2935461pjr.39.1699574442116; Thu, 09 Nov 2023 16:00:42 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:41 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 18/52] perf report: Add 'type' sort key Date: Thu, 9 Nov 2023 15:59:37 -0800 Message-ID: <20231110000012.3538610-19-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The 'type' sort key is to aggregate hist entries by data type they access. Add mem_type field to hist_entry struct to save the type. If hist_entry__get_data_type() returns NULL, it'd use the 'unknown_type' instance. Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-report.txt | 1 + tools/perf/util/annotate-data.h | 2 + tools/perf/util/hist.h | 1 + tools/perf/util/sort.c | 69 +++++++++++++++++++++++- tools/perf/util/sort.h | 4 ++ 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index af068b4f1e5a..aec34417090b 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -118,6 +118,7 @@ OPTIONS - retire_lat: On X86, this reports pipeline stall of this instruction compared to the previous instruction in cycles. And currently supported only on X86 - simd: Flags describing a SIMD operation. "e" for empty Arm SVE predicate. "p" for partial Arm SVE predicate + - type: Data type of sample memory access. By default, comm, dso and symbol keys are used. (i.e. --sort comm,dso,symbol) diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index ab9f187bd7f1..6efdd7e21b28 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -22,6 +22,8 @@ struct annotated_data_type { int type_size; }; +extern struct annotated_data_type unknown_type; + #ifdef HAVE_DWARF_SUPPORT /* Returns data type at the location (ip, reg, offset) */ diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index afc9f1c7f4dc..9bfed867f288 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -82,6 +82,7 @@ enum hist_column { HISTC_ADDR_TO, HISTC_ADDR, HISTC_SIMD, + HISTC_TYPE, HISTC_NR_COLS, /* Last entry */ }; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 27b123ccd2d1..e647f0117bb5 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -24,6 +24,7 @@ #include "strbuf.h" #include "mem-events.h" #include "annotate.h" +#include "annotate-data.h" #include "event.h" #include "time-utils.h" #include "cgroup.h" @@ -2094,7 +2095,7 @@ struct sort_entry sort_dso_size = { .se_width_idx = HISTC_DSO_SIZE, }; -/* --sort dso_size */ +/* --sort addr */ static int64_t sort__addr_cmp(struct hist_entry *left, struct hist_entry *right) @@ -2131,6 +2132,69 @@ struct sort_entry sort_addr = { .se_width_idx = HISTC_ADDR, }; +/* --sort type */ + +struct annotated_data_type unknown_type = { + .type_name = (char *)"(unknown)", +}; + +static int64_t +sort__type_cmp(struct hist_entry *left, struct hist_entry *right) +{ + return sort__addr_cmp(left, right); +} + +static void sort__type_init(struct hist_entry *he) +{ + if (he->mem_type) + return; + + he->mem_type = hist_entry__get_data_type(he); + if (he->mem_type == NULL) + he->mem_type = &unknown_type; +} + +static int64_t +sort__type_collapse(struct hist_entry *left, struct hist_entry *right) +{ + struct annotated_data_type *left_type = left->mem_type; + struct annotated_data_type *right_type = right->mem_type; + + if (!left_type) { + sort__type_init(left); + left_type = left->mem_type; + } + + if (!right_type) { + sort__type_init(right); + right_type = right->mem_type; + } + + return strcmp(left_type->type_name, right_type->type_name); +} + +static int64_t +sort__type_sort(struct hist_entry *left, struct hist_entry *right) +{ + return sort__type_collapse(left, right); +} + +static int hist_entry__type_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) +{ + return repsep_snprintf(bf, size, "%-*s", width, he->mem_type->type_name); +} + +struct sort_entry sort_type = { + .se_header = "Data Type", + .se_cmp = sort__type_cmp, + .se_collapse = sort__type_collapse, + .se_sort = sort__type_sort, + .se_init = sort__type_init, + .se_snprintf = hist_entry__type_snprintf, + .se_width_idx = HISTC_TYPE, +}; + struct sort_dimension { const char *name; @@ -2185,7 +2249,8 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_ADDR, "addr", sort_addr), DIM(SORT_LOCAL_RETIRE_LAT, "local_retire_lat", sort_local_p_stage_cyc), DIM(SORT_GLOBAL_RETIRE_LAT, "retire_lat", sort_global_p_stage_cyc), - DIM(SORT_SIMD, "simd", sort_simd) + DIM(SORT_SIMD, "simd", sort_simd), + DIM(SORT_ANNOTATE_DATA_TYPE, "type", sort_type), }; #undef DIM diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index ecfb7f1359d5..aabf0b8331a3 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -15,6 +15,7 @@ struct option; struct thread; +struct annotated_data_type; extern regex_t parent_regex; extern const char *sort_order; @@ -34,6 +35,7 @@ extern struct sort_entry sort_dso_to; extern struct sort_entry sort_sym_from; extern struct sort_entry sort_sym_to; extern struct sort_entry sort_srcline; +extern struct sort_entry sort_type; extern const char default_mem_sort_order[]; extern bool chk_double_cl; @@ -154,6 +156,7 @@ struct hist_entry { struct perf_hpp_list *hpp_list; struct hist_entry *parent_he; struct hist_entry_ops *ops; + struct annotated_data_type *mem_type; union { /* this is for hierarchical entry structure */ struct { @@ -243,6 +246,7 @@ enum sort_type { SORT_LOCAL_RETIRE_LAT, SORT_GLOBAL_RETIRE_LAT, SORT_SIMD, + SORT_ANNOTATE_DATA_TYPE, /* branch stack specific sort keys */ __SORT_BRANCH_STACK, From patchwork Thu Nov 9 23:59:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451887 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4866614290; Fri, 10 Nov 2023 00:00:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hewpSY+M" Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 02B324C12; Thu, 9 Nov 2023 16:00:44 -0800 (PST) Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-27ff7fe7fbcso1299961a91.1; Thu, 09 Nov 2023 16:00:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574443; x=1700179243; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=EJFFyw141jUP/xKayMqLdMQ+KiPiQ49S3rXykXIzrtU=; b=hewpSY+M0Ilee/HvRvj+BMRJ5nds7ngzW3sNArweE5dKbyElgMsVFrLa/soTZSiQyC 6yUqPEW8yfUF8u7/+dXfjO+xEPiRRGR0XM/HdVjo9wskXjr4F0fjED5/841J7ubjv2ww GEjCptdXWtePI71qD4eKMTYpPsHo4tpeNBiGZXt/Z6njLp2ZkUub/TbUciq8O+JKutGi S3Yg3Vq8EcNF7Q3h96my8YVd+YZh5gx2VL63p9vGuSOmDVD1VpQxhihjmfyQSO6vaGaG UDd6wwob+jhqMhZWq/cM1MmpfCU3M/9fEBBdxX4Pk0ntlVeGjMW14/r+XmvJH925Zla/ ipgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574443; x=1700179243; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=EJFFyw141jUP/xKayMqLdMQ+KiPiQ49S3rXykXIzrtU=; b=OWsh++P4a2uXIIu9n+E8QeC5SHq189/21i33deZWA5fo+3NkRJOshYRkdiRcSDgCbL lBgDeJ79fzoXcnBnTEkJ7TdXkHBtrIfPWBpVJwESMYMCGsXrY2ZCPKfO2eXNlrxY029p Ko5hzWVdV7zitSFcaCnVhUHrjyFcT0VjpoHNA2juEmNYlT5NFxlzFqFVb2Jdr75JCTeb nuaiHofK2zt7J1QedGdEYL2yB83ts1yZmm446tm9DrEkutR+3PhN3diu4JiphSvne5Wy SMhNMJS8NukMegRUgecwdrWYbeIgx3+Gp/beJ/+oO5an/o0Yh474TcJ4/Pnu0CWbqWCa lhBw== X-Gm-Message-State: AOJu0Ywc24/a8V3i93XtUIciJFLZX3gF4ivF2FRRiSZ4ha/MYDnC2vM9 a5i8Ne/2P/SLC3ijW35xKxQ= X-Google-Smtp-Source: AGHT+IHDHaDW37hwqHR5XoEDWe6IHBrXhO7qVBENgL2GooV3ZNmPbnE5m9AccnpfOrMZO/2UbyU/dQ== X-Received: by 2002:a17:90a:ea85:b0:280:2652:d46 with SMTP id h5-20020a17090aea8500b0028026520d46mr3769910pjz.28.1699574443393; Thu, 09 Nov 2023 16:00:43 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:43 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 19/52] perf report: Support data type profiling Date: Thu, 9 Nov 2023 15:59:38 -0800 Message-ID: <20231110000012.3538610-20-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Enable type annotation when the 'type' sort key is used. It shows type of variables the samples access at the moment. Users can see which types are accessed frequently. $ perf report -s dso,type --stdio ... # Overhead Shared Object Data Type # ........ ................. ......... # 35.47% [kernel.kallsyms] (unknown) 1.62% [kernel.kallsyms] struct sched_entry 1.23% [kernel.kallsyms] struct cfs_rq 0.83% [kernel.kallsyms] struct task_struct 0.34% [kernel.kallsyms] struct list_head 0.30% [kernel.kallsyms] struct mem_cgroup ... Signed-off-by: Namhyung Kim --- tools/perf/builtin-report.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 121a2781323c..cd2cefd1ea9a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -96,6 +96,7 @@ struct report { bool stitch_lbr; bool disable_order; bool skip_empty; + bool data_type; int max_stack; struct perf_read_values show_threads_values; struct annotation_options annotation_opts; @@ -171,7 +172,7 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter, struct mem_info *mi; struct branch_info *bi; - if (!ui__has_annotation() && !rep->symbol_ipc) + if (!ui__has_annotation() && !rep->symbol_ipc && !rep->data_type) return 0; if (sort__mode == SORT_MODE__BRANCH) { @@ -323,10 +324,19 @@ static int process_sample_event(struct perf_tool *tool, if (al.map != NULL) map__dso(al.map)->hit = 1; - if (ui__has_annotation() || rep->symbol_ipc || rep->total_cycles_mode) { + if (ui__has_annotation() || rep->symbol_ipc || rep->total_cycles_mode || + rep->data_type) { hist__account_cycles(sample->branch_stack, &al, sample, rep->nonany_branch_mode, &rep->total_cycles); + if (rep->data_type) { + struct symbol *sym = al.sym; + struct annotation *notes = sym ? symbol__annotation(sym) : NULL; + + /* XXX: Save annotate options here */ + if (notes) + notes->options = &rep->annotation_opts; + } } ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep); @@ -1622,6 +1632,11 @@ int cmd_report(int argc, const char **argv) sort_order = NULL; } + if (sort_order && strstr(sort_order, "type")) { + report.data_type = true; + report.annotation_opts.annotate_src = false; + } + if (strcmp(input_name, "-") != 0) setup_browser(true); else @@ -1680,7 +1695,7 @@ int cmd_report(int argc, const char **argv) * so don't allocate extra space that won't be used in the stdio * implementation. */ - if (ui__has_annotation() || report.symbol_ipc || + if (ui__has_annotation() || report.symbol_ipc || report.data_type || report.total_cycles_mode) { ret = symbol__annotation_init(); if (ret < 0) From patchwork Thu Nov 9 23:59:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451888 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6647C3986B; Fri, 10 Nov 2023 00:00:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SNHAB9Yd" Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 12C0C4696; Thu, 9 Nov 2023 16:00:46 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id 98e67ed59e1d1-280200949c3so1314252a91.0; Thu, 09 Nov 2023 16:00:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574445; x=1700179245; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=ev4lcXoXXAVu+gC+hJoK8YAdIF4FX7WA6BkgnnH9tX4=; b=SNHAB9YdS6tN2OMozH4hiVB87uDQEzI+nR4g+xRXYqVD2TxBk4nIhqf4sS23vi9irn QNq72lPi9hDcPKa+WjFqUcbDv7fA8t0a+mBjoTu2It9hmfWGG3WLcD3+oDvyy+SG8gHD W1HXplHvbLbsJNLFzx9QJnbwd7C5WJbGkD5diH6+/8tXh7LlGqtj6xGl1CzBmSiW2/Pz myqFD2NwBalZO0HOAqOm/4LW7WoYI8t/grL1mgaaIqKVPJM5LHX6VoNHOjS8gQaU2Zae wlbSgKeauBQYpMsfkbp6eZlwE3jr06ImtCa3sNkXXoLZRlJGo+pZF86a3fKhaLz4K6f2 urdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574445; x=1700179245; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ev4lcXoXXAVu+gC+hJoK8YAdIF4FX7WA6BkgnnH9tX4=; b=HISp4EO63Xj4W1wJQK6tO1HsJCfe/4F2CP8Gh6TMRbnf+/2VSkeFLSKgAHEf2XtlFM X16UvgtYjCBfjuYW7bUpglEnUbF/9+cYu5T6zGOWYWKNooTMnfp30f4UyHwL/gmiM5D4 O/LhKwDbqE3Cv2q+HKeasI7p9AK4VgK66MuAYCVGbt+zrnjYB4uPPaGJVqyvKRrtUCvx Hq6xOaayGhmXieG9JzBlll8vS83bAI9V+mNXUNghOFebpciQA3H+LsqUm6JuX7UMFQwJ xmCIpFsB1Tx8Vbbndx5vxyLWF9Y+ghFTgXvJRh0KCz+068h09H8ooscI/UZ6SSqOKo/m J6hA== X-Gm-Message-State: AOJu0YzZCOOwUqaLSHhNotrE08t2hVxCka50opoiYYCdts5fib7ijjHK LxlyuPQzea4zhu+Vnstg8YK5gkmpaxE= X-Google-Smtp-Source: AGHT+IFMh6HqlNgTLnCnJ6bPYRNtYkHgNbavu6lzF7Wl5FteLzbTVv0g9aRjogA4UGvoLTWp3OUFQw== X-Received: by 2002:a17:90b:3b87:b0:27f:fc2f:4831 with SMTP id pc7-20020a17090b3b8700b0027ffc2f4831mr3536639pjb.13.1699574445472; Thu, 09 Nov 2023 16:00:45 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:44 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 20/52] perf annotate-data: Add member field in the data type Date: Thu, 9 Nov 2023 15:59:39 -0800 Message-ID: <20231110000012.3538610-21-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add child member field if the current type is a composite type like a struct or union. The member fields are linked in the children list and do the same recursively if the child itself is a composite type. Add 'self' member to the annotated_data_type to handle the members in the same way. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 101 ++++++++++++++++++++++++++++---- tools/perf/util/annotate-data.h | 27 +++++++-- tools/perf/util/sort.c | 9 ++- 3 files changed, 119 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 475cc30b33e1..107e3248a541 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -30,9 +30,9 @@ static int data_type_cmp(const void *_key, const struct rb_node *node) type = rb_entry(node, struct annotated_data_type, node); - if (key->type_size != type->type_size) - return key->type_size - type->type_size; - return strcmp(key->type_name, type->type_name); + if (key->self.size != type->self.size) + return key->self.size - type->self.size; + return strcmp(key->self.type_name, type->self.type_name); } static bool data_type_less(struct rb_node *node_a, const struct rb_node *node_b) @@ -42,9 +42,80 @@ static bool data_type_less(struct rb_node *node_a, const struct rb_node *node_b) a = rb_entry(node_a, struct annotated_data_type, node); b = rb_entry(node_b, struct annotated_data_type, node); - if (a->type_size != b->type_size) - return a->type_size < b->type_size; - return strcmp(a->type_name, b->type_name) < 0; + if (a->self.size != b->self.size) + return a->self.size < b->self.size; + return strcmp(a->self.type_name, b->self.type_name) < 0; +} + +/* Recursively add new members for struct/union */ +static int __add_member_cb(Dwarf_Die *die, void *arg) +{ + struct annotated_member *parent = arg; + struct annotated_member *member; + Dwarf_Die member_type, die_mem; + Dwarf_Word size, loc; + Dwarf_Attribute attr; + struct strbuf sb; + int tag; + + if (dwarf_tag(die) != DW_TAG_member) + return DIE_FIND_CB_SIBLING; + + member = zalloc(sizeof(*member)); + if (member == NULL) + return DIE_FIND_CB_END; + + strbuf_init(&sb, 32); + die_get_typename(die, &sb); + + die_get_real_type(die, &member_type); + if (dwarf_aggregate_size(&member_type, &size) < 0) + size = 0; + + if (!dwarf_attr_integrate(die, DW_AT_data_member_location, &attr)) + loc = 0; + else + dwarf_formudata(&attr, &loc); + + member->type_name = strbuf_detach(&sb, NULL); + /* member->var_name can be NULL */ + if (dwarf_diename(die)) + member->var_name = strdup(dwarf_diename(die)); + member->size = size; + member->offset = loc + parent->offset; + INIT_LIST_HEAD(&member->children); + list_add_tail(&member->node, &parent->children); + + tag = dwarf_tag(&member_type); + switch (tag) { + case DW_TAG_structure_type: + case DW_TAG_union_type: + die_find_child(&member_type, __add_member_cb, member, &die_mem); + break; + default: + break; + } + return DIE_FIND_CB_SIBLING; +} + +static void add_member_types(struct annotated_data_type *parent, Dwarf_Die *type) +{ + Dwarf_Die die_mem; + + die_find_child(type, __add_member_cb, &parent->self, &die_mem); +} + +static void delete_members(struct annotated_member *member) +{ + struct annotated_member *child, *tmp; + + list_for_each_entry_safe(child, tmp, &member->children, node) { + list_del(&child->node); + delete_members(child); + free(child->type_name); + free(child->var_name); + free(child); + } } static struct annotated_data_type *dso__findnew_data_type(struct dso *dso, @@ -64,8 +135,8 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso, dwarf_aggregate_size(type_die, &size); /* Check existing nodes in dso->data_types tree */ - key.type_name = type_name; - key.type_size = size; + key.self.type_name = type_name; + key.self.size = size; node = rb_find(&key, &dso->data_types, data_type_cmp); if (node) { result = rb_entry(node, struct annotated_data_type, node); @@ -80,8 +151,15 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso, return NULL; } - result->type_name = type_name; - result->type_size = size; + result->self.type_name = type_name; + result->self.size = size; + INIT_LIST_HEAD(&result->self.children); + + /* + * Fill member info unconditionally for now, + * later perf annotate would need it. + */ + add_member_types(result, type_die); rb_add(&result->node, &dso->data_types, data_type_less); return result; @@ -232,7 +310,8 @@ void annotated_data_type__tree_delete(struct rb_root *root) rb_erase(node, root); pos = rb_entry(node, struct annotated_data_type, node); - free(pos->type_name); + delete_members(&pos->self); + free(pos->self.type_name); free(pos); } } diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 6efdd7e21b28..33748222e6aa 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -9,17 +9,36 @@ struct map_symbol; +/** + * struct annotated_member - Type of member field + * @node: List entry in the parent list + * @children: List head for child nodes + * @type_name: Name of the member type + * @var_name: Name of the member variable + * @offset: Offset from the outer data type + * @size: Size of the member field + * + * This represents a member type in a data type. + */ +struct annotated_member { + struct list_head node; + struct list_head children; + char *type_name; + char *var_name; + int offset; + int size; +}; + /** * struct annotated_data_type - Data type to profile - * @type_name: Name of the data type - * @type_size: Size of the data type + * @node: RB-tree node for dso->type_tree + * @self: Actual type information * * This represents a data type accessed by samples in the profile data. */ struct annotated_data_type { struct rb_node node; - char *type_name; - int type_size; + struct annotated_member self; }; extern struct annotated_data_type unknown_type; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index e647f0117bb5..a41209e242ae 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2135,7 +2135,10 @@ struct sort_entry sort_addr = { /* --sort type */ struct annotated_data_type unknown_type = { - .type_name = (char *)"(unknown)", + .self = { + .type_name = (char *)"(unknown)", + .children = LIST_HEAD_INIT(unknown_type.self.children), + }, }; static int64_t @@ -2170,7 +2173,7 @@ sort__type_collapse(struct hist_entry *left, struct hist_entry *right) right_type = right->mem_type; } - return strcmp(left_type->type_name, right_type->type_name); + return strcmp(left_type->self.type_name, right_type->self.type_name); } static int64_t @@ -2182,7 +2185,7 @@ sort__type_sort(struct hist_entry *left, struct hist_entry *right) static int hist_entry__type_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%-*s", width, he->mem_type->type_name); + return repsep_snprintf(bf, size, "%-*s", width, he->mem_type->self.type_name); } struct sort_entry sort_type = { From patchwork Thu Nov 9 23:59:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451889 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DB6139855; Fri, 10 Nov 2023 00:00:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WnyNYorj" Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C1C084C25; Thu, 9 Nov 2023 16:00:47 -0800 (PST) Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-6b44befac59so2029360b3a.0; Thu, 09 Nov 2023 16:00:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574447; x=1700179247; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=WTfqQAAd/5CGutPceOaWOmUfDAEvCDKelyByybftScQ=; b=WnyNYorj7WJz73tPkjAjyVYjXziAiGpTJKDzZPiZaKtGC9Tbv6KOc0sOz8sgRq8q6F cEdEvPfCWKy6jQ5AFxU3hoj6ZMN1riDbvXGyTNwJlRviUxvJlnwxgLA19KwVLuA+1q2M 3IwmQRjwFQ9N360uZrcqBUmsJ5AJq7knWONQdFpy+ApBzE0HBwoGt+aQWIel22zmjlTQ 6afjgIRt3ZlGPn9vetoVwY3aR5lv4G4zJjQkjRk9CJdj7+iMqwc9VyFp0WfGMcLFqx9U TecK04pU+SdExhxeFVsZpXH2OiEzfzfCycsmztdYYw31pEXnjdasfIGe/DEBQQMymqhN r3GA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574447; x=1700179247; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=WTfqQAAd/5CGutPceOaWOmUfDAEvCDKelyByybftScQ=; b=RoyY4vwwdqH9LbKAspJtV52FvEAYjYRH0Wkoiu4E0fbHoL8cxtCazvSDdc3HnL6xWQ 0fathkQeH47qm+Krm6wLihQgIT+8e+l40R6rSnMCPNZqtUqsjo2vW9e5HjKY46KiOnj2 hdY8oO28OOrUwYa0C0pmzXyS8llMSGplscL7X6eZiGUQonfXp0fJuFk1uQD82mTEvQIs x8eJecq2a0TJ+fONVH5C82OTo1MseeBv3pBvlyiTlJk+isKZ7McK6/haixA5o9ADGwwy klhWRTc8AUkG4YeuXMpHhCaygCpVymggzz6NvahGzcmw2QRwUSDjmEr/5KEXRYVd7d2B cb0Q== X-Gm-Message-State: AOJu0YzPgymmxz4HUJ1CUYh49Vp6u3nB0slXkpROtQexsF/U+QActAnk IN6/rAByJo23R4C+Enz9sJI= X-Google-Smtp-Source: AGHT+IFDtVzKmhOafEaeGQXeKZ1pEB4GVk6NvLzvWbA7yxBkF0CE2fw7vmUNngao1c/RW1Qccn3CUA== X-Received: by 2002:a17:90a:b803:b0:280:37a0:69d4 with SMTP id n3-20020a17090ab80300b0028037a069d4mr1181822pjr.19.1699574446942; Thu, 09 Nov 2023 16:00:46 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:46 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 21/52] perf annotate-data: Update sample histogram for type Date: Thu, 9 Nov 2023 15:59:40 -0800 Message-ID: <20231110000012.3538610-22-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The annotated_data_type__update_samples() to get histogram for data type access. It'll be called by perf annotate to show which fields in the data type are accessed frequently. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 81 +++++++++++++++++++++++++++++++++ tools/perf/util/annotate-data.h | 42 +++++++++++++++++ tools/perf/util/annotate.c | 9 +++- 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 107e3248a541..3c452d037948 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -12,6 +12,8 @@ #include "debuginfo.h" #include "debug.h" #include "dso.h" +#include "evsel.h" +#include "evlist.h" #include "map.h" #include "map_symbol.h" #include "strbuf.h" @@ -301,6 +303,44 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, return result; } +static int alloc_data_type_histograms(struct annotated_data_type *adt, int nr_entries) +{ + int i; + size_t sz = sizeof(struct type_hist); + + sz += sizeof(struct type_hist_entry) * adt->self.size; + + /* Allocate a table of pointers for each event */ + adt->nr_histograms = nr_entries; + adt->histograms = calloc(nr_entries, sizeof(*adt->histograms)); + if (adt->histograms == NULL) + return -ENOMEM; + + /* + * Each histogram is allocated for the whole size of the type. + * TODO: Probably we can move the histogram to members. + */ + for (i = 0; i < nr_entries; i++) { + adt->histograms[i] = zalloc(sz); + if (adt->histograms[i] == NULL) + goto err; + } + return 0; + +err: + while (--i >= 0) + free(adt->histograms[i]); + free(adt->histograms); + return -ENOMEM; +} + +static void delete_data_type_histograms(struct annotated_data_type *adt) +{ + for (int i = 0; i < adt->nr_histograms; i++) + free(adt->histograms[i]); + free(adt->histograms); +} + void annotated_data_type__tree_delete(struct rb_root *root) { struct annotated_data_type *pos; @@ -311,7 +351,48 @@ void annotated_data_type__tree_delete(struct rb_root *root) rb_erase(node, root); pos = rb_entry(node, struct annotated_data_type, node); delete_members(&pos->self); + delete_data_type_histograms(pos); free(pos->self.type_name); free(pos); } } + +/** + * annotated_data_type__update_samples - Update histogram + * @adt: Data type to update + * @evsel: Event to update + * @offset: Offset in the type + * @nr_samples: Number of samples at this offset + * @period: Event count at this offset + * + * This function updates type histogram at @ofs for @evsel. Samples are + * aggregated before calling this function so it can be called with more + * than one samples at a certain offset. + */ +int annotated_data_type__update_samples(struct annotated_data_type *adt, + struct evsel *evsel, int offset, + int nr_samples, u64 period) +{ + struct type_hist *h; + + if (adt == NULL) + return 0; + + if (adt->histograms == NULL) { + int nr = evsel->evlist->core.nr_entries; + + if (alloc_data_type_histograms(adt, nr) < 0) + return -1; + } + + if (offset < 0 || offset >= adt->self.size) + return -1; + + h = adt->histograms[evsel->core.idx]; + + h->nr_samples += nr_samples; + h->addr[offset].nr_samples += nr_samples; + h->period += period; + h->addr[offset].period += period; + return 0; +} diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 33748222e6aa..d2dc025b1934 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -7,6 +7,7 @@ #include #include +struct evsel; struct map_symbol; /** @@ -29,16 +30,42 @@ struct annotated_member { int size; }; +/** + * struct type_hist_entry - Histogram entry per offset + * @nr_samples: Number of samples + * @period: Count of event + */ +struct type_hist_entry { + int nr_samples; + u64 period; +}; + +/** + * struct type_hist - Type histogram for each event + * @nr_samples: Total number of samples in this data type + * @period: Total count of the event in this data type + * @offset: Array of histogram entry + */ +struct type_hist { + u64 nr_samples; + u64 period; + struct type_hist_entry addr[]; +}; + /** * struct annotated_data_type - Data type to profile * @node: RB-tree node for dso->type_tree * @self: Actual type information + * @nr_histogram: Number of histogram entries + * @histograms: An array of pointers to histograms * * This represents a data type accessed by samples in the profile data. */ struct annotated_data_type { struct rb_node node; struct annotated_member self; + int nr_histograms; + struct type_hist **histograms; }; extern struct annotated_data_type unknown_type; @@ -49,6 +76,11 @@ extern struct annotated_data_type unknown_type; struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, int reg, int offset); +/* Update type access histogram at the given offset */ +int annotated_data_type__update_samples(struct annotated_data_type *adt, + struct evsel *evsel, int offset, + int nr_samples, u64 period); + /* Release all data type information in the tree */ void annotated_data_type__tree_delete(struct rb_root *root); @@ -61,6 +93,16 @@ find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused, return NULL; } +static inline int +annotated_data_type__update_samples(struct annotated_data_type *adt __maybe_unused, + struct evsel *evsel __maybe_unused, + int offset __maybe_unused, + int nr_samples __maybe_unused, + u64 period __maybe_unused) +{ + return -1; +} + static inline void annotated_data_type__tree_delete(struct rb_root *root __maybe_unused) { } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index c08686b91861..049d6ba394bd 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3683,6 +3683,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) struct disasm_line *dl; struct annotated_insn_loc loc; struct annotated_op_loc *op_loc; + struct annotated_data_type *mem_type; u64 ip = he->ip; int i; @@ -3710,7 +3711,13 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) if (!op_loc->mem_ref) continue; - return find_data_type(ms, ip, op_loc->reg, op_loc->offset); + mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); + + annotated_data_type__update_samples(mem_type, evsel, + op_loc->offset, + he->stat.nr_events, + he->stat.period); + return mem_type; } return NULL; } From patchwork Thu Nov 9 23:59:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451890 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E418114290; Fri, 10 Nov 2023 00:00:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PTNZoxaO" Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8435046AF; Thu, 9 Nov 2023 16:00:49 -0800 (PST) Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-28023eadc70so1292033a91.2; Thu, 09 Nov 2023 16:00:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574449; x=1700179249; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=BRCqm2GnkYmrLuCjylP2f18LqkR0iX6lcZ1rY/e/O1s=; b=PTNZoxaOyGrU5x78JhEZOBreSu3Mmec4esEkMB3tzF0WLY3CA6CyCI0CSUXwt+8DYG d2w81TTF1g6Gim826PtHRdP92j4tAP9W7FeZkfR2Fnfcdk5FvLhsxdRUyHxAmof3Z/90 V8eRhxFOWL/086LQvX9JD/aATq/8J0mg3A7eyLwoHiq+AKmJ7jFKBav3PI+FVAxvH+5a V75DTQ65cR1liphkop3iCsAQKqgcx8fE2ejfSTIlLj3cPEt5TOI1+ElBER+nSCE6kkbH QdwDANyzwTFKQ7KPsW1O50svYwtXuGCZ+LsmAQD84mESl2iRY3QwUOz+qQ+clwrZKMra fC8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574449; x=1700179249; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=BRCqm2GnkYmrLuCjylP2f18LqkR0iX6lcZ1rY/e/O1s=; b=ZU6jDnzlSKiS3UG0Wwu8OnmnG2VDAHEFkEe4ScFxxCPkLrUegmL4egPxkoDF4sI9HT aUOUZdjTZKChM2EmS3paRhVJEfzmZTrZnH3iSmbRDOa5nKC4UzsA7IAKprE69/wZJOD3 1M0fqpNn35WuiiFHRB3By3hdEQP15SCiLxZSocrMZtvaptYIejTFac9h1JgZD+1/DRje YDdxlKP3gRd6gk109uHF07DFtxhzENiqNbzi3EcFpP/Zeyt1nubQOsjuZmx8jaD8qiPN FhC/qC7k7Yb0ndhNirUVUW41BC35W6lIYmO2TZKajH3a52EjCc7u9WQ0D+hDCa63p1Ll BZKA== X-Gm-Message-State: AOJu0Ywn8Ief9G6pkOxj1pW2N5m3YUfu9JQFPfo3M8qQEo4jDZR29pev EngEO65aQjaUh6GjYJwkO1U= X-Google-Smtp-Source: AGHT+IHFO55iZ4g4+DQZGg2ugAkjYW64pdtPH/chbAneIr2uFKK/XwoLQZTAEl1uS5FbFituC7sNDQ== X-Received: by 2002:a17:90b:4b12:b0:27d:882f:e6c5 with SMTP id lx18-20020a17090b4b1200b0027d882fe6c5mr3317267pjb.9.1699574448539; Thu, 09 Nov 2023 16:00:48 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:47 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 22/52] perf report: Add 'typeoff' sort key Date: Thu, 9 Nov 2023 15:59:41 -0800 Message-ID: <20231110000012.3538610-23-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The typeoff sort key shows the data type name, offset and the name of the field. This is useful to see which field in the struct is accessed most frequently. $ perf report -s type,typeoff --hierarchy --stdio ... # Overhead Data Type / Data Type Offset # ............ ............................ # ... 1.23% struct cfs_rq 0.19% struct cfs_rq +404 (throttle_count) 0.19% struct cfs_rq +0 (load.weight) 0.19% struct cfs_rq +336 (leaf_cfs_rq_list.next) 0.09% struct cfs_rq +272 (propagate) 0.09% struct cfs_rq +196 (removed.nr) 0.09% struct cfs_rq +80 (curr) 0.09% struct cfs_rq +544 (lt_b_children_throttled) 0.06% struct cfs_rq +320 (rq) Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-report.txt | 1 + tools/perf/util/annotate.c | 1 + tools/perf/util/hist.h | 1 + tools/perf/util/sort.c | 83 +++++++++++++++++++++++- tools/perf/util/sort.h | 2 + 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index aec34417090b..b57eb51b47aa 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -119,6 +119,7 @@ OPTIONS to the previous instruction in cycles. And currently supported only on X86 - simd: Flags describing a SIMD operation. "e" for empty Arm SVE predicate. "p" for partial Arm SVE predicate - type: Data type of sample memory access. + - typeoff: Offset in the data type of sample memory access. By default, comm, dso and symbol keys are used. (i.e. --sort comm,dso,symbol) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 049d6ba394bd..76309f1e6e39 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3717,6 +3717,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) op_loc->offset, he->stat.nr_events, he->stat.period); + he->mem_type_off = op_loc->offset; return mem_type; } return NULL; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 9bfed867f288..941176afcebc 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -83,6 +83,7 @@ enum hist_column { HISTC_ADDR, HISTC_SIMD, HISTC_TYPE, + HISTC_TYPE_OFFSET, HISTC_NR_COLS, /* Last entry */ }; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index a41209e242ae..d78e680d3988 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2153,8 +2153,10 @@ static void sort__type_init(struct hist_entry *he) return; he->mem_type = hist_entry__get_data_type(he); - if (he->mem_type == NULL) + if (he->mem_type == NULL) { he->mem_type = &unknown_type; + he->mem_type_off = 0; + } } static int64_t @@ -2198,6 +2200,84 @@ struct sort_entry sort_type = { .se_width_idx = HISTC_TYPE, }; +/* --sort typeoff */ + +static int64_t +sort__typeoff_sort(struct hist_entry *left, struct hist_entry *right) +{ + struct annotated_data_type *left_type = left->mem_type; + struct annotated_data_type *right_type = right->mem_type; + int64_t ret; + + if (!left_type) { + sort__type_init(left); + left_type = left->mem_type; + } + + if (!right_type) { + sort__type_init(right); + right_type = right->mem_type; + } + + ret = strcmp(left_type->self.type_name, right_type->self.type_name); + if (ret) + return ret; + return left->mem_type_off - right->mem_type_off; +} + +static void fill_member_name(char *buf, size_t sz, struct annotated_member *m, + int offset, bool first) +{ + struct annotated_member *child; + + if (list_empty(&m->children)) + return; + + list_for_each_entry(child, &m->children, node) { + if (child->offset <= offset && offset < child->offset + child->size) { + int len = 0; + + /* It can have anonymous struct/union members */ + if (child->var_name) { + len = scnprintf(buf, sz, "%s%s", + first ? "" : ".", child->var_name); + first = false; + } + + fill_member_name(buf + len, sz - len, child, offset, first); + return; + } + } +} + +static int hist_entry__typeoff_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width __maybe_unused) +{ + struct annotated_data_type *he_type = he->mem_type; + char buf[4096]; + + buf[0] = '\0'; + if (list_empty(&he_type->self.children)) + snprintf(buf, sizeof(buf), "no field"); + else + fill_member_name(buf, sizeof(buf), &he_type->self, + he->mem_type_off, true); + buf[4095] = '\0'; + + return repsep_snprintf(bf, size, "%s %+d (%s)", he_type->self.type_name, + he->mem_type_off, buf); +} + +struct sort_entry sort_type_offset = { + .se_header = "Data Type Offset", + .se_cmp = sort__type_cmp, + .se_collapse = sort__typeoff_sort, + .se_sort = sort__typeoff_sort, + .se_init = sort__type_init, + .se_snprintf = hist_entry__typeoff_snprintf, + .se_width_idx = HISTC_TYPE_OFFSET, +}; + struct sort_dimension { const char *name; @@ -2254,6 +2334,7 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_GLOBAL_RETIRE_LAT, "retire_lat", sort_global_p_stage_cyc), DIM(SORT_SIMD, "simd", sort_simd), DIM(SORT_ANNOTATE_DATA_TYPE, "type", sort_type), + DIM(SORT_ANNOTATE_DATA_TYPE_OFFSET, "typeoff", sort_type_offset), }; #undef DIM diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index aabf0b8331a3..d806adcc1e1e 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -113,6 +113,7 @@ struct hist_entry { u64 p_stage_cyc; u8 cpumode; u8 depth; + int mem_type_off; struct simd_flags simd_flags; /* We are added by hists__add_dummy_entry. */ @@ -247,6 +248,7 @@ enum sort_type { SORT_GLOBAL_RETIRE_LAT, SORT_SIMD, SORT_ANNOTATE_DATA_TYPE, + SORT_ANNOTATE_DATA_TYPE_OFFSET, /* branch stack specific sort keys */ __SORT_BRANCH_STACK, From patchwork Thu Nov 9 23:59:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451891 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4824A39855; Fri, 10 Nov 2023 00:00:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hn34fM5w" Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F055146BB; Thu, 9 Nov 2023 16:00:50 -0800 (PST) Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1cc394f4cdfso12438565ad.0; Thu, 09 Nov 2023 16:00:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574450; x=1700179250; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=fZWD+Xm8A+pCVGPG3VW7Xs9+o4dQn/qSi3meRIUI+UM=; b=hn34fM5w5RmF8tqgc7sNsruH71/1aIVQzBW2Va0q9FbxSj55YmUJNbJyX3BQj+Kw45 9aSPqfpBwJ4oEWMxsCUggIcTutC8gQDVx9pxJwWfBCBF40WuB0FHhXDnJJ9TNbJ5p8ja pF2xpQQU5bUq8W7vumKOvF+0xr+zovbrIwSCtHushRL+T2mFlKTgXCVKd5kJgfKo7w/a 6lo9X6CyW70aYtc0VsdOwiFBi3TtoJYiQOjWfaT5KOJZut7pJz60JTO1TIGJCQXAJ7Pr dbKZzGQyuISMf2/mxLUyjE2Sk5mLoNhMcXKiorKIjci8cP8lAvZhvd/fb4/ho3pCUxZg YcZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574450; x=1700179250; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=fZWD+Xm8A+pCVGPG3VW7Xs9+o4dQn/qSi3meRIUI+UM=; b=XGE+EEiCP/Ffg6UmLigfr5aoDGVpJYsg5qx9ioGFx9lCvyHIv2p5DPinNoUyYmQZgR 8kqeaJaoY84O5JIp+Zgk7KpCEsogA5eNXXgzrJS0gOa/bSAA0uNQw37oX0CJmBXmCQwr 4bWkucmtdX+GmmtjybvTdnlcYACj85IIvvN5VhyDUvbza/YCt3H4CwXok4qJdIhAeQhN XPgs5Ba54bGV1rvpxRs8Oz7nUToarysD6te8r4WYgOXWravMt6errd/8IE1Ef/tIoB/D 5Id9UptH4qcnTiYWm7DpUWIMPKqsYQS+Dv1MiO2uXO5oBhyQbgjGFcK5nOAJE/pCiLOz qfFA== X-Gm-Message-State: AOJu0YzhlAEmSxgD88d6nTSGUzeRqRtLogJ2kLIu4MzLt/WTcb1hdhnw 8Pl0nuthnYEqjwCyOtT309s= X-Google-Smtp-Source: AGHT+IHQo/kRvhc5lrELJdyBLPwcI4/yzjO5UJkyDXIgoSSegO+ofnjbUFutrl06Gg0CDORkAkJNCA== X-Received: by 2002:a17:90b:390b:b0:280:2652:d4e with SMTP id ob11-20020a17090b390b00b0028026520d4emr2895128pjb.29.1699574450352; Thu, 09 Nov 2023 16:00:50 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:49 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 23/52] perf report: Add 'symoff' sort key Date: Thu, 9 Nov 2023 15:59:42 -0800 Message-ID: <20231110000012.3538610-24-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The symoff sort key is to print symbol and offset of sample. This is useful for data type profiling to show exact instruction in the function which refers the data. $ perf report -s type,sym,typeoff,symoff --hierarchy ... # Overhead Data Type / Symbol / Data Type Offset / Symbol Offset # .............. ..................................................... # 1.23% struct cfs_rq 0.84% update_blocked_averages 0.19% struct cfs_rq +336 (leaf_cfs_rq_list.next) 0.19% [k] update_blocked_averages+0x96 0.19% struct cfs_rq +0 (load.weight) 0.14% [k] update_blocked_averages+0x104 0.04% [k] update_blocked_averages+0x31c 0.17% struct cfs_rq +404 (throttle_count) 0.12% [k] update_blocked_averages+0x9d 0.05% [k] update_blocked_averages+0x1f9 0.08% struct cfs_rq +272 (propagate) 0.07% [k] update_blocked_averages+0x3d3 0.02% [k] update_blocked_averages+0x45b ... Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-report.txt | 1 + tools/perf/util/hist.h | 1 + tools/perf/util/sort.c | 47 ++++++++++++++++++++++++ tools/perf/util/sort.h | 1 + 4 files changed, 50 insertions(+) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index b57eb51b47aa..38f59ac064f7 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -120,6 +120,7 @@ OPTIONS - simd: Flags describing a SIMD operation. "e" for empty Arm SVE predicate. "p" for partial Arm SVE predicate - type: Data type of sample memory access. - typeoff: Offset in the data type of sample memory access. + - symoff: Offset in the symbol. By default, comm, dso and symbol keys are used. (i.e. --sort comm,dso,symbol) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 941176afcebc..1ce0ee262abe 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -84,6 +84,7 @@ enum hist_column { HISTC_SIMD, HISTC_TYPE, HISTC_TYPE_OFFSET, + HISTC_SYMBOL_OFFSET, HISTC_NR_COLS, /* Last entry */ }; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index d78e680d3988..0cbbd5ba8175 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -419,6 +419,52 @@ struct sort_entry sort_sym = { .se_width_idx = HISTC_SYMBOL, }; +/* --sort symoff */ + +static int64_t +sort__symoff_cmp(struct hist_entry *left, struct hist_entry *right) +{ + int64_t ret; + + ret = sort__sym_cmp(left, right); + if (ret) + return ret; + + return left->ip - right->ip; +} + +static int64_t +sort__symoff_sort(struct hist_entry *left, struct hist_entry *right) +{ + int64_t ret; + + ret = sort__sym_sort(left, right); + if (ret) + return ret; + + return left->ip - right->ip; +} + +static int +hist_entry__symoff_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) +{ + struct symbol *sym = he->ms.sym; + + if (sym == NULL) + return repsep_snprintf(bf, size, "[%c] %-#.*llx", he->level, width - 4, he->ip); + + return repsep_snprintf(bf, size, "[%c] %s+0x%llx", he->level, sym->name, he->ip - sym->start); +} + +struct sort_entry sort_sym_offset = { + .se_header = "Symbol Offset", + .se_cmp = sort__symoff_cmp, + .se_sort = sort__symoff_sort, + .se_snprintf = hist_entry__symoff_snprintf, + .se_filter = hist_entry__sym_filter, + .se_width_idx = HISTC_SYMBOL_OFFSET, +}; + /* --sort srcline */ char *hist_entry__srcline(struct hist_entry *he) @@ -2335,6 +2381,7 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_SIMD, "simd", sort_simd), DIM(SORT_ANNOTATE_DATA_TYPE, "type", sort_type), DIM(SORT_ANNOTATE_DATA_TYPE_OFFSET, "typeoff", sort_type_offset), + DIM(SORT_SYM_OFFSET, "symoff", sort_sym_offset), }; #undef DIM diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index d806adcc1e1e..6f6b4189a389 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -249,6 +249,7 @@ enum sort_type { SORT_SIMD, SORT_ANNOTATE_DATA_TYPE, SORT_ANNOTATE_DATA_TYPE_OFFSET, + SORT_SYM_OFFSET, /* branch stack specific sort keys */ __SORT_BRANCH_STACK, From patchwork Thu Nov 9 23:59:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451892 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFC075687; Fri, 10 Nov 2023 00:00:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QEmsw5Ib" Received: from mail-pg1-x529.google.com (mail-pg1-x529.google.com [IPv6:2607:f8b0:4864:20::529]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A6325478B; Thu, 9 Nov 2023 16:00:52 -0800 (PST) Received: by mail-pg1-x529.google.com with SMTP id 41be03b00d2f7-5b9390d6bd3so2052782a12.0; Thu, 09 Nov 2023 16:00:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574452; x=1700179252; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=z3p/0qsKuHXZ71nZRToEzeJmSxz+5PnmASt9/Ym8sAw=; b=QEmsw5IbPNVdeVM+E4OQ4Ow4pnYZdm6CoOAmjvApS45/Nw82jjXApR9q+f+LER8SGf +JD8VALlt//G//lTkF2L9pbGguCnzxQ4E9eBAZ+RIkhEnmvq8whxG8WmxwtSzMInIsYt EgHovb61zNo2Mt5lxDj17HeLjqZ79tXgIz5t+I3D6GLtpYSlcIYKGd+oSO3gwbKXJmuF 4guCMZw1zTztwKnO7sI3VNIu9PuPOmoW6T2XDggFPqdaccaq4NRRNd3ha1iFdt3xYaS5 g3ZwLJS0zCQcUBKC8B2igLy/vAL+5o0WFPqsrnQ4a71LoIjFeDyGGVENJ+NcV/4ESg3F 6bow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574452; x=1700179252; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=z3p/0qsKuHXZ71nZRToEzeJmSxz+5PnmASt9/Ym8sAw=; b=QksSmjfcrZxMIwGLjSCz7BuVteUiDyEJVH+7/ew9yi3UxXKvUHDB3w7J7n7ewokcSo Jg4or0+e7Hc9PybuFf+Vv+wF6ViSWPZ5YiV2u45LEO9QnEz4n2M2PImD4khrJAoIlozy usPJzQ8Rz0JzvJ9nVPvlF7c/29ECxxNYNzdSInOzsXlRKQGNnX5IDeNODLpDbS+UTSfg 7IJJUO7uGZs8jGcjww+QA5aWrzw957+5+RV6GolvvCrrdpjKRZ0NMZgTuPYrMA9pGGV6 u78gNGsm6Dwv8ecrXSYXB3MNIjoP+6q2KgpWgUoITC4Z1ZsMXeoKYq2/u2G9WfebNqfr 554g== X-Gm-Message-State: AOJu0Yyr5PqEoKL2EcP4dz7oJVokgn6E39xCfRqYyasUaUKff2hQArJz jZVyrFLYqzlr7QxWHdflH9U= X-Google-Smtp-Source: AGHT+IE7GjZMCJt+06XhSqkg7mgNP+8BVanL2EdM0Rmo1Tvvp4/L5bEoFMLOSvJsztFe3SNtnY5LGg== X-Received: by 2002:a17:90b:11c1:b0:277:68c3:64b9 with SMTP id gv1-20020a17090b11c100b0027768c364b9mr1200733pjb.5.1699574451924; Thu, 09 Nov 2023 16:00:51 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:51 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 24/52] perf annotate: Add --data-type option Date: Thu, 9 Nov 2023 15:59:43 -0800 Message-ID: <20231110000012.3538610-25-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Support data type annotation with new --data-type option. It internally uses type sort key to collect sample histogram for the type and display every members like below. $ perf annotate --data-type ... Annotate type: 'struct cfs_rq' in [kernel.kallsyms] (13 samples): ============================================================================ samples offset size field 13 0 640 struct cfs_rq { 2 0 16 struct load_weight load { 2 0 8 unsigned long weight; 0 8 4 u32 inv_weight; }; 0 16 8 unsigned long runnable_weight; 0 24 4 unsigned int nr_running; 1 28 4 unsigned int h_nr_running; ... For simplicity it prints the number of samples per field for now. But it should be easy to show the overhead percentage instead. The number at the outer struct is a sum of the numbers of the inner members. For example, struct cfs_rq got total 13 samples, and 2 came from the load (struct load_weight) and 1 from h_nr_running. Similarly, the struct load_weight got total 2 samples and they all came from the weight field. I've added two new flags in the symbol_conf for this. The annotate_data_member is to get the members of the type. This is also needed for perf report with typeoff sort key. The annotate_data_sample is to update sample stats for each offset and used only in annotate. Currently it only support stdio output mode, TUI support can be added later. Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-annotate.txt | 8 ++ tools/perf/builtin-annotate.c | 94 +++++++++++++++++++++- tools/perf/util/annotate-data.c | 8 +- tools/perf/util/annotate.c | 10 ++- tools/perf/util/sort.c | 2 + tools/perf/util/symbol_conf.h | 4 +- 6 files changed, 115 insertions(+), 11 deletions(-) diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index fe168e8165c8..0e6a49b7795c 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -155,6 +155,14 @@ include::itrace.txt[] stdio or stdio2 (Default: 0). Note that this is about selection of functions to display, not about lines within the function. +--data-type[=TYPE_NAME]:: + Display data type annotation instead of code. It infers data type of + samples (if they are memory accessing instructions) using DWARF debug + information. It can take an optional argument of data type name. In + that case it'd show annotation for the type only, otherwise it'd show + all data types it finds. + + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index a9129b51d511..2290ce3bdc2e 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -20,6 +20,7 @@ #include "util/evlist.h" #include "util/evsel.h" #include "util/annotate.h" +#include "util/annotate-data.h" #include "util/event.h" #include #include "util/parse-events.h" @@ -56,9 +57,11 @@ struct perf_annotate { bool skip_missing; bool has_br_stack; bool group_set; + bool data_type; float min_percent; const char *sym_hist_filter; const char *cpu_list; + const char *target_data_type; DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); }; @@ -234,8 +237,12 @@ static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, { struct hists *hists = evsel__hists(evsel); struct hist_entry *he; + struct annotation *notes = al->sym ? symbol__annotation(al->sym) : NULL; int ret; + if (notes) + notes->options = &ann->opts; + if ((!ann->has_br_stack || !has_annotation(ann)) && ann->sym_hist_filter != NULL && (al->sym == NULL || @@ -323,6 +330,32 @@ static int hist_entry__tty_annotate(struct hist_entry *he, return symbol__tty_annotate2(&he->ms, evsel, &ann->opts); } +static void print_annotated_data_type(struct annotated_data_type *mem_type, + struct annotated_member *member, + struct evsel *evsel, int indent) +{ + struct annotated_member *child; + struct type_hist *h = mem_type->histograms[evsel->core.idx]; + int i, samples = 0; + + for (i = 0; i < member->size; i++) + samples += h->addr[member->offset + i].nr_samples; + + printf(" %10d %10d %10d %*s%s\t%s", + samples, member->offset, member->size, indent, "", member->type_name, + member->var_name ?: ""); + + if (!list_empty(&member->children)) + printf(" {\n"); + + list_for_each_entry(child, &member->children, node) + print_annotated_data_type(mem_type, child, evsel, indent + 4); + + if (!list_empty(&member->children)) + printf("%*s}", 35 + indent, ""); + printf(";\n"); +} + static void hists__find_annotations(struct hists *hists, struct evsel *evsel, struct perf_annotate *ann) @@ -362,6 +395,40 @@ static void hists__find_annotations(struct hists *hists, continue; } + if (ann->data_type) { + struct map *map = he->ms.map; + + /* skip unknown type */ + if (he->mem_type->histograms == NULL) + goto find_next; + + if (ann->target_data_type) { + const char *type_name = he->mem_type->self.type_name; + + /* skip 'struct ' prefix in the type name */ + if (strncmp(ann->target_data_type, "struct ", 7) && + !strncmp(type_name, "struct ", 7)) + type_name += 7; + + /* skip 'union ' prefix in the type name */ + if (strncmp(ann->target_data_type, "union ", 6) && + !strncmp(type_name, "union ", 6)) + type_name += 6; + + if (strcmp(ann->target_data_type, type_name)) + goto find_next; + } + + printf("Annotate type: '%s' in %s (%d samples):\n", + he->mem_type->self.type_name, map->dso->name, he->stat.nr_events); + printf("============================================================================\n"); + printf(" %10s %10s %10s %s\n", "samples", "offset", "size", "field"); + + print_annotated_data_type(he->mem_type, &he->mem_type->self, evsel, 0); + printf("\n"); + goto find_next; + } + if (use_browser == 2) { int ret; int (*annotate)(struct hist_entry *he, @@ -498,6 +565,17 @@ static int parse_percent_limit(const struct option *opt, const char *str, return 0; } +static int parse_data_type(const struct option *opt, const char *str, int unset) +{ + struct perf_annotate *ann = opt->value; + + ann->data_type = !unset; + if (str) + ann->target_data_type = strdup(str); + + return 0; +} + static const char * const annotate_usage[] = { "perf annotate []", NULL @@ -609,6 +687,9 @@ int cmd_annotate(int argc, const char **argv) OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", "Instruction Tracing options\n" ITRACE_HELP, itrace_parse_synth_opts), + OPT_CALLBACK_OPTARG(0, "data-type", &annotate, NULL, "name", + "Show data type annotate for the memory accesses", + parse_data_type), OPT_END() }; @@ -705,6 +786,14 @@ int cmd_annotate(int argc, const char **argv) use_browser = 2; #endif + /* FIXME: only support stdio for now */ + if (annotate.data_type) { + use_browser = 0; + annotate.opts.annotate_src = false; + symbol_conf.annotate_data_member = true; + symbol_conf.annotate_data_sample = true; + } + setup_browser(true); /* @@ -712,7 +801,10 @@ int cmd_annotate(int argc, const char **argv) * symbol, we do not care about the processes in annotate, * set sort order to avoid repeated output. */ - sort_order = "dso,symbol"; + if (annotate.data_type) + sort_order = "dso,type"; + else + sort_order = "dso,symbol"; /* * Set SORT_MODE__BRANCH so that annotate display IPC/Cycle diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 3c452d037948..5326396b08ec 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -18,6 +18,7 @@ #include "map_symbol.h" #include "strbuf.h" #include "symbol.h" +#include "symbol_conf.h" /* * Compare type name and size to maintain them in a tree. @@ -157,11 +158,8 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso, result->self.size = size; INIT_LIST_HEAD(&result->self.children); - /* - * Fill member info unconditionally for now, - * later perf annotate would need it. - */ - add_member_types(result, type_die); + if (symbol_conf.annotate_data_member) + add_member_types(result, type_die); rb_add(&result->node, &dso->data_types, data_type_less); return result; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 76309f1e6e39..4d725562fd0a 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3713,10 +3713,12 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); - annotated_data_type__update_samples(mem_type, evsel, - op_loc->offset, - he->stat.nr_events, - he->stat.period); + if (symbol_conf.annotate_data_sample) { + annotated_data_type__update_samples(mem_type, evsel, + op_loc->offset, + he->stat.nr_events, + he->stat.period); + } he->mem_type_off = op_loc->offset; return mem_type; } diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 0cbbd5ba8175..30254eb63709 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -3401,6 +3401,8 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok, list->thread = 1; } else if (sd->entry == &sort_comm) { list->comm = 1; + } else if (sd->entry == &sort_type_offset) { + symbol_conf.annotate_data_member = true; } return __sort_dimension__add(sd, list, level); diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h index 6040286e07a6..c114bbceef40 100644 --- a/tools/perf/util/symbol_conf.h +++ b/tools/perf/util/symbol_conf.h @@ -44,7 +44,9 @@ struct symbol_conf { buildid_mmap2, guest_code, lazy_load_kernel_maps, - keep_exited_threads; + keep_exited_threads, + annotate_data_member, + annotate_data_sample; const char *vmlinux_name, *kallsyms_name, *source_prefix, From patchwork Thu Nov 9 23:59:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451893 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6DCA1DDAD; Fri, 10 Nov 2023 00:00:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UrghWcXL" Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 27D8D4C28; Thu, 9 Nov 2023 16:00:54 -0800 (PST) Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-282e3beb418so1387360a91.0; Thu, 09 Nov 2023 16:00:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574453; x=1700179253; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=ZBPueJvgwiS4jbMZ32+YHhWj7LPDThqjPdS48KXuEko=; b=UrghWcXLKPW7mopPOEUgxZlMZI+CtiysiZ2TXGkze24aQ1nKGMiWARmzScNRMQZ7RJ Sfxep8kPlxQ+ADLhgODqbFXdW+eD8IFGxl3+3ND/vyzFxaB7N+vozb0tqhaYxW6bI+Zk Ht4zH2LMqRjD544qNt0tkrd7jY4IKhelhuzFMm8/O5kwGrgLObCCr9oAavNyTzrQCVlR 5abiBjwtcyuNsQL5aLQjxgpVEeSz0Hj4ZvkRqqow5zMi3IfqqqziucEZF4VnySJ9Lqi4 AOEQjS7dSnEJ1ListPKwYVQA5i7yrIuYkn2LJ9QbmJgyUTjD0j1rUEx5maK4qbnzXZfh VD+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574453; x=1700179253; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ZBPueJvgwiS4jbMZ32+YHhWj7LPDThqjPdS48KXuEko=; b=KimWzzlh58lduIiEtiAyXAp4Q8l8h8eWcmFKV0nbMUQ4d2OrEJt1B+zECSm4xM1trz 2cQNMM0T9fQpdM+u1x9yeZuOZBRx75OPBxg6SpHKs2DvZuvtaN7+4LwSCl0y039rfDU3 w6L2dlgY3WkoXVVLEAYQE6rwF7VmkJrthYf4wsgS9cwh5nL6/j28ozTy/vaETRCgXGtC /wI1BeE7P08mcvhVyTQfvfv1YzOYW/6HoMwbStlNIECYhGrR8AQe5jkZG0Xyf2fYZyME 3c1sv3D9mSFwmtFkMC+RFxxRN0smsvk3oYdk6rWty/2whrEQJVpD9KyptiMVBCyM/uYS +Lnw== X-Gm-Message-State: AOJu0Yy2NmZMFkhThDi9sZmhZP1ghqx4LC6SMNSq/32txqIihoyTuTaB 9UAlDrVSZ7HPbSzeVHOEdgo= X-Google-Smtp-Source: AGHT+IGXhnm2PrbjKXH9oJ3EqaCbBZdb/2qU0WaQVC9ZbmHqg1p2uSRGngvgatFefhxbYMDult/NBQ== X-Received: by 2002:a17:90b:4c10:b0:280:c0:9d3f with SMTP id na16-20020a17090b4c1000b0028000c09d3fmr3411524pjb.34.1699574453531; Thu, 09 Nov 2023 16:00:53 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:52 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 25/52] perf annotate: Support event group display Date: Thu, 9 Nov 2023 15:59:44 -0800 Message-ID: <20231110000012.3538610-26-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When events are grouped together, it'd be natural to show them at once like in other mode. Handle group leaders with members to collect the number of samples together and display like below: $ perf annotate --data-type --group ... Annotate type: 'struct page' in vmlinux (1 samples): event[0] = cpu/mem-loads,ldlat=30/P event[1] = cpu/mem-stores/P event[2] = dummy:u ============================================================================ samples offset size field 1 0 0 0 64 struct page { 0 0 0 0 8 long unsigned int flags; 0 0 0 8 40 union { 0 0 0 8 40 struct { 0 0 0 8 16 union { 0 0 0 8 16 struct list_head lru { 0 0 0 8 8 struct list_head* next; 0 0 0 16 8 struct list_head* prev; }; 0 0 0 8 16 struct { 0 0 0 8 8 void* __filler; 0 0 0 16 4 unsigned int mlock_count; }; 0 0 0 8 16 struct list_head buddy_list { 0 0 0 8 8 struct list_head* next; 0 0 0 16 8 struct list_head* prev; }; Signed-off-by: Namhyung Kim --- tools/perf/builtin-annotate.c | 89 ++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 12 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 2290ce3bdc2e..7e4ef93b19a0 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -330,19 +330,64 @@ static int hist_entry__tty_annotate(struct hist_entry *he, return symbol__tty_annotate2(&he->ms, evsel, &ann->opts); } +static void print_annotated_data_header(struct hist_entry *he, struct evsel *evsel) +{ + struct map *map = he->ms.map; + int nr_members = 1; + int nr_samples = he->stat.nr_events; + + if (evsel__is_group_event(evsel)) { + struct hist_entry *pair; + + list_for_each_entry(pair, &he->pairs.head, pairs.node) + nr_samples += pair->stat.nr_events; + } + + printf("Annotate type: '%s' in %s (%d samples):\n", + he->mem_type->self.type_name, map->dso->name, nr_samples); + + if (evsel__is_group_event(evsel)) { + struct evsel *pos; + int i = 0; + + for_each_group_evsel(pos, evsel) + printf(" event[%d] = %s\n", i++, pos->name); + + nr_members = evsel->core.nr_members; + } + + printf("============================================================================\n"); + printf("%*s %10s %10s %s\n", 11 * nr_members, "samples", "offset", "size", "field"); +} + static void print_annotated_data_type(struct annotated_data_type *mem_type, struct annotated_member *member, struct evsel *evsel, int indent) { struct annotated_member *child; struct type_hist *h = mem_type->histograms[evsel->core.idx]; - int i, samples = 0; + int i, nr_events = 1, samples = 0; for (i = 0; i < member->size; i++) samples += h->addr[member->offset + i].nr_samples; + printf(" %10d", samples); + + if (evsel__is_group_event(evsel)) { + struct evsel *pos; + + for_each_group_member(pos, evsel) { + h = mem_type->histograms[pos->core.idx]; + + samples = 0; + for (i = 0; i < member->size; i++) + samples += h->addr[member->offset + i].nr_samples; + printf(" %10d", samples); + } + nr_events = evsel->core.nr_members; + } - printf(" %10d %10d %10d %*s%s\t%s", - samples, member->offset, member->size, indent, "", member->type_name, + printf(" %10d %10d %*s%s\t%s", + member->offset, member->size, indent, "", member->type_name, member->var_name ?: ""); if (!list_empty(&member->children)) @@ -352,7 +397,7 @@ static void print_annotated_data_type(struct annotated_data_type *mem_type, print_annotated_data_type(mem_type, child, evsel, indent + 4); if (!list_empty(&member->children)) - printf("%*s}", 35 + indent, ""); + printf("%*s}", 11 * nr_events + 24 + indent, ""); printf(";\n"); } @@ -396,8 +441,6 @@ static void hists__find_annotations(struct hists *hists, } if (ann->data_type) { - struct map *map = he->ms.map; - /* skip unknown type */ if (he->mem_type->histograms == NULL) goto find_next; @@ -419,11 +462,7 @@ static void hists__find_annotations(struct hists *hists, goto find_next; } - printf("Annotate type: '%s' in %s (%d samples):\n", - he->mem_type->self.type_name, map->dso->name, he->stat.nr_events); - printf("============================================================================\n"); - printf(" %10s %10s %10s %s\n", "samples", "offset", "size", "field"); - + print_annotated_data_header(he, evsel); print_annotated_data_type(he->mem_type, &he->mem_type->self, evsel, 0); printf("\n"); goto find_next; @@ -527,8 +566,20 @@ static int __cmd_annotate(struct perf_annotate *ann) evsel__reset_sample_bit(pos, CALLCHAIN); evsel__output_resort(pos, NULL); - if (symbol_conf.event_group && !evsel__is_group_leader(pos)) + /* + * An event group needs to display other events too. + * Let's delay printing until other events are processed. + */ + if (symbol_conf.event_group) { + if (!evsel__is_group_leader(pos)) { + struct hists *leader_hists; + + leader_hists = evsel__hists(evsel__leader(pos)); + hists__match(leader_hists, hists); + hists__link(leader_hists, hists); + } continue; + } hists__find_annotations(hists, pos, ann); } @@ -539,6 +590,20 @@ static int __cmd_annotate(struct perf_annotate *ann) goto out; } + /* Display group events together */ + evlist__for_each_entry(session->evlist, pos) { + struct hists *hists = evsel__hists(pos); + u32 nr_samples = hists->stats.nr_samples; + + if (nr_samples == 0) + continue; + + if (!symbol_conf.event_group || !evsel__is_group_leader(pos)) + continue; + + hists__find_annotations(hists, pos, ann); + } + if (use_browser == 2) { void (*show_annotations)(void); From patchwork Thu Nov 9 23:59:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451894 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A5B9539875; Fri, 10 Nov 2023 00:00:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VTF5oqgj" Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A7A304C38; Thu, 9 Nov 2023 16:00:55 -0800 (PST) Received: by mail-pj1-x102b.google.com with SMTP id 98e67ed59e1d1-2809b4d648bso1368931a91.2; Thu, 09 Nov 2023 16:00:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574455; x=1700179255; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=bLPs+b2+I6kBBMczH7djDlQ1eMDA2/OeXGnP74ag0eE=; b=VTF5oqgjc6sCxtGBZ/c6C7jpRK/6YllMRLSvjq+9fDGI1LqStvohOSuW4uRs4MWHB4 bGvC1QeFSoBQzNZq3f/rH16ix4TpXChkV2DFtA7i8qOFyIVzfggfA7CMY2NSY++CcSp2 bRPKw+QoR112jdGtZgjGl2FIv8pTp7ek63nRY5GG5IQP3ypMOWUxYk9W+JKOacY/lrWb l01PPXgeXWJJIpcjXqUTRKlxuuUvrm2lZHq+IlUTZ89NBfy5Rz65MMrBFAekAksPpifj YnatzJ9s8ayjPXpTf0vK0P0UJTuABP2MathpwJ5qvWNTwT68ojzcl0/yPFqRBDxdRKvJ b9Gw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574455; x=1700179255; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bLPs+b2+I6kBBMczH7djDlQ1eMDA2/OeXGnP74ag0eE=; b=Fehc3BQlJW33R5QmwpdQWBgT8NMgMX3h1gk8t0dHM8HSnE/LOrpLGYD5HKaiU26GEv +dEuTMfE70bARWe7oXKwhATKMRbLQq6/EsQ07hLRNvmPu0KN5TFQGOH000XGT+Cg5km4 MSJ79USwPea+S68Mx8/5MR9BOj97u8Xq2IC9BxsmrwMOFt4TAknA20CVABWbOvMpuidq Ac7Ho9FCU/fcHcCuppKezXqq7MeGLg4+I9ckXfAPTxY43ccYUUM/6J5sAQsm6CHGw3zD 1tM5zUXAkFGAUVgERMTlIXg0EFVbm9gziXtDJRXyG+OG9A29sp+5fIQ59XjhlWKs3tLz ofQA== X-Gm-Message-State: AOJu0YySkoT00GVwGePQle2gn679vA3r7uuyD5OfeBab2Oh0Pdxq9M87 kNDpeMc/EMOAcbhL2Hz4xj+MmPW1oag= X-Google-Smtp-Source: AGHT+IH+fHpN05CKnOv88A1cfYBYqtI5MFpXw2R3wlzt1SUmD3XDEVQyIN6gtJcOZ1ADzVKqWIMYng== X-Received: by 2002:a17:90b:3909:b0:281:b37:2038 with SMTP id ob9-20020a17090b390900b002810b372038mr3291178pjb.1.1699574455054; Thu, 09 Nov 2023 16:00:55 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:54 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 26/52] perf annotate: Add --type-stat option for debugging Date: Thu, 9 Nov 2023 15:59:45 -0800 Message-ID: <20231110000012.3538610-27-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The --type-stat option is to be used with --data-type and to print detailed failure reasons for the data type annotation. $ perf annotate --data-type --type-stat Annotate data type stats: total 294, ok 116 (39.5%), bad 178 (60.5%) ----------------------------------------------------------- 30 : no_sym 40 : no_insn_ops 33 : no_mem_ops 63 : no_var 4 : no_typeinfo 8 : bad_offset Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-annotate.txt | 3 ++ tools/perf/builtin-annotate.c | 44 +++++++++++++++++++++- tools/perf/util/annotate-data.c | 10 ++++- tools/perf/util/annotate-data.h | 31 +++++++++++++++ tools/perf/util/annotate.c | 23 +++++++++-- 5 files changed, 105 insertions(+), 6 deletions(-) diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 0e6a49b7795c..b95524bea021 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -162,6 +162,9 @@ include::itrace.txt[] that case it'd show annotation for the type only, otherwise it'd show all data types it finds. +--type-stat:: + Show stats for the data type annotation. + SEE ALSO -------- diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 7e4ef93b19a0..e4fc00bc8fdf 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -58,6 +58,7 @@ struct perf_annotate { bool has_br_stack; bool group_set; bool data_type; + bool type_stat; float min_percent; const char *sym_hist_filter; const char *cpu_list; @@ -401,6 +402,43 @@ static void print_annotated_data_type(struct annotated_data_type *mem_type, printf(";\n"); } +static void print_annotate_data_stat(struct annotated_data_stat *s) +{ +#define PRINT_STAT(fld) if (s->fld) printf("%10d : %s\n", s->fld, #fld) + + int bad = s->no_sym + + s->no_insn + + s->no_insn_ops + + s->no_mem_ops + + s->no_reg + + s->no_dbginfo + + s->no_cuinfo + + s->no_var + + s->no_typeinfo + + s->invalid_size + + s->bad_offset; + int ok = s->total - bad; + + printf("Annotate data type stats:\n"); + printf("total %d, ok %d (%.1f%%), bad %d (%.1f%%)\n", + s->total, ok, 100.0 * ok / (s->total ?: 1), bad, 100.0 * bad / (s->total ?: 1)); + printf("-----------------------------------------------------------\n"); + PRINT_STAT(no_sym); + PRINT_STAT(no_insn); + PRINT_STAT(no_insn_ops); + PRINT_STAT(no_mem_ops); + PRINT_STAT(no_reg); + PRINT_STAT(no_dbginfo); + PRINT_STAT(no_cuinfo); + PRINT_STAT(no_var); + PRINT_STAT(no_typeinfo); + PRINT_STAT(invalid_size); + PRINT_STAT(bad_offset); + printf("\n"); + +#undef PRINT_STAT +} + static void hists__find_annotations(struct hists *hists, struct evsel *evsel, struct perf_annotate *ann) @@ -408,6 +446,9 @@ static void hists__find_annotations(struct hists *hists, struct rb_node *nd = rb_first_cached(&hists->entries), *next; int key = K_RIGHT; + if (ann->type_stat) + print_annotate_data_stat(&ann_data_stat); + while (nd) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); struct annotation *notes; @@ -755,7 +796,8 @@ int cmd_annotate(int argc, const char **argv) OPT_CALLBACK_OPTARG(0, "data-type", &annotate, NULL, "name", "Show data type annotate for the memory accesses", parse_data_type), - + OPT_BOOLEAN(0, "type-stat", &annotate.type_stat, + "Show stats for the data type annotation"), OPT_END() }; int ret; diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 5326396b08ec..79f09ce92f15 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -198,6 +198,7 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) /* Get the type of the variable */ if (die_get_real_type(var_die, type_die) == NULL) { pr_debug("variable has no type\n"); + ann_data_stat.no_typeinfo++; return -1; } @@ -208,18 +209,21 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) if (dwarf_tag(type_die) != DW_TAG_pointer_type || die_get_real_type(type_die, type_die) == NULL) { pr_debug("no pointer or no type\n"); + ann_data_stat.no_typeinfo++; return -1; } /* Get the size of the actual type */ if (dwarf_aggregate_size(type_die, &size) < 0) { pr_debug("type size is unknown\n"); + ann_data_stat.invalid_size++; return -1; } /* Minimal sanity check */ if ((unsigned)offset >= size) { pr_debug("offset: %d is bigger than size: %lu\n", offset, size); + ann_data_stat.bad_offset++; return -1; } @@ -238,6 +242,7 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, /* Get a compile_unit for this address */ if (!find_cu_die(di, pc, &cu_die)) { pr_debug("cannot find CU for address %lx\n", pc); + ann_data_stat.no_cuinfo++; return -1; } @@ -252,9 +257,12 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, /* Found a variable, see if it's correct */ ret = check_variable(&var_die, type_die, offset); - break; + goto out; } + if (ret < 0) + ann_data_stat.no_var++; +out: free(scopes); return ret; } diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index d2dc025b1934..8e73096c01d1 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -70,6 +70,37 @@ struct annotated_data_type { extern struct annotated_data_type unknown_type; +/** + * struct annotated_data_stat - Debug statistics + * @total: Total number of entry + * @no_sym: No symbol or map found + * @no_insn: Failed to get disasm line + * @no_insn_ops: The instruction has no operands + * @no_mem_ops: The instruction has no memory operands + * @no_reg: Failed to extract a register from the operand + * @no_dbginfo: The binary has no debug information + * @no_cuinfo: Failed to find a compile_unit + * @no_var: Failed to find a matching variable + * @no_typeinfo: Failed to get a type info for the variable + * @invalid_size: Failed to get a size info of the type + * @bad_offset: The access offset is out of the type + */ +struct annotated_data_stat { + int total; + int no_sym; + int no_insn; + int no_insn_ops; + int no_mem_ops; + int no_reg; + int no_dbginfo; + int no_cuinfo; + int no_var; + int no_typeinfo; + int invalid_size; + int bad_offset; +}; +extern struct annotated_data_stat ann_data_stat; + #ifdef HAVE_DWARF_SUPPORT /* Returns data type at the location (ip, reg, offset) */ diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4d725562fd0a..c284a29979d6 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -100,6 +100,9 @@ static struct ins_ops nop_ops; static struct ins_ops lock_ops; static struct ins_ops ret_ops; +/* Data type collection debug statistics */ +struct annotated_data_stat ann_data_stat; + static int arch__grow_instructions(struct arch *arch) { struct ins *new_instructions; @@ -3687,11 +3690,17 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) u64 ip = he->ip; int i; - if (ms->map == NULL || ms->sym == NULL) + ann_data_stat.total++; + + if (ms->map == NULL || ms->sym == NULL) { + ann_data_stat.no_sym++; return NULL; + } - if (evsel__get_arch(evsel, &arch) < 0) + if (evsel__get_arch(evsel, &arch) < 0) { + ann_data_stat.no_insn++; return NULL; + } /* Make sure it runs objdump to get disasm of the function */ symbol__ensure_annotate(ms, evsel); @@ -3701,11 +3710,15 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) * This is too slow... */ dl = find_disasm_line(ms->sym, ip); - if (dl == NULL) + if (dl == NULL) { + ann_data_stat.no_insn++; return NULL; + } - if (annotate_get_insn_location(arch, dl, &loc) < 0) + if (annotate_get_insn_location(arch, dl, &loc) < 0) { + ann_data_stat.no_insn_ops++; return NULL; + } for_each_insn_op_loc(&loc, i, op_loc) { if (!op_loc->mem_ref) @@ -3722,5 +3735,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) he->mem_type_off = op_loc->offset; return mem_type; } + + ann_data_stat.no_mem_ops++; return NULL; } From patchwork Thu Nov 9 23:59:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451895 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 93572DDAD; Fri, 10 Nov 2023 00:00:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Eq0rnRph" Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 17CB8479C; Thu, 9 Nov 2023 16:00:57 -0800 (PST) Received: by mail-pj1-x102f.google.com with SMTP id 98e67ed59e1d1-280260db156so1276059a91.2; Thu, 09 Nov 2023 16:00:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574456; x=1700179256; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=0IiGmHiFZ7D8eBmQHmks1FISgbWWSEVYxrId79vUA9A=; b=Eq0rnRphh4YG20cPFNmkcSzETaKJt8nd1qDchWfJkuOKY1lxl7LPLrdDPykuWpVVp2 /IFc4KxpsdYlMok88fTnJL4Kr0Abtvr6AyKpdPHnTXTG+KDgg6B1O0J8AdwhaR1uiicE 2X0WdbZTMjRCZLtbX0t5VU6NpoECsLZaEec9zVmDeg+Z9ineF/r6g88Z5iVhefitxWvP phUj0/mH1SUlNVFM0zxTsXB5qEnXnVHKsbRt62332NuvVMG/GTYinEC2qRugk/ayCOVI 6FtE0JKbzBjKl32y52UF2nWeJxqUOw219jINWiV1S9dJ4I9qlbCuU20XpCdIbab4GAsD mpQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574456; x=1700179256; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=0IiGmHiFZ7D8eBmQHmks1FISgbWWSEVYxrId79vUA9A=; b=cmM9sqsRONLFZEhj2n745mYwc5HUltQiM4jCDK2AudVBas8vQb9Hv6hCGq2Pq6i+EA hrj33m8+XeUbmfsVNrFkUGoAZfjX0YLVKoWnF5ulOzvWjeBo8lfnc0C8kbzRm7ozJ6Od 92Ozuyyq9z9uf9tUFcEoE5F3FjBnHKEH5fDa8DzvdlNbA9KleHU8p4nOmQjJ0YQ8Hjzi Cg/IDQGSmxEa/snwZe1ZUGRdA/AmtI63gDL5hSvNG9OS+OXfH+/fAz/ws0F4ME1NlHFk LCJgvZE7ZKo1ajEd7IaF2mcp2soyB7csI3PaCSPKzgBh9AONCCdsCBUjo3u5HwSI0yzU 4bbA== X-Gm-Message-State: AOJu0YyUzgNNZZgW+jXavps+P8Ewt+UYNEtTSISKjfFqkSOtWUvOSBVC t3HGGvUXlwOqRtvzh56uafs= X-Google-Smtp-Source: AGHT+IGCWjduWpdUVjZXB56YDufm3cDQsD1BO7u6omVdHPoZzDMh6CJF+QlEpOMhRhOf5B+X6hWE3g== X-Received: by 2002:a17:90b:4d0f:b0:281:a69:4430 with SMTP id mw15-20020a17090b4d0f00b002810a694430mr3219663pjb.42.1699574456512; Thu, 09 Nov 2023 16:00:56 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:56 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 27/52] perf annotate: Add --insn-stat option for debugging Date: Thu, 9 Nov 2023 15:59:46 -0800 Message-ID: <20231110000012.3538610-28-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This is for a debugging purpose. It'd be useful to see per-instrucion level success/failure stats. $ perf annotate --data-type --insn-stat Annotate Instruction stats total 264, ok 143 (54.2%), bad 121 (45.8%) Name : Good Bad ----------------------------------------------------------- movq : 45 31 movl : 22 11 popq : 0 19 cmpl : 16 3 addq : 8 7 cmpq : 11 3 cmpxchgl : 3 7 cmpxchgq : 8 0 incl : 3 3 movzbl : 4 2 incq : 4 2 decl : 6 0 ... Signed-off-by: Namhyung Kim --- tools/perf/builtin-annotate.c | 41 +++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.c | 38 ++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 8 +++++++ 3 files changed, 87 insertions(+) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index e4fc00bc8fdf..9516d2dbc488 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -59,6 +59,7 @@ struct perf_annotate { bool group_set; bool data_type; bool type_stat; + bool insn_stat; float min_percent; const char *sym_hist_filter; const char *cpu_list; @@ -439,6 +440,42 @@ static void print_annotate_data_stat(struct annotated_data_stat *s) #undef PRINT_STAT } +static void print_annotate_item_stat(struct list_head *head, const char *title) +{ + struct annotated_item_stat *istat, *pos, *iter; + int total_good, total_bad, total; + int sum1, sum2; + LIST_HEAD(tmp); + + /* sort the list by count */ + list_splice_init(head, &tmp); + total_good = total_bad = 0; + + list_for_each_entry_safe(istat, pos, &tmp, list) { + total_good += istat->good; + total_bad += istat->bad; + sum1 = istat->good + istat->bad; + + list_for_each_entry(iter, head, list) { + sum2 = iter->good + iter->bad; + if (sum1 > sum2) + break; + } + list_move_tail(&istat->list, &iter->list); + } + total = total_good + total_bad; + + printf("Annotate %s stats\n", title); + printf("total %d, ok %d (%.1f%%), bad %d (%.1f%%)\n\n", total, + total_good, 100.0 * total_good / (total ?: 1), + total_bad, 100.0 * total_bad / (total ?: 1)); + printf(" %-10s: %5s %5s\n", "Name", "Good", "Bad"); + printf("-----------------------------------------------------------\n"); + list_for_each_entry(istat, head, list) + printf(" %-10s: %5d %5d\n", istat->name, istat->good, istat->bad); + printf("\n"); +} + static void hists__find_annotations(struct hists *hists, struct evsel *evsel, struct perf_annotate *ann) @@ -448,6 +485,8 @@ static void hists__find_annotations(struct hists *hists, if (ann->type_stat) print_annotate_data_stat(&ann_data_stat); + if (ann->insn_stat) + print_annotate_item_stat(&ann_insn_stat, "Instruction"); while (nd) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); @@ -798,6 +837,8 @@ int cmd_annotate(int argc, const char **argv) parse_data_type), OPT_BOOLEAN(0, "type-stat", &annotate.type_stat, "Show stats for the data type annotation"), + OPT_BOOLEAN(0, "insn-stat", &annotate.insn_stat, + "Show instruction stats for the data type annotation"), OPT_END() }; int ret; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index c284a29979d6..3ac601d70f61 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -102,6 +102,7 @@ static struct ins_ops ret_ops; /* Data type collection debug statistics */ struct annotated_data_stat ann_data_stat; +LIST_HEAD(ann_insn_stat); static int arch__grow_instructions(struct arch *arch) { @@ -3669,6 +3670,30 @@ static struct disasm_line *find_disasm_line(struct symbol *sym, u64 ip) return NULL; } +static struct annotated_item_stat *annotate_data_stat(struct list_head *head, + const char *name) +{ + struct annotated_item_stat *istat; + + list_for_each_entry(istat, head, list) { + if (!strcmp(istat->name, name)) + return istat; + } + + istat = zalloc(sizeof(*istat)); + if (istat == NULL) + return NULL; + + istat->name = strdup(name); + if (istat->name == NULL) { + free(istat); + return NULL; + } + + list_add_tail(&istat->list, head); + return istat; +} + /** * hist_entry__get_data_type - find data type for given hist entry * @he: hist entry @@ -3687,6 +3712,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) struct annotated_insn_loc loc; struct annotated_op_loc *op_loc; struct annotated_data_type *mem_type; + struct annotated_item_stat *istat; u64 ip = he->ip; int i; @@ -3715,8 +3741,15 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) return NULL; } + istat = annotate_data_stat(&ann_insn_stat, dl->ins.name); + if (istat == NULL) { + ann_data_stat.no_insn++; + return NULL; + } + if (annotate_get_insn_location(arch, dl, &loc) < 0) { ann_data_stat.no_insn_ops++; + istat->bad++; return NULL; } @@ -3725,6 +3758,10 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) continue; mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); + if (mem_type) + istat->good++; + else + istat->bad++; if (symbol_conf.annotate_data_sample) { annotated_data_type__update_samples(mem_type, evsel, @@ -3737,5 +3774,6 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) } ann_data_stat.no_mem_ops++; + istat->bad++; return NULL; } diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 06281a50ecf6..2cef96859e45 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -485,4 +485,12 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, /* Returns a data type from the sample instruction (if any) */ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he); +struct annotated_item_stat { + struct list_head list; + char *name; + int good; + int bad; +}; +extern struct list_head ann_insn_stat; + #endif /* __PERF_ANNOTATE_H */ From patchwork Thu Nov 9 23:59:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451896 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1EDC83986E; Fri, 10 Nov 2023 00:00:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MhvZQEh/" Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B645C4EC4; Thu, 9 Nov 2023 16:00:58 -0800 (PST) Received: by mail-pj1-x1031.google.com with SMTP id 98e67ed59e1d1-280260db156so1276076a91.2; Thu, 09 Nov 2023 16:00:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574458; x=1700179258; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=4VL5lFahygayw5UMi6X2ej0x4hwwXaVjpVtEOwOIuJ0=; b=MhvZQEh/BGG8l4eAag3n5BBmx2AC+35Qb+sllIKYUW/NjMiE2k1pZT758yErUjkTDv vn85WMTpGMPLWJl9RYFQS20e8tij23ZvTUFsWDUBS+o8q/xj81W7lUnh2kaz+KTSbnTL euXi8A9l2lTir8HWrpb8nzv4aCCajPBn23Sl/7cdhrlrW0yYUTatva6EhbNL9OtLOmFK qKjdJH+zPtHKBUZEQhrG59lyOl/2BZc1FuwDohRMMCWYQ2Eq5JwT5SlDrY0sWVLTxq3E 1TKlEFhypikbZmem8LW/i0/T9TqL5DLCLTkSs8oRpXZ3ogV2qw5/QUVlNKGjdvDl/Z+s iHLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574458; x=1700179258; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=4VL5lFahygayw5UMi6X2ej0x4hwwXaVjpVtEOwOIuJ0=; b=h/KaLOfTlBlfs7Rr7PrXjLc/dEwUf5s29651Xxu/3t6nIzO5KIMoLpP4Z492zk55n4 I65WXFmOfZ6/SDFl6aweGFxvIa9XZBwSxLm1pFlFUj1FtNvPhfRH8f1uyBC8O+gHVWef 0Wl/eD3Kn8mUWuXKPHWYEirEGtS4jz1ecJIaWVJrPecJEl2g7vdmvtv2XFSRM+Cn4anA uTEcq0hI+kXVP0iEZg8CUDc0gMjhpHyRCaJ6IsrSSGeeoVb8LucNt35O42JNeNexx+rp OPxdd8alq2K6DoXCRYwzMK0w+PG5JyDGEsrEHF7BYRFNO8GywXoRrhV5XNiWl1ltuWyh I8lA== X-Gm-Message-State: AOJu0YyszSB9XfeOUEIigaPxgrT7Z96rF2wWP45LGimjWL9iwyvn/10I QyciQ5nIye8i/IXhqXaRM3VRR1KA9bo= X-Google-Smtp-Source: AGHT+IHnhMPNvmJsVZfBFuBNeAlGWgo0DHbDXqrexM/KH8E8BrECGZkEjOFOWNgZ7wLNmYdTXNOgWA== X-Received: by 2002:a17:90b:4f49:b0:27d:4b6e:b405 with SMTP id pj9-20020a17090b4f4900b0027d4b6eb405mr3562538pjb.33.1699574458144; Thu, 09 Nov 2023 16:00:58 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:57 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 28/52] perf annotate-data: Parse 'lock' prefix from llvm-objdump Date: Thu, 9 Nov 2023 15:59:47 -0800 Message-ID: <20231110000012.3538610-29-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For the performance reason, I prefer llvm-objdump over GNU's. But I found that llvm-objdump puts x86 lock prefix in a separate line like below. ffffffff81000695: f0 lock ffffffff81000696: ff 83 54 0b 00 00 incl 2900(%rbx) This should be parsed properly, but I just changed to find the insn with next offset for now. This improves the statistics as it can process more instructions. Annotate data type stats: total 294, ok 144 (49.0%), bad 150 (51.0%) ----------------------------------------------------------- 30 : no_sym 35 : no_mem_ops 71 : no_var 6 : no_typeinfo 8 : bad_offset Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 3ac601d70f61..2f325a9cf33a 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3664,8 +3664,17 @@ static struct disasm_line *find_disasm_line(struct symbol *sym, u64 ip) notes = symbol__annotation(sym); list_for_each_entry(dl, ¬es->src->source, al.node) { - if (sym->start + dl->al.offset == ip) + if (sym->start + dl->al.offset == ip) { + /* + * llvm-objdump places "lock" in a separate line and + * in that case, we want to get the next line. + */ + if (!strcmp(dl->ins.name, "lock") && *dl->ops.raw == '\0') { + ip++; + continue; + } return dl; + } } return NULL; } @@ -3757,6 +3766,9 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) if (!op_loc->mem_ref) continue; + /* Recalculate IP since it can be changed due to LOCK prefix */ + ip = ms->sym->start + dl->al.offset; + mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); if (mem_type) istat->good++; From patchwork Thu Nov 9 23:59:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451897 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22C9532180; Fri, 10 Nov 2023 00:01:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cSqhRC+v" Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 715B44ED0; Thu, 9 Nov 2023 16:01:00 -0800 (PST) Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-27ddc1b1652so1292884a91.2; Thu, 09 Nov 2023 16:01:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574460; x=1700179260; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=5ia7kvZ+eaGI+H0XOPg0NJ+OKOWxPEjxcavewxuznSI=; b=cSqhRC+vmPv8UmB4RieRSId0DnW33fNO73dC2vF1mGLP+Vpf+ohOmIe3cI515CBHVy oeMni24x48r0zjf41tpkmDhNfFotq26wh26xdmPIl/8MwvUn3XJsSfi63qYUs03QX+Gv PpX6dBz4CY8QiiLVr5EdSkyve+mEDSiwugwFINyfta9oDQVDQ8mfuZE3QWULu20iGj1M YtnsRDO1Vj4l8f8xLQSLGN/Qkz6xE8h3Y7Jf+zhp3Yt0vAW8Ol093VAwEc8bU3mgHGiF F6u2Qic+4ZD2EakCMZXyLhWQ2D6Ry9L9RURDJ/5eGaow9bJ+8dgzMFKY/Z0tsdn51vQa fSOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574460; x=1700179260; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=5ia7kvZ+eaGI+H0XOPg0NJ+OKOWxPEjxcavewxuznSI=; b=AfEmLYiivFHNcDFUTHWI57niLtYBWibTIBjS03mOspuyEsrby5WIQzozTQ+HbsRjyf 0IBCatQ/WwLA1Gjj+OlZSEGYVsP2bcZ97UtSYDPErutubBxN0SiuBSl0/B9JUdDQsDGC bZd/zCRPsn8SrRor2W6TjZ7PgeECVUk+ydXab4D1Okp0yOIK+qpUsubG8STodmiSMupV lDK5/QxKzPhYkXk/W3VeHysglPStdSgLi78caU8QOpUNfEF0M0GmzLUqiAjfHFZqAoa6 pAO8kCXRg00aYP8H7jNqLcHHADvopyesdEkwfbFv3fWqsxxhTVwBQlP59z7udhEBO73h Lk9Q== X-Gm-Message-State: AOJu0Yznp1iWEHFQ6n+mHodTbj9RCBdbq48ENVoFKmuYUUaCetl1xa+l oLqvHaxG/iV9llURld3CnnI= X-Google-Smtp-Source: AGHT+IHrw+WJOxhr/YA5r9qqGxD0I9fuPFs34KyYR7qggeWg/Bxckkc0iovWCk5JS6i26HbQum3Blg== X-Received: by 2002:a17:90b:4c12:b0:280:3f33:64d8 with SMTP id na18-20020a17090b4c1200b002803f3364d8mr3606376pjb.21.1699574459747; Thu, 09 Nov 2023 16:00:59 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:00:59 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 29/52] perf annotate-data: Handle macro fusion on x86 Date: Thu, 9 Nov 2023 15:59:48 -0800 Message-ID: <20231110000012.3538610-30-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When a sample was come from a conditional branch without a memory operand, it could be due to a macro fusion with a previous instruction. So it needs to check the memory operand in the previous one. This improves the stat like below: Annotate data type stats: total 294, ok 147 (50.0%), bad 147 (50.0%) ----------------------------------------------------------- 30 : no_sym 32 : no_mem_ops 71 : no_var 6 : no_typeinfo 8 : bad_offset Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 2f325a9cf33a..7d733bc85c9a 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3750,6 +3750,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) return NULL; } +retry: istat = annotate_data_stat(&ann_insn_stat, dl->ins.name); if (istat == NULL) { ann_data_stat.no_insn++; @@ -3766,7 +3767,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) if (!op_loc->mem_ref) continue; - /* Recalculate IP since it can be changed due to LOCK prefix */ + /* Recalculate IP because of LOCK prefix or insn fusion */ ip = ms->sym->start + dl->al.offset; mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); @@ -3785,6 +3786,20 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) return mem_type; } + /* + * Some instructions can be fused and the actual memory access came + * from the previous instruction. + */ + if (dl->al.offset > 0) { + struct disasm_line *prev_dl; + + prev_dl = list_prev_entry(dl, al.node); + if (ins__is_fused(arch, prev_dl->ins.name, dl->ins.name)) { + dl = prev_dl; + goto retry; + } + } + ann_data_stat.no_mem_ops++; istat->bad++; return NULL; From patchwork Thu Nov 9 23:59:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451898 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36D238837; Fri, 10 Nov 2023 00:01:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hzH6EjlV" Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2451C4EC7; Thu, 9 Nov 2023 16:01:02 -0800 (PST) Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-28041176e77so1264761a91.0; Thu, 09 Nov 2023 16:01:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574461; x=1700179261; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=YuNYbGY/TZYhNEl+3fPnXMSkLeW2sk5VhkJK2QzHpkM=; b=hzH6EjlVoC0nARk2tfjCo+O2gyxvT2ut7muxDJ9E54A9xcmhMa44mfkvAbEeZf9a6n yFZWC1AeIAfgn7nui+7sEUoexX2G306Lc2h40l9b2IbhCNYxHyLs5Tpri4Tfjc/wwfv0 N5g14yb5Oj1+OipF8wJlHzG5Oi6+EVp77zsZfquWhsWPWvHbg2vvAZpVuPcXfqexObtZ 2Y+f9gPHunYbBem68JCDVGfXh5p0f2bjxGxsTxKizrB67ApskGXQU0TPZp5Yf0aAadhN i17b7OpfYh1RQ6ZwOHKAob5lN+w9gyB+2AQWYHRieNXAGZAoWGLbArGpPpwNvLfkD94V 2XBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574461; x=1700179261; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=YuNYbGY/TZYhNEl+3fPnXMSkLeW2sk5VhkJK2QzHpkM=; b=kxh9ViG+AzJUaWgd0e6L6mSSeY+LfA+CS/Yq+D/VJym43nyz4oV4U9JPeVsOOBgIqQ X3MPEiEvBF4EDoYl19QTGL1A4x8elxGJh+BeW1p2oBSNLtDneBn/HsgIaDIymz06bzCc J0XB2BUlqsoSc9c9fXCGk+nQdDsYnnNduTDChaQ8wwJQoMeFKJYJbHy1Ki0Mv0W4x4Z+ 83MmFIkMDfFMKB/rFf/kBrgATAQuQY0H5ABEeT+gp+JJMqQ3cqudmdbee9YkIPkcYyKB /qBiGfQ+YaPKAoE3IIfqrDJJ+VOS0ptLnzvmHz9Wc3BvFTNrCdK3wFJhp+IqPcK7cJhv gBiQ== X-Gm-Message-State: AOJu0Yy6ZQJrDtnqgXm5WQW7Yyt4KFeYDsXwo13ZXBB8E/GtiTlEuVI0 XgQdkRxVdKHUZiQynh1TPXs= X-Google-Smtp-Source: AGHT+IHDsKq1HdvnM0iIpag/xmlhWcwJIvdyEuXoKH27k00GyWB0ZyF6HDeG1jjfbUx5hE7qOfm9dg== X-Received: by 2002:a17:90a:5d86:b0:281:3a4a:2e61 with SMTP id t6-20020a17090a5d8600b002813a4a2e61mr3049790pji.14.1699574461515; Thu, 09 Nov 2023 16:01:01 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.00.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:00 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 30/52] perf annotate-data: Handle array style accesses Date: Thu, 9 Nov 2023 15:59:49 -0800 Message-ID: <20231110000012.3538610-31-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 On x86, instructions for array access often looks like below. mov 0x1234(%rax,%rbx,8), %rcx Usually the first register holds the type information and the second one has the index. And the current code only looks up a variable for the first register. But it's possible to be in the other way around so it needs to check the second register if the first one failed. The stat changed like this. Annotate data type stats: total 294, ok 148 (50.3%), bad 146 (49.7%) ----------------------------------------------------------- 30 : no_sym 32 : no_mem_ops 66 : no_var 10 : no_typeinfo 8 : bad_offset Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 24 +++++++++++++----- tools/perf/util/annotate-data.h | 5 ++-- tools/perf/util/annotate.c | 43 ++++++++++++++++++++++++++------- tools/perf/util/annotate.h | 8 ++++-- 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 79f09ce92f15..159fceeebaa4 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -8,6 +8,7 @@ #include #include +#include "annotate.h" #include "annotate-data.h" #include "debuginfo.h" #include "debug.h" @@ -206,7 +207,8 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) * It expects a pointer type for a memory access. * Convert to a real type it points to. */ - if (dwarf_tag(type_die) != DW_TAG_pointer_type || + if ((dwarf_tag(type_die) != DW_TAG_pointer_type && + dwarf_tag(type_die) != DW_TAG_array_type) || die_get_real_type(type_die, type_die) == NULL) { pr_debug("no pointer or no type\n"); ann_data_stat.no_typeinfo++; @@ -232,10 +234,11 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) /* The result will be saved in @type_die */ static int find_data_type_die(struct debuginfo *di, u64 pc, - int reg, int offset, Dwarf_Die *type_die) + struct annotated_op_loc *loc, Dwarf_Die *type_die) { Dwarf_Die cu_die, var_die; Dwarf_Die *scopes = NULL; + int reg, offset; int ret = -1; int i, nr_scopes; @@ -249,6 +252,10 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, /* Get a list of nested scopes - i.e. (inlined) functions and blocks. */ nr_scopes = die_get_scopes(&cu_die, pc, &scopes); + reg = loc->reg1; + offset = loc->offset; + +retry: /* Search from the inner-most scope to the outer */ for (i = nr_scopes - 1; i >= 0; i--) { /* Look up variables/parameters in this scope */ @@ -259,6 +266,12 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, ret = check_variable(&var_die, type_die, offset); goto out; } + + if (loc->multi_regs && reg == loc->reg1 && loc->reg1 != loc->reg2) { + reg = loc->reg2; + goto retry; + } + if (ret < 0) ann_data_stat.no_var++; @@ -271,15 +284,14 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, * find_data_type - Return a data type at the location * @ms: map and symbol at the location * @ip: instruction address of the memory access - * @reg: register that holds the base address - * @offset: offset from the base address + * @loc: instruction operand location * * This functions searches the debug information of the binary to get the data * type it accesses. The exact location is expressed by (ip, reg, offset). * It return %NULL if not found. */ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, - int reg, int offset) + struct annotated_op_loc *loc) { struct annotated_data_type *result = NULL; struct dso *dso = ms->map->dso; @@ -299,7 +311,7 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, * a file address for DWARF processing. */ pc = map__rip_2objdump(ms->map, ip); - if (find_data_type_die(di, pc, reg, offset, &type_die) < 0) + if (find_data_type_die(di, pc, loc, &type_die) < 0) goto out; result = dso__findnew_data_type(dso, &type_die); diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 8e73096c01d1..65ddd839850f 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -7,6 +7,7 @@ #include #include +struct annotated_op_loc; struct evsel; struct map_symbol; @@ -105,7 +106,7 @@ extern struct annotated_data_stat ann_data_stat; /* Returns data type at the location (ip, reg, offset) */ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, - int reg, int offset); + struct annotated_op_loc *loc); /* Update type access histogram at the given offset */ int annotated_data_type__update_samples(struct annotated_data_type *adt, @@ -119,7 +120,7 @@ void annotated_data_type__tree_delete(struct rb_root *root); static inline struct annotated_data_type * find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused, - int reg __maybe_unused, int offset __maybe_unused) + struct annotated_op_loc *loc __maybe_unused) { return NULL; } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 7d733bc85c9a..19e7f4000368 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3567,8 +3567,22 @@ static int extract_reg_offset(struct arch *arch, const char *str, if (regname == NULL) return -1; - op_loc->reg = get_dwarf_regnum(regname, 0); + op_loc->reg1 = get_dwarf_regnum(regname, 0); free(regname); + + /* Get the second register */ + if (op_loc->multi_regs) { + p = strchr(p + 1, arch->objdump.register_char); + if (p == NULL) + return -1; + + regname = strdup(p); + if (regname == NULL) + return -1; + + op_loc->reg2 = get_dwarf_regnum(regname, 0); + free(regname); + } return 0; } @@ -3581,14 +3595,20 @@ static int extract_reg_offset(struct arch *arch, const char *str, * Get detailed location info (register and offset) in the instruction. * It needs both source and target operand and whether it accesses a * memory location. The offset field is meaningful only when the - * corresponding mem flag is set. + * corresponding mem flag is set. The reg2 field is meaningful only + * when multi_regs flag is set. * * Some examples on x86: * - * mov (%rax), %rcx # src_reg = rax, src_mem = 1, src_offset = 0 - * # dst_reg = rcx, dst_mem = 0 + * mov (%rax), %rcx # src_reg1 = rax, src_mem = 1, src_offset = 0 + * # dst_reg1 = rcx, dst_mem = 0 * - * mov 0x18, %r8 # src_reg = -1, dst_reg = r8 + * mov 0x18, %r8 # src_reg1 = -1, src_mem = 0 + * # dst_reg1 = r8, dst_mem = 0 + * + * mov %rsi, 8(%rbx,%rcx,4) # src_reg1 = rsi, src_mem = 0, dst_multi_regs = 0 + * # dst_reg1 = rbx, dst_reg2 = rcx, dst_mem = 1 + * # dst_multi_regs = 1, dst_offset = 8 */ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, struct annotated_insn_loc *loc) @@ -3609,24 +3629,29 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, for_each_insn_op_loc(loc, i, op_loc) { const char *insn_str = ops->source.raw; + bool multi_regs = ops->source.multi_regs; - if (i == INSN_OP_TARGET) + if (i == INSN_OP_TARGET) { insn_str = ops->target.raw; + multi_regs = ops->target.multi_regs; + } /* Invalidate the register by default */ - op_loc->reg = -1; + op_loc->reg1 = -1; + op_loc->reg2 = -1; if (insn_str == NULL) continue; if (strchr(insn_str, arch->objdump.memory_ref_char)) { op_loc->mem_ref = true; + op_loc->multi_regs = multi_regs; extract_reg_offset(arch, insn_str, op_loc); } else { char *s = strdup(insn_str); if (s) { - op_loc->reg = get_dwarf_regnum(s, 0); + op_loc->reg1 = get_dwarf_regnum(s, 0); free(s); } } @@ -3770,7 +3795,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) /* Recalculate IP because of LOCK prefix or insn fusion */ ip = ms->sym->start + dl->al.offset; - mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); + mem_type = find_data_type(ms, ip, op_loc); if (mem_type) istat->good++; else diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 2cef96859e45..f5a6c3227757 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -448,14 +448,18 @@ int annotate_check_args(struct annotation_options *args); /** * struct annotated_op_loc - Location info of instruction operand - * @reg: Register in the operand + * @reg1: First register in the operand + * @reg2: Second register in the operand * @offset: Memory access offset in the operand * @mem_ref: Whether the operand accesses memory + * @multi_regs: Whether the second register is used */ struct annotated_op_loc { - int reg; + int reg1; + int reg2; int offset; bool mem_ref; + bool multi_regs; }; enum annotated_insn_ops { From patchwork Thu Nov 9 23:59:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451899 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A13232180; Fri, 10 Nov 2023 00:01:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ddug7hb7" Received: from mail-pg1-x52b.google.com (mail-pg1-x52b.google.com [IPv6:2607:f8b0:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 411154EFC; Thu, 9 Nov 2023 16:01:04 -0800 (PST) Received: by mail-pg1-x52b.google.com with SMTP id 41be03b00d2f7-5bdbe2de25fso1194928a12.3; Thu, 09 Nov 2023 16:01:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574464; x=1700179264; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=7JAGBpBGaq4osme9n0JKrBguz8AS2l54XNgGym3lX7g=; b=ddug7hb72+i8Imy0A1D9OjOZPrMnla0CvKNs/3Tns6uIVWweHWbSR2NgfJdQblLfhq miRlmXlAbJVAacRTOnMsHrk7nMR2gDlKYweCMHjgTM2n/HSvcveYL+F7hZitrzncA0gD nxRQ7FFwT7aBTCJrJMUeRYvZVTrfCpJ46ARiYkdAa4wrmM5uAW0pPmoxFl3HW4s/jtl/ zniSAF58h1QbMm+LYw2iWHrstSumK7FjR+ivIyR3L7+dlUzv8E6GwHXKCi3ErtaQbwRS M2Gztenck8wEddXNA/pAy1Th6IZZaIetUMTRZRljJm+JgZ36QUUDeJK8M4A4/zbbMsJU /9sg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574464; x=1700179264; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=7JAGBpBGaq4osme9n0JKrBguz8AS2l54XNgGym3lX7g=; b=Qr0WGT2lqVPS5vxX/Dzd867ZPVQHsDQQtaz0nIjnYLLOLSYGnzNvqBY8dXwEuUn/P2 ptfbDfX52MqcTcLj6euKaxCDMmHB+HEZaJtDuMh/2unDhnMN/8KWmj7J3hC/Abya1HE3 w3vNUYAp3X9unv/TCBJmTSV6QOFYnTRI663SqkNjxUQuGfhzLNedJnah97E9rM/C9NoM Gs3NSHkhftptTQNN1atXYOTKr01CGAUG+6YFBZ2oVEY2cYXRP95TM5/gQcNUGIYfn1fX Ja8hr5wwi5Bwfv8/USdOe6PiZ83xFmwoN9mL5nGg1U0C4nxbmvSs+m0g9QTtg2M3DYGf vT8w== X-Gm-Message-State: AOJu0YwQPCMP+1s3qpujx72lBRM3El1HfRjP3eQoSWIzPnRsn8AZfyGk qYbXo+86X/ZoF/7DzzRpMjA= X-Google-Smtp-Source: AGHT+IEwZ2gYlskDDB5oreKUo9s7/LOJTZVK1IKLbgzsRlq9u1SjQD4taZgFIjm7x+qsyk/B+SYVyA== X-Received: by 2002:a17:90b:17cb:b0:27d:d9c2:6ee5 with SMTP id me11-20020a17090b17cb00b0027dd9c26ee5mr3556223pjb.9.1699574463252; Thu, 09 Nov 2023 16:01:03 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:02 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 31/52] perf annotate-data: Add stack operation pseudo type Date: Thu, 9 Nov 2023 15:59:50 -0800 Message-ID: <20231110000012.3538610-32-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 A typical function prologue and epilogue include multiple stack operations to save and restore the current value of registers. On x86, it looks like below: push r15 push r14 push r13 push r12 ... pop r12 pop r13 pop r14 pop r15 ret As these all touches the stack memory region, chances are high that they appear in a memory profile data. But these are not used for any real purpose yet so it'd return no types. One of my profile type shows that non neglible portion of data came from the stack operations. It also seems GCC generates more stack operations than clang. Annotate Instruction stats total 264, ok 169 (64.0%), bad 95 (36.0%) Name : Good Bad ----------------------------------------------------------- movq : 49 27 movl : 24 9 popq : 0 19 <-- here cmpl : 17 2 addq : 14 1 cmpq : 12 2 cmpxchgl : 3 7 Instead of dealing them as unknown, let's create a seperate pseudo type to represent those stack operations separately. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.h | 1 + tools/perf/util/annotate.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 65ddd839850f..214c625e7bc9 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -70,6 +70,7 @@ struct annotated_data_type { }; extern struct annotated_data_type unknown_type; +extern struct annotated_data_type stackop_type; /** * struct annotated_data_stat - Debug statistics diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 19e7f4000368..4ea32c2dee4b 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -104,6 +104,14 @@ static struct ins_ops ret_ops; struct annotated_data_stat ann_data_stat; LIST_HEAD(ann_insn_stat); +/* Pseudo data types */ +struct annotated_data_type stackop_type = { + .self = { + .type_name = (char *)"(stack operation)", + .children = LIST_HEAD_INIT(stackop_type.self.children), + }, +}; + static int arch__grow_instructions(struct arch *arch) { struct ins *new_instructions; @@ -3728,6 +3736,18 @@ static struct annotated_item_stat *annotate_data_stat(struct list_head *head, return istat; } +static bool is_stack_operation(struct arch *arch, struct disasm_line *dl) +{ + if (arch__is(arch, "x86")) { + if (!strncmp(dl->ins.name, "push", 4) || + !strncmp(dl->ins.name, "pop", 3) || + !strncmp(dl->ins.name, "ret", 3)) + return true; + } + + return false; +} + /** * hist_entry__get_data_type - find data type for given hist entry * @he: hist entry @@ -3788,6 +3808,12 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) return NULL; } + if (is_stack_operation(arch, dl)) { + istat->good++; + he->mem_type_off = 0; + return &stackop_type; + } + for_each_insn_op_loc(&loc, i, op_loc) { if (!op_loc->mem_ref) continue; From patchwork Thu Nov 9 23:59:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451900 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9287432189; Fri, 10 Nov 2023 00:01:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EfHKOtdI" Received: from mail-pg1-x533.google.com (mail-pg1-x533.google.com [IPv6:2607:f8b0:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B2B645257; Thu, 9 Nov 2023 16:01:05 -0800 (PST) Received: by mail-pg1-x533.google.com with SMTP id 41be03b00d2f7-5a9bc2ec556so1108808a12.0; Thu, 09 Nov 2023 16:01:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574465; x=1700179265; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=xjEl3q6T8aZ2C9UHCLhYA2cSxHBerxf7uY5QArHiSe8=; b=EfHKOtdIgzEaTPWORXYZsLBAYYYLAc6iYVEdnPbGHNHVituPjYOELHxNHPONiYmtTp glzEL5U9IPfCgn+2YSFu9JPPHlxbDjJ2EfSq9w3BUPSWC92hkNkAZLegTG/udKZMxgdy effHaJyRHTlc5YpeBF9jANXonykrAQR3oU7IHxaJzfQo72hneBFjt0fki0T3tgAKM/6k Uttwdq8XJSkRotp9BFGPXHBqGzZHwAu/dy349indyyKtg4rURZO6tuOc1RZdk1THrYKs JBkL+sa/rqsPv7k91u8d+x/xbPW3QjpPz+kv/MCkEeb/UI0OpIGXYX5oQI1iEAq7wIy3 ZtMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574465; x=1700179265; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=xjEl3q6T8aZ2C9UHCLhYA2cSxHBerxf7uY5QArHiSe8=; b=LVz5Mp0AwoBxHcgW74EmPpkDLLoq3f++rMjeYJJbNwx4mXv/pSULEliSrJKAaBSeNX V24ywjukl7nPNHr11y95sOQ8UG0uxd5vlFmO6eJbF+waQ8fYXRY78Q7v4wo3SiTfN2Hi Vp45N9SSimhEsNw0B5EYD0Gqj+yNQJgW4lecLumUbYQf8dr31kv5yP91tWJs/8BhVp/9 1e7bwbdi/lBHo1r0w7LVZZFi4G3O5B6okHF09l4DvxfBGO/EgBQMH7NKOwj1tDhLswhq I2HRgnyvoEgZTqjFkgk4j3cRV9Yjnh0xUlNxVCR2G06ePs9bGvNm6HhU0PxsJhs79jHF xxGw== X-Gm-Message-State: AOJu0Yx29oQqymQkFE0ikp+iRGlA7AnuNU/lcqvkW7hUDMTcndobdk5+ 6vUFT30sVZK/9C8jpa3J+Dw= X-Google-Smtp-Source: AGHT+IFe4ieLldc6KrSz5mKX86U9BuRX1+txGq4lZdQQfJRXwcmIPzy9i1H8w2j1Lv6jrfTUdQ9XxA== X-Received: by 2002:a17:90b:4a91:b0:27d:1538:e324 with SMTP id lp17-20020a17090b4a9100b0027d1538e324mr3249850pjb.32.1699574465081; Thu, 09 Nov 2023 16:01:05 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:04 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 32/52] perf dwarf-aux: Add die_find_variable_by_addr() Date: Thu, 9 Nov 2023 15:59:51 -0800 Message-ID: <20231110000012.3538610-33-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The die_find_variable_by_addr() is to find a variables in the given DIE using given (PC-relative) address. Global variables will have a location expression with DW_OP_addr which has an address so can simply compare it with the address. <1><143a7>: Abbrev Number: 2 (DW_TAG_variable) <143a8> DW_AT_name : loops_per_jiffy <143ac> DW_AT_type : <0x1cca> <143b0> DW_AT_external : 1 <143b0> DW_AT_decl_file : 193 <143b1> DW_AT_decl_line : 213 <143b2> DW_AT_location : 9 byte block: 3 b0 46 41 82 ff ff ff ff (DW_OP_addr: ffffffff824146b0) Note that the type-offset should be calculated from the base address of the global variable. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 79 +++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 14 +++++++ 2 files changed, 93 insertions(+) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 4bdcd3dea28f..7aa5fee0da19 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1266,8 +1266,12 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) struct find_var_data { /* Target instruction address */ Dwarf_Addr pc; + /* Target memory address (for global data) */ + Dwarf_Addr addr; /* Target register */ unsigned reg; + /* Access offset, set for global data */ + int offset; }; /* Max number of registers DW_OP_regN supports */ @@ -1328,6 +1332,81 @@ Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg, }; return die_find_child(sc_die, __die_find_var_reg_cb, &data, die_mem); } + +/* Only checks direct child DIEs in the given scope */ +static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg) +{ + struct find_var_data *data = arg; + int tag = dwarf_tag(die_mem); + ptrdiff_t off = 0; + Dwarf_Attribute attr; + Dwarf_Addr base, start, end; + Dwarf_Word size; + Dwarf_Die type_die; + Dwarf_Op *ops; + size_t nops; + + if (tag != DW_TAG_variable) + return DIE_FIND_CB_SIBLING; + + if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) + return DIE_FIND_CB_SIBLING; + + while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) { + if (ops->atom != DW_OP_addr) + continue; + + if (data->addr < ops->number) + continue; + + if (data->addr == ops->number) { + /* Update offset relative to the start of the variable */ + data->offset = 0; + return DIE_FIND_CB_END; + } + + if (die_get_real_type(die_mem, &type_die) == NULL) + continue; + + if (dwarf_aggregate_size(&type_die, &size) < 0) + continue; + + if (data->addr >= ops->number + size) + continue; + + /* Update offset relative to the start of the variable */ + data->offset = data->addr - ops->number; + return DIE_FIND_CB_END; + } + return DIE_FIND_CB_SIBLING; +} + +/** + * die_find_variable_by_addr - Find variable located at given address + * @sc_die: a scope DIE + * @pc: the program address to find + * @addr: the data address to find + * @die_mem: a buffer to save the resulting DIE + * @offset: the offset in the resulting type + * + * Find the variable DIE located at the given address (in PC-relative mode). + * This is usually for global variables. + */ +Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr pc, + Dwarf_Addr addr, Dwarf_Die *die_mem, + int *offset) +{ + struct find_var_data data = { + .pc = pc, + .addr = addr, + }; + Dwarf_Die *result; + + result = die_find_child(sc_die, __die_find_var_addr_cb, &data, die_mem); + if (result) + *offset = data.offset; + return result; +} #endif /* diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index f9763d3b7572..4e64caac6df8 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -144,6 +144,11 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg, Dwarf_Die *die_mem); +/* Find a (global) variable located in the 'addr' */ +Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr pc, + Dwarf_Addr addr, Dwarf_Die *die_mem, + int *offset); + #else /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, @@ -161,6 +166,15 @@ static inline Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die __maybe_unus return NULL; } +static inline Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die __maybe_unused, + Dwarf_Addr pc __maybe_unused, + Dwarf_Addr addr __maybe_unused, + Dwarf_Die *die_mem __maybe_unused, + int *offset __maybe_unused) +{ + return NULL; +} + #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ #endif /* _DWARF_AUX_H */ From patchwork Thu Nov 9 23:59:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451901 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E29D321A1; Fri, 10 Nov 2023 00:01:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BAgtCuSS" Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 33703525C; Thu, 9 Nov 2023 16:01:07 -0800 (PST) Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-28010522882so1314629a91.0; Thu, 09 Nov 2023 16:01:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574466; x=1700179266; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=rwhq2HXjG2411ugWKKGi+YPUSV7LvJmORRwVZhcG1E4=; b=BAgtCuSSk8OO/rkuonWq0zB/Pxz/JRF3c5mtaDpuIk9L+DZ4Fq7gz+XTEtxrz0Hnw/ pjPrcy4EKCNp/ppQnNQTOzY3kMHes2bDfmk2qO/H5LZ9DFafpE4w5JfsL0knC6N4oXCa 9TYhUb68nUbu1qg6evUxeenRyH/7C/ZYuRNnvdMsSNDRfC4zVJdVCWDDSlD2e0rwimpz QZ997rhoVKeZHHahpgheQ5oD6W5m4AQwYPOD2T4DDDRA/l7MSP4tskPLiOxHurU0s8yU Rn9oiYE2iwgxmJns+pKX/T5mKcGWixgo9pkeyK7ULwR9JbDzOOQuYFMCxzlWPM3LHlyZ H5dQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574466; x=1700179266; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=rwhq2HXjG2411ugWKKGi+YPUSV7LvJmORRwVZhcG1E4=; b=k43bnA8FRfgbx1e52qe52sXIIE9yGKXKW1TNe2aVcS/AtKr9ViqkS7zOwCwt3ET3lN XH0ZVUyCGgbuRls1b3QxPouzwNyF6mzV4hi1TUu94GEoNlGadnPaD98d+ob8CgQsX8HE LwFSARUYi7KKHEWfFa7gruSmVloiX5wqOU9Fc6xXsKXLcLeZEBZpaqRRlfGXPJmoOc3p dqhPRzDT1hGK8LDKbBvx0mCFqreavDw7YrYzyR0CKObRkyH1iz4MUB4a0AXeAsLRIn+8 oT8U1UHaNBVKcRj/A+JV90Vmr+OXWNsOh0CkyODX5Q4WOgsxN1d6aQwFWyoDJJmTkWoL IQZg== X-Gm-Message-State: AOJu0YzzQovqh+ViYamasfOhQySynyB3nbUq0wB1XvB20o2lkiTesR8/ KjLb70V3FmOyDNhZzbkIf7A= X-Google-Smtp-Source: AGHT+IHDL+Z4a9rWgnaAQPyeqkbi1U+vt6X03McufmDlefT0OtYZG3E99FadkSmHlPtiOcaOGr7FyA== X-Received: by 2002:a17:90b:4d09:b0:283:84c:3871 with SMTP id mw9-20020a17090b4d0900b00283084c3871mr622222pjb.3.1699574466457; Thu, 09 Nov 2023 16:01:06 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:06 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 33/52] perf annotate-data: Handle PC-relative addressing Date: Thu, 9 Nov 2023 15:59:52 -0800 Message-ID: <20231110000012.3538610-34-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Extend find_data_type_die() to find data type from PC-relative address using die_find_variable_by_addr(). Users need to pass the address for the (global) variable. The offset for the variable should be updated after finding the type because the offset in the instruction is just to calcuate the address for the variable. So it changed to pass a pointer to offset and renamed it to 'poffset'. First it searches variables in the CU DIE as it's likely that the global variables are defined in the file level. And then it iterates the scope DIEs to find a local (static) variable. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 56 ++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 159fceeebaa4..61d2a17044c0 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -13,6 +13,7 @@ #include "debuginfo.h" #include "debug.h" #include "dso.h" +#include "dwarf-regs.h" #include "evsel.h" #include "evlist.h" #include "map.h" @@ -192,7 +193,8 @@ static bool find_cu_die(struct debuginfo *di, u64 pc, Dwarf_Die *cu_die) } /* The type info will be saved in @type_die */ -static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) +static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset, + bool is_pointer) { Dwarf_Word size; @@ -204,15 +206,18 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) } /* - * It expects a pointer type for a memory access. - * Convert to a real type it points to. + * Usually it expects a pointer type for a memory access. + * Convert to a real type it points to. But global variables + * are accessed directly without a pointer. */ - if ((dwarf_tag(type_die) != DW_TAG_pointer_type && - dwarf_tag(type_die) != DW_TAG_array_type) || - die_get_real_type(type_die, type_die) == NULL) { - pr_debug("no pointer or no type\n"); - ann_data_stat.no_typeinfo++; - return -1; + if (is_pointer) { + if ((dwarf_tag(type_die) != DW_TAG_pointer_type && + dwarf_tag(type_die) != DW_TAG_array_type) || + die_get_real_type(type_die, type_die) == NULL) { + pr_debug("no pointer or no type\n"); + ann_data_stat.no_typeinfo++; + return -1; + } } /* Get the size of the actual type */ @@ -233,7 +238,7 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) } /* The result will be saved in @type_die */ -static int find_data_type_die(struct debuginfo *di, u64 pc, +static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, struct annotated_op_loc *loc, Dwarf_Die *type_die) { Dwarf_Die cu_die, var_die; @@ -249,21 +254,36 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, return -1; } - /* Get a list of nested scopes - i.e. (inlined) functions and blocks. */ - nr_scopes = die_get_scopes(&cu_die, pc, &scopes); - reg = loc->reg1; offset = loc->offset; + if (reg == DWARF_REG_PC && + die_find_variable_by_addr(&cu_die, pc, addr, &var_die, &offset)) { + ret = check_variable(&var_die, type_die, offset, + /*is_pointer=*/false); + goto out; + } + + /* Get a list of nested scopes - i.e. (inlined) functions and blocks. */ + nr_scopes = die_get_scopes(&cu_die, pc, &scopes); + retry: /* Search from the inner-most scope to the outer */ for (i = nr_scopes - 1; i >= 0; i--) { - /* Look up variables/parameters in this scope */ - if (!die_find_variable_by_reg(&scopes[i], pc, reg, &var_die)) - continue; + if (reg == DWARF_REG_PC) { + if (!die_find_variable_by_addr(&scopes[i], pc, addr, + &var_die, &offset)) + continue; + } else { + /* Look up variables/parameters in this scope */ + if (!die_find_variable_by_reg(&scopes[i], pc, reg, + &var_die)) + continue; + } /* Found a variable, see if it's correct */ - ret = check_variable(&var_die, type_die, offset); + ret = check_variable(&var_die, type_die, offset, + reg != DWARF_REG_PC); goto out; } @@ -311,7 +331,7 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, * a file address for DWARF processing. */ pc = map__rip_2objdump(ms->map, ip); - if (find_data_type_die(di, pc, loc, &type_die) < 0) + if (find_data_type_die(di, pc, 0, loc, &type_die) < 0) goto out; result = dso__findnew_data_type(dso, &type_die); From patchwork Thu Nov 9 23:59:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451902 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25C0932189; Fri, 10 Nov 2023 00:01:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="L/QDVr0k" Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A49B7526B; Thu, 9 Nov 2023 16:01:08 -0800 (PST) Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-28014fed9efso1389320a91.0; Thu, 09 Nov 2023 16:01:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574468; x=1700179268; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=2TirQszoov6JDdd3RJseoTrT5O03ly6KXmzpIjweuds=; b=L/QDVr0kzQq9LFND7WQdh6Xuo1ObER688a3szWzxSn8yZCRVkApS+01eM1WYPBa/Jr OxtelX3RM9WQf6mcMjx8dT1fqtYg74UzDVGJ1x0aqlrun+KAUD0xTFBbOdcKHsX2mDLV cJ0ppXNwojjeTt1Fwv5vrWG28RXs6pJI5n7cs+WZh4b1842VIR7bh/ZVi80tyqgMrrtT jgwfpT+U493Zc2db1UlMAj+xhl6nXdq08McNsB85XbqO4doRADMyfxVLRUqYcMga77Bb U8J5JvSoX466eid2dJTK82uTsKBYqpuOHFm3EatCr7p6OMsDnl7DCRFRafMcnYb6iO2l 2V2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574468; x=1700179268; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=2TirQszoov6JDdd3RJseoTrT5O03ly6KXmzpIjweuds=; b=c+ZtG8FoRNExRLBdvzX8wuYZW04p2mmxyTAUCDp9VJY012EkrL0wA4iOPKJfxA49kh XrpbPNg7AHVx1oi9jcw/6XtYvv+8YG+YwUuTNpTi6rhRVaas3GoOITKwekGpy8WJjkmE EGdCC3rlSFJPp8GHZot8wTyiZ+hWlkLUK3TR6zTdr0FXjxu/fwicVvRugtbW2fDp9w8Z 93i/bTWf4Kq7PEXeeNAUgfWViNG6kVMY+umThLGhw+jc+JTy8l/79/9G22WC8EnD5EHe 1kSlMgc97QbUo584NhbvTwr1mJVUBv3fTCYb1IsiVeXnDzUwsF3RUIG0POEk6AFU+l0o mvtQ== X-Gm-Message-State: AOJu0YxHDFUBgtKw/nl8ayg1DaVwRaQk4cj+0pTDipD0+Rrxel4GWhHT B+ZfGAGdAvEtw2qqgBoPaklKhzWNfdo= X-Google-Smtp-Source: AGHT+IEssv0pWffhmUk+ug7fFo5ER9HZljsxKpaAjJ3cgiGCv86TG9hxJffxveYqLUFjUHmqX0PGEg== X-Received: by 2002:a17:90b:350a:b0:27f:fe79:eb6c with SMTP id ls10-20020a17090b350a00b0027ffe79eb6cmr2885865pjb.29.1699574467991; Thu, 09 Nov 2023 16:01:07 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:07 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 34/52] perf annotate-data: Support global variables Date: Thu, 9 Nov 2023 15:59:53 -0800 Message-ID: <20231110000012.3538610-35-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Global variables are accessed using PC-relative address so it needs to be handled separately. The PC-rel addressing is detected by using DWARF_REG_PC. On x86, %rip register would be used. The address can be calculated using the ip and offset in the instruction. But it should start from the next instruction so add calculate_pcrel_addr() to do it properly. But global variables defined in a different file would only have a declaration which doesn't include a location list. So it first tries to get the type info using the address, and then looks up the variable declarations using name. The name of global variables should be get from the symbol table. The declaration would have the type info. So extend find_var_type() to take both address and name for global variables. The stat is now looks like: Annotate data type stats: total 294, ok 153 (52.0%), bad 141 (48.0%) ----------------------------------------------------------- 30 : no_sym 32 : no_mem_ops 61 : no_var 10 : no_typeinfo 8 : bad_offset Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 38 ++++++++++++++++------ tools/perf/util/annotate-data.h | 6 ++-- tools/perf/util/annotate.c | 57 +++++++++++++++++++++++++++++++-- tools/perf/util/annotate.h | 4 +++ 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 61d2a17044c0..99ecf4b3665c 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -239,7 +239,8 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset, /* The result will be saved in @type_die */ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, - struct annotated_op_loc *loc, Dwarf_Die *type_die) + const char *var_name, struct annotated_op_loc *loc, + Dwarf_Die *type_die) { Dwarf_Die cu_die, var_die; Dwarf_Die *scopes = NULL; @@ -257,11 +258,21 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, reg = loc->reg1; offset = loc->offset; - if (reg == DWARF_REG_PC && - die_find_variable_by_addr(&cu_die, pc, addr, &var_die, &offset)) { - ret = check_variable(&var_die, type_die, offset, - /*is_pointer=*/false); - goto out; + if (reg == DWARF_REG_PC) { + if (die_find_variable_by_addr(&cu_die, pc, addr, &var_die, &offset)) { + ret = check_variable(&var_die, type_die, offset, + /*is_pointer=*/false); + loc->offset = offset; + goto out; + } + + if (var_name && die_find_variable_at(&cu_die, var_name, pc, + &var_die)) { + ret = check_variable(&var_die, type_die, 0, + /*is_pointer=*/false); + /* loc->offset will be updated by the caller */ + goto out; + } } /* Get a list of nested scopes - i.e. (inlined) functions and blocks. */ @@ -284,6 +295,7 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, /* Found a variable, see if it's correct */ ret = check_variable(&var_die, type_die, offset, reg != DWARF_REG_PC); + loc->offset = offset; goto out; } @@ -305,13 +317,21 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, * @ms: map and symbol at the location * @ip: instruction address of the memory access * @loc: instruction operand location + * @addr: data address of the memory access + * @var_name: global variable name * * This functions searches the debug information of the binary to get the data - * type it accesses. The exact location is expressed by (ip, reg, offset). + * type it accesses. The exact location is expressed by (@ip, reg, offset) + * for pointer variables or (@ip, @addr) for global variables. Note that global + * variables might update the @loc->offset after finding the start of the variable. + * If it cannot find a global variable by address, it tried to fine a declaration + * of the variable using @var_name. In that case, @loc->offset won't be updated. + * * It return %NULL if not found. */ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, - struct annotated_op_loc *loc) + struct annotated_op_loc *loc, u64 addr, + const char *var_name) { struct annotated_data_type *result = NULL; struct dso *dso = ms->map->dso; @@ -331,7 +351,7 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, * a file address for DWARF processing. */ pc = map__rip_2objdump(ms->map, ip); - if (find_data_type_die(di, pc, 0, loc, &type_die) < 0) + if (find_data_type_die(di, pc, addr, var_name, loc, &type_die) < 0) goto out; result = dso__findnew_data_type(dso, &type_die); diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 214c625e7bc9..1b0db8e8c40e 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -107,7 +107,8 @@ extern struct annotated_data_stat ann_data_stat; /* Returns data type at the location (ip, reg, offset) */ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, - struct annotated_op_loc *loc); + struct annotated_op_loc *loc, u64 addr, + const char *var_name); /* Update type access histogram at the given offset */ int annotated_data_type__update_samples(struct annotated_data_type *adt, @@ -121,7 +122,8 @@ void annotated_data_type__tree_delete(struct rb_root *root); static inline struct annotated_data_type * find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused, - struct annotated_op_loc *loc __maybe_unused) + struct annotated_op_loc *loc __maybe_unused, + u64 addr __maybe_unused, const char *var_name __maybe_unused) { return NULL; } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4ea32c2dee4b..4f74db1d3256 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -37,6 +37,7 @@ #include "util/sharded_mutex.h" #include "arch/common.h" #include "namespaces.h" +#include "thread.h" #include #include #include @@ -3748,6 +3749,30 @@ static bool is_stack_operation(struct arch *arch, struct disasm_line *dl) return false; } +u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset, + struct disasm_line *dl) +{ + struct annotation *notes; + struct disasm_line *next; + u64 addr; + + notes = symbol__annotation(ms->sym); + /* + * PC-relative addressing starts from the next instruction address + * But the IP is for the current instruction. Since disasm_line + * doesn't have the instruction size, calculate it using the next + * disasm_line. If it's the last one, we can use symbol's end + * address directly. + */ + if (&dl->al.node == notes->src->source.prev) + addr = ms->sym->end + offset; + else { + next = list_next_entry(dl, al.node); + addr = ip + (next->al.offset - dl->al.offset) + offset; + } + return map__rip_2objdump(ms->map, addr); +} + /** * hist_entry__get_data_type - find data type for given hist entry * @he: hist entry @@ -3767,7 +3792,9 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) struct annotated_op_loc *op_loc; struct annotated_data_type *mem_type; struct annotated_item_stat *istat; - u64 ip = he->ip; + u64 ip = he->ip, addr = 0; + const char *var_name = NULL; + int var_offset; int i; ann_data_stat.total++; @@ -3821,12 +3848,38 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) /* Recalculate IP because of LOCK prefix or insn fusion */ ip = ms->sym->start + dl->al.offset; - mem_type = find_data_type(ms, ip, op_loc); + var_offset = op_loc->offset; + + /* PC-relative addressing */ + if (op_loc->reg1 == DWARF_REG_PC) { + struct addr_location al; + struct symbol *var; + u64 map_addr; + + addr = annotate_calc_pcrel(ms, ip, op_loc->offset, dl); + /* Kernel symbols might be relocated */ + map_addr = addr + map__reloc(ms->map); + + addr_location__init(&al); + var = thread__find_symbol_fb(he->thread, he->cpumode, + map_addr, &al); + if (var) { + var_name = var->name; + /* Calculate type offset from the start of variable */ + var_offset = map_addr - map__unmap_ip(al.map, var->start); + } + addr_location__exit(&al); + } + + mem_type = find_data_type(ms, ip, op_loc, addr, var_name); if (mem_type) istat->good++; else istat->bad++; + if (mem_type && var_name) + op_loc->offset = var_offset; + if (symbol_conf.annotate_data_sample) { annotated_data_type__update_samples(mem_type, evsel, op_loc->offset, diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index f5a6c3227757..79ccc65c9ff9 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -497,4 +497,8 @@ struct annotated_item_stat { }; extern struct list_head ann_insn_stat; +/* Calculate PC-relative address */ +u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset, + struct disasm_line *dl); + #endif /* __PERF_ANNOTATE_H */ From patchwork Thu Nov 9 23:59:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451903 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96F48DDAD; Fri, 10 Nov 2023 00:01:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BvvqvxGm" Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 267E744BC; Thu, 9 Nov 2023 16:01:10 -0800 (PST) Received: by mail-pj1-x102c.google.com with SMTP id 98e67ed59e1d1-280200949c3so1314752a91.0; Thu, 09 Nov 2023 16:01:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574469; x=1700179269; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=Ea03R/KMOWK9jWm9N2N4NwL8Qridb15kzrUrffJWfOA=; b=BvvqvxGmiPLRjvVpuOt5oXUjstaaAm2NM3qZS9WVE87uKLEvGHYBQzX3qD0ychvSv6 n4w9lCq1tXomjrP6l6Uk4LDHOWjDN8nnypAOJP+3b+ruQ/Qa4TZ7t/levDeLfjnwMGU4 hgw0Rz/mxCzc7yifTo9BBWb1aSYjSi0NgJObvYEqjC6DvVkdUtrw00GRnI72r//Yk7Rs nTxbCtnm67e1uzh308eN11R11NSydxeGWwB/zxOwOSyB1bVZrjrhqmUqq33x5s3UL9Ln URooexM0zfySHbwY/ElC0XJgppNRll5QCPSc5Hyz/S7lSkpyV7W2bXp4PaONsx/2Ehp+ Ow7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574469; x=1700179269; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Ea03R/KMOWK9jWm9N2N4NwL8Qridb15kzrUrffJWfOA=; b=eqb4iXeH3G8eQ70hi3KVGdtSPWMDxV3WfXwbv5jrbvGVCu0AopN8iGdEFPHHr2G6Yj lre+rG16o1kMzQfRPnWL1S4c9SGWdSvQmkz55qso+antFoWsQZaNICNSJItF94g6B/WX Kl3y7zpp6YJaFV/VjU89qYmrMWjswlGFmWy+tlNNqgSGmdG1QYhIN0ot+uMbsa+HiKo+ wQafA3V+L2YxlxrNeevoYWzflY3cfKXqbmx8//y3LrLzXU+9GIHqFYqJ/3IcIRWSJRIb 914jkYqxNJH2UHtWMail4B6Jm5YI589GzUS0QYU/s3bvBfT9aCWLOuF4PV9JaD4HjTQS qebA== X-Gm-Message-State: AOJu0Yy5S8NsHUaDh+3QiKVVPuLSfbRfD5XHVXV/50Y4DCSAF/4fFDaP Zqz3YVT91rsCqZd+5DOKN6k= X-Google-Smtp-Source: AGHT+IECt0YJd4231LO+X66sGFsIH17Oo36mO+fy8ihhV7GbKGQI2qP7XBBdTxVN4KOudH6rgYujPA== X-Received: by 2002:a17:90b:4b0f:b0:27d:46e5:2d7c with SMTP id lx15-20020a17090b4b0f00b0027d46e52d7cmr3380378pjb.26.1699574469540; Thu, 09 Nov 2023 16:01:09 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:09 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 35/52] perf dwarf-aux: Add die_get_cfa() Date: Thu, 9 Nov 2023 15:59:54 -0800 Message-ID: <20231110000012.3538610-36-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The die_get_cfa() is to get frame base register and offset at the given instruction address (pc). This info will be used to locate stack variables which have location expression using DW_OP_fbreg. Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 68 ++++++++++++++++++++++++++++++++++++- tools/perf/util/dwarf-aux.h | 15 ++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 7aa5fee0da19..3d42a8613869 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1407,7 +1407,73 @@ Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr pc, *offset = data.offset; return result; } -#endif +#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ + +#ifdef HAVE_DWARF_CFI_SUPPORT +static int reg_from_dwarf_op(Dwarf_Op *op) +{ + switch (op->atom) { + case DW_OP_reg0 ... DW_OP_reg31: + return op->atom - DW_OP_reg0; + case DW_OP_breg0 ... DW_OP_breg31: + return op->atom - DW_OP_breg0; + case DW_OP_regx: + case DW_OP_bregx: + return op->number; + default: + break; + } + return -1; +} + +static int offset_from_dwarf_op(Dwarf_Op *op) +{ + switch (op->atom) { + case DW_OP_reg0 ... DW_OP_reg31: + case DW_OP_regx: + return 0; + case DW_OP_breg0 ... DW_OP_breg31: + return op->number; + case DW_OP_bregx: + return op->number2; + default: + break; + } + return -1; +} + +/** + * die_get_cfa - Get frame base information + * @dwarf: a Dwarf info + * @pc: program address + * @preg: pointer for saved register + * @poffset: pointer for saved offset + * + * This function gets register and offset for CFA (Canonical Frame Address) + * by searching the CIE/FDE info. The CFA usually points to the start address + * of the current stack frame and local variables can be located using an offset + * from the CFA. The @preg and @poffset will be updated if it returns 0. + */ +int die_get_cfa(Dwarf *dwarf, u64 pc, int *preg, int *poffset) +{ + Dwarf_CFI *cfi; + Dwarf_Frame *frame = NULL; + Dwarf_Op *ops = NULL; + size_t nops; + + cfi = dwarf_getcfi(dwarf); + if (cfi == NULL) + return -1; + + if (!dwarf_cfi_addrframe(cfi, pc, &frame) && + !dwarf_frame_cfa(frame, &ops, &nops) && nops == 1) { + *preg = reg_from_dwarf_op(ops); + *poffset = offset_from_dwarf_op(ops); + return 0; + } + return -1; +} +#endif /* HAVE_DWARF_CFI_SUPPORT */ /* * die_has_loclist - Check if DW_AT_location of @vr_die is a location list diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index 4e64caac6df8..f209f9162908 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -177,4 +177,19 @@ static inline Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die __maybe_unu #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ +#ifdef HAVE_DWARF_CFI_SUPPORT + +/* Get the frame base information from CFA */ +int die_get_cfa(Dwarf *dwarf, u64 pc, int *preg, int *poffset); + +#else /* HAVE_DWARF_CFI_SUPPORT */ + +static inline int die_get_cfa(Dwarf *dwarf __maybe_unused, u64 pc __maybe_unused, + int *preg __maybe_unused, int *poffset __maybe_unused) +{ + return -1; +} + +#endif /* HAVE_DWARF_CFI_SUPPORT */ + #endif /* _DWARF_AUX_H */ From patchwork Thu Nov 9 23:59:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451904 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6E60039869; Fri, 10 Nov 2023 00:01:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AAx/yLIF" Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ED76E5588; Thu, 9 Nov 2023 16:01:11 -0800 (PST) Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-28035cf6a30so1362029a91.3; Thu, 09 Nov 2023 16:01:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574471; x=1700179271; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=JYFwIAb7kxbU9cm7QXOeqNap9fm6ZmSIsEYNNSyiElg=; b=AAx/yLIFsFyA4TLBEEBIPwiXspEhEGilnfFR32RWIvOse8KwN9HkvcAxCwozreS+aA zQ2N94PKcJdNt7NA41LttT2nBbhhNYuJag/Ds7FcIb0jQOXqMFtm0RwbyPjsnUAryS/O T7RN3347oEddcXxv+e28iL7n5r6pRwH2oX880t02uy4bzIJB+sNUE19OFYvan9+Nj0xx F69GPPqDf/TDgeYBj1G8wfrr3ME3d+aASzg3vkQBMMJBKl9J8FvQNziwhix4o7hCLzXT PzAdnSeJQ6AkXPIFrpi0wRcO/XFR+xrStysH0UayytIdFKjxQ403S5/Y++v8LyOer4w0 cz+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574471; x=1700179271; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=JYFwIAb7kxbU9cm7QXOeqNap9fm6ZmSIsEYNNSyiElg=; b=iJwpinMeNZcThINvTiUWSH2DDWf4u/9hp88JKmEQP69vjeDC8Ew/v7oPaXZoB/C8aC /Gi19n5Hlw/9bMvmatiWMdV7P+BGXAOPKQndCmS1a7t+QI7d0eQaIWXzlVmTxkLn0Qq3 saESQKbEYld+IZffrRq0aTs0i5tSO3OMkUjzdycLMzMydYAZYxxiRG0AgLUZsTXDjykG RePAokP8q39ubvLqI678NTPcPh52MySoGvCoK5PNKTM6CZJnnAftJ2BB3a7Go6hG6Rb5 5mvRmq+VUM57ljxfkdGaHjCQ9rQ11WYCDsUxteDnMue21JjaSjjVbEEpCY3bm5pCw2M3 GYVg== X-Gm-Message-State: AOJu0YxY7/old4rVtlCsjALRrtKtV9rmlHCDAmhz+runiSZ7Qi77irDA f6d0oCg4KUjRNvDujw/wLSI= X-Google-Smtp-Source: AGHT+IEGqDLGnipkF9YoFz2felgnvo7Vb5L588AAUbBd74/hi1FnZonlpf6NmX8xoius41IHXeYBkA== X-Received: by 2002:a17:90b:4a0c:b0:279:23a:9e70 with SMTP id kk12-20020a17090b4a0c00b00279023a9e70mr3237201pjb.2.1699574471020; Thu, 09 Nov 2023 16:01:11 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:10 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 36/52] perf annotate-data: Support stack variables Date: Thu, 9 Nov 2023 15:59:55 -0800 Message-ID: <20231110000012.3538610-37-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Local variables are allocated in the stack and the location list should look like base register(s) and an offset. Extend the die_find_variable_by_reg() to handle the following expressions * DW_OP_breg{0..31} * DW_OP_bregx * DW_OP_fbreg Ususally DWARF subprogram entries have frame base information and use it to locate stack variable like below: <2><43d1575>: Abbrev Number: 62 (DW_TAG_variable) <43d1576> DW_AT_location : 2 byte block: 91 7c (DW_OP_fbreg: -4) <--- here <43d1579> DW_AT_name : (indirect string, offset: 0x2c00c9): i <43d157d> DW_AT_decl_file : 1 <43d157e> DW_AT_decl_line : 78 <43d157f> DW_AT_type : <0x43d19d7> I found some differences on saving the frame base between gcc and clang. The gcc uses the CFA to get the base so it needs to check the current frame's CFI info. In this case, stack offset needs to be adjusted from the start of the CFA. <1><1bb8d>: Abbrev Number: 102 (DW_TAG_subprogram) <1bb8e> DW_AT_name : (indirect string, offset: 0x74d41): kernel_init <1bb92> DW_AT_decl_file : 2 <1bb92> DW_AT_decl_line : 1440 <1bb94> DW_AT_decl_column : 18 <1bb95> DW_AT_prototyped : 1 <1bb95> DW_AT_type : <0xcc> <1bb99> DW_AT_low_pc : 0xffffffff81bab9e0 <1bba1> DW_AT_high_pc : 0x1b2 <1bba9> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <------ here <1bbab> DW_AT_call_all_calls: 1 <1bbab> DW_AT_sibling : <0x1bf5a> While clang sets it to a register directly and it can check the register and offset in the instruction directly. <1><43d1542>: Abbrev Number: 60 (DW_TAG_subprogram) <43d1543> DW_AT_low_pc : 0xffffffff816a7c60 <43d154b> DW_AT_high_pc : 0x98 <43d154f> DW_AT_frame_base : 1 byte block: 56 (DW_OP_reg6 (rbp)) <---------- here <43d1551> DW_AT_GNU_all_call_sites: 1 <43d1551> DW_AT_name : (indirect string, offset: 0x3bce91): foo <43d1555> DW_AT_decl_file : 1 <43d1556> DW_AT_decl_line : 75 <43d1557> DW_AT_prototyped : 1 <43d1557> DW_AT_type : <0x43c7332> <43d155b> DW_AT_external : 1 Also it needs to update the offset after finding the type like global variables since the offset was from the frame base. Factor out match_var_offset() to check global and local variables in the same way. The type stats are improved too: Annotate data type stats: total 294, ok 160 (54.4%), bad 134 (45.6%) ----------------------------------------------------------- 30 : no_sym 32 : no_mem_ops 51 : no_var 14 : no_typeinfo 7 : bad_offset Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 35 +++++++++++++-- tools/perf/util/dwarf-aux.c | 79 ++++++++++++++++++++++++--------- tools/perf/util/dwarf-aux.h | 3 ++ 3 files changed, 93 insertions(+), 24 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 99ecf4b3665c..b60c24091360 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -208,7 +208,7 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset, /* * Usually it expects a pointer type for a memory access. * Convert to a real type it points to. But global variables - * are accessed directly without a pointer. + * and local variables are accessed directly without a pointer. */ if (is_pointer) { if ((dwarf_tag(type_die) != DW_TAG_pointer_type && @@ -247,6 +247,9 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, int reg, offset; int ret = -1; int i, nr_scopes; + int fbreg = -1; + bool is_fbreg = false; + int fb_offset = 0; /* Get a compile_unit for this address */ if (!find_cu_die(di, pc, &cu_die)) { @@ -278,7 +281,33 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, /* Get a list of nested scopes - i.e. (inlined) functions and blocks. */ nr_scopes = die_get_scopes(&cu_die, pc, &scopes); + if (reg != DWARF_REG_PC && dwarf_hasattr(&scopes[0], DW_AT_frame_base)) { + Dwarf_Attribute attr; + Dwarf_Block block; + + /* Check if the 'reg' is assigned as frame base register */ + if (dwarf_attr(&scopes[0], DW_AT_frame_base, &attr) != NULL && + dwarf_formblock(&attr, &block) == 0 && block.length == 1) { + switch (*block.data) { + case DW_OP_reg0 ... DW_OP_reg31: + fbreg = *block.data - DW_OP_reg0; + break; + case DW_OP_call_frame_cfa: + if (die_get_cfa(di->dbg, pc, &fbreg, + &fb_offset) < 0) + fbreg = -1; + break; + default: + break; + } + } + } + retry: + is_fbreg = (reg == fbreg); + if (is_fbreg) + offset = loc->offset - fb_offset; + /* Search from the inner-most scope to the outer */ for (i = nr_scopes - 1; i >= 0; i--) { if (reg == DWARF_REG_PC) { @@ -288,13 +317,13 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, } else { /* Look up variables/parameters in this scope */ if (!die_find_variable_by_reg(&scopes[i], pc, reg, - &var_die)) + &offset, is_fbreg, &var_die)) continue; } /* Found a variable, see if it's correct */ ret = check_variable(&var_die, type_die, offset, - reg != DWARF_REG_PC); + reg != DWARF_REG_PC && !is_fbreg); loc->offset = offset; goto out; } diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 3d42a8613869..7caf52fdc255 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1272,11 +1272,39 @@ struct find_var_data { unsigned reg; /* Access offset, set for global data */ int offset; + /* True if the current register is the frame base */ + bool is_fbreg; }; /* Max number of registers DW_OP_regN supports */ #define DWARF_OP_DIRECT_REGS 32 +static bool match_var_offset(Dwarf_Die *die_mem, struct find_var_data *data, + u64 addr_offset, u64 addr_type) +{ + Dwarf_Die type_die; + Dwarf_Word size; + + if (addr_offset == addr_type) { + /* Update offset relative to the start of the variable */ + data->offset = 0; + return true; + } + + if (die_get_real_type(die_mem, &type_die) == NULL) + return false; + + if (dwarf_aggregate_size(&type_die, &size) < 0) + return false; + + if (addr_offset >= addr_type + size) + return false; + + /* Update offset relative to the start of the variable */ + data->offset = addr_offset - addr_type; + return true; +} + /* Only checks direct child DIEs in the given scope. */ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) { @@ -1301,14 +1329,30 @@ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) if (start > data->pc) break; + /* Local variables accessed using frame base register */ + if (data->is_fbreg && ops->atom == DW_OP_fbreg && + data->offset >= (int)ops->number && + match_var_offset(die_mem, data, data->offset, ops->number)) + return DIE_FIND_CB_END; + /* Only match with a simple case */ if (data->reg < DWARF_OP_DIRECT_REGS) { if (ops->atom == (DW_OP_reg0 + data->reg) && nops == 1) return DIE_FIND_CB_END; + + /* Local variables accessed by a register + offset */ + if (ops->atom == (DW_OP_breg0 + data->reg) && + match_var_offset(die_mem, data, data->offset, ops->number)) + return DIE_FIND_CB_END; } else { if (ops->atom == DW_OP_regx && ops->number == data->reg && nops == 1) return DIE_FIND_CB_END; + + /* Local variables accessed by a register + offset */ + if (ops->atom == DW_OP_bregx && data->reg == ops->number && + match_var_offset(die_mem, data, data->offset, ops->number2)) + return DIE_FIND_CB_END; } } return DIE_FIND_CB_SIBLING; @@ -1319,18 +1363,29 @@ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) * @sc_die: a scope DIE * @pc: the program address to find * @reg: the register number to find + * @poffset: pointer to offset, will be updated for fbreg case + * @is_fbreg: boolean value if the current register is the frame base * @die_mem: a buffer to save the resulting DIE * - * Find the variable DIE accessed by the given register. + * Find the variable DIE accessed by the given register. It'll update the @offset + * when the variable is in the stack. */ Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg, + int *poffset, bool is_fbreg, Dwarf_Die *die_mem) { struct find_var_data data = { .pc = pc, .reg = reg, + .offset = *poffset, + .is_fbreg = is_fbreg, }; - return die_find_child(sc_die, __die_find_var_reg_cb, &data, die_mem); + Dwarf_Die *result; + + result = die_find_child(sc_die, __die_find_var_reg_cb, &data, die_mem); + if (result) + *poffset = data.offset; + return result; } /* Only checks direct child DIEs in the given scope */ @@ -1341,8 +1396,6 @@ static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg) ptrdiff_t off = 0; Dwarf_Attribute attr; Dwarf_Addr base, start, end; - Dwarf_Word size; - Dwarf_Die type_die; Dwarf_Op *ops; size_t nops; @@ -1359,24 +1412,8 @@ static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg) if (data->addr < ops->number) continue; - if (data->addr == ops->number) { - /* Update offset relative to the start of the variable */ - data->offset = 0; + if (match_var_offset(die_mem, data, data->addr, ops->number)) return DIE_FIND_CB_END; - } - - if (die_get_real_type(die_mem, &type_die) == NULL) - continue; - - if (dwarf_aggregate_size(&type_die, &size) < 0) - continue; - - if (data->addr >= ops->number + size) - continue; - - /* Update offset relative to the start of the variable */ - data->offset = data->addr - ops->number; - return DIE_FIND_CB_END; } return DIE_FIND_CB_SIBLING; } diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index f209f9162908..85dd527ae1f7 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -142,6 +142,7 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); /* Find a variable saved in the 'reg' at given address */ Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg, + int *poffset, bool is_fbreg, Dwarf_Die *die_mem); /* Find a (global) variable located in the 'addr' */ @@ -161,6 +162,8 @@ static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, static inline Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die __maybe_unused, Dwarf_Addr pc __maybe_unused, int reg __maybe_unused, + int *poffset __maybe_unused, + bool is_fbreg __maybe_unused, Dwarf_Die *die_mem __maybe_unused) { return NULL; From patchwork Thu Nov 9 23:59:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451905 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2812DDAD; Fri, 10 Nov 2023 00:01:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HmjcQBy/" Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3587C558E; Thu, 9 Nov 2023 16:01:13 -0800 (PST) Received: by mail-pj1-x1029.google.com with SMTP id 98e67ed59e1d1-28035cf6a30so1362058a91.3; Thu, 09 Nov 2023 16:01:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574472; x=1700179272; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=A+ZW371zrAQmL/YEw25gnL0bJ3efAAYgDERy3nsHpt4=; b=HmjcQBy/5Bei5ZI/kPXDfHvQo9tZOOwY7XubHzqe3rvg8UqcU8kFuZhwIkAjVYhRp9 X3MuylRlp9wzGU2/c4MnguOXhArhP39XQU20TJh5r4lyBlsqVtRhm01BL0cAJbM6+R8t Azct0dK38yrYmRUl0lJNZrVcdk2P24OimoT5/78eoMMnKNsneSB3KWRQDuA0gghXF1tF OaKOVuEnkSWQlGf8eAUecGdIzNypbvjvInCZ0VZFVvDmNmdpoeqpuTOp97RTB4zbD/hn 7dNIHOxJm0Mnbj6A3kWF3ahcsiMffmZuZrFecCwu+a+18bxX1D6k9yQRrHIVlw20rfP0 1DOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574472; x=1700179272; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=A+ZW371zrAQmL/YEw25gnL0bJ3efAAYgDERy3nsHpt4=; b=rBdT7bgNn1E+M9VmwMuhhdMT6g0nD6DBSlE50Qbpt3Mnit/Zk+f+9dZIOm92RR0opf j7ymnHr6e04rUyLiKM4UpvMP5KbCjKcpqpAZYoB+XiG75pYZ+x5s3alvpt9esirjMqj+ R1D/Cz+rjU6AaRv3xbiIoGFS5I1Hgsp3InJUZ218C0rP6P8/hcTapHFWy79c8Alm8tnt 6P8OEa2QUtFyZiNXOgh+UXxdqRg/dffPoOmMQAp2Chl6ePyvVKKT20EK6U9B7Gv9yzCa iV/V70IyZbmOwcesENONnV3JPFw9QZfyru9OxAk6hm3hnrqxH6IFepv7oEznh2cIQT7C Mskw== X-Gm-Message-State: AOJu0YyvQJ+HTzx62JwyDHQJzhCg6pgWGDKZLAh7Olnt5WvY8HtjlsOz OoKMQe3xwksCmzKt9vQJvGA= X-Google-Smtp-Source: AGHT+IHnzIzsFJ4cRt1Hhz1BOfUl9ub+emNl3QoYKdLz0QKEvX7n/t0ubzYKS2dCVqI0V+EHgXiubA== X-Received: by 2002:a17:90a:e54f:b0:27c:efe3:89dc with SMTP id ei15-20020a17090ae54f00b0027cefe389dcmr3014391pjb.14.1699574472581; Thu, 09 Nov 2023 16:01:12 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:12 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 37/52] perf dwarf-aux: Check allowed DWARF Ops Date: Thu, 9 Nov 2023 15:59:56 -0800 Message-ID: <20231110000012.3538610-38-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The DWARF location expression can be fairly complex and it'd be hard to match it with the condition correctly. So let's be conservative and only allow simple expressions. For now it just checks the first operation in the list. The following operations looks ok: * DW_OP_stack_value * DW_OP_deref_size * DW_OP_deref * DW_OP_piece To refuse complex (and unsupported) location expressions, add check_allowed_ops() to compare the rest of the list. It seems earlier result contained those unsupported expressions. For example, I found some local struct variable is placed like below. <2><43d1517>: Abbrev Number: 62 (DW_TAG_variable) <43d1518> DW_AT_location : 15 byte block: 91 50 93 8 91 78 93 4 93 84 8 91 68 93 4 (DW_OP_fbreg: -48; DW_OP_piece: 8; DW_OP_fbreg: -8; DW_OP_piece: 4; DW_OP_piece: 1028; DW_OP_fbreg: -24; DW_OP_piece: 4) Another example is something like this. 0057c8be ffffffffffffffff ffffffff812109f0 (base address) 0057c8ce ffffffff812112b5 ffffffff812112c8 (DW_OP_breg3 (rbx): 0; DW_OP_constu: 18446744073709551612; DW_OP_and; DW_OP_stack_value) It should refuse them. After the change, the stat shows: Annotate data type stats: total 294, ok 158 (53.7%), bad 136 (46.3%) ----------------------------------------------------------- 30 : no_sym 32 : no_mem_ops 53 : no_var 14 : no_typeinfo 7 : bad_offset Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 44 +++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 7caf52fdc255..2791126069b4 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1305,6 +1305,34 @@ static bool match_var_offset(Dwarf_Die *die_mem, struct find_var_data *data, return true; } +static bool check_allowed_ops(Dwarf_Op *ops, size_t nops) +{ + /* The first op is checked separately */ + ops++; + nops--; + + /* + * It needs to make sure if the location expression matches to the given + * register and offset exactly. Thus it rejects any complex expressions + * and only allows a few of selected operators that doesn't change the + * location. + */ + while (nops) { + switch (ops->atom) { + case DW_OP_stack_value: + case DW_OP_deref_size: + case DW_OP_deref: + case DW_OP_piece: + break; + default: + return false; + } + ops++; + nops--; + } + return true; +} + /* Only checks direct child DIEs in the given scope. */ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) { @@ -1332,25 +1360,31 @@ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) /* Local variables accessed using frame base register */ if (data->is_fbreg && ops->atom == DW_OP_fbreg && data->offset >= (int)ops->number && + check_allowed_ops(ops, nops) && match_var_offset(die_mem, data, data->offset, ops->number)) return DIE_FIND_CB_END; /* Only match with a simple case */ if (data->reg < DWARF_OP_DIRECT_REGS) { - if (ops->atom == (DW_OP_reg0 + data->reg) && nops == 1) + /* pointer variables saved in a register 0 to 31 */ + if (ops->atom == (DW_OP_reg0 + data->reg) && + check_allowed_ops(ops, nops)) return DIE_FIND_CB_END; /* Local variables accessed by a register + offset */ if (ops->atom == (DW_OP_breg0 + data->reg) && + check_allowed_ops(ops, nops) && match_var_offset(die_mem, data, data->offset, ops->number)) return DIE_FIND_CB_END; } else { + /* pointer variables saved in a register 32 or above */ if (ops->atom == DW_OP_regx && ops->number == data->reg && - nops == 1) + check_allowed_ops(ops, nops)) return DIE_FIND_CB_END; /* Local variables accessed by a register + offset */ if (ops->atom == DW_OP_bregx && data->reg == ops->number && + check_allowed_ops(ops, nops) && match_var_offset(die_mem, data, data->offset, ops->number2)) return DIE_FIND_CB_END; } @@ -1412,7 +1446,8 @@ static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg) if (data->addr < ops->number) continue; - if (match_var_offset(die_mem, data, data->addr, ops->number)) + if (check_allowed_ops(ops, nops) && + match_var_offset(die_mem, data, data->addr, ops->number)) return DIE_FIND_CB_END; } return DIE_FIND_CB_SIBLING; @@ -1503,7 +1538,8 @@ int die_get_cfa(Dwarf *dwarf, u64 pc, int *preg, int *poffset) return -1; if (!dwarf_cfi_addrframe(cfi, pc, &frame) && - !dwarf_frame_cfa(frame, &ops, &nops) && nops == 1) { + !dwarf_frame_cfa(frame, &ops, &nops) && + check_allowed_ops(ops, nops)) { *preg = reg_from_dwarf_op(ops); *poffset = offset_from_dwarf_op(ops); return 0; From patchwork Thu Nov 9 23:59:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451906 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 251F03219F; Fri, 10 Nov 2023 00:01:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eQSfHD6q" Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B4EFC44BD; Thu, 9 Nov 2023 16:01:14 -0800 (PST) Received: by mail-pj1-x102b.google.com with SMTP id 98e67ed59e1d1-28019b66ad5so1294056a91.3; Thu, 09 Nov 2023 16:01:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574474; x=1700179274; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=uT1nC/9fwVyUyj/Fu7de7zQ927+akdOp694fgBwHADA=; b=eQSfHD6qRSxxcCJ4zVBQiHAVW0LYKgFgXjSzEZ8SNsi0xsq8hMByVP00UMwVdYUdO+ TPvk0oiBybTql7XrmO+p8oljr/zD7pD+93m9NsDkBsrkjVtaPgcQUNRIpsUs0qCEj+EZ XCAUrtqiSlX19j6CaFYEhUEaZCNOPjGmybm9CcOWQ/ocnRdJpZ14qowUqEMIQX7JHkGp d/lfRx+BRROYjE8Go2S8NPlkOfdjj32R0+goFYOJ4oxYuULgWCkyemzrsi4MFkeshEPE nxdZBHChrBJqpJNuFbHdghQ1/utoUHDNzNfoWkBha4vosMwPQTOFdJ/zVtEd4zrfC/HI nvCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574474; x=1700179274; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=uT1nC/9fwVyUyj/Fu7de7zQ927+akdOp694fgBwHADA=; b=VZpKlAPYJGdevsXByj4RBjP7TnSQ0Ec9vAtsGyVpNCPFDFknYJEgUR6egPzGcV+YaO iPKYuTZI4Vk9ljT6QIlWw3X+qStrtLBgSdbTDnCkdMEZAs0B3jIhMsPO0ulp1Cu6yPhe lD1+1xfsAErXliq8ciWw46OK9x/DXRC+mA1xK0r1V667tzMci2rrb1ZlyssUM+mZvKF8 8aWlZXtF4jOnrnNVj9StR51Yt4kvDxuPyRGHZpWD6pQFydyQZMafNQ/6Px+Z8/vRZtby Rj/raLI89dHp02w+ImiN3VdhnFd4M+aNwYbM4GQyeCNUZOjMeTUAMSqb9m6LjbZDrYr1 ggoA== X-Gm-Message-State: AOJu0YwT69TBSD/ZdBPhV2DUUWy0GJg88igh8jjcd2XG+J7SWXXGjg6F eZzuZx1pUjcdJZ1va5oVXAg= X-Google-Smtp-Source: AGHT+IFO/JkanR9IR/Lp11Sg73brWz8xYwaLrFQ+5d854RWPIu8c2V7iw3LrpPbt3IIieBVPIz5Ytg== X-Received: by 2002:a17:90b:1b45:b0:27d:9f6:47a3 with SMTP id nv5-20020a17090b1b4500b0027d09f647a3mr3498693pjb.31.1699574474120; Thu, 09 Nov 2023 16:01:14 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:13 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 38/52] perf dwarf-aux: Add die_collect_vars() Date: Thu, 9 Nov 2023 15:59:57 -0800 Message-ID: <20231110000012.3538610-39-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The die_collect_vars() is to find all variable information in the scope including function parameters. The struct die_var_type is to save the type of the variable with the location (reg and offset) as well as where it's defined in the code (addr). Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 118 +++++++++++++++++++++++++++--------- tools/perf/util/dwarf-aux.h | 17 ++++++ 2 files changed, 107 insertions(+), 28 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 2791126069b4..f878014c9e27 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1136,6 +1136,40 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); } +#if defined(HAVE_DWARF_GETLOCATIONS_SUPPORT) || defined(HAVE_DWARF_CFI_SUPPORT) +static int reg_from_dwarf_op(Dwarf_Op *op) +{ + switch (op->atom) { + case DW_OP_reg0 ... DW_OP_reg31: + return op->atom - DW_OP_reg0; + case DW_OP_breg0 ... DW_OP_breg31: + return op->atom - DW_OP_breg0; + case DW_OP_regx: + case DW_OP_bregx: + return op->number; + default: + break; + } + return -1; +} + +static int offset_from_dwarf_op(Dwarf_Op *op) +{ + switch (op->atom) { + case DW_OP_reg0 ... DW_OP_reg31: + case DW_OP_regx: + return 0; + case DW_OP_breg0 ... DW_OP_breg31: + return op->number; + case DW_OP_bregx: + return op->number2; + default: + break; + } + return -1; +} +#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT || HAVE_DWARF_CFI_SUPPORT */ + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT /** * die_get_var_innermost_scope - Get innermost scope range of given variable DIE @@ -1479,41 +1513,69 @@ Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr pc, *offset = data.offset; return result; } -#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ -#ifdef HAVE_DWARF_CFI_SUPPORT -static int reg_from_dwarf_op(Dwarf_Op *op) +static int __die_collect_vars_cb(Dwarf_Die *die_mem, void *arg) { - switch (op->atom) { - case DW_OP_reg0 ... DW_OP_reg31: - return op->atom - DW_OP_reg0; - case DW_OP_breg0 ... DW_OP_breg31: - return op->atom - DW_OP_breg0; - case DW_OP_regx: - case DW_OP_bregx: - return op->number; - default: - break; - } - return -1; + struct die_var_type **var_types = arg; + Dwarf_Die type_die; + int tag = dwarf_tag(die_mem); + Dwarf_Attribute attr; + Dwarf_Addr base, start, end; + Dwarf_Op *ops; + size_t nops; + struct die_var_type *vt; + + if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter) + return DIE_FIND_CB_SIBLING; + + if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) + return DIE_FIND_CB_SIBLING; + + /* + * Only collect the first location as it can reconstruct the + * remaining state by following the instructions. + * start = 0 means it covers the whole range. + */ + if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0) + return DIE_FIND_CB_SIBLING; + + if (die_get_real_type(die_mem, &type_die) == NULL) + return DIE_FIND_CB_SIBLING; + + vt = malloc(sizeof(*vt)); + if (vt == NULL) + return DIE_FIND_CB_END; + + vt->die_off = dwarf_dieoffset(&type_die); + vt->addr = start; + vt->reg = reg_from_dwarf_op(ops); + vt->offset = offset_from_dwarf_op(ops); + vt->next = *var_types; + *var_types = vt; + + return DIE_FIND_CB_SIBLING; } -static int offset_from_dwarf_op(Dwarf_Op *op) +/** + * die_collect_vars - Save all variables and parameters + * @sc_die: a scope DIE + * @var_types: a pointer to save the resulting list + * + * Save all variables and parameters in the @sc_die and save them to @var_types. + * The @var_types is a singly-linked list containing type and location info. + * Actual type can be retrieved using dwarf_offdie() with 'die_off' later. + * + * Callers should free @var_types. + */ +void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types) { - switch (op->atom) { - case DW_OP_reg0 ... DW_OP_reg31: - case DW_OP_regx: - return 0; - case DW_OP_breg0 ... DW_OP_breg31: - return op->number; - case DW_OP_bregx: - return op->number2; - default: - break; - } - return -1; + Dwarf_Die die_mem; + + die_find_child(sc_die, __die_collect_vars_cb, (void *)var_types, &die_mem); } +#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ +#ifdef HAVE_DWARF_CFI_SUPPORT /** * die_get_cfa - Get frame base information * @dwarf: a Dwarf info diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index 85dd527ae1f7..efafd3a1f5b6 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -135,6 +135,15 @@ void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die, /* Get the list of including scopes */ int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes); +/* Variable type information */ +struct die_var_type { + struct die_var_type *next; + u64 die_off; + u64 addr; + int reg; + int offset; +}; + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT /* Get byte offset range of given variable DIE */ @@ -150,6 +159,9 @@ Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr pc, Dwarf_Addr addr, Dwarf_Die *die_mem, int *offset); +/* Save all variables and parameters in this scope */ +void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types); + #else /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, @@ -178,6 +190,11 @@ static inline Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die __maybe_unu return NULL; } +static inline void die_collect_vars(Dwarf_Die *sc_die __maybe_unused, + struct die_var_type **var_types __maybe_unused) +{ +} + #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ #ifdef HAVE_DWARF_CFI_SUPPORT From patchwork Thu Nov 9 23:59:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451907 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96516DDAD; Fri, 10 Nov 2023 00:01:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BUVnHbZG" Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32B0447AE; Thu, 9 Nov 2023 16:01:16 -0800 (PST) Received: by mail-pg1-x532.google.com with SMTP id 41be03b00d2f7-5be24d41bb8so162466a12.0; Thu, 09 Nov 2023 16:01:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574475; x=1700179275; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=m0dxuEbR5jZqtd2BZmTVNrG3auPejdj7FpqX+DTGvcY=; b=BUVnHbZGmi+uO/b+nNeOxmtkpuUrU6OZkMF+l5hOuiKBBqyk2JIwT8q3YI47TrkwEi Y7mNNVRwhHS7tnBmCrfjgxbMoOnVSG64lLSGqRQRF6aVr4tIoQ8fzLlxyGZBUo6pXknK 4Azgr9W8HTpdfKbfSR5BmnDsKD5kcPXGb71hHNdSZIESWFvfD/y4cPytV1lw0BB8SFrp +22Yt1RRLtzSvuuiEaiodHDWLCRp+i1ypAHaprxu7SexYVoJceCFBl8/yAKbiFIWYfNL sRSvqw+oA609GcoYGL0cP9P4vCCsQrwsWone+lBi0ZWpaWm98h+wK7kpX+07iaIsWdxK V8iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574475; x=1700179275; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=m0dxuEbR5jZqtd2BZmTVNrG3auPejdj7FpqX+DTGvcY=; b=BwueXOl6evZg3RqiUV4ZH7YGV9k7S2vK/DA7uuOmUdXG1AZ27eJ/CkCIF3Qvp5IAiU LqW2CNIibVlygWtmtqIeGoCgkpbc+kd7LE7VU4N/rAPPqJQdQBHW7LYDbjPzpWQP830T MQMwGauCbq0jtjfO9wI7OmcKbXeef4W/RS4EqaZ14MyKRuHZEj7PUZqnp59m9tUjr1Fe RluX8Ql12Aa28a3H4eZ4lghSsSAtRFe2ZxBlOrQ+mksk5uYf4f+0O4BU4vYUKRPo0AGM Q+mwcXDJHarhGflmAYVVXKfVUim7+exrJHsQaSIbmlfUIaxGIPMSz7vgJxjm7fM6jI+I zV+w== X-Gm-Message-State: AOJu0YyDPDOb+8o5nIjjcdppIXLUnhvEZho+sd9eQzYMDy34cRFtx9aD SH5n+mW3Nqx0OON+AiDqGZbGCj4262w= X-Google-Smtp-Source: AGHT+IGrAF9hEktqUyOvfsnTKTIzu6+ZaZ6dDMZZZh3UJUErCS54lmHI3Q9hYCg+zcZBmapjxKK9RA== X-Received: by 2002:a17:90b:1e09:b0:280:4af4:1a41 with SMTP id pg9-20020a17090b1e0900b002804af41a41mr1208908pjb.15.1699574475552; Thu, 09 Nov 2023 16:01:15 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:15 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 39/52] perf dwarf-aux: Handle type transfer for memory access Date: Thu, 9 Nov 2023 15:59:58 -0800 Message-ID: <20231110000012.3538610-40-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We want to track type states as instructions are executed. Each instruction can access compound types like struct or union and load/ store its members to a different location. The die_deref_ptr_type() is to find a type of memory access with a pointer variable. If it points to a compound type like struct, the target memory is a member in the struct. The access will happen with an offset indicating which member it refers. Let's follow the DWARF info to figure out the type of the pointer target. For example, say we have the following code. struct foo { int a; int b; }; struct foo *p = malloc(sizeof(*p)); p->b = 0; The last pointer access should produce x86 asm like below: mov 0x0, 4(%rbx) And we know %rbx register has a pointer to struct foo. Then offset 4 should return the debug info of member 'b'. Also variables of compound types can be accessed directly without a pointer. The die_get_member_type() is to handle a such case. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 110 ++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 6 ++ 2 files changed, 116 insertions(+) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index f878014c9e27..39851ff1d5c4 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1841,3 +1841,113 @@ int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes) *scopes = data.scopes; return data.nr; } + +static int __die_find_member_offset_cb(Dwarf_Die *die_mem, void *arg) +{ + Dwarf_Die type_die; + Dwarf_Word size, loc; + Dwarf_Word offset = (long)arg; + int tag = dwarf_tag(die_mem); + + if (tag != DW_TAG_member) + return DIE_FIND_CB_SIBLING; + + /* Unions might not have location */ + if (die_get_data_member_location(die_mem, &loc) < 0) + loc = 0; + + if (offset == loc) + return DIE_FIND_CB_END; + + die_get_real_type(die_mem, &type_die); + + if (dwarf_aggregate_size(&type_die, &size) < 0) + size = 0; + + if (loc < offset && offset < (loc + size)) + return DIE_FIND_CB_END; + + return DIE_FIND_CB_SIBLING; +} + +/** + * die_get_member_type - Return type info of struct member + * @type_die: a type DIE + * @offset: offset in the type + * @die_mem: a buffer to save the resulting DIE + * + * This function returns a type of a member in @type_die where it's located at + * @offset if it's a struct. For now, it just returns the first matching + * member in a union. For other types, it'd return the given type directly + * if it's within the size of the type or NULL otherwise. + */ +Dwarf_Die *die_get_member_type(Dwarf_Die *type_die, int offset, + Dwarf_Die *die_mem) +{ + Dwarf_Die *member; + Dwarf_Die mb_type; + int tag; + + tag = dwarf_tag(type_die); + /* If it's not a compound type, return the type directly */ + if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { + Dwarf_Word size; + + if (dwarf_aggregate_size(type_die, &size) < 0) + size = 0; + + if ((unsigned)offset >= size) + return NULL; + + *die_mem = *type_die; + return die_mem; + } + + mb_type = *type_die; + /* TODO: Handle union types better? */ + while (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) { + member = die_find_child(&mb_type, __die_find_member_offset_cb, + (void *)(long)offset, die_mem); + if (member == NULL) + return NULL; + + if (die_get_real_type(member, &mb_type) == NULL) + return NULL; + + tag = dwarf_tag(&mb_type); + + if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) { + Dwarf_Word loc; + + /* Update offset for the start of the member struct */ + if (die_get_data_member_location(member, &loc) == 0) + offset -= loc; + } + } + *die_mem = mb_type; + return die_mem; +} + +/** + * die_deref_ptr_type - Return type info for pointer access + * @ptr_die: a pointer type DIE + * @offset: access offset for the pointer + * @die_mem: a buffer to save the resulting DIE + * + * This function follows the pointer in @ptr_die with given @offset + * and saves the resulting type in @die_mem. If the pointer points + * a struct type, actual member at the offset would be returned. + */ +Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset, + Dwarf_Die *die_mem) +{ + Dwarf_Die type_die; + + if (dwarf_tag(ptr_die) != DW_TAG_pointer_type) + return NULL; + + if (die_get_real_type(ptr_die, &type_die) == NULL) + return NULL; + + return die_get_member_type(&type_die, offset, die_mem); +} diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index efafd3a1f5b6..ad4d7322fcbf 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -144,6 +144,12 @@ struct die_var_type { int offset; }; +/* Return type info of a member at offset */ +Dwarf_Die *die_get_member_type(Dwarf_Die *type_die, int offset, Dwarf_Die *die_mem); + +/* Return type info where the pointer and offset point to */ +Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset, Dwarf_Die *die_mem); + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT /* Get byte offset range of given variable DIE */ From patchwork Thu Nov 9 23:59:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451908 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A435DDDAD; Fri, 10 Nov 2023 00:01:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="CdWoo7/6" Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1147355A6; Thu, 9 Nov 2023 16:01:19 -0800 (PST) Received: by mail-pg1-x52f.google.com with SMTP id 41be03b00d2f7-5bdfbd69bd5so1154218a12.1; Thu, 09 Nov 2023 16:01:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574478; x=1700179278; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=G6d/FA31Uj2SsYaTp5usbFIpZAA9TNzMF7pdudXcMtQ=; b=CdWoo7/65Z7hLhOItG/Dgnxx1GmRfnoHRc7K+U2CHBEYue2esUgWA33PbFUKdCJK4A Gy87hZInfjM+tNY1W6SRMYEpyWFr8B5Qx0Ahl977DYlgdUngN6JVHIQ3qvHEeI3DEc61 WJBTCF+gd58RXvdDts7nggpicHpMc/Wd/d6WebaGJVlOZUedlQf6RIImvzXo+kh17M8+ /2ftG8rj5i4FAFTrBfN7NQbpMolSiCg6or/sYdBUM8Vt461IENPoQfbb1cc7emubS8FM Crq8NZh04qsx9vkkjJCAb/Apsx+Pl06lLGX7Rxd4KffnTCNQi5P+k4YY0L60f1IhQk9O 9E2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574478; x=1700179278; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=G6d/FA31Uj2SsYaTp5usbFIpZAA9TNzMF7pdudXcMtQ=; b=ow3ThDYeANnIQEk80JpowBs62tVLMPWTKEegEj+brH2L78qHoIN58cExCx4+hpmKUm ur2Qav/ItU11PuIvTqFrY+aNrrlLGGgDTzWHelj5+CzyF6dH4ADz+OVS2q36bo5Yq8Te zfghUlQP5uAHKYB9AnYfFYGT/5nU3KVXFQ1ibfdr+xoXjmAq1hJuS7CPKULk7mP0gj8K 0a7BjOnDB8EsYo/Ea15hNMDKxWZPJJ3x5scCiCPMSXjZCGChhCn50oEdmLaivFgTeeCU ZNdY2RtajyFUaxwazaZtM1Jt8zhHidaX+EqTgzAR0GQZWkL5IBCf9SIveKVbJvKSJkHV m0YA== X-Gm-Message-State: AOJu0YxfgWr0fQp4WZTIEmF/OJYX2x6WI8lV+6qRjGHuiuzQeB+ng1io sJGVkqR09TTWkjDbXqNngMB6DSiE4Pk= X-Google-Smtp-Source: AGHT+IFMxmDOO5t2lp9FXgNLagth6EfPcNgk3z5mnJR/US3+QmfbhP1h6ub3dyQPUSQTSo/wyeO5EQ== X-Received: by 2002:a17:90b:3c88:b0:280:2a3f:9938 with SMTP id pv8-20020a17090b3c8800b002802a3f9938mr1172667pjb.12.1699574478137; Thu, 09 Nov 2023 16:01:18 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:16 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 40/52] perf annotate-data: Introduce struct data_loc_info Date: Thu, 9 Nov 2023 15:59:59 -0800 Message-ID: <20231110000012.3538610-41-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The find_data_type() needs many information to describe the location of the data. Add the new struct data_loc_info to pass those information at once. No functional changes intended. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 83 +++++++++++++++++---------------- tools/perf/util/annotate-data.h | 38 ++++++++++++--- tools/perf/util/annotate.c | 30 ++++++------ 3 files changed, 91 insertions(+), 60 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index b60c24091360..c61f5b5b6adc 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -238,21 +238,28 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset, } /* The result will be saved in @type_die */ -static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, - const char *var_name, struct annotated_op_loc *loc, - Dwarf_Die *type_die) +static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) { + struct annotated_op_loc *loc = dloc->op; Dwarf_Die cu_die, var_die; Dwarf_Die *scopes = NULL; int reg, offset; int ret = -1; int i, nr_scopes; int fbreg = -1; - bool is_fbreg = false; int fb_offset = 0; + bool is_fbreg = false; + u64 pc; + + /* + * IP is a relative instruction address from the start of the map, as + * it can be randomized/relocated, it needs to translate to PC which is + * a file address for DWARF processing. + */ + pc = map__rip_2objdump(dloc->ms->map, dloc->ip); /* Get a compile_unit for this address */ - if (!find_cu_die(di, pc, &cu_die)) { + if (!find_cu_die(dloc->di, pc, &cu_die)) { pr_debug("cannot find CU for address %lx\n", pc); ann_data_stat.no_cuinfo++; return -1; @@ -262,18 +269,19 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, offset = loc->offset; if (reg == DWARF_REG_PC) { - if (die_find_variable_by_addr(&cu_die, pc, addr, &var_die, &offset)) { + if (die_find_variable_by_addr(&cu_die, pc, dloc->var_addr, + &var_die, &offset)) { ret = check_variable(&var_die, type_die, offset, /*is_pointer=*/false); - loc->offset = offset; + dloc->type_offset = offset; goto out; } - if (var_name && die_find_variable_at(&cu_die, var_name, pc, - &var_die)) { - ret = check_variable(&var_die, type_die, 0, + if (dloc->var_name && + die_find_variable_at(&cu_die, dloc->var_name, pc, &var_die)) { + ret = check_variable(&var_die, type_die, dloc->type_offset, /*is_pointer=*/false); - /* loc->offset will be updated by the caller */ + /* dloc->type_offset was updated by the caller */ goto out; } } @@ -290,10 +298,11 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, dwarf_formblock(&attr, &block) == 0 && block.length == 1) { switch (*block.data) { case DW_OP_reg0 ... DW_OP_reg31: - fbreg = *block.data - DW_OP_reg0; + fbreg = dloc->fbreg = *block.data - DW_OP_reg0; break; case DW_OP_call_frame_cfa: - if (die_get_cfa(di->dbg, pc, &fbreg, + dloc->fb_cfa = true; + if (die_get_cfa(dloc->di->dbg, pc, &fbreg, &fb_offset) < 0) fbreg = -1; break; @@ -311,7 +320,7 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, /* Search from the inner-most scope to the outer */ for (i = nr_scopes - 1; i >= 0; i--) { if (reg == DWARF_REG_PC) { - if (!die_find_variable_by_addr(&scopes[i], pc, addr, + if (!die_find_variable_by_addr(&scopes[i], pc, dloc->var_addr, &var_die, &offset)) continue; } else { @@ -324,7 +333,7 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, /* Found a variable, see if it's correct */ ret = check_variable(&var_die, type_die, offset, reg != DWARF_REG_PC && !is_fbreg); - loc->offset = offset; + dloc->type_offset = offset; goto out; } @@ -343,50 +352,46 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr, /** * find_data_type - Return a data type at the location - * @ms: map and symbol at the location - * @ip: instruction address of the memory access - * @loc: instruction operand location - * @addr: data address of the memory access - * @var_name: global variable name + * @dloc: data location * * This functions searches the debug information of the binary to get the data - * type it accesses. The exact location is expressed by (@ip, reg, offset) - * for pointer variables or (@ip, @addr) for global variables. Note that global - * variables might update the @loc->offset after finding the start of the variable. - * If it cannot find a global variable by address, it tried to fine a declaration - * of the variable using @var_name. In that case, @loc->offset won't be updated. + * type it accesses. The exact location is expressed by (ip, reg, offset) + * for pointer variables or (ip, addr) for global variables. Note that global + * variables might update the @dloc->type_offset after finding the start of the + * variable. If it cannot find a global variable by address, it tried to find + * a declaration of the variable using var_name. In that case, @dloc->offset + * won't be updated. * * It return %NULL if not found. */ -struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, - struct annotated_op_loc *loc, u64 addr, - const char *var_name) +struct annotated_data_type *find_data_type(struct data_loc_info *dloc) { struct annotated_data_type *result = NULL; - struct dso *dso = ms->map->dso; - struct debuginfo *di; + struct dso *dso = dloc->ms->map->dso; Dwarf_Die type_die; - u64 pc; - di = debuginfo__new(dso->long_name); - if (di == NULL) { + dloc->di = debuginfo__new(dso->long_name); + if (dloc->di == NULL) { pr_debug("cannot get the debug info\n"); return NULL; } /* - * IP is a relative instruction address from the start of the map, as - * it can be randomized/relocated, it needs to translate to PC which is - * a file address for DWARF processing. + * The type offset is the same as instruction offset by default. + * But when finding a global variable, the offset won't be valid. */ - pc = map__rip_2objdump(ms->map, ip); - if (find_data_type_die(di, pc, addr, var_name, loc, &type_die) < 0) + if (dloc->var_name == NULL) + dloc->type_offset = dloc->op->offset; + + dloc->fbreg = -1; + + if (find_data_type_die(dloc, &type_die) < 0) goto out; result = dso__findnew_data_type(dso, &type_die); out: - debuginfo__delete(di); + debuginfo__delete(dloc->di); return result; } diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 1b0db8e8c40e..ad6493ea2c8e 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -8,6 +8,7 @@ #include struct annotated_op_loc; +struct debuginfo; struct evsel; struct map_symbol; @@ -72,6 +73,35 @@ struct annotated_data_type { extern struct annotated_data_type unknown_type; extern struct annotated_data_type stackop_type; +/** + * struct data_loc_info - Data location information + * @ms: Map and Symbol info + * @ip: Instruction address + * @var_addr: Data address (for global variables) + * @var_name: Variable name (for global variables) + * @op: Instruction operand location (regs and offset) + * @di: Debug info + * @fbreg: Frame base register + * @fb_cfa: Whether the frame needs to check CFA + * @type_offset: Final offset in the type + */ +struct data_loc_info { + /* These are input field, should be filled by caller */ + struct map_symbol *ms; + u64 ip; + u64 var_addr; + const char *var_name; + struct annotated_op_loc *op; + + /* These are used internally */ + struct debuginfo *di; + int fbreg; + bool fb_cfa; + + /* This is for the result */ + int type_offset; +}; + /** * struct annotated_data_stat - Debug statistics * @total: Total number of entry @@ -106,9 +136,7 @@ extern struct annotated_data_stat ann_data_stat; #ifdef HAVE_DWARF_SUPPORT /* Returns data type at the location (ip, reg, offset) */ -struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, - struct annotated_op_loc *loc, u64 addr, - const char *var_name); +struct annotated_data_type *find_data_type(struct data_loc_info *dloc); /* Update type access histogram at the given offset */ int annotated_data_type__update_samples(struct annotated_data_type *adt, @@ -121,9 +149,7 @@ void annotated_data_type__tree_delete(struct rb_root *root); #else /* HAVE_DWARF_SUPPORT */ static inline struct annotated_data_type * -find_data_type(struct map_symbol *ms __maybe_unused, u64 ip __maybe_unused, - struct annotated_op_loc *loc __maybe_unused, - u64 addr __maybe_unused, const char *var_name __maybe_unused) +find_data_type(struct data_loc_info *dloc __maybe_unused) { return NULL; } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4f74db1d3256..136a00e17a5c 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3792,9 +3792,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) struct annotated_op_loc *op_loc; struct annotated_data_type *mem_type; struct annotated_item_stat *istat; - u64 ip = he->ip, addr = 0; - const char *var_name = NULL; - int var_offset; + u64 ip = he->ip; int i; ann_data_stat.total++; @@ -3842,51 +3840,53 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) } for_each_insn_op_loc(&loc, i, op_loc) { + struct data_loc_info dloc = { + .ms = ms, + /* Recalculate IP for LOCK prefix or insn fusion */ + .ip = ms->sym->start + dl->al.offset, + .op = op_loc, + }; + if (!op_loc->mem_ref) continue; /* Recalculate IP because of LOCK prefix or insn fusion */ ip = ms->sym->start + dl->al.offset; - var_offset = op_loc->offset; - /* PC-relative addressing */ if (op_loc->reg1 == DWARF_REG_PC) { struct addr_location al; struct symbol *var; u64 map_addr; - addr = annotate_calc_pcrel(ms, ip, op_loc->offset, dl); + dloc.var_addr = annotate_calc_pcrel(ms, ip, op_loc->offset, dl); /* Kernel symbols might be relocated */ - map_addr = addr + map__reloc(ms->map); + map_addr = dloc.var_addr + map__reloc(ms->map); addr_location__init(&al); var = thread__find_symbol_fb(he->thread, he->cpumode, map_addr, &al); if (var) { - var_name = var->name; + dloc.var_name = var->name; /* Calculate type offset from the start of variable */ - var_offset = map_addr - map__unmap_ip(al.map, var->start); + dloc.type_offset = map_addr - map__unmap_ip(al.map, var->start); } addr_location__exit(&al); } - mem_type = find_data_type(ms, ip, op_loc, addr, var_name); + mem_type = find_data_type(&dloc); if (mem_type) istat->good++; else istat->bad++; - if (mem_type && var_name) - op_loc->offset = var_offset; - if (symbol_conf.annotate_data_sample) { annotated_data_type__update_samples(mem_type, evsel, - op_loc->offset, + dloc.type_offset, he->stat.nr_events, he->stat.period); } - he->mem_type_off = op_loc->offset; + he->mem_type_off = dloc.type_offset; return mem_type; } From patchwork Fri Nov 10 00:00:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451909 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71E7B3219F; Fri, 10 Nov 2023 00:01:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AN8aGCrG" Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A44D549CD; Thu, 9 Nov 2023 16:01:20 -0800 (PST) Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-28094a3b760so1326053a91.3; Thu, 09 Nov 2023 16:01:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574480; x=1700179280; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=c8QAEj7ZpfAN1FTj9/Rbc4l4YuXZwz+MzirCDbahEG4=; b=AN8aGCrGr5kzSpBxetWwxuC7GWWCHC1j8ePkydSrIMLQ9avi1EhEO+1zjIJDikBqJx vcJmx9ELsNqvPZMs+7ha5Bt+WMjt9WTWRGF7ekvX8V2GOWVtGFDusGbJ9dv+8EtsaBLt Dcz9PE1jvjOzUu7FfijnXlqbtfwOfzMq4meOjkG7/uthVykQb8ffp0loWTncCR+cj3Fw 3OHua5N2GwnSBDMgq9YeUg0KpYY2fYQcRwUcQTkZmEKTv0F7b7zrChUtdYfgCKMyztUo md/ztkyJJEh5DBJ7NkIXNZH/sP9ART9YyC0EkWilVjaKC3joKmXnHkkYNpk0xMnwYphr U4rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574480; x=1700179280; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=c8QAEj7ZpfAN1FTj9/Rbc4l4YuXZwz+MzirCDbahEG4=; b=YEbzJnSQyzyrLzDdwP46+F/8Gzk1yXQIjaUTQ3tzgLGLaUdI9VHtm2ut/PGDDXOb7j ldehnbF9TB9bDZmf6EjT76UfsSphxGaHlGoBdWF/QlxflQuKiXNhJiGsCWIYTbRP+iKV JYFUoxN5Fu+PdM6b/FR6RhAIXjvoriwSb7mQlZHH/MjSUDY8jn3wRa6NgabEFgE5zVPl xua6Zxfnt04xy7TvTjE3Ayn+W1MNB/PepepYsfG7SSY/Fvh2gJBTNM13eNQZfQ6t2Oa6 Maw9eo5uR+y22/CMddEp/pLJOUwTU5kSRS74D2x+HhfvU6bMQ+I3Ut3leq1wgySIMeeZ nrrg== X-Gm-Message-State: AOJu0Yxx8/P1/EYMGcCofNln9FT9LauXwRsGBzp3mrtS41r0fzOmCqvA fC6Gf1b/nlfUGvdoWOiIwv0= X-Google-Smtp-Source: AGHT+IG2CoWOYMeP6e+QCAuiIg/l0LJpUL0phHQ9IrCQRn5wIuruABY5evY7r+2R0HykGR1mpUp3lw== X-Received: by 2002:a17:90b:3b88:b0:27d:6b5:9e07 with SMTP id pc8-20020a17090b3b8800b0027d06b59e07mr3255050pjb.1.1699574479929; Thu, 09 Nov 2023 16:01:19 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:19 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 41/52] perf map: Add map__objdump_2rip() Date: Thu, 9 Nov 2023 16:00:00 -0800 Message-ID: <20231110000012.3538610-42-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Sometimes we want to convert an address in objdump output to map-relative address to match with a sample data. Let's add map__objdump_2rip() for that. Cc: Adrian Hunter Signed-off-by: Namhyung Kim --- tools/perf/util/map.c | 20 ++++++++++++++++++++ tools/perf/util/map.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index f64b83004421..f25cf664c898 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -595,6 +595,26 @@ u64 map__objdump_2mem(struct map *map, u64 ip) return ip + map__reloc(map); } +u64 map__objdump_2rip(struct map *map, u64 ip) +{ + const struct dso *dso = map__dso(map); + + if (!dso->adjust_symbols) + return ip; + + if (dso->rel) + return ip + map__pgoff(map); + + /* + * kernel modules also have DSO_TYPE_USER in dso->kernel, + * but all kernel modules are ET_REL, so won't get here. + */ + if (dso->kernel == DSO_SPACE__USER) + return ip - dso->text_offset; + + return map__map_ip(map, ip + map__reloc(map)); +} + bool map__contains_symbol(const struct map *map, const struct symbol *sym) { u64 ip = map__unmap_ip(map, sym->start); diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 1b53d53adc86..b7bcf0aa3b67 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -129,6 +129,9 @@ u64 map__rip_2objdump(struct map *map, u64 rip); /* objdump address -> memory address */ u64 map__objdump_2mem(struct map *map, u64 ip); +/* objdump address -> rip */ +u64 map__objdump_2rip(struct map *map, u64 ip); + struct symbol; struct thread; From patchwork Fri Nov 10 00:00:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451910 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EEE40DDAD; Fri, 10 Nov 2023 00:01:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hPh5Nk7Q" Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5C2FB55AC; Thu, 9 Nov 2023 16:01:22 -0800 (PST) Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-2802d218242so1366192a91.1; Thu, 09 Nov 2023 16:01:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574482; x=1700179282; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=8cqeJZmBhtU/NkALu7mtebMrt9fMeiVjhj08pg6EDRw=; b=hPh5Nk7QObWRd8XWHd04eL1NaNyx5lRLDVoO0CH0Vdfbm8Bro41XmQdRGWdB445v4u oDFjse4i4DL65UU5ZhRr79XXy23H/MZ2D5lM+2j6v54bwqxmdFaM/0mPcj4rX7joBA42 MDg7m0T6+AmuD1KR5TW6g7nx8ZKyrlzyNOzVtqYNjgdI9DtZU3dekyGNFayhvehBBT8W 1ve1tJLy6Ppj+FiMh4hfnnpfemsdaIG+c58ZFLLIneX0l4sX7t1H2evwY9TK0Qh1Ff6b FVX18K8jvCkJjYMqlnzLNNMGb0uYC4eM1DQL1x7FEAARdX4IRZ9OruykyUhs0jqQI2kM gIQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574482; x=1700179282; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=8cqeJZmBhtU/NkALu7mtebMrt9fMeiVjhj08pg6EDRw=; b=JStcRFqRxLJBtUvIEdXsG8cf2vhvWvObFqGNvL65+RuXKh9J1yQ6cljx/3cm4XetH8 7upFBZb1Ac5LX+Y4JyzFz7DYrL3gyDmVwM5wQTXS3ni/5wAe+mI+KN1ZLg2+6DlTnEp3 EdSGo/Luboqs2iV+mjUoBpLWkgDDZw8MhFvk7yaTlfcvfj7F+yA0IkEYOVMoslndqgGR Q2D9eKE4zfx2r5PYkpvCYjmnEVt93tK+aqmLZge1n9mx89poUQc0U46MpNIlyrQEqahS 4a3wWF3Nnf4ptEKrqzmqpXsBUknQ+Zn+09/4fk+drgV+XdLW3OGiz8O8ntIoYDeyhdGB z+2A== X-Gm-Message-State: AOJu0YxHNqcRdFnpbuR1+XXsXv/NvcNGqLyCxK+DBtojNjbKTWRYBB2M yMUaFb1NYs87fpemUVDzD8Y= X-Google-Smtp-Source: AGHT+IHV1RmD15dLsiIGYRIq5hnxkjmITt9lt1rndfkOLUyvzK6xHgLm+L2uYY/hRkRlFn1S/oCMEA== X-Received: by 2002:a17:90b:2250:b0:27d:b811:2fe4 with SMTP id hk16-20020a17090b225000b0027db8112fe4mr3465564pjb.26.1699574481529; Thu, 09 Nov 2023 16:01:21 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:21 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 42/52] perf annotate: Add annotate_get_basic_blocks() Date: Thu, 9 Nov 2023 16:00:01 -0800 Message-ID: <20231110000012.3538610-43-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The annotate_get_basic_blocks() is to find a list of basic blocks from the source instruction to the destination instruction in a function. It'll be used to find variables in a scope. Use BFS (Breadth First Search) to find a shortest path to carry the variable/register state minimally. Also change find_disasm_line() to be used in annotate_get_basic_blocks() and add 'allow_update' argument to control if it can update the IP. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 222 ++++++++++++++++++++++++++++++++++++- tools/perf/util/annotate.h | 16 +++ 2 files changed, 235 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 136a00e17a5c..d54a9ec16af4 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3690,7 +3690,8 @@ static void symbol__ensure_annotate(struct map_symbol *ms, struct evsel *evsel) } } -static struct disasm_line *find_disasm_line(struct symbol *sym, u64 ip) +static struct disasm_line *find_disasm_line(struct symbol *sym, u64 ip, + bool allow_update) { struct disasm_line *dl; struct annotation *notes; @@ -3703,7 +3704,8 @@ static struct disasm_line *find_disasm_line(struct symbol *sym, u64 ip) * llvm-objdump places "lock" in a separate line and * in that case, we want to get the next line. */ - if (!strcmp(dl->ins.name, "lock") && *dl->ops.raw == '\0') { + if (!strcmp(dl->ins.name, "lock") && + *dl->ops.raw == '\0' && allow_update) { ip++; continue; } @@ -3814,7 +3816,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) * Get a disasm to extract the location from the insn. * This is too slow... */ - dl = find_disasm_line(ms->sym, ip); + dl = find_disasm_line(ms->sym, ip, /*allow_update=*/true); if (dl == NULL) { ann_data_stat.no_insn++; return NULL; @@ -3908,3 +3910,217 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) istat->bad++; return NULL; } + +/* Basic block traversal (BFS) data structure */ +struct basic_block_data { + struct list_head queue; + struct list_head visited; +}; + +/* + * During the traversal, it needs to know the parent block where the current + * block block started from. Note that single basic block can be parent of + * two child basic blocks (in case of condition jump). + */ +struct basic_block_link { + struct list_head node; + struct basic_block_link *parent; + struct annotated_basic_block *bb; +}; + +/* Check any of basic block in the list already has the offset */ +static bool basic_block_has_offset(struct list_head *head, s64 offset) +{ + struct basic_block_link *link; + + list_for_each_entry(link, head, node) { + s64 begin_offset = link->bb->begin->al.offset; + s64 end_offset = link->bb->end->al.offset; + + if (begin_offset <= offset && offset <= end_offset) + return true; + } + return false; +} + +static bool is_new_basic_block(struct basic_block_data *bb_data, + struct disasm_line *dl) +{ + s64 offset = dl->al.offset; + + if (basic_block_has_offset(&bb_data->visited, offset)) + return false; + if (basic_block_has_offset(&bb_data->queue, offset)) + return false; + return true; +} + +/* Add a basic block starting from dl and link it to the parent */ +static int add_basic_block(struct basic_block_data *bb_data, + struct basic_block_link *parent, + struct disasm_line *dl) +{ + struct annotated_basic_block *bb; + struct basic_block_link *link; + + if (dl == NULL) + return -1; + + if (!is_new_basic_block(bb_data, dl)) + return 0; + + bb = zalloc(sizeof(*bb)); + if (bb == NULL) + return -1; + + bb->begin = dl; + bb->end = dl; + INIT_LIST_HEAD(&bb->list); + + link = malloc(sizeof(*link)); + if (link == NULL) { + free(bb); + return -1; + } + + link->bb = bb; + link->parent = parent; + list_add_tail(&link->node, &bb_data->queue); + return 0; +} + +/* Returns true when it finds the target in the current basic block */ +static bool process_basic_block(struct basic_block_data *bb_data, + struct basic_block_link *link, + struct symbol *sym, u64 target) +{ + struct disasm_line *dl, *next_dl, *last_dl; + struct annotation *notes = symbol__annotation(sym); + bool found = false; + + dl = link->bb->begin; + /* Check if it's already visited */ + if (basic_block_has_offset(&bb_data->visited, dl->al.offset)) + return false; + + last_dl = list_last_entry(¬es->src->source, + struct disasm_line, al.node); + + list_for_each_entry_from(dl, ¬es->src->source, al.node) { + /* Found the target instruction */ + if (sym->start + dl->al.offset == target) { + found = true; + break; + } + /* End of the function, finish the block */ + if (dl == last_dl) + break; + /* 'return' instruction finishes the block */ + if (dl->ins.ops == &ret_ops) + break; + /* normal instructions are part of the basic block */ + if (dl->ins.ops != &jump_ops) + continue; + /* jump to a different function, tail call or return */ + if (dl->ops.target.outside) + break; + /* jump instruction creates new basic block(s) */ + next_dl = find_disasm_line(sym, sym->start + dl->ops.target.offset, + /*allow_update=*/false); + add_basic_block(bb_data, link, next_dl); + + /* + * FIXME: determine conditional jumps properly. + * Conditional jumps create another basic block with the + * next disasm line. + */ + if (!strstr(dl->ins.name, "jmp")) { + next_dl = list_next_entry(dl, al.node); + add_basic_block(bb_data, link, next_dl); + } + break; + + } + link->bb->end = dl; + return found; +} + +/* + * It founds a target basic block, build a proper linked list of basic blocks + * by following the link recursively. + */ +static void link_found_basic_blocks(struct basic_block_link *link, + struct list_head *head) +{ + while (link) { + struct basic_block_link *parent = link->parent; + + list_move(&link->bb->list, head); + list_del(&link->node); + free(link); + + link = parent; + } +} + +static void delete_basic_blocks(struct basic_block_data *bb_data) +{ + struct basic_block_link *link, *tmp; + + list_for_each_entry_safe(link, tmp, &bb_data->queue, node) { + list_del(&link->node); + free(link->bb); + free(link); + } + + list_for_each_entry_safe(link, tmp, &bb_data->visited, node) { + list_del(&link->node); + free(link->bb); + free(link); + } +} + +/** + * annotate_get_basic_blocks - Get basic blocks for given address range + * @sym: symbol to annotate + * @src: source address + * @dst: destination address + * @head: list head to save basic blocks + * + * This function traverses disasm_lines from @src to @dst and save them in a + * list of annotated_basic_block to @head. It uses BFS to find the shortest + * path between two. The basic_block_link is to maintain parent links so + * that it can build a list of blocks from the start. + */ +int annotate_get_basic_blocks(struct symbol *sym, s64 src, s64 dst, + struct list_head *head) +{ + struct basic_block_data bb_data = { + .queue = LIST_HEAD_INIT(bb_data.queue), + .visited = LIST_HEAD_INIT(bb_data.visited), + }; + struct basic_block_link *link; + struct disasm_line *dl; + int ret = -1; + + dl = find_disasm_line(sym, src, /*allow_update=*/false); + if (dl == NULL) + return -1; + + if (add_basic_block(&bb_data, /*parent=*/NULL, dl) < 0) + return -1; + + /* Find shortest path from src to dst using BFS */ + while (!list_empty(&bb_data.queue)) { + link = list_first_entry(&bb_data.queue, struct basic_block_link, node); + + if (process_basic_block(&bb_data, link, sym, dst)) { + link_found_basic_blocks(link, head); + ret = 0; + break; + } + list_move(&link->node, &bb_data.visited); + } + delete_basic_blocks(&bb_data); + return ret; +} diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 79ccc65c9ff9..e1fa86341281 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -501,4 +501,20 @@ extern struct list_head ann_insn_stat; u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset, struct disasm_line *dl); +/** + * struct annotated_basic_block - Basic block of instructions + * @list: List node + * @begin: start instruction in the block + * @end: end instruction in the block + */ +struct annotated_basic_block { + struct list_head list; + struct disasm_line *begin; + struct disasm_line *end; +}; + +/* Get a list of basic blocks from src to dst addresses */ +int annotate_get_basic_blocks(struct symbol *sym, s64 src, s64 dst, + struct list_head *head); + #endif /* __PERF_ANNOTATE_H */ From patchwork Fri Nov 10 00:00:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451911 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE9BF2E40F; Fri, 10 Nov 2023 00:01:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="goKoS3+h" Received: from mail-pg1-x52b.google.com (mail-pg1-x52b.google.com [IPv6:2607:f8b0:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8087555B6; Thu, 9 Nov 2023 16:01:23 -0800 (PST) Received: by mail-pg1-x52b.google.com with SMTP id 41be03b00d2f7-5bd6ac9833fso1121352a12.0; Thu, 09 Nov 2023 16:01:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574483; x=1700179283; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=kvTfv482Q4PYRjTpfYUAW6Q8pGRZjJf+S0DM/gjie/M=; b=goKoS3+hEtjNEmwDoegPLNieykU8JjffpOH06hD2FsqPQGlUtZC5fLBwHWs0mGwlQq miISCxD20AaU0X69+TgDviwyRQD8nyXUb97ewKtGppxttK2gQRF+7LFraPb+MMsteD2a jzFxkpGnOH0xJICANwiU4rO37K9sb4h6E/Br2q/VQrNr+XkBhHOwcXPTcJXevKVeaWgG UkFT72H4usOwDfQJtVJ5Ox4gGv6YQjVk7BXXYonuru/UJA89q/9b9DrfJa1Vw59cApXQ d1P8XrHvr3UomIU0nzsUfaLNQo3h1hnwcYmGIy8BP2yEheEgtE3w/6v4Auo4J71KRhFK VOGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574483; x=1700179283; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=kvTfv482Q4PYRjTpfYUAW6Q8pGRZjJf+S0DM/gjie/M=; b=hcum198OQalSh4LH3VDWw5mQv/k1HTdIBSRHrxSJkSLvpjsLRjpzOM7tgqBd/QqOP+ FEX/P91JRNiR9xpQb/SD8kGqA9ijUMHppMmfmRLW7V3mI3c8IEyj5P5lSZrjpEp863mI yHJZtFwSobR38+f4PLBCVI+Uz2/My1AgK6kTIkjeWkMrViOnJX7ResmGmXwpKyJn3Nq1 a4hxqK9TwOKsOmwVZEBiFz7YA8bTpOpRyDf+7TKGlMhN9epFeKekTEJ9ewsq7LqGA4Ev /C3RgYgdadlWirkvD2PRp2ucLd80rgEJDO/dx8Qfbsh20WSkxowaTeuJ0IytCduxE6HE CX1A== X-Gm-Message-State: AOJu0YxuiarsaI5Ams+NP8RrxU9tKakACP4OiUDpY+NQNv5xsNp/9t1S RO3eqACzSPgEyH2mQE5QW0o= X-Google-Smtp-Source: AGHT+IFKV9nmHh39ZaEncpP2mUU/qTToe7W832z98mIHNn/T/TPaAaEQU0o6985aaVIeiGICVa5IzA== X-Received: by 2002:a17:90b:1a91:b0:27d:114e:d4a3 with SMTP id ng17-20020a17090b1a9100b0027d114ed4a3mr3003610pjb.14.1699574482871; Thu, 09 Nov 2023 16:01:22 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:22 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 43/52] perf annotate-data: Maintain variable type info Date: Thu, 9 Nov 2023 16:00:02 -0800 Message-ID: <20231110000012.3538610-44-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 As it collected basic block and variable information in each scope, it now can build a state table to find matching variable at the location. The struct type_state is to keep the type info saved in each register and stack slot. The update_var_state() updates the table when it finds variables in the current address. It expects die_collect_vars() filled a list of variables with type info and starting address. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 155 ++++++++++++++++++++++++++++++++ tools/perf/util/annotate-data.h | 29 ++++++ tools/perf/util/dwarf-aux.c | 4 + 3 files changed, 188 insertions(+) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index c61f5b5b6adc..438d6234020b 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -22,6 +22,57 @@ #include "symbol.h" #include "symbol_conf.h" +/* Type information in a register, valid when ok is true */ +struct type_state_reg { + Dwarf_Die type; + bool ok; + bool scratch; +}; + +/* Type information in a stack location, dynamically allocated */ +struct type_state_stack { + struct list_head list; + Dwarf_Die type; + int offset; + int size; + bool compound; +}; + +/* FIXME: This should be arch-dependent */ +#define TYPE_STATE_MAX_REGS 16 + +/* + * State table to maintain type info in each register and stack location. + * It'll be updated when new variable is allocated or type info is moved + * to a new location (register or stack). As it'd be used with the + * shortest path of basic blocks, it only maintains a single table. + */ +struct type_state { + struct type_state_reg regs[TYPE_STATE_MAX_REGS]; + struct list_head stack_vars; +}; + +static bool has_reg_type(struct type_state *state, int reg) +{ + return (unsigned)reg < ARRAY_SIZE(state->regs); +} + +void init_type_state(struct type_state *state, struct arch *arch __maybe_unused) +{ + memset(state, 0, sizeof(*state)); + INIT_LIST_HEAD(&state->stack_vars); +} + +void exit_type_state(struct type_state *state) +{ + struct type_state_stack *stack, *tmp; + + list_for_each_entry_safe(stack, tmp, &state->stack_vars, list) { + list_del(&stack->list); + free(stack); + } +} + /* * Compare type name and size to maintain them in a tree. * I'm not sure if DWARF would have information of a single type in many @@ -237,6 +288,110 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset, return 0; } +static struct type_state_stack *find_stack_state(struct type_state *state, + int offset) +{ + struct type_state_stack *stack; + + list_for_each_entry(stack, &state->stack_vars, list) { + if (offset == stack->offset) + return stack; + + if (stack->compound && stack->offset < offset && + offset < stack->offset + stack->size) + return stack; + } + return NULL; +} + +static void set_stack_state(struct type_state_stack *stack, int offset, + Dwarf_Die *type_die) +{ + int tag; + Dwarf_Word size; + + if (dwarf_aggregate_size(type_die, &size) < 0) + size = 0; + + tag = dwarf_tag(type_die); + + stack->type = *type_die; + stack->size = size; + stack->offset = offset; + + switch (tag) { + case DW_TAG_structure_type: + case DW_TAG_union_type: + stack->compound = true; + break; + default: + stack->compound = false; + break; + } +} + +static struct type_state_stack *findnew_stack_state(struct type_state *state, + int offset, Dwarf_Die *type_die) +{ + struct type_state_stack *stack = find_stack_state(state, offset); + + if (stack) { + set_stack_state(stack, offset, type_die); + return stack; + } + + stack = malloc(sizeof(*stack)); + if (stack) { + set_stack_state(stack, offset, type_die); + list_add(&stack->list, &state->stack_vars); + } + return stack; +} + +/** + * update_var_state - Update type state using given variables + * @state: type state table + * @dloc: data location info + * @addr: instruction address to update + * @var_types: list of variables with type info + * + * This function fills the @state table using @var_types info. Each variable + * is used only at the given location and updates an entry in the table. + */ +void update_var_state(struct type_state *state, struct data_loc_info *dloc, + u64 addr, struct die_var_type *var_types) +{ + Dwarf_Die mem_die; + struct die_var_type *var; + int fbreg = dloc->fbreg; + int fb_offset = 0; + + if (dloc->fb_cfa) { + if (die_get_cfa(dloc->di->dbg, addr, &fbreg, &fb_offset) < 0) + fbreg = -1; + } + + for (var = var_types; var != NULL; var = var->next) { + if (var->addr != addr) + continue; + /* Get the type DIE using the offset */ + if (!dwarf_offdie(dloc->di->dbg, var->die_off, &mem_die)) + continue; + + if (var->reg == DWARF_REG_FB) { + findnew_stack_state(state, var->offset, &mem_die); + } else if (var->reg == fbreg) { + findnew_stack_state(state, var->offset - fb_offset, &mem_die); + } else if (has_reg_type(state, var->reg)) { + struct type_state_reg *reg; + + reg = &state->regs[var->reg]; + reg->type = mem_die; + reg->ok = true; + } + } +} + /* The result will be saved in @type_die */ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) { diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index ad6493ea2c8e..7fbb9eb2e96f 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -8,9 +8,12 @@ #include struct annotated_op_loc; +struct arch; struct debuginfo; +struct die_var_type; struct evsel; struct map_symbol; +struct type_state; /** * struct annotated_member - Type of member field @@ -146,6 +149,16 @@ int annotated_data_type__update_samples(struct annotated_data_type *adt, /* Release all data type information in the tree */ void annotated_data_type__tree_delete(struct rb_root *root); +/* Initialize type state table */ +void init_type_state(struct type_state *state, struct arch *arch); + +/* Destroy type state table */ +void exit_type_state(struct type_state *state); + +/* Update type state table using variables */ +void update_var_state(struct type_state *state, struct data_loc_info *dloc, + u64 addr, struct die_var_type *var_types); + #else /* HAVE_DWARF_SUPPORT */ static inline struct annotated_data_type * @@ -168,6 +181,22 @@ static inline void annotated_data_type__tree_delete(struct rb_root *root __maybe { } +static inline void init_type_state(struct type_state *state __maybe_unused, + struct arch *arch __maybe_unused) +{ +} + +static inline void exit_type_state(struct type_state *state __maybe_unused) +{ +} + +static inline void update_var_state(struct type_state *state __maybe_unused, + struct data_loc_info *dloc __maybe_unused, + u64 addr __maybe_unused, + struct die_var_type *var_types __maybe_unused) +{ +} + #endif /* HAVE_DWARF_SUPPORT */ #endif /* _PERF_ANNOTATE_DATA_H */ diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 39851ff1d5c4..f88a8fb4a350 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -9,6 +9,7 @@ #include #include "debug.h" #include "dwarf-aux.h" +#include "dwarf-regs.h" #include "strbuf.h" #include "string2.h" @@ -1147,6 +1148,8 @@ static int reg_from_dwarf_op(Dwarf_Op *op) case DW_OP_regx: case DW_OP_bregx: return op->number; + case DW_OP_fbreg: + return DWARF_REG_FB; default: break; } @@ -1160,6 +1163,7 @@ static int offset_from_dwarf_op(Dwarf_Op *op) case DW_OP_regx: return 0; case DW_OP_breg0 ... DW_OP_breg31: + case DW_OP_fbreg: return op->number; case DW_OP_bregx: return op->number2; From patchwork Fri Nov 10 00:00:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451912 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6372D3986C; Fri, 10 Nov 2023 00:01:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Z1bOBmAR" Received: from mail-pg1-x52e.google.com (mail-pg1-x52e.google.com [IPv6:2607:f8b0:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1084A49CA; Thu, 9 Nov 2023 16:01:24 -0800 (PST) Received: by mail-pg1-x52e.google.com with SMTP id 41be03b00d2f7-5bdb0be3591so1199633a12.2; Thu, 09 Nov 2023 16:01:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574484; x=1700179284; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=h8r6yMR8qZ6aWaX50TTJmshQLLIUq/rTAmPUtwjxMSo=; b=Z1bOBmARQKVM7EEm/Xz6OAjvbdLkxnnBKznpEOPjlw5peH1M8oj4PFJJYYoFQjzlGV gMX4Fj5mjprsh6C3qikoWSDqs/ji0TteJlgZv0BLqryGvkLVawfERq0ELzJgFyhI9Fqy cGIsdrlZEVLT7djkZZrpL0jJue/fwa2FaEe3gWbyq0wcCxEiuXNSt7RPaFZXuWXxwu1k 87O1CPVwTfX7eZuCokE/jmcNRGCTJz0n5OS0aMkoOxoUV4EG+JWYeHX2qsEx/O07T0Is R+gp2s0mGSh0EYgEFWANb16vhqQfgrUABxE4cAVBXHUNn/QhzOawdUySH3dwOsrKO5uY NEpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574484; x=1700179284; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=h8r6yMR8qZ6aWaX50TTJmshQLLIUq/rTAmPUtwjxMSo=; b=EaASSuITOQ+o8YdrOPwbMzcHH55sc5zWmzCrcXuwau1R6Hm8LXb1I2EEzDIsN56paL 2tUhhyVL8v2PCPM5CQ0HX3WCMwlnHy1qhDq/XlpXZ0ariUUOqwlYDzqGDhCiTkXefRnv YlR1QuUMugeFGzKYs04bL/3ts9CzNoBD0u9cl2bjSYgSCY2oUUcS7INiILZ1vS0NfrAG 2It8LE/u9VcN7SW8H5rHGdNqUCkQ3SyIpnXW3M08DduopICBprSDLN1Hv1efTTrLDU8Q mVpnXmDuFicT0lG+pgqBuode2ylb9KOh5SEfWj9cYo5lHbxQZioG352Ej7bwSNlKHG3G aLwA== X-Gm-Message-State: AOJu0Yyt7iioVR2BG9tHaXDz2UyhKdYrZ8dQeeqKwP8FrFedC6DomMMQ oSjVDNrISKHQyQoezwdvV7U= X-Google-Smtp-Source: AGHT+IGvtc2xCQtxIACTHeP0XgfIlTVV5MSwhPBzqTLlDxaRBOkkR1JGlGpqRUfhBeBKLDlItFWJkw== X-Received: by 2002:a17:90b:1b0e:b0:281:e1:af1d with SMTP id nu14-20020a17090b1b0e00b0028100e1af1dmr3055942pjb.18.1699574484182; Thu, 09 Nov 2023 16:01:24 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:23 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 44/52] perf annotate-data: Add update_insn_state() Date: Thu, 9 Nov 2023 16:00:03 -0800 Message-ID: <20231110000012.3538610-45-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The update_insn_state() function is to update the type state table after processing each instruction. For now, it handles MOV (on x86) insn to transfer type info from the source location to the target. The location can be a register or a stack slot. Check carefully when memory reference happens and fetch the type correctly. It basically ignores write to a memory since it doesn't change the type info. One exception is writes to (new) stack slots for register spilling. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 128 +++++++++++++++++++++++++++++++- tools/perf/util/annotate-data.h | 13 ++++ tools/perf/util/annotate.c | 1 + 3 files changed, 140 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 438d6234020b..09ccac1d0769 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -26,7 +26,6 @@ struct type_state_reg { Dwarf_Die type; bool ok; - bool scratch; }; /* Type information in a stack location, dynamically allocated */ @@ -382,7 +381,7 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc, findnew_stack_state(state, var->offset, &mem_die); } else if (var->reg == fbreg) { findnew_stack_state(state, var->offset - fb_offset, &mem_die); - } else if (has_reg_type(state, var->reg)) { + } else if (has_reg_type(state, var->reg) && var->offset == 0) { struct type_state_reg *reg; reg = &state->regs[var->reg]; @@ -392,6 +391,131 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc, } } +/** + * update_insn_state - Update type state for an instruction + * @state: type state table + * @dloc: data location info + * @dl: disasm line for the instruction + * + * This function updates the @state table for the target operand of the + * instruction at @dl if it transfers the type like MOV on x86. Since it + * tracks the type, it won't care about the values like in arithmetic + * instructions like ADD/SUB/MUL/DIV and INC/DEC. + * + * Note that ops->reg2 is only available when both mem_ref and multi_regs + * are true. + */ +void update_insn_state(struct type_state *state, struct data_loc_info *dloc, + struct disasm_line *dl) +{ + struct annotated_insn_loc loc; + struct annotated_op_loc *src = &loc.ops[INSN_OP_SOURCE]; + struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET]; + Dwarf_Die type_die; + int fbreg = dloc->fbreg; + int fboff = 0; + + /* FIXME: remove x86 specific code and handle more instructions like LEA */ + if (!strstr(dl->ins.name, "mov")) + return; + + if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0) + return; + + if (dloc->fb_cfa) { + u64 ip = dloc->ms->sym->start + dl->al.offset; + u64 pc = map__rip_2objdump(dloc->ms->map, ip); + + if (die_get_cfa(dloc->di->dbg, pc, &fbreg, &fboff) < 0) + fbreg = -1; + } + + /* Case 1. register to register transfers */ + if (!src->mem_ref && !dst->mem_ref) { + if (!has_reg_type(state, dst->reg1)) + return; + + if (has_reg_type(state, src->reg1)) + state->regs[dst->reg1] = state->regs[src->reg1]; + else + state->regs[dst->reg1].ok = false; + } + /* Case 2. memory to register transers */ + if (src->mem_ref && !dst->mem_ref) { + int sreg = src->reg1; + + if (!has_reg_type(state, dst->reg1)) + return; + +retry: + /* Check stack variables with offset */ + if (sreg == fbreg) { + struct type_state_stack *stack; + int offset = src->offset - fboff; + + stack = find_stack_state(state, offset); + if (stack && die_get_member_type(&stack->type, + offset - stack->offset, + &type_die)) { + state->regs[dst->reg1].type = type_die; + state->regs[dst->reg1].ok = true; + } else + state->regs[dst->reg1].ok = false; + } + /* And then dereference the pointer if it has one */ + else if (has_reg_type(state, sreg) && state->regs[sreg].ok && + die_deref_ptr_type(&state->regs[sreg].type, + src->offset, &type_die)) { + state->regs[dst->reg1].type = type_die; + state->regs[dst->reg1].ok = true; + } + /* Or try another register if any */ + else if (src->multi_regs && sreg == src->reg1 && + src->reg1 != src->reg2) { + sreg = src->reg2; + goto retry; + } + /* It failed to get a type info, mark it as invalid */ + else { + state->regs[dst->reg1].ok = false; + } + } + /* Case 3. register to memory transfers */ + if (!src->mem_ref && dst->mem_ref) { + if (!has_reg_type(state, src->reg1) || + !state->regs[src->reg1].ok) + return; + + /* Check stack variables with offset */ + if (dst->reg1 == fbreg) { + struct type_state_stack *stack; + int offset = dst->offset - fboff; + + stack = find_stack_state(state, offset); + if (stack) { + /* + * The source register is likely to hold a type + * of member if it's a compound type. Do not + * update the stack variable type since we can + * get the member type later by using the + * die_get_member_type(). + */ + if (!stack->compound) + set_stack_state(stack, offset, + &state->regs[src->reg1].type); + } else { + findnew_stack_state(state, offset, + &state->regs[src->reg1].type); + } + } + /* + * Ignore other transfers since it'd set a value in a struct + * and won't change the type. + */ + } + /* Case 4. memory to memory transfers (not handled for now) */ +} + /* The result will be saved in @type_die */ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) { diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 7fbb9eb2e96f..ff9acf6ea808 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -11,6 +11,7 @@ struct annotated_op_loc; struct arch; struct debuginfo; struct die_var_type; +struct disasm_line; struct evsel; struct map_symbol; struct type_state; @@ -78,6 +79,7 @@ extern struct annotated_data_type stackop_type; /** * struct data_loc_info - Data location information + * @arch: architecture info * @ms: Map and Symbol info * @ip: Instruction address * @var_addr: Data address (for global variables) @@ -90,6 +92,7 @@ extern struct annotated_data_type stackop_type; */ struct data_loc_info { /* These are input field, should be filled by caller */ + struct arch *arch; struct map_symbol *ms; u64 ip; u64 var_addr; @@ -159,6 +162,10 @@ void exit_type_state(struct type_state *state); void update_var_state(struct type_state *state, struct data_loc_info *dloc, u64 addr, struct die_var_type *var_types); +/* Update type state table for an instruction */ +void update_insn_state(struct type_state *state, struct data_loc_info *dloc, + struct disasm_line *dl); + #else /* HAVE_DWARF_SUPPORT */ static inline struct annotated_data_type * @@ -197,6 +204,12 @@ static inline void update_var_state(struct type_state *state __maybe_unused, { } +static inline void update_insn_state(struct type_state *state __maybe_unused, + struct data_loc_info *dloc __maybe_unused, + struct disasm_line *dl __maybe_unused) +{ +} + #endif /* HAVE_DWARF_SUPPORT */ #endif /* _PERF_ANNOTATE_DATA_H */ diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index d54a9ec16af4..ffbdba50b50a 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3843,6 +3843,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) for_each_insn_op_loc(&loc, i, op_loc) { struct data_loc_info dloc = { + .arch = arch, .ms = ms, /* Recalculate IP for LOCK prefix or insn fusion */ .ip = ms->sym->start + dl->al.offset, From patchwork Fri Nov 10 00:00:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451913 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5CC9E2E40F; Fri, 10 Nov 2023 00:01:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HTA3VSxy" Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7AFF159D2; Thu, 9 Nov 2023 16:01:26 -0800 (PST) Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-5bdb0be3591so1199650a12.2; Thu, 09 Nov 2023 16:01:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574486; x=1700179286; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=Pf63LKSCgXyhHnD+XwDAgtgdupMVZihRN7VkTjYL3UY=; b=HTA3VSxyLnuHEB9eolK8U+kksewBMlnYL0GHB7nVpnfAlSihELpGwjm7zD1KqBIfSV t4/i8G76KZjHjRkdTM7RyUFoSnsBeWplBYwcGNVAKltmppwJeH7zZeqPgnrGIfsnYVKM 4lsOnxs8vOjgiQF+BqtfCdbCzFLURcs3EzipPpQ8ejr4FtYDcM8i8KdFJjpC0hDSvBuD xwGDOInqYBkr63hZtiJQlCYynr5inoTyHI8LuRSy+XhSh9DIbn5xCmUt3xk/LrCOLBKe lgfUNTwVAe0gCMBadQu21mfxPtKDEHTCdObFtMjHzpvSOgGQM1Hb+b161OuS1yjfBkZO oaEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574486; x=1700179286; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Pf63LKSCgXyhHnD+XwDAgtgdupMVZihRN7VkTjYL3UY=; b=Icgkp7Poin+lZCLXQ1hRIc+VUskzVi9YuwuX0hDEND9EX0LpTvhIgSGS2PCAr3cb+L /2H8yJwKDXkDndwmmXd9Pc3R3Qt8feNEJuHa8py9Qmut0VyCjqoxj4zbMv4pqGzBvhEj BlIuYkGfPVbWj60psyt395o2kcdgxEm7BNl332ZW+dHdbjLnqGMrDc4oW+8Q7Ct3vkRq UBMskEB/LQkonEVRrXv2BsS6CHw8dBn03/tiFcAM7+8bV7l7z1CRSHKn5apNdtpVV48b DMVBj8FbTH0hGExnwBTcapZUv3Xj1d+CPE6T9IFdhSg0YqEVXZYHQMHThD1pXBWNw9Fl 8/sA== X-Gm-Message-State: AOJu0YzhpM4iI1Ga5T4hfOENK5xHlpzaOuPqQd0E0ZYysE4WcV5XtBez P3zxliey8QDStFENVjXMeg0= X-Google-Smtp-Source: AGHT+IGsgRx+n4PAToauWhpKAfcWdhRBJcOZU8f06h8naNWW7DoEX1OjwVUS15uv0muMVvYbWPxouw== X-Received: by 2002:a17:90b:4d8f:b0:27f:fce3:2266 with SMTP id oj15-20020a17090b4d8f00b0027ffce32266mr3125637pjb.24.1699574485851; Thu, 09 Nov 2023 16:01:25 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:25 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 45/52] perf annotate-data: Handle global variable access Date: Thu, 9 Nov 2023 16:00:04 -0800 Message-ID: <20231110000012.3538610-46-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When updating the instruction states, it also needs to handle global variable accesses. Same as it does for PC-relative addressing, it can look up the type by address (if it's defined in the same file), or by name after finding the symbol by address (for declarations). Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 45 ++++++++++++++++++++++++++++++--- tools/perf/util/annotate-data.h | 10 ++++++-- tools/perf/util/annotate.c | 45 ++++++++++++++++++++------------- tools/perf/util/annotate.h | 5 ++++ 4 files changed, 83 insertions(+), 22 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 09ccac1d0769..bbd271cd3419 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -395,6 +395,7 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc, * update_insn_state - Update type state for an instruction * @state: type state table * @dloc: data location info + * @cu_die: compile unit debug entry * @dl: disasm line for the instruction * * This function updates the @state table for the target operand of the @@ -406,7 +407,7 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc, * are true. */ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, - struct disasm_line *dl) + void *cu_die, struct disasm_line *dl) { struct annotated_insn_loc loc; struct annotated_op_loc *src = &loc.ops[INSN_OP_SOURCE]; @@ -448,8 +449,46 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, return; retry: - /* Check stack variables with offset */ - if (sreg == fbreg) { + /* Check if it's a global variable */ + if (sreg == DWARF_REG_PC) { + Dwarf_Die var_die; + struct map_symbol *ms = dloc->ms; + int offset = src->offset; + u64 ip = ms->sym->start + dl->al.offset; + u64 pc, addr; + const char *var_name = NULL; + + addr = annotate_calc_pcrel(ms, ip, offset, dl); + pc = map__rip_2objdump(ms->map, ip); + + if (die_find_variable_by_addr(cu_die, pc, addr, + &var_die, &offset) && + check_variable(&var_die, &type_die, offset, + /*is_pointer=*/false) == 0 && + die_get_member_type(&type_die, offset, &type_die)) { + state->regs[dst->reg1].type = type_die; + state->regs[dst->reg1].ok = true; + return; + } + + /* Try to get the name of global variable */ + offset = src->offset; + get_global_var_info(dloc->thread, ms, ip, dl, + dloc->cpumode, &addr, + &var_name, &offset); + + if (var_name && die_find_variable_at(cu_die, var_name, + pc, &var_die) && + check_variable(&var_die, &type_die, offset, + /*is_pointer=*/false) == 0 && + die_get_member_type(&type_die, offset, &type_die)) { + state->regs[dst->reg1].type = type_die; + state->regs[dst->reg1].ok = true; + } else + state->regs[dst->reg1].ok = false; + } + /* And check stack variables with offset */ + else if (sreg == fbreg) { struct type_state_stack *stack; int offset = src->offset - fboff; diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index ff9acf6ea808..0bfef29fa52c 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -14,6 +14,7 @@ struct die_var_type; struct disasm_line; struct evsel; struct map_symbol; +struct thread; struct type_state; /** @@ -79,11 +80,13 @@ extern struct annotated_data_type stackop_type; /** * struct data_loc_info - Data location information - * @arch: architecture info + * @arch: CPU architecture info + * @thread: Thread info * @ms: Map and Symbol info * @ip: Instruction address * @var_addr: Data address (for global variables) * @var_name: Variable name (for global variables) + * @cpumode: CPU execution mode * @op: Instruction operand location (regs and offset) * @di: Debug info * @fbreg: Frame base register @@ -94,8 +97,10 @@ struct data_loc_info { /* These are input field, should be filled by caller */ struct arch *arch; struct map_symbol *ms; + struct thread *thread; u64 ip; u64 var_addr; + u8 cpumode; const char *var_name; struct annotated_op_loc *op; @@ -164,7 +169,7 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc, /* Update type state table for an instruction */ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, - struct disasm_line *dl); + void *cu_die, struct disasm_line *dl); #else /* HAVE_DWARF_SUPPORT */ @@ -206,6 +211,7 @@ static inline void update_var_state(struct type_state *state __maybe_unused, static inline void update_insn_state(struct type_state *state __maybe_unused, struct data_loc_info *dloc __maybe_unused, + void *cu_die __maybe_unused, struct disasm_line *dl __maybe_unused) { } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index ffbdba50b50a..33fd032bf463 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3775,6 +3775,28 @@ u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset, return map__rip_2objdump(ms->map, addr); } +void get_global_var_info(struct thread *thread, struct map_symbol *ms, u64 ip, + struct disasm_line *dl, u8 cpumode, u64 *var_addr, + const char **var_name, int *poffset) +{ + struct addr_location al; + struct symbol *var; + u64 map_addr; + + *var_addr = annotate_calc_pcrel(ms, ip, *poffset, dl); + /* Kernel symbols might be relocated */ + map_addr = *var_addr + map__reloc(ms->map); + + addr_location__init(&al); + var = thread__find_symbol_fb(thread, cpumode, map_addr, &al); + if (var) { + *var_name = var->name; + /* Calculate type offset from the start of variable */ + *poffset = map_addr - map__unmap_ip(al.map, var->start); + } + addr_location__exit(&al); +} + /** * hist_entry__get_data_type - find data type for given hist entry * @he: hist entry @@ -3844,6 +3866,8 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) for_each_insn_op_loc(&loc, i, op_loc) { struct data_loc_info dloc = { .arch = arch, + .thread = he->thread, + .cpumode = he->cpumode, .ms = ms, /* Recalculate IP for LOCK prefix or insn fusion */ .ip = ms->sym->start + dl->al.offset, @@ -3858,23 +3882,10 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) /* PC-relative addressing */ if (op_loc->reg1 == DWARF_REG_PC) { - struct addr_location al; - struct symbol *var; - u64 map_addr; - - dloc.var_addr = annotate_calc_pcrel(ms, ip, op_loc->offset, dl); - /* Kernel symbols might be relocated */ - map_addr = dloc.var_addr + map__reloc(ms->map); - - addr_location__init(&al); - var = thread__find_symbol_fb(he->thread, he->cpumode, - map_addr, &al); - if (var) { - dloc.var_name = var->name; - /* Calculate type offset from the start of variable */ - dloc.type_offset = map_addr - map__unmap_ip(al.map, var->start); - } - addr_location__exit(&al); + dloc.type_offset = op_loc->offset; + get_global_var_info(he->thread, ms, ip, dl, he->cpumode, + &dloc.var_addr, &dloc.var_name, + &dloc.type_offset); } mem_type = find_data_type(&dloc); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index e1fa86341281..13c9b6a30b15 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -23,6 +23,7 @@ struct option; struct perf_sample; struct evsel; struct symbol; +struct thread; struct annotated_data_type; struct ins { @@ -501,6 +502,10 @@ extern struct list_head ann_insn_stat; u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset, struct disasm_line *dl); +void get_global_var_info(struct thread *thread, struct map_symbol *ms, u64 ip, + struct disasm_line *dl, u8 cpumode, u64 *var_addr, + const char **var_name, int *poffset); + /** * struct annotated_basic_block - Basic block of instructions * @list: List node From patchwork Fri Nov 10 00:00:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451914 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5476D3986C; Fri, 10 Nov 2023 00:01:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GWgsEV/0" Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0E8949D0; Thu, 9 Nov 2023 16:01:27 -0800 (PST) Received: by mail-pg1-x52d.google.com with SMTP id 41be03b00d2f7-5b980391d7cso1159996a12.0; Thu, 09 Nov 2023 16:01:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574487; x=1700179287; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=UMm2Aciykg8ub3kZoou0mh34QtErvedZkYd88iOeNUI=; b=GWgsEV/027OQHPtC1vnznP7fK32F+EGGTsRj3b7eQ25n5xf0zhbd2FCaLmh59h4wZj iY+cAR1eUhO2IDDfmsbI+hm9pWQMz+X6084/mw6xxXE07/6miPiErLijn2AMMM9U1O35 I2LMH+++b9k6oZPNh33Wgubf77zYZQrtLilcW0J1v4OSvaPtoOmKl9C9ebXbjU14yWVh ArfJtJRmjEUIY4T3x9MOu0fsoc/46Ju+mUUC8FJ5xCSndq1hwXKuop8NoZtAK2vDRCxv JbYaXymqURuTHDuNGF8vUq/qOEnulN7bOnv4eaj2cuu7CDgYvIZOmJHOgjpeWWBpFImj SpuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574487; x=1700179287; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=UMm2Aciykg8ub3kZoou0mh34QtErvedZkYd88iOeNUI=; b=TzdRZi2jXEgnU9AqmQ+hG36vBoN38jiMuGLEY4qGuIQOnG5I3qr5zZDtI6bGYDrk52 R7wgij0HnQLxsSYoUs8wnGhro7fMb+eQEfZMRViv6TT5eOI6/HKfIBkxI3F9XfJXTG5W tx4wlHCnTdMQ35WgFzamgEbY9UxwWbv4tpRzdmVXQxj6ADNHV3KzIhIF1lxM+hQdPDrB anjeZPu8ClEB/MgI8FZxs3DF6dRvpn/kXIO/s7jacEDckCR+8ClimK8mqDzUf+AKFUEH qJzG5/Koh5eML86kxkaKcbuRIadHik13Mx0gE/sWnC8GjLY3ZYYJaZddAee7QBZEdaq6 WltA== X-Gm-Message-State: AOJu0YwPtEqais6KbDNcIrBdPlQkl1qCnbkfe13nTTamkG6Lztna0LJe rfshPr12LKAbcNf5LQdYAqE= X-Google-Smtp-Source: AGHT+IEqIX8Ilygba3G5AqaL4yv+sKFHQLE4mgXEmlL1oemnFPD9DOndYWyANbbTga92wtGIt4Nh9w== X-Received: by 2002:a17:90a:1a0c:b0:280:290f:4d38 with SMTP id 12-20020a17090a1a0c00b00280290f4d38mr2923365pjk.36.1699574487262; Thu, 09 Nov 2023 16:01:27 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:26 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 46/52] perf annotate-data: Handle call instructions Date: Thu, 9 Nov 2023 16:00:05 -0800 Message-ID: <20231110000012.3538610-47-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When updating instruction states, the call instruction should play a role since it can change the register states. For simplicity, mark some registers as scratch registers (should be arch-dependent), and invalidate them all after a function call. If the function returns something, the designated register (ret_reg) will have the type info. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 45 +++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index bbd271cd3419..54791dfc6244 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -22,10 +22,14 @@ #include "symbol.h" #include "symbol_conf.h" -/* Type information in a register, valid when ok is true */ +/* + * Type information in a register, valid when @ok is true. + * The @scratch registers are invalidated after a function call. + */ struct type_state_reg { Dwarf_Die type; bool ok; + bool scratch; }; /* Type information in a stack location, dynamically allocated */ @@ -49,6 +53,7 @@ struct type_state_stack { struct type_state { struct type_state_reg regs[TYPE_STATE_MAX_REGS]; struct list_head stack_vars; + int ret_reg; }; static bool has_reg_type(struct type_state *state, int reg) @@ -56,10 +61,23 @@ static bool has_reg_type(struct type_state *state, int reg) return (unsigned)reg < ARRAY_SIZE(state->regs); } -void init_type_state(struct type_state *state, struct arch *arch __maybe_unused) +void init_type_state(struct type_state *state, struct arch *arch) { memset(state, 0, sizeof(*state)); INIT_LIST_HEAD(&state->stack_vars); + + if (arch__is(arch, "x86")) { + state->regs[0].scratch = true; + state->regs[1].scratch = true; + state->regs[2].scratch = true; + state->regs[4].scratch = true; + state->regs[5].scratch = true; + state->regs[8].scratch = true; + state->regs[9].scratch = true; + state->regs[10].scratch = true; + state->regs[11].scratch = true; + state->ret_reg = 0; + } } void exit_type_state(struct type_state *state) @@ -416,6 +434,29 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, int fbreg = dloc->fbreg; int fboff = 0; + if (ins__is_call(&dl->ins)) { + Dwarf_Die func_die; + + /* __fentry__ will preserve all registers */ + if (dl->ops.target.sym && + !strcmp(dl->ops.target.sym->name, "__fentry__")) + return; + + /* Otherwise invalidate scratch registers after call */ + for (unsigned i = 0; i < ARRAY_SIZE(state->regs); i++) { + if (state->regs[i].scratch) + state->regs[i].ok = false; + } + + /* Update register with the return type (if any) */ + if (die_find_realfunc(cu_die, dl->ops.target.addr, &func_die) && + die_get_real_type(&func_die, &type_die)) { + state->regs[state->ret_reg].type = type_die; + state->regs[state->ret_reg].ok = true; + } + return; + } + /* FIXME: remove x86 specific code and handle more instructions like LEA */ if (!strstr(dl->ins.name, "mov")) return; From patchwork Fri Nov 10 00:00:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451915 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 52F9239867; Fri, 10 Nov 2023 00:01:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Djc2Yho+" Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7B05E49D7; Thu, 9 Nov 2023 16:01:29 -0800 (PST) Received: by mail-pj1-x102c.google.com with SMTP id 98e67ed59e1d1-2802d218242so1366347a91.1; Thu, 09 Nov 2023 16:01:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574489; x=1700179289; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=wLivHB+5XUGw6AKIAysW4dP2ru9/y+S3j/0jOvIeF8g=; b=Djc2Yho+skNKb7DRd2yQzJbbjaRFDJX1Y+jshUbx7oQFu8dq5z4NfZ6PsxhdndbiQy nRM+2ERZUFQK0xpOnqjMLN1KoVvqxe+mT2Us7U7lK1+VsA252+Dg7p0qNA4FNj41RwDp 8O86yY+u9H6f1YpbHRvmg6TNzEfhzC3jkcKdfE7S4c27jehkZge71jAAQh3L0c9dphnN bG6qQLf6Ztfr4CdgyMpk5VD8zviQNnN8fwzSbFB4spjl3QTVMnKr/ddb+iVpy8ovUze/ 8GpUo6+EDO5l8w2F1CNyBzPL31YYw0Ob/bbVDyWJy/jkbD6akI5lQBIo3OvQ9Sm2gAIW eWHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574489; x=1700179289; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=wLivHB+5XUGw6AKIAysW4dP2ru9/y+S3j/0jOvIeF8g=; b=X6Gb4WUPwI/4QzhoLEkSvKcHmf30fbD5goMQjEcUA3yP37wsirPDepfiPDsVdkXb3M Tou0hYOUgGX5KoyYOy1kYqV2gTlBqeyF7QBPYejgL1OtMKBjNBkJSFuPPVUoLZz+WOML OfLux9f1tFeBs7XWFchqRSbL6dz5YeaPFOvDauGL+AalF5++V+mGhvTxNritzyUM1+5w QR1J0qRFry9mCTtez4YQVsF+I8TR6F/y3DpkOLv85+0RIRA8KJYdzT60G/Z59f0Y42sG SBcN+wFho6QxrbnSHwzwtj5mqb4NIbZoYPW/78OMoenTU6JDZFyPcpGiEEvbvmoFoKkV 8ZUg== X-Gm-Message-State: AOJu0YxC1bpQ78jkA4UCBWvdmxF4hyiyHrevmEzv84+53+9vyq6hJhjY Zwc/HMfPdrmu7K9D5IgTGzk= X-Google-Smtp-Source: AGHT+IGI0onRDTRqBWLn2qrikHQpQrZY7STqD8HXdY0ipQQSrtg4YCTaSEqiHGUeie+tWWzWOK/dUw== X-Received: by 2002:a17:90b:38c4:b0:27c:fc2a:a178 with SMTP id nn4-20020a17090b38c400b0027cfc2aa178mr3512366pjb.9.1699574488843; Thu, 09 Nov 2023 16:01:28 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:28 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 47/52] perf annotate-data: Implement instruction tracking Date: Thu, 9 Nov 2023 16:00:06 -0800 Message-ID: <20231110000012.3538610-48-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 If it failed to find a variable for the location directly, it might be due to a missing variable in the source code. For example, accessing pointer variables in a chain can result in the case like below: struct foo *foo = ...; int i = foo->bar->baz; The DWARF debug information is created for each variable so it'd have one for 'foo'. But there's no variable for 'foo->bar' and then it cannot know the type of 'bar' and 'baz'. The above source code can be compiled to the follow x86 instructions: mov 0x8(%rax), %rcx mov 0x4(%rcx), %rdx <=== PMU sample mov %rdx, -4(%rbp) Let's say 'foo' is located in the %rax and it has a pointer to struct foo. But perf sample is captured in the second instruction and there is no variable or type info for the %rcx. It'd be great if compiler could generate debug info for %rcx, but we should handle it on our side. So this patch implements the logic to iterate instructions and update the type table for each location. As it already collected a list of scopes including the target instruction, we can use it to construct the type table smartly. +---------------- scope[0] subprogram | | +-------------- scope[1] lexical_block | | | | +------------ scope[2] inlined_subroutine | | | | | | +---------- scope[3] inlined_subroutine | | | | | | | | +-------- scope[4] lexical_block | | | | | | | | | | *** target instruction ... Image the target instruction has 5 scopes, each scope will have its own variables and parameters. Then it can start with the innermost scope (4). So it'd search the shortest path from the start of scope[4] to the target address and build a list of basic blocks. Then it iterates the basic blocks with the variables in the scope and update the table. If it finds a type at the target instruction, then returns it. Otherwise, it moves to the upper scope[3]. Now it'd search the shortest path from the start of scope[3] to the start of scope[4]. Then connect it to the existing basic block list. Then it'd iterate the blocks with variables for both scopes. It can repeat this until it finds a type at the target instruction or reaches to the top scope[0]. As the basic blocks contain the shortest path, it won't worry about branches and can update the table simply. With this change, the stat now looks like below: Annotate data type stats: total 294, ok 185 (62.9%), bad 109 (37.1%) ----------------------------------------------------------- 30 : no_sym 32 : no_mem_ops 27 : no_var 13 : no_typeinfo 7 : bad_offset Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 232 ++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 54791dfc6244..56dfbddb53d2 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -596,6 +596,231 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, /* Case 4. memory to memory transfers (not handled for now) */ } +/* Prepend this_list to full_list, removing duplicate disasm line */ +static void prepend_basic_blocks(struct list_head *this_blocks, + struct list_head *full_blocks) +{ + struct annotated_basic_block *first_bb, *last_bb; + + last_bb = list_last_entry(this_blocks, typeof(*last_bb), list); + first_bb = list_first_entry(full_blocks, typeof(*first_bb), list); + + if (list_empty(full_blocks)) + goto out; + + if (last_bb->end != first_bb->begin) { + pr_debug("prepend basic blocks: mismatched disasm line %lx -> %lx\n", + last_bb->end->al.offset, first_bb->begin->al.offset); + goto out; + } + + /* Is the basic block have only one disasm_line? */ + if (last_bb->begin == last_bb->end) { + list_del(&last_bb->list); + free(last_bb); + goto out; + } + + last_bb->end = list_prev_entry(last_bb->end, al.node); + +out: + list_splice(this_blocks, full_blocks); +} + +static void delete_basic_blocks(struct list_head *basic_blocks) +{ + struct annotated_basic_block *bb, *tmp; + + list_for_each_entry_safe(bb, tmp, basic_blocks, list) { + list_del(&bb->list); + free(bb); + } +} + +/* Make sure all variables have a valid start address */ +static void fixup_var_address(struct die_var_type *var_types, u64 addr) +{ + while (var_types) { + /* + * Some variables have no address range meaning it's always + * available in the whole scope. Let's adjust the start + * address to the start of the scope. + */ + if (var_types->addr == 0) + var_types->addr = addr; + + var_types = var_types->next; + } +} + +static void delete_var_types(struct die_var_type *var_types) +{ + while (var_types) { + struct die_var_type *next = var_types->next; + + free(var_types); + var_types = next; + } +} + +/* It's at the target address, check if it has a matching type */ +static bool find_matching_type(struct type_state *state, + struct data_loc_info *dloc, int reg, + Dwarf_Die *type_die) +{ + Dwarf_Word size; + + if (state->regs[reg].ok) { + int tag = dwarf_tag(&state->regs[reg].type); + + /* + * Normal registers should hold a pointer (or array) to + * dereference a memory location. + */ + if (tag != DW_TAG_pointer_type && tag != DW_TAG_array_type) + return false; + + if (die_get_real_type(&state->regs[reg].type, type_die) == NULL) + return false; + + dloc->type_offset = dloc->op->offset; + + /* Get the size of the actual type */ + if (dwarf_aggregate_size(type_die, &size) < 0 || + (unsigned)dloc->type_offset >= size) + return false; + + return true; + } + + if (reg == dloc->fbreg) { + struct type_state_stack *stack; + + stack = find_stack_state(state, dloc->type_offset); + if (stack == NULL) + return false; + + *type_die = stack->type; + /* Update the type offset from the start of slot */ + dloc->type_offset -= stack->offset; + return true; + } + + if (dloc->fb_cfa) { + struct type_state_stack *stack; + u64 pc = map__rip_2objdump(dloc->ms->map, dloc->ip); + int fbreg, fboff; + + if (die_get_cfa(dloc->di->dbg, pc, &fbreg, &fboff) < 0) + fbreg = -1; + + if (reg != fbreg) + return false; + + stack = find_stack_state(state, dloc->type_offset - fboff); + if (stack == NULL) + return false; + + *type_die = stack->type; + /* Update the type offset from the start of slot */ + dloc->type_offset -= fboff + stack->offset; + return true; + } + + return false; +} + +/* Iterate instructions in basic blocks and update type table */ +static bool find_data_type_insn(struct data_loc_info *dloc, int reg, + struct list_head *basic_blocks, + struct die_var_type *var_types, + Dwarf_Die *cu_die, Dwarf_Die *type_die) +{ + struct type_state state; + struct symbol *sym = dloc->ms->sym; + struct annotation *notes = symbol__annotation(sym); + struct annotated_basic_block *bb; + bool found = false; + + init_type_state(&state, dloc->arch); + + list_for_each_entry(bb, basic_blocks, list) { + struct disasm_line *dl = bb->begin; + + list_for_each_entry_from(dl, ¬es->src->source, al.node) { + u64 this_ip = sym->start + dl->al.offset; + u64 addr = map__rip_2objdump(dloc->ms->map, this_ip); + + /* Update variable type at this address */ + update_var_state(&state, dloc, addr, var_types); + + if (this_ip == dloc->ip) { + found = find_matching_type(&state, dloc, reg, + type_die); + goto out; + } + + /* Update type table after processing the instruction */ + update_insn_state(&state, dloc, cu_die, dl); + if (dl == bb->end) + break; + } + } + +out: + exit_type_state(&state); + return found; +} + +/* + * Construct a list of basic blocks for each scope with variables and try to find + * the data type by updating a type state table through instructions. + */ +static int find_data_type_block(struct data_loc_info *dloc, int reg, + Dwarf_Die *cu_die, Dwarf_Die *scopes, + int nr_scopes, Dwarf_Die *type_die) +{ + LIST_HEAD(basic_blocks); + struct die_var_type *var_types = NULL; + u64 src_ip, dst_ip; + int ret = -1; + + dst_ip = dloc->ip; + for (int i = nr_scopes - 1; i >= 0; i--) { + Dwarf_Addr base, start, end; + LIST_HEAD(this_blocks); + + if (dwarf_ranges(&scopes[i], 0, &base, &start, &end) < 0) + break; + + src_ip = map__objdump_2rip(dloc->ms->map, start); + + /* Get basic blocks for this scope */ + if (annotate_get_basic_blocks(dloc->ms->sym, src_ip, dst_ip, + &this_blocks) < 0) + continue; + prepend_basic_blocks(&this_blocks, &basic_blocks); + + /* Get variable info for this scope and add to var_types list */ + die_collect_vars(&scopes[i], &var_types); + fixup_var_address(var_types, start); + + /* Find from start of this scope to the target instruction */ + if (find_data_type_insn(dloc, reg, &basic_blocks, var_types, + cu_die, type_die)) { + ret = 0; + break; + } + + /* Go up to the next scope and find blocks to the start */ + dst_ip = src_ip; + } + + delete_basic_blocks(&basic_blocks); + delete_var_types(var_types); + return ret; +} + /* The result will be saved in @type_die */ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) { @@ -696,6 +921,13 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) goto out; } + if (reg != DWARF_REG_PC) { + ret = find_data_type_block(dloc, reg, &cu_die, scopes, + nr_scopes, type_die); + if (ret == 0) + goto out; + } + if (loc->multi_regs && reg == loc->reg1 && loc->reg1 != loc->reg2) { reg = loc->reg2; goto retry; From patchwork Fri Nov 10 00:00:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451916 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5EFD3219D; Fri, 10 Nov 2023 00:01:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="c+VfexW6" Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1206259EC; Thu, 9 Nov 2023 16:01:30 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id 98e67ed59e1d1-280cc5f3fdcso1333627a91.1; Thu, 09 Nov 2023 16:01:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574490; x=1700179290; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=j0yOHOAq2UksaEKkQj6eSLR4JX7ylWQzwIPxJpm20xg=; b=c+VfexW65ZEebHKtDPlF+UjTtrxO72HsToiCOJQnkqBrC6rup7yZELOQolEigYhhvZ fWlUv0GAY/4tRGfn3VlCcWUQBphIFtfsVjMZI8Al45m7961Cg3hdI9KA4EjKy1yjPSep ovNyOFnPiI3GPUNKnFBKlKzd/dnFD8+jtObOqHmqFT/x5lZkoGWlQkYg37W6P0lwcMx5 b8mFhZgMKUzmEXRDG9aaHel6BSxHJEwSpREeXnKiOrhfG+M2jHbIwd/ek4W/3AkA6cB6 jDySlwP+4etvoHzcq+WOP8gdwlpb8U/kAymGywBmAU1bRD/tTDk4H6iYtN2uBJ+03+bV WJcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574490; x=1700179290; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=j0yOHOAq2UksaEKkQj6eSLR4JX7ylWQzwIPxJpm20xg=; b=bVPZ94Qdl1/si3E5OlboMUy0IZ2IMeNV6JWTIzmHyRhhqSmGTEvoEqAsl952qjF9Jl QuzMHaKVGkyvlGQEcZAqKP5XjBf+SUxf5+NAxjbKr9drywRell8oxWX+RpQvNgR7IRB+ jMuxrZbtxK7vVHIo/vxCfkl51gBhR0TSuqfzgn6DJlCnzrYtXR4cuRXS6jRR/pfc0d51 vu5rkpKs9419iw6wB9TVPVJuSKM8wGbY5KhEo4Mumn4RlfyJxx7ZkJrIGb2kVihKX2j3 QsUWtkE8ZlcEoylT6p+QNG3556LNrAVapK5wK1q+JgoiOLc4+9WAaMdisA3ljdsHnL23 HTZg== X-Gm-Message-State: AOJu0Yxig2Mv3EAZ5VfS2o8MrL/Fzqm1jXqiePvQ/LuG1of9mbZeaBJl 3sZT51/sBcNk8tflgFvHIxA= X-Google-Smtp-Source: AGHT+IF+88KdonlCki49GFMVxctkL0pwwYI/XQUw7DKdjSyociTWztm1J1KuUHnNSzTxmrgeLIXagg== X-Received: by 2002:a17:90b:1bc3:b0:280:1ffe:5930 with SMTP id oa3-20020a17090b1bc300b002801ffe5930mr2998201pjb.14.1699574490226; Thu, 09 Nov 2023 16:01:30 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:29 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 48/52] perf annotate: Parse x86 segment register location Date: Thu, 9 Nov 2023 16:00:07 -0800 Message-ID: <20231110000012.3538610-49-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a segment field in the struct annotated_insn_loc and save it for the segment based addressing like %gs:0x28. For simplicity it now handles %gs register only. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 21 +++++++++++++++++++-- tools/perf/util/annotate.h | 13 +++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 33fd032bf463..a9075af10d24 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3561,6 +3561,12 @@ static int extract_reg_offset(struct arch *arch, const char *str, * %gs:0x18(%rbx). In that case it should skip the part. */ if (*str == arch->objdump.register_char) { + if (arch__is(arch, "x86")) { + /* FIXME: Handle other segment registers */ + if (!strncmp(str, "%gs:", 4)) + op_loc->segment = INSN_SEG_X86_GS; + } + while (*str && !isdigit(*str) && *str != arch->objdump.memory_ref_char) str++; @@ -3657,8 +3663,19 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, op_loc->multi_regs = multi_regs; extract_reg_offset(arch, insn_str, op_loc); } else { - char *s = strdup(insn_str); + char *s; + + if (arch__is(arch, "x86")) { + /* FIXME: Handle other segment registers */ + if (!strncmp(insn_str, "%gs:", 4)) { + op_loc->segment = INSN_SEG_X86_GS; + op_loc->offset = strtol(insn_str + 4, + NULL, 0); + continue; + } + } + s = strdup(insn_str); if (s) { op_loc->reg1 = get_dwarf_regnum(s, 0); free(s); @@ -3874,7 +3891,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) .op = op_loc, }; - if (!op_loc->mem_ref) + if (!op_loc->mem_ref && op_loc->segment == INSN_SEG_NONE) continue; /* Recalculate IP because of LOCK prefix or insn fusion */ diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 13c9b6a30b15..21a0947ed5e9 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -452,6 +452,7 @@ int annotate_check_args(struct annotation_options *args); * @reg1: First register in the operand * @reg2: Second register in the operand * @offset: Memory access offset in the operand + * @segment: Segment selector register * @mem_ref: Whether the operand accesses memory * @multi_regs: Whether the second register is used */ @@ -459,6 +460,7 @@ struct annotated_op_loc { int reg1; int reg2; int offset; + u8 segment; bool mem_ref; bool multi_regs; }; @@ -470,6 +472,17 @@ enum annotated_insn_ops { INSN_OP_MAX, }; +enum annotated_x86_segment { + INSN_SEG_NONE = 0, + + INSN_SEG_X86_CS, + INSN_SEG_X86_DS, + INSN_SEG_X86_ES, + INSN_SEG_X86_FS, + INSN_SEG_X86_GS, + INSN_SEG_X86_SS, +}; + /** * struct annotated_insn_loc - Location info of instruction * @ops: Array of location info for source and target operands From patchwork Fri Nov 10 00:00:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451917 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CACFF11C86; Fri, 10 Nov 2023 00:01:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="k48OsoUf" Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A5F421FFD; Thu, 9 Nov 2023 16:01:32 -0800 (PST) Received: by mail-pj1-x102f.google.com with SMTP id 98e67ed59e1d1-2809b4d648bso1369689a91.2; Thu, 09 Nov 2023 16:01:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574492; x=1700179292; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=PPYCIl0SPFtUtXhBJ2STPHUgQ84W10L+ZFD5fhYt5l4=; b=k48OsoUfHytUkMVPN/zc+YpSz3fz4LzjI0/hcjSRAZdO+g1yF9MljGrgvj51CcUC7c DMtmMkC8FAtwn/e0pwGUOv5fqDZND24rUBLe24OD6CymI424G8rJ1+Z1J2SYaD9JfErR Z4O/wGZCmJO0dLA+iL3Cw4wl//wY9vh/DaM+e8uiZ8HeNn6dUMH+qINH7XOOH5ZCVpJp MMeVk8mCjtBEwufm4wsGD9HFUMwUp0DsqLTVMz6kVmxuo5h/2h2KWlkTJE4XMNPX1L4V AjmXFpgoTL1S7lpLv4HiuTqQPjIcHLeHTKbwzVoaLOVsEhmROggWuZcpq3SQpi1fGESU yKUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574492; x=1700179292; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=PPYCIl0SPFtUtXhBJ2STPHUgQ84W10L+ZFD5fhYt5l4=; b=pufvxUGNlVh9Vy30u7mczicFAQIrxY0bskCzoenYwQIi1MhDoVsZKnDLhI4YN15l/9 JkrP8IdgVtuloPnJQmQ9x5lxVGXiF1is0M/wx/VuFNjdmgU7FhutFSnMQ0UFV+X9hWBj RkZpYS2hzMiAluLwCvIniznEkoZKMVJ9rw4GO4NevzTcP+bt6d+ZYjVe0arHng62SvPg sKnkojOQ48C17ykVYDv2gtsCuY6+zCNvSRvm+wpTUbYQYFHXGWjHeUp1yrEIcMTx3sDP bmN+jgsvxU+xrBYpghurtHcW9i9/lOA9VlgyG+4OppzyTancuNsGxNLNt0EdukGoQXQ0 vl8g== X-Gm-Message-State: AOJu0Yy7O9ANpqz6P92527ec0aRMorje2xKadxSK5fnqmb+FMBXlOSu4 FmYht/w4kXfVDdIGrXaYukI= X-Google-Smtp-Source: AGHT+IGUJznhRPjctQDkM4r0GLaixAGJfmawGPpiW1jghgltzY4EsWoA1Hf6TdtpsHwv8bKSyfi1uw== X-Received: by 2002:a17:90b:1e04:b0:280:62a7:3743 with SMTP id pg4-20020a17090b1e0400b0028062a73743mr3412008pjb.30.1699574491830; Thu, 09 Nov 2023 16:01:31 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:31 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 49/52] perf annotate-data: Handle this-cpu variables in kernel Date: Thu, 9 Nov 2023 16:00:08 -0800 Message-ID: <20231110000012.3538610-50-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 On x86, the kernel gets the current task using the current macro like below: #define current get_current() static __always_inline struct task_struct *get_current(void) { return this_cpu_read_stable(pcpu_hot.current_task); } So it returns the current_task field of struct pcpu_hot which is the first member. On my build, it's located at 0x32940. $ nm vmlinux | grep pcpu_hot 0000000000032940 D pcpu_hot And the current macro generates the instructions like below: mov %gs:0x32940, %rcx So the %gs segment register points to the beginning of the per-cpu region of this cpu and it points the variable with a constant. Let's update the instruction location info to have a segment register and handle %gs in kernel to look up a global variable. The new get_percpu_var_info() helper is to get information about the variable. Pretend it as a global variable by changing the register number to DWARF_REG_PC. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate.c | 31 +++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 4 ++++ 2 files changed, 35 insertions(+) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index a9075af10d24..9b72eae2400c 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -3814,6 +3814,27 @@ void get_global_var_info(struct thread *thread, struct map_symbol *ms, u64 ip, addr_location__exit(&al); } +void get_percpu_var_info(struct thread *thread, struct map_symbol *ms, + u8 cpumode, u64 var_addr, const char **var_name, + int *poffset) +{ + struct addr_location al; + struct symbol *var; + u64 map_addr; + + /* Kernel symbols might be relocated */ + map_addr = var_addr + map__reloc(ms->map); + + addr_location__init(&al); + var = thread__find_symbol_fb(thread, cpumode, map_addr, &al); + if (var) { + *var_name = var->name; + /* Calculate type offset from the start of variable */ + *poffset = map_addr - map__unmap_ip(al.map, var->start); + } + addr_location__exit(&al); +} + /** * hist_entry__get_data_type - find data type for given hist entry * @he: hist entry @@ -3905,6 +3926,16 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) &dloc.type_offset); } + /* This CPU access in kernel - pretend PC-relative addressing */ + if (op_loc->reg1 < 0 && ms->map->dso->kernel && + arch__is(arch, "x86") && op_loc->segment == INSN_SEG_X86_GS) { + dloc.var_addr = op_loc->offset; + get_percpu_var_info(he->thread, ms, he->cpumode, + dloc.var_addr, &dloc.var_name, + &dloc.type_offset); + op_loc->reg1 = DWARF_REG_PC; + } + mem_type = find_data_type(&dloc); if (mem_type) istat->good++; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 21a0947ed5e9..c3cc0cba10b7 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -519,6 +519,10 @@ void get_global_var_info(struct thread *thread, struct map_symbol *ms, u64 ip, struct disasm_line *dl, u8 cpumode, u64 *var_addr, const char **var_name, int *poffset); +void get_percpu_var_info(struct thread *thread, struct map_symbol *ms, + u8 cpumode, u64 var_addr, const char **var_name, + int *poffset); + /** * struct annotated_basic_block - Basic block of instructions * @list: List node From patchwork Fri Nov 10 00:00:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451918 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 629DA374; Fri, 10 Nov 2023 00:01:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Q3u4WB7t" Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6CBD5B8B; Thu, 9 Nov 2023 16:01:33 -0800 (PST) Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-1cc316ccc38so12761285ad.1; Thu, 09 Nov 2023 16:01:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574493; x=1700179293; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=7LQMqcV8+xKPMkuCeGhhLbjMOgNrw0IhfnrFjgWw4W4=; b=Q3u4WB7taRsrngFLMMtKkhcDTCLRRLdMvh2S9Ax4NvfSD4YUGXbX5RWT+tjBGYE72A coGPfKtFWNVEFzOUJ5eEHrezi0lMJdZX4o61BS7a5MCLQu98nYSs7J8IkzMmuAgccUC/ JCmvP8J/AO6ZtexOHGDJmx0SK4yEQaqR1mhq7/TpfoaHQDAHmmd3tOg6Fsx2sjdbzdIs nRXrL5hZcS/FoBgfyxjj0yBHvvIz6IqVc/01QqDTo7M7cum997oCwL9ja81pwHrpJEoY TqPks52j07Wlkzr/3zVgt8aRE/cEu308R7vY3jMRhh5McGkbZPKpVf+k8yKEY3DTw6wo BSCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574493; x=1700179293; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=7LQMqcV8+xKPMkuCeGhhLbjMOgNrw0IhfnrFjgWw4W4=; b=WL8PKJAeRxBoprpJK0XsZWhZUCyOpt2242IAKxhV4V9IiL9qVGbHXaBQnhuemUf2/C tQk81n5lmzjt7vUiXIjP6TJY+3UzmPOQF72N4M1LQXoGNY8oyLThbl4pYSQkci3kQ5gy Chxvf8bqKZE7kB+6L/eXiR0wqh4LyRCkirMHGH35zqIjYiSRqEMv4kRujXwQ1o6cOM0r DvNXeXAZaSx1AqBTId9aF3asi/tcPSCjBIDlZxyghQE7EApLlp0EiU/QzxRBDN6NmHhI AzfypziGuFLgsUNOgevwqvRcB3UjEwzR8uywMqaF+EQjkKxH3UbCVKh2FeR3ze++u7nE 0Fdw== X-Gm-Message-State: AOJu0YwB/KGRl+fYYxB3vxNsuYgx5hvAsARaQauN3ztql83s3EpjyJJI J2DKr6ks28rmlh/f+6qWSiEjp+nj3LQ= X-Google-Smtp-Source: AGHT+IGk43I3VkvyGIAng10T1TVRcP4V9gcBaWqsidFcRNWTeD86MkCSZxWlztrLTz7ISIwqxrCCfw== X-Received: by 2002:a17:90b:4f48:b0:281:3f1e:c26d with SMTP id pj8-20020a17090b4f4800b002813f1ec26dmr3401074pjb.45.1699574493117; Thu, 09 Nov 2023 16:01:33 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:32 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 50/52] perf annotate-data: Track instructions with a this-cpu variable Date: Thu, 9 Nov 2023 16:00:09 -0800 Message-ID: <20231110000012.3538610-51-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Like global variables, this per-cpu variables should be tracked correctly. Factor our get_global_var_type() to handle both global and per-cpu (for this cpu) variables in the same manner. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 84 +++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 56dfbddb53d2..416c0b5649fc 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -409,6 +409,37 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc, } } +static bool get_global_var_type(Dwarf_Die *cu_die, struct map_symbol *ms, u64 ip, + u64 var_addr, const char *var_name, int var_offset, + Dwarf_Die *type_die) +{ + u64 pc; + int offset = var_offset; + bool is_pointer = false; + Dwarf_Die var_die; + + pc = map__rip_2objdump(ms->map, ip); + + /* Try to get the variable by address first */ + if (die_find_variable_by_addr(cu_die, pc, var_addr, &var_die, &offset) && + check_variable(&var_die, type_die, offset, is_pointer) == 0 && + die_get_member_type(type_die, offset, type_die)) + return true; + + if (var_name == NULL) + return false; + + offset = var_offset; + + /* Try to get the name of global variable */ + if (die_find_variable_at(cu_die, var_name, pc, &var_die) && + check_variable(&var_die, type_die, offset, is_pointer) == 0 && + die_get_member_type(type_die, offset, type_die)) + return true; + + return false; +} + /** * update_insn_state - Update type state for an instruction * @state: type state table @@ -472,14 +503,36 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, fbreg = -1; } - /* Case 1. register to register transfers */ + /* Case 1. register to register or segment:offset to register transfers */ if (!src->mem_ref && !dst->mem_ref) { if (!has_reg_type(state, dst->reg1)) return; if (has_reg_type(state, src->reg1)) state->regs[dst->reg1] = state->regs[src->reg1]; - else + else if (dloc->ms->map->dso->kernel && + src->segment == INSN_SEG_X86_GS) { + struct map_symbol *ms = dloc->ms; + int offset = src->offset; + u64 ip = ms->sym->start + dl->al.offset; + const char *var_name = NULL; + u64 var_addr; + + /* + * In kernel, %gs points to a per-cpu region for the + * current CPU. Access with a constant offset should + * be treated as a global variable access. + */ + var_addr = src->offset; + get_percpu_var_info(dloc->thread, ms, dloc->cpumode, + var_addr, &var_name, &offset); + + if (get_global_var_type(cu_die, ms, ip, var_addr, + var_name, offset, &type_die)) { + state->regs[dst->reg1].type = type_die; + state->regs[dst->reg1].ok = true; + } + } else state->regs[dst->reg1].ok = false; } /* Case 2. memory to register transers */ @@ -492,37 +545,20 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, retry: /* Check if it's a global variable */ if (sreg == DWARF_REG_PC) { - Dwarf_Die var_die; struct map_symbol *ms = dloc->ms; int offset = src->offset; u64 ip = ms->sym->start + dl->al.offset; - u64 pc, addr; const char *var_name = NULL; + u64 var_addr; - addr = annotate_calc_pcrel(ms, ip, offset, dl); - pc = map__rip_2objdump(ms->map, ip); - - if (die_find_variable_by_addr(cu_die, pc, addr, - &var_die, &offset) && - check_variable(&var_die, &type_die, offset, - /*is_pointer=*/false) == 0 && - die_get_member_type(&type_die, offset, &type_die)) { - state->regs[dst->reg1].type = type_die; - state->regs[dst->reg1].ok = true; - return; - } + var_addr = annotate_calc_pcrel(ms, ip, offset, dl); - /* Try to get the name of global variable */ - offset = src->offset; get_global_var_info(dloc->thread, ms, ip, dl, - dloc->cpumode, &addr, + dloc->cpumode, &var_addr, &var_name, &offset); - if (var_name && die_find_variable_at(cu_die, var_name, - pc, &var_die) && - check_variable(&var_die, &type_die, offset, - /*is_pointer=*/false) == 0 && - die_get_member_type(&type_die, offset, &type_die)) { + if (get_global_var_type(cu_die, ms, ip, var_addr, + var_name, offset, &type_die)) { state->regs[dst->reg1].type = type_die; state->regs[dst->reg1].ok = true; } else From patchwork Fri Nov 10 00:00:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451919 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96EEB627; Fri, 10 Nov 2023 00:01:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YlL3bMM9" Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C8405B99; Thu, 9 Nov 2023 16:01:35 -0800 (PST) Received: by mail-pj1-x102c.google.com with SMTP id 98e67ed59e1d1-2809a824bbbso1302896a91.3; Thu, 09 Nov 2023 16:01:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574494; x=1700179294; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=GXd2Gsh6T356KjpJSN7Pi3N8Wc0Rm5WPOLB0ueGaGFA=; b=YlL3bMM93qLidLsBGM9xZ7Gl2aG5EZli0f7ZjdONZ3362LkvH+xpXJEcMJPFhVTz50 abkA6UdzEiHJVAac0h1yhQOP7P7w/LDnxA9066+k4McwAqA2+ziyBjzOvygoF9Je5Ht9 A2NvW7IdwHO3UwNM2yiHlhbgO+4oGhSyWQAlQckY+s+qQiGdSQTCvAJHcm4sDnOD01iY Ge7cDY9I1DRAeNHBdFoVoLWo9eJvky5x1fKkl75RsRHwOE2LWVvQYHC3rvqdifiXa27+ gtLsmLOBAqMWqgbb581OVklB5xR21uFXYrqUbfzVvPsOPe4ysjPrO17NansrJu3D6Yj8 hdZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574494; x=1700179294; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=GXd2Gsh6T356KjpJSN7Pi3N8Wc0Rm5WPOLB0ueGaGFA=; b=wxi3+EFBLGUyWgzy9bGvdJNZ0B53Ze1NxqDxea0Vf7NmmnzA5nF0Aik1ayNW76em3T gTjftDBmzvwVXiP9k2adUbuBUyrulhk2wUNuGg4MMkIq80pU8mDe2J5RYZFeQswcSytP pseFwinWt6y2PNTdVfQhgnmwHW518K3/c2+rCxtSdYSXstTFuOJvND0SXb61wHCESdl6 lgGM7u5XwCz+nKuxxkDOrS0oSCpnnIymhlClutLsGpzxdpR2mBuPVzepZ/zm57zd0LQk +azkCcWcgxwu4xsMcv2XdOzpu8LCzZTSdPMZdXBuRuxA0KC2Uc5zHAMUMOKHeMsqWRxc 0ncw== X-Gm-Message-State: AOJu0YwMhMD5kNQuIX4fvFQ70uaHh+OrVyalBzjW1mBIIZOYY3i0uOpi wbLV/UNdKf1w3VR/OyljJ5Y= X-Google-Smtp-Source: AGHT+IHCCKiw5gXzT7bthEv3cSdjsP6iZ/RhhMp1hvxUIIiQ7dl1wHdTO3VhP0wYW0daBJiAzpFENw== X-Received: by 2002:a17:90b:1809:b0:280:8c99:1801 with SMTP id lw9-20020a17090b180900b002808c991801mr3205423pjb.16.1699574494509; Thu, 09 Nov 2023 16:01:34 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:34 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 51/52] perf annotate-data: Add stack canary type Date: Thu, 9 Nov 2023 16:00:10 -0800 Message-ID: <20231110000012.3538610-52-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When the stack protector is enabled, compiler would generate code to check stack overflow with a special value called 'stack carary' at runtime. On x86_64, GCC hard-codes the stack canary as %gs:40. While there's a definition of fixed_percpu_data in asm/processor.h, it seems that the header is not included everywhere and many places it cannot find the type info. As it's in the well-known location (at %gs:40), let's add a pseudo stack canary type to handle it specially. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.h | 1 + tools/perf/util/annotate.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index 0bfef29fa52c..e293980eb11b 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -77,6 +77,7 @@ struct annotated_data_type { extern struct annotated_data_type unknown_type; extern struct annotated_data_type stackop_type; +extern struct annotated_data_type canary_type; /** * struct data_loc_info - Data location information diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 9b72eae2400c..e183c53531fe 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -113,6 +113,13 @@ struct annotated_data_type stackop_type = { }, }; +struct annotated_data_type canary_type = { + .self = { + .type_name = (char *)"(stack canary)", + .children = LIST_HEAD_INIT(canary_type.self.children), + }, +}; + static int arch__grow_instructions(struct arch *arch) { struct ins *new_instructions; @@ -3768,6 +3775,17 @@ static bool is_stack_operation(struct arch *arch, struct disasm_line *dl) return false; } +static bool is_stack_canary(struct arch *arch, struct annotated_op_loc *loc) +{ + /* On x86_64, %gs:40 is used for stack canary */ + if (arch__is(arch, "x86")) { + if (loc->segment == INSN_SEG_X86_GS && loc->offset == 40) + return true; + } + + return false; +} + u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset, struct disasm_line *dl) { @@ -3937,6 +3955,12 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) } mem_type = find_data_type(&dloc); + + if (mem_type == NULL && is_stack_canary(arch, op_loc)) { + mem_type = &canary_type; + dloc.type_offset = 0; + } + if (mem_type) istat->good++; else From patchwork Fri Nov 10 00:00:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13451920 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1237B7FE; Fri, 10 Nov 2023 00:01:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hgtoRHm7" Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2CA649E4; Thu, 9 Nov 2023 16:01:36 -0800 (PST) Received: by mail-pj1-x1036.google.com with SMTP id 98e67ed59e1d1-28098ebd5aeso1308221a91.0; Thu, 09 Nov 2023 16:01:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699574496; x=1700179296; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=DnROzZu8XXAZvFxHI/WlJvEJJ2mL81wo6OnJpfh/LW4=; b=hgtoRHm7guWQMo/K9hHRiuJoWHqVgpd5TBlW7MshZBHuEMzvviIWVUmBYDxN6xQ0IT DbD9JECK1RHlQfTp+wDSjscDGL6rWiV9z//qcwL1yBKV06YFKd9HFzE7XS6K6o++oDq9 AzMxk3OLjc8/+XTp8W0h8adL1RLkBHBJL5sZ8oXjE5eEl1WtsdgXsxAqKW4kLN11Qs2R mr/sjvTsEmt9lAD5PvZYoOfdtFUNm1NnvvB7tO0kHetlwpgdIFWpjL5v90K5TRj9rF1k Ilz/8fOwJ3nYu6xkBb0ky6FoRynoDNd04/hDZcnflouMMRle2505bVfncVJA64j2qS0X QFyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699574496; x=1700179296; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=DnROzZu8XXAZvFxHI/WlJvEJJ2mL81wo6OnJpfh/LW4=; b=BOSbFhhz/PbKD1pmC7ygwAaKohpgSuVGwCsXjm5n7t2uVmlLoL/9OWphhsEw28jehX R4UuQItjZEgFnbjbwAzfjqrxmtB/VfNyBNdWphlB8duWcIPL0aDC147IOB15rrshBW3/ W88RxP9x5tT0GTGNze8cK4nMZthLyemCA7EHug1dfwFzNV7C21rYRbRkzlqpV0neOsoC 6N+966+LwpyEgM3zce5HCnjR4Qmqf95J6L8lv9D4tnt6mzcdl4p3omQMUo0wnb5+ezsH itxEeQl12bjX3sCsdzMFd8WxgX5GjQvNPtw7I2Yn0RGe39dxdIf9NiaBUA+cLS1WKC4h C0GA== X-Gm-Message-State: AOJu0YyBlhVYbpvzj5zWEwlNtVHfXpYeJXQlp2Ne6bRCFQ9njbkPsALr 2a3o+I3FrQqcV0RS8OMOg5Q= X-Google-Smtp-Source: AGHT+IGbmcszCffgVvol1Yj6r8qsQfRHBV8HeaHxIKAgx9VrznJPdZtv8xPzEKqSJ36wtyq09K4Z4w== X-Received: by 2002:a17:90b:38cf:b0:27d:6937:db89 with SMTP id nn15-20020a17090b38cf00b0027d6937db89mr3256557pjb.43.1699574496008; Thu, 09 Nov 2023 16:01:36 -0800 (PST) Received: from bangji.corp.google.com ([2620:15c:2c0:5:d45c:ae16:d959:a5f1]) by smtp.gmail.com with ESMTPSA id k32-20020a17090a4ca300b002635db431a0sm371312pjh.45.2023.11.09.16.01.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Nov 2023 16:01:35 -0800 (PST) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa , Peter Zijlstra Cc: Ian Rogers , Adrian Hunter , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , Andi Kleen , linux-trace-devel@vger.kernel.org, linux-toolchains@vger.kernel.org Subject: [PATCH 52/52] perf annotate-data: Add debug message Date: Thu, 9 Nov 2023 16:00:11 -0800 Message-ID: <20231110000012.3538610-53-namhyung@kernel.org> X-Mailer: git-send-email 2.42.0.869.gea05f2083d-goog In-Reply-To: <20231110000012.3538610-1-namhyung@kernel.org> References: <20231110000012.3538610-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This is just for debugging and not for merge. Signed-off-by: Namhyung Kim --- tools/perf/util/annotate-data.c | 122 +++++++++++++++++++++++++++++--- tools/perf/util/annotate-data.h | 2 +- 2 files changed, 114 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 416c0b5649fc..8e318349f430 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -90,6 +90,21 @@ void exit_type_state(struct type_state *state) } } +static void debug_print_type_name(Dwarf_Die *die) +{ + struct strbuf sb; + char *str; + + if (!verbose) + return; + + strbuf_init(&sb, 32); + die_get_typename_from_type(die, &sb); + str = strbuf_detach(&sb, NULL); + pr_debug("%s (die:%lx)\n", str, dwarf_dieoffset(die)); + free(str); +} + /* * Compare type name and size to maintain them in a tree. * I'm not sure if DWARF would have information of a single type in many @@ -376,7 +391,7 @@ static struct type_state_stack *findnew_stack_state(struct type_state *state, * is used only at the given location and updates an entry in the table. */ void update_var_state(struct type_state *state, struct data_loc_info *dloc, - u64 addr, struct die_var_type *var_types) + u64 addr, u64 off, struct die_var_type *var_types) { Dwarf_Die mem_die; struct die_var_type *var; @@ -397,14 +412,20 @@ void update_var_state(struct type_state *state, struct data_loc_info *dloc, if (var->reg == DWARF_REG_FB) { findnew_stack_state(state, var->offset, &mem_die); + pr_debug("var [%lx] stack fbreg (%x, %d) type=", off, var->offset, var->offset); + debug_print_type_name(&mem_die); } else if (var->reg == fbreg) { findnew_stack_state(state, var->offset - fb_offset, &mem_die); + pr_debug("var [%lx] stack cfa (%x, %d) fb-offset=%d type=", off, var->offset - fb_offset, var->offset - fb_offset, fb_offset); + debug_print_type_name(&mem_die); } else if (has_reg_type(state, var->reg) && var->offset == 0) { struct type_state_reg *reg; reg = &state->regs[var->reg]; reg->type = mem_die; reg->ok = true; + pr_debug("var [%lx] reg%d type=", off, var->reg); + debug_print_type_name(&mem_die); } } } @@ -484,6 +505,8 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, die_get_real_type(&func_die, &type_die)) { state->regs[state->ret_reg].type = type_die; state->regs[state->ret_reg].ok = true; + pr_debug("fun [%lx] reg0 return from %s type=", dl->al.offset, dwarf_diename(&func_die)); + debug_print_type_name(&type_die); } return; } @@ -492,8 +515,10 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, if (!strstr(dl->ins.name, "mov")) return; - if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0) + if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0) { + pr_debug("failed to get mov insn loc\n"); return; + } if (dloc->fb_cfa) { u64 ip = dloc->ms->sym->start + dl->al.offset; @@ -508,10 +533,14 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, if (!has_reg_type(state, dst->reg1)) return; - if (has_reg_type(state, src->reg1)) + if (has_reg_type(state, src->reg1)) { state->regs[dst->reg1] = state->regs[src->reg1]; - else if (dloc->ms->map->dso->kernel && - src->segment == INSN_SEG_X86_GS) { + if (state->regs[dst->reg1].ok) { + pr_debug("mov [%lx] reg%d -> reg%d type=", dl->al.offset, src->reg1, dst->reg1); + debug_print_type_name(&state->regs[dst->reg1].type); + } + } else if (dloc->ms->map->dso->kernel && + src->segment == INSN_SEG_X86_GS) { struct map_symbol *ms = dloc->ms; int offset = src->offset; u64 ip = ms->sym->start + dl->al.offset; @@ -531,6 +560,8 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, var_name, offset, &type_die)) { state->regs[dst->reg1].type = type_die; state->regs[dst->reg1].ok = true; + pr_debug("mov [%lx] percpu -> reg%d type=", dl->al.offset, dst->reg1); + debug_print_type_name(&state->regs[dst->reg1].type); } } else state->regs[dst->reg1].ok = false; @@ -561,8 +592,13 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, var_name, offset, &type_die)) { state->regs[dst->reg1].type = type_die; state->regs[dst->reg1].ok = true; - } else + pr_debug("mov [%lx] PC-rel -> reg%d type=", dl->al.offset, dst->reg1); + debug_print_type_name(&type_die); + } else { + if (var_name) + pr_debug("??? [%lx] PC-rel (%lx: %s%+d)\n", dl->al.offset, var_addr, var_name, offset); state->regs[dst->reg1].ok = false; + } } /* And check stack variables with offset */ else if (sreg == fbreg) { @@ -575,6 +611,8 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, &type_die)) { state->regs[dst->reg1].type = type_die; state->regs[dst->reg1].ok = true; + pr_debug("mov [%lx] stack (-%#x, %d) -> reg%d type=", dl->al.offset, -offset, offset, dst->reg1); + debug_print_type_name(&type_die); } else state->regs[dst->reg1].ok = false; } @@ -584,6 +622,8 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, src->offset, &type_die)) { state->regs[dst->reg1].type = type_die; state->regs[dst->reg1].ok = true; + pr_debug("mov [%lx] %#x(reg%d) -> reg%d type=", dl->al.offset, src->offset, sreg, dst->reg1); + debug_print_type_name(&type_die); } /* Or try another register if any */ else if (src->multi_regs && sreg == src->reg1 && @@ -623,6 +663,8 @@ void update_insn_state(struct type_state *state, struct data_loc_info *dloc, findnew_stack_state(state, offset, &state->regs[src->reg1].type); } + pr_debug("mov [%lx] reg%d -> stack (-%#x, %d) type=", dl->al.offset, src->reg1, -offset, offset); + debug_print_type_name(&state->regs[src->reg1].type); } /* * Ignore other transfers since it'd set a value in a struct @@ -726,6 +768,9 @@ static bool find_matching_type(struct type_state *state, (unsigned)dloc->type_offset >= size) return false; + pr_debug("%s: [%lx] reg=%d offset=%d type=", + __func__, dloc->ip - dloc->ms->sym->start, reg, dloc->type_offset); + debug_print_type_name(type_die); return true; } @@ -739,6 +784,10 @@ static bool find_matching_type(struct type_state *state, *type_die = stack->type; /* Update the type offset from the start of slot */ dloc->type_offset -= stack->offset; + + pr_debug("%s: [%lx] stack offset=%d type=", + __func__, dloc->ip - dloc->ms->sym->start, dloc->type_offset); + debug_print_type_name(type_die); return true; } @@ -760,6 +809,11 @@ static bool find_matching_type(struct type_state *state, *type_die = stack->type; /* Update the type offset from the start of slot */ dloc->type_offset -= fboff + stack->offset; + + pr_debug("%s: [%lx] cfa stack offset=%d type_offset=%d type=", + __func__, dloc->ip - dloc->ms->sym->start, + dloc->type_offset + stack->offset, dloc->type_offset); + debug_print_type_name(type_die); return true; } @@ -783,12 +837,13 @@ static bool find_data_type_insn(struct data_loc_info *dloc, int reg, list_for_each_entry(bb, basic_blocks, list) { struct disasm_line *dl = bb->begin; + pr_debug("bb: [%lx - %lx]\n", bb->begin->al.offset, bb->end->al.offset); list_for_each_entry_from(dl, ¬es->src->source, al.node) { u64 this_ip = sym->start + dl->al.offset; u64 addr = map__rip_2objdump(dloc->ms->map, this_ip); /* Update variable type at this address */ - update_var_state(&state, dloc, addr, var_types); + update_var_state(&state, dloc, addr, dl->al.offset, var_types); if (this_ip == dloc->ip) { found = find_matching_type(&state, dloc, reg, @@ -821,6 +876,16 @@ static int find_data_type_block(struct data_loc_info *dloc, int reg, u64 src_ip, dst_ip; int ret = -1; + if (dloc->fb_cfa) { + u64 pc = map__rip_2objdump(dloc->ms->map, dloc->ip); + int fbreg, fboff; + + if (die_get_cfa(dloc->di->dbg, pc, &fbreg, &fboff) < 0) + fbreg = -1; + + pr_debug("CFA reg=%d offset=%d\n", fbreg, fboff); + } + dst_ip = dloc->ip; for (int i = nr_scopes - 1; i >= 0; i--) { Dwarf_Addr base, start, end; @@ -829,12 +894,16 @@ static int find_data_type_block(struct data_loc_info *dloc, int reg, if (dwarf_ranges(&scopes[i], 0, &base, &start, &end) < 0) break; + pr_debug("scope: [%d/%d] (die:%lx)\n", i + 1, nr_scopes, dwarf_dieoffset(&scopes[i])); src_ip = map__objdump_2rip(dloc->ms->map, start); /* Get basic blocks for this scope */ if (annotate_get_basic_blocks(dloc->ms->sym, src_ip, dst_ip, - &this_blocks) < 0) + &this_blocks) < 0) { + pr_debug("cannot find a basic block from %lx to %lx\n", + src_ip - dloc->ms->sym->start, dst_ip - dloc->ms->sym->start); continue; + } prepend_basic_blocks(&this_blocks, &basic_blocks); /* Get variable info for this scope and add to var_types list */ @@ -870,6 +939,18 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) int fb_offset = 0; bool is_fbreg = false; u64 pc; + char buf[64]; + + if (dloc->op->multi_regs) + snprintf(buf, sizeof(buf), " or reg%d", dloc->op->reg2); + else if (dloc->op->reg1 == DWARF_REG_PC) + snprintf(buf, sizeof(buf), " (PC)"); + else + buf[0] = '\0'; + + pr_debug("-----------------------------------------------------------\n"); + pr_debug("%s [%lx] for reg%d%s in %s\n", __func__, dloc->ip - dloc->ms->sym->start, + dloc->op->reg1, buf, dloc->ms->sym->name); /* * IP is a relative instruction address from the start of the map, as @@ -888,11 +969,15 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) reg = loc->reg1; offset = loc->offset; + pr_debug("CU die offset: %lx\n", dwarf_dieoffset(&cu_die)); + if (reg == DWARF_REG_PC) { if (die_find_variable_by_addr(&cu_die, pc, dloc->var_addr, &var_die, &offset)) { ret = check_variable(&var_die, type_die, offset, /*is_pointer=*/false); + if (ret == 0) + pr_debug("found PC-rel by addr=%lx offset=%d\n", dloc->var_addr, offset); dloc->type_offset = offset; goto out; } @@ -901,6 +986,8 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) die_find_variable_at(&cu_die, dloc->var_name, pc, &var_die)) { ret = check_variable(&var_die, type_die, dloc->type_offset, /*is_pointer=*/false); + if (ret == 0) + pr_debug("found \"%s\" by name offset=%d\n", dloc->var_name, dloc->type_offset); /* dloc->type_offset was updated by the caller */ goto out; } @@ -953,6 +1040,21 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) /* Found a variable, see if it's correct */ ret = check_variable(&var_die, type_die, offset, reg != DWARF_REG_PC && !is_fbreg); + if (ret == 0) { +#if 0 + const char *filename; + int lineno; + + if (cu_find_lineinfo(&cu_die, pc, &filename, &lineno) < 0) { + filename = "unknown"; + lineno = 0; + } +#endif + pr_debug("found \"%s\" in scope=%d/%d reg=%d offset=%#x (%d) loc->offset=%d fb-offset=%d (die:%lx scope:%lx) type=", + dwarf_diename(&var_die), i+1, nr_scopes, reg, offset, offset, loc->offset, fb_offset, dwarf_dieoffset(&var_die), + dwarf_dieoffset(&scopes[i])/*, filename, lineno*/); + debug_print_type_name(type_die); + } dloc->type_offset = offset; goto out; } @@ -969,8 +1071,10 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) goto retry; } - if (ret < 0) + if (ret < 0) { + pr_debug("no variable found\n"); ann_data_stat.no_var++; + } out: free(scopes); diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h index e293980eb11b..44e0f3770432 100644 --- a/tools/perf/util/annotate-data.h +++ b/tools/perf/util/annotate-data.h @@ -166,7 +166,7 @@ void exit_type_state(struct type_state *state); /* Update type state table using variables */ void update_var_state(struct type_state *state, struct data_loc_info *dloc, - u64 addr, struct die_var_type *var_types); + u64 addr, u64 off, struct die_var_type *var_types); /* Update type state table for an instruction */ void update_insn_state(struct type_state *state, struct data_loc_info *dloc,