From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685777; cv=none; d=zohomail.com; s=zohoarc; b=BUtG/1hT3ROgFS5yf9uP/9fuZeEsYJ2E0RRsUWtUtjSkNwDBxnL7k47qJ7BkclmiTTaRHY6w2phpx30l+dC2PnjASlEUqixzTGTBx0nRGxrA/SAznCDsppV7V59NdeYvCD35nBsEb6Q67yPfh5HnhKwXY4qze/OMzFYTpnuv9Y4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685777; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KsrgAwcfXPf60wLi3R10FjsXpsAPM+d7uJ0mGFTRCRw=; b=nZ6Ddom5t6AFIXXtqZWbOHbeUzrQoCi+a/MqmJFauV/CccEct+jbrD/wtjF/Yh0KLg7AjAO3JsE/uu/NmWWTzbuCHjELSIlta5sGMfWF2idVCEFW/ikMjhVTB0rk2/F1bvHXKeJbyFtURSmKzVKUIc21v9Ev6Wh3I5cgz/izCrs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685777302999.8522161359583; Fri, 8 Aug 2025 13:42:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTus-0002zJ-50; Fri, 08 Aug 2025 16:42:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTum-0002x0-Tb for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:14 -0400 Received: from mail-pl1-x633.google.com ([2607:f8b0:4864:20::633]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTuk-0003Cc-9U for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:12 -0400 Received: by mail-pl1-x633.google.com with SMTP id d9443c01a7336-2400f746440so20851205ad.2 for ; Fri, 08 Aug 2025 13:42:08 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685728; x=1755290528; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KsrgAwcfXPf60wLi3R10FjsXpsAPM+d7uJ0mGFTRCRw=; b=MAI31nQ3dMQTULDWyoAItG0hL9C3jpRfp5XuMgyaMWi9xEXVapwng51RaEihIOHw6b xHryHrJHscPIEQK9aObAt44ETHEmkuG1vGS0bPL+V3oT8VclH6cENFS8PdsuASDVfbbE jkgtUfjOSiOVp5XJ8pPJtTiX3W5Xz+Jt69qVcHnnfZKUKtE0WXT/k86kAYH7VS39O5rN EeX/sGK5Ro+Yp65gCRir27sZSyjG85qd27vFfAzZsuMkENUJli2vbf/JKzkEVDqHufha BdaeIsmmlb4XwMMPWjvD6byoBHyRmLRT74gUp3AtLYPtWZ0Qh9dzvU0ANKRzUmijng4j pnJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685728; x=1755290528; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KsrgAwcfXPf60wLi3R10FjsXpsAPM+d7uJ0mGFTRCRw=; b=kJIBKJp2xeXBCth3JOP7vVas0X8OK2v8es+zOhskWZYff+9okoVtHEWPkgmKrPehfX sjCOJAUka9RkCQeUAMVNUbkrL5jiHKkbzWJyRpklCbZiTk1Sv7+NUAKS/lWH7pt/wMcP Bfa5+csD7YJqAqTq/PI+xZHqgZf/T9i0yuTD1Io8PocT9Z50E/m5rhkXVLzmbM2BnozF ize7oeziWdTAkkNV1yp0RzgjIt4hqNcOLWbX/VgAbwc5sJHz1ec1XHcDj3EnIJlQ3dM4 L5/9dBsQUQTQDDPlvq7R1h8GwhHHwO82A66drceEwEt1xVVt/X3LVTOOzKVJuHvV4kj3 SlcA== X-Gm-Message-State: AOJu0YyBSRF+nEyKNi3D+E3p6a+FAJbJGnMTiP/iGDO10Tux/51bF/06 tc7jgFw74QX4sLLzLIRNbBGoq5Qe27+imdu2/njKDl/Z50kYGBJqFNh3FP2G+PGR2DlCHWDCsRa Dugz/1VPmdA== X-Gm-Gg: ASbGncs48XgdFA6/iMP+v1eh0h1XbQdGT9Z3XxrDp79VqOSCM/+/L7nS8mx7Tdtxz1y ad4Kt8a1qy+j9Cv4qyodT9hiKJwz3Kbfg0LSfpR7r3oi9KgdjBd3pPgrnmGDBgWa6eGcdzTwLTR 9nW4S4oMQpJJR1XG3x3qJmBDF718Zjg9UjJHKheIjVJn7y5tin1R7imxMxn84bIN54kzw6FDDVO 8/fWplsJ2Jgg86WikQBnNOsP4tqL2U5qdher2ipmA/5ctAs1ivw9galRmgNYeqgTvNwla7EidE/ JVoQHxdEXsBG3qZLDqER1hW2gGN3zJXgHoWDriD3mNbcqedZ09Q/Y88gGLjXAwUPOpU3RF5th9X mD+ohXt4L+S5Z7WPeuPhzpA== X-Google-Smtp-Source: AGHT+IEwyCsAeCiNeliWBaQeHKXOqBNPQx4cnRwJB7/U5KzSuW3BJCZlF3epghzUvbxKefiWhlTrtA== X-Received: by 2002:a17:903:1aa3:b0:240:8262:1a46 with SMTP id d9443c01a7336-242c21e355fmr60893775ad.25.1754685727922; Fri, 08 Aug 2025 13:42:07 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 1/9] contrib/plugins/uftrace: skeleton file Date: Fri, 8 Aug 2025 13:41:48 -0700 Message-ID: <20250808204156.659715-2-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::633; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pl1-x633.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685779668116600 Content-Type: text/plain; charset="utf-8" We define a scoreboard that will hold our data per cpu. As well, we define a buffer per cpu that will be used to read registers and memories in a thread-safe way. For now, we just instrument all instructions with an empty callback. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 73 +++++++++++++++++++++++++++++++++++++ contrib/plugins/meson.build | 3 +- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 contrib/plugins/uftrace.c diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c new file mode 100644 index 00000000000..4af0130b159 --- /dev/null +++ b/contrib/plugins/uftrace.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2025, Pierrick Bouvier + * + * Generates a trace compatible with uftrace (similar to uftrace record). + * https://github.com/namhyung/uftrace + * + * See docs/about/emulation.rst|Uftrace for details and examples. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; + +typedef struct Cpu { + GByteArray *buf; +} Cpu; + +static struct qemu_plugin_scoreboard *score; + +static void track_callstack(unsigned int cpu_index, void *udata) +{ +} + +static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) +{ + size_t n_insns =3D qemu_plugin_tb_n_insns(tb); + + for (size_t i =3D 0; i < n_insns; i++) { + struct qemu_plugin_insn *insn =3D qemu_plugin_tb_get_insn(tb, i); + + uintptr_t pc =3D qemu_plugin_insn_vaddr(insn); + qemu_plugin_register_vcpu_insn_exec_cb(insn, track_callstack, + QEMU_PLUGIN_CB_R_REGS, + (void *) pc); + } +} + +static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) +{ + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); + cpu->buf =3D g_byte_array_new(); +} + +static void vcpu_end(unsigned int vcpu_index) +{ + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); + g_byte_array_free(cpu->buf, true); + memset(cpu, 0, sizeof(Cpu)); +} + +static void at_exit(qemu_plugin_id_t id, void *data) +{ + for (size_t i =3D 0; i < qemu_plugin_num_vcpus(); ++i) { + vcpu_end(i); + } + + qemu_plugin_scoreboard_free(score); +} + +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, + const qemu_info_t *info, + int argc, char **argv) +{ + score =3D qemu_plugin_scoreboard_new(sizeof(Cpu)); + qemu_plugin_register_vcpu_init_cb(id, vcpu_init); + qemu_plugin_register_atexit_cb(id, at_exit, NULL); + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); + + return 0; +} diff --git a/contrib/plugins/meson.build b/contrib/plugins/meson.build index 1876bc78438..7eb3629c95d 100644 --- a/contrib/plugins/meson.build +++ b/contrib/plugins/meson.build @@ -1,5 +1,6 @@ contrib_plugins =3D ['bbv', 'cache', 'cflow', 'drcov', 'execlog', 'hotbloc= ks', - 'hotpages', 'howvec', 'hwprofile', 'ips', 'stoptrigger'] + 'hotpages', 'howvec', 'hwprofile', 'ips', 'stoptrigger', + 'uftrace'] if host_os !=3D 'windows' # lockstep uses socket.h contrib_plugins +=3D 'lockstep' --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685813; cv=none; d=zohomail.com; s=zohoarc; b=DYVmwpmvEHGC4o/e2qwJDbqpf/eAOIcNnx/1aH2jFYAhWzeI/8QSHCaOLEhMQIVKqywblDijsmxLqQckVa/ymMJMljRQPJpq5t2yYdxkO5Fy+E6DBoPtm9Rdr35ZoxAZjBvX/lE8yPp57LRZNum78Tut5S9+K8PsUwoX+0+fFvY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685813; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=UCnnXWfvqtRCVbfN0E52T8SkudA5RqZI+yQNyvWP9uU=; b=dH39+rSnCIlLbwz4Kx06vg+jf2HN+jhXGiEWNf41FjKUPVCaIbJOabJ+gdtp5ppd6EU+WDrEvGzkWLWUKSDrEsGoqoKY+0FRb/dZ/SV7DpBayGWAIJnz8jYf2Aixtlbh/GAsfEdfH0XL5OthI61rhwD+CbqNMudcfhnPPAvPzV4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685813647357.93915307060263; Fri, 8 Aug 2025 13:43:33 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTur-0002yj-Do; Fri, 08 Aug 2025 16:42:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTuo-0002x6-6R for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:14 -0400 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTuk-0003Ck-M1 for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:13 -0400 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-24003ed822cso15373225ad.1 for ; Fri, 08 Aug 2025 13:42:10 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685729; x=1755290529; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UCnnXWfvqtRCVbfN0E52T8SkudA5RqZI+yQNyvWP9uU=; b=I/nd8qIDJUXGKJ7IlD4L8YSv33Xwm4Dp1Y4kXDTl8WloIdLSoHa9N3BsHCkKZFQWly mdBFqeJt3C8onEKqyvdqOyPlwyBvcrYAkBl+WmmqRaAlmt2f98dXcH4BReiEWPMZDQqQ e5nq5xqe4IzBcMUXf6gnjnkyo2QOD4dPMytHalJ3m7KVC/kDlmYPKBBFN9VjdEQyk+lS CmwjUSRQdRk0JrbhISLh/ezg0kePrc4mD76DW7d7zlTxhTqWuOgwTDomaLw0zOFefuAe uIyxJyO1sXNtjdyMqwWkYTPW8avFVjt6hfwao80VWKnxonWU2ICftu4rGVYpFMdlrG8h jr5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685729; x=1755290529; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UCnnXWfvqtRCVbfN0E52T8SkudA5RqZI+yQNyvWP9uU=; b=sAzuiwWXs9cCxa6ZI0xvfI4MNebKFqYsIER8M/0X4Yb9U+jtAJHisQl33jqt3NibmY hobfmre58RBC8USey1D4jYESA0gi8B+9r9Olknyv27btkDsfdsyVsE1WZvGZF/6ybyBg 8WNZ1YFbCZvB2g4xbL9m2apHcjgRZ/QEB1KUyvVr7+SoLPxCOUzffCDXFp7UW8YWuIy4 GQTbq2axtF29zJ8wt1vhk2uSh+5wnlU3pRrVCT8M3S9ETrJ6zy82ehDAK2zE+H1B9hAA /u3/CzYHhXaunVsaX8Lq+KcG4Q1NhRk99UsVwc9oCnYjpeRdWhxabmh/UQYa6iyhnxGd 177A== X-Gm-Message-State: AOJu0YzBBGHEv58o15D6YH6bwRLzchHgQgKYs8Cn/zq6qFtuWAYYAvSN zM5u3AnmOMHBUFx0fM7H9yXFQycuBTtPAi3OI4AFL4kCiiJ1UmXoVzL+7a9vMOyOUg4NiGAJinC cwi68KKWXCA== X-Gm-Gg: ASbGncvac2wrgs+5OrGlhuThvjKWri+OXvgD+4H4bie1G2FXGmmBwmDTO6ssllQQcBC y1tV38FhLz1E7LcGsxP4iRppMGvdWei6JZHERRzBcXDqdw2JfFr6DUvXhLxRIOe9AU+cT65VPmm ogq22S2fqVKktgrc3W9GO9+hBLPN19uRgDd7xl+DPYyw6HCV0Jf9y/0T15jKJ/Xkw01ZXP6Rz0k xlgwO9In8IkSJpYlhrQy7++LykYdveXWG59+RcxOuQ1xpNSl4iJKgAOR7oF2nbiJEKDdhuoauss fqdw3kr9yc7V/ZWwak38rxYRp9Q5U2sMHGuEwRyTCujgzzL2aAKCJjWWLrAHwupEgWpXjNjkaEL 90Yy2YCHP3NuQwyBTubU5Sg== X-Google-Smtp-Source: AGHT+IF+/I1UFWXuqW7ersrevQbUhhb3sW9sFPZm1yVR4tLdHSZPy0jKl7WPbock4hQPk5SCiG5jdw== X-Received: by 2002:a17:903:1b43:b0:240:2145:e527 with SMTP id d9443c01a7336-242c204c492mr51205175ad.25.1754685728871; Fri, 08 Aug 2025 13:42:08 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 2/9] contrib/plugins/uftrace: define cpu operations and implement aarch64 Date: Fri, 8 Aug 2025 13:41:49 -0700 Message-ID: <20250808204156.659715-3-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::634; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pl1-x634.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685815380124100 Content-Type: text/plain; charset="utf-8" We define a new CpuOps structure that will be used to implement tracking independently of guest architecture. As well, we now instrument only instructions following ones that might have touched the frame pointer. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 114 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 4 deletions(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 4af0130b159..d060513446c 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -11,14 +11,94 @@ =20 #include #include +#include =20 QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; =20 +typedef struct Cpu Cpu; + +typedef struct { + void (*init)(Cpu *cpu); + void (*end)(Cpu *cpu); + uint64_t (*get_frame_pointer)(Cpu *cpu); + bool (*does_insn_modify_frame_pointer)(const char *disas); +} CpuOps; + typedef struct Cpu { GByteArray *buf; + CpuOps ops; + void *arch; } Cpu; =20 +typedef struct { + struct qemu_plugin_register *reg_fp; +} Aarch64Cpu; + static struct qemu_plugin_scoreboard *score; +static CpuOps arch_ops; + +static uint64_t cpu_read_register64(Cpu *cpu, struct qemu_plugin_register = *reg) +{ + GByteArray *buf =3D cpu->buf; + g_byte_array_set_size(buf, 0); + size_t sz =3D qemu_plugin_read_register(reg, buf); + g_assert(sz =3D=3D 8); + g_assert(buf->len =3D=3D 8); + return *((uint64_t *) buf->data); +} + +static struct qemu_plugin_register *plugin_find_register(const char *name) +{ + g_autoptr(GArray) regs =3D qemu_plugin_get_registers(); + for (int i =3D 0; i < regs->len; ++i) { + qemu_plugin_reg_descriptor *reg; + reg =3D &g_array_index(regs, qemu_plugin_reg_descriptor, i); + if (!strcmp(reg->name, name)) { + return reg->handle; + } + } + return NULL; +} + +static uint64_t aarch64_get_frame_pointer(Cpu *cpu_) +{ + Aarch64Cpu *cpu =3D cpu_->arch; + return cpu_read_register64(cpu_, cpu->reg_fp); +} + +static void aarch64_init(Cpu *cpu_) +{ + Aarch64Cpu *cpu =3D g_new0(Aarch64Cpu, 1); + cpu_->arch =3D cpu; + cpu->reg_fp =3D plugin_find_register("x29"); + if (!cpu->reg_fp) { + fprintf(stderr, "uftrace plugin: frame pointer register (x29) is n= ot " + "available. Please use an AArch64 cpu (or -cpu max= ).\n"); + g_abort(); + } +} + +static void aarch64_end(Cpu *cpu) +{ + g_free(cpu->arch); +} + +static bool aarch64_does_insn_modify_frame_pointer(const char *disas) +{ + /* + * Check if current instruction concerns fp register "x29". + * We add a prefix space to make sure we don't match addresses dump + * in disassembly. + */ + return strstr(disas, " x29"); +} + +static CpuOps aarch64_ops =3D { + .init =3D aarch64_init, + .end =3D aarch64_end, + .get_frame_pointer =3D aarch64_get_frame_pointer, + .does_insn_modify_frame_pointer =3D aarch64_does_insn_modify_frame_poi= nter, +}; =20 static void track_callstack(unsigned int cpu_index, void *udata) { @@ -28,19 +108,37 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct = qemu_plugin_tb *tb) { size_t n_insns =3D qemu_plugin_tb_n_insns(tb); =20 + /* + * Callbacks and inline instrumentation are inserted before an instruc= tion. + * Thus, to see instruction effect, we need to wait for next one. + * Potentially, the last instruction of a block could modify the frame + * pointer. Thus, we need to always instrument first instruction in a = tb. + */ + bool instrument_insn =3D true; for (size_t i =3D 0; i < n_insns; i++) { struct qemu_plugin_insn *insn =3D qemu_plugin_tb_get_insn(tb, i); =20 - uintptr_t pc =3D qemu_plugin_insn_vaddr(insn); - qemu_plugin_register_vcpu_insn_exec_cb(insn, track_callstack, - QEMU_PLUGIN_CB_R_REGS, - (void *) pc); + if (instrument_insn) { + uintptr_t pc =3D qemu_plugin_insn_vaddr(insn); + qemu_plugin_register_vcpu_insn_exec_cb(insn, track_callstack, + QEMU_PLUGIN_CB_R_REGS, + (void *) pc); + instrument_insn =3D false; + } + + char *disas =3D qemu_plugin_insn_disas(insn); + if (arch_ops.does_insn_modify_frame_pointer(disas)) { + instrument_insn =3D true; + } } } =20 static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); + cpu->ops =3D arch_ops; + + cpu->ops.init(cpu); cpu->buf =3D g_byte_array_new(); } =20 @@ -64,6 +162,14 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, const qemu_info_t *info, int argc, char **argv) { + if (!strcmp(info->target_name, "aarch64")) { + arch_ops =3D aarch64_ops; + } else { + fprintf(stderr, "plugin uftrace: %s target is not supported\n", + info->target_name); + return 1; + } + score =3D qemu_plugin_scoreboard_new(sizeof(Cpu)); qemu_plugin_register_vcpu_init_cb(id, vcpu_init); qemu_plugin_register_atexit_cb(id, at_exit, NULL); --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685805; cv=none; d=zohomail.com; s=zohoarc; b=VWLccSPCI/aWhZ9rWXOFNZfjDjBtPlGa9s9IMJk4qiPCQXH3rpO8nn+wBBhErIiFQyxhIE+jUZFzX0c4Ie0ZYvg1PBpcbLah/Oln9I5PxrHj+WoDtI3uwWBWvenJKHAyd8ziWhXMI6NAMJ5PiINxEu/Qm9DMnIS+4umsBSwD88E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685805; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=n8jo0LSSh8lJpsdcimtvOxocpTr/cr5eTG3kdaxxUXg=; b=Q+4QTbmPUW8FXA6RL/e5GFFGhuIt3/XnMLnAhbGcrLBiWqiJVFK6GWJ22HcUotxvpAPNHlSpMq6r6pKK3iqq5j7OwFE60Fy/2M9fr8aMpUn0FNZ/JLMw73kjRAGcesonwY5+UpYCcI9uq/f9a6PcTF6DZDC0tpf/142ne7SyC8Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685805003684.118152649568; Fri, 8 Aug 2025 13:43:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTut-00030W-Rg; Fri, 08 Aug 2025 16:42:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTup-0002xd-0M for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:16 -0400 Received: from mail-pl1-x62c.google.com ([2607:f8b0:4864:20::62c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTul-0003Cn-D6 for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:14 -0400 Received: by mail-pl1-x62c.google.com with SMTP id d9443c01a7336-23fc5aedaf0so17958255ad.2 for ; Fri, 08 Aug 2025 13:42:11 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685730; x=1755290530; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=n8jo0LSSh8lJpsdcimtvOxocpTr/cr5eTG3kdaxxUXg=; b=xR+5p2yf+WaJCXZfrMeAJFHIutsX8m1tK51Mcs2j/8sQ9bn2n/aTdGZRCcf9qftbrO G12uQdy/a1WZCcRDHxVBEyGXL4g6zKLyG1eWWRmu2TeGbDu7kUQKbqGooqxoey8k8L92 k/g0swKW+HikCu7S4sQ/fhL/TrrebxEixJBZXwp5cZOd4KSBsCJzFMhbJmjtH1k5qJal hZH9rSg0YGx70YYVvKCl42xwAG3h8wxY1Dk3FI++3hlFmZL+AnTKTFwLCUNIv8/FT/UT Yn+Y9JqUaLgH9ob9I6NxKfxBSHku30ik4/sZgtKYQDnYaChskUKtchs2jhKef0khmpyS Biyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685730; x=1755290530; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=n8jo0LSSh8lJpsdcimtvOxocpTr/cr5eTG3kdaxxUXg=; b=UYoZum8mCTNYt4E53/fyP5ToaLWAvc3ghc1UXnamm0MNUkn+7S+ejkknBAao5lo7OJ Mz4tk1pKt8CcSE4Ok82ly0eLout1KXDM6M83p+l+c4ueH6T1Z6kh/X64sg2ilZ2Rgtnx c/09zhnhtSSPAVBAxXbr6fvJFb2oyCilWlgNZoxc1GEzHP4hW/K6idjjaT9mZsJO3ugy 5RuW1gVTwIm97bfg7zVM10MnkUP27o8vF7rC6TVviLROIBbnuOIGhyyEz1u/2myxRvjD GviZ4VpJ2nwtPJMGUwEFqf/bJatJclBwr3Eb4AjYmR1gRsEWI7FY1/945RFYXn1vUQGl RGww== X-Gm-Message-State: AOJu0YzIwFnxrS/7B7KAcV9C9deNpPSyEB13rmBx+iZh4UeQPbWpHK6v L8PsOK5JJLdHqDv/o60ZIhmtKj4gmhB/F1W8G9WtTER/vyChyYIH968ivrVmTYFBJz+FyJUf/Et ohzqOPR4oUg== X-Gm-Gg: ASbGncuTa5Fi74yh5rFd3Id2ZZWNt+u2SfOGRdiIsAvLCKWCUp9DZLKoKu0EloQwHan XpmZWeNvd538kz8Eoj3YWE/CD90Utvlm81sDp+5j+TJgOamQeIYz9Sw51B63aDYBP/ELjo15lUH fLgc01hyu5dDXTINSO5fOHTKsj/HkmGvvPH9m4ID0kgPiLBV0in/vMcX4Xkr5trteqtDIlL4AYC V+W6hYpvGsB7Rk5/WFUc8vfplmzO6f3fqLcag7Kc1P0Omwf0MOB/71g5W6MT5FouHHdMuu41En9 4Hy914iJDNFPkYjGLmAei+g+isK46O8Xr8wTvxnuTv7Ktt8RvK51cABE781W17uJLj5f/fApJZF YQS9SWyjoVRrJ7CRlvPnjWg== X-Google-Smtp-Source: AGHT+IHdyzwZo6v3pLXWFd5wdi1PwGtBgW4b459IoDCidfZlewJaQGcNMIUZEfzm2EH8PTbD0W6R6Q== X-Received: by 2002:a17:903:40c9:b0:240:5549:708e with SMTP id d9443c01a7336-242c225ad36mr67222365ad.46.1754685729829; Fri, 08 Aug 2025 13:42:09 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 3/9] contrib/plugins/uftrace: track callstack Date: Fri, 8 Aug 2025 13:41:50 -0700 Message-ID: <20250808204156.659715-4-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::62c; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pl1-x62c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685807560116600 Content-Type: text/plain; charset="utf-8" We now track callstack, based on frame pointer analysis. We can detect function calls, returns, and discontinuities. We implement a frame pointer based unwinding that is used for discontinuities. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 160 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index d060513446c..bb775916270 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -15,6 +15,15 @@ =20 QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; =20 +typedef struct { + GArray *s; +} Callstack; + +typedef struct { + uint64_t pc; + uint64_t frame_pointer; +} CallstackEntry; + typedef struct Cpu Cpu; =20 typedef struct { @@ -25,6 +34,7 @@ typedef struct { } CpuOps; =20 typedef struct Cpu { + Callstack *cs; GByteArray *buf; CpuOps ops; void *arch; @@ -37,6 +47,71 @@ typedef struct { static struct qemu_plugin_scoreboard *score; static CpuOps arch_ops; =20 +static Callstack *callstack_new(void) +{ + Callstack *cs =3D g_new0(Callstack, 1); + cs->s =3D g_array_new(false, false, sizeof(CallstackEntry)); + return cs; +} + +static void callstack_free(Callstack *cs) +{ + g_array_free(cs->s, true); + cs->s =3D NULL; + g_free(cs); +} + +static size_t callstack_depth(const Callstack *cs) +{ + return cs->s->len; +} + +static size_t callstack_empty(const Callstack *cs) +{ + return callstack_depth(cs) =3D=3D 0; +} + +static void callstack_clear(Callstack *cs) +{ + g_array_set_size(cs->s, 0); +} + +static const CallstackEntry *callstack_at(const Callstack *cs, size_t dept= h) +{ + g_assert(depth > 0); + g_assert(depth <=3D callstack_depth(cs)); + return &g_array_index(cs->s, CallstackEntry, depth - 1); +} + +static CallstackEntry callstack_top(const Callstack *cs) +{ + if (callstack_depth(cs) >=3D 1) { + return *callstack_at(cs, callstack_depth(cs)); + } + return (CallstackEntry){}; +} + +static CallstackEntry callstack_caller(const Callstack *cs) +{ + if (callstack_depth(cs) >=3D 2) { + return *callstack_at(cs, callstack_depth(cs) - 1); + } + return (CallstackEntry){}; +} + +static void callstack_push(Callstack *cs, CallstackEntry e) +{ + g_array_append_val(cs->s, e); +} + +static CallstackEntry callstack_pop(Callstack *cs) +{ + g_assert(!callstack_empty(cs)); + CallstackEntry e =3D callstack_top(cs); + g_array_set_size(cs->s, callstack_depth(cs) - 1); + return e; +} + static uint64_t cpu_read_register64(Cpu *cpu, struct qemu_plugin_register = *reg) { GByteArray *buf =3D cpu->buf; @@ -47,6 +122,50 @@ static uint64_t cpu_read_register64(Cpu *cpu, struct qe= mu_plugin_register *reg) return *((uint64_t *) buf->data); } =20 +static uint64_t cpu_read_memory64(Cpu *cpu, uint64_t addr) +{ + g_assert(addr); + GByteArray *buf =3D cpu->buf; + g_byte_array_set_size(buf, 0); + bool read =3D qemu_plugin_read_memory_vaddr(addr, buf, 8); + if (!read) { + return 0; + } + g_assert(buf->len =3D=3D 8); + return *((uint64_t *) buf->data); +} + +static void cpu_unwind_stack(Cpu *cpu, uint64_t frame_pointer, uint64_t pc) +{ + g_assert(callstack_empty(cpu->cs)); + + #define UNWIND_STACK_MAX_DEPTH 1024 + CallstackEntry unwind[UNWIND_STACK_MAX_DEPTH]; + size_t depth =3D 0; + do { + /* check we don't have an infinite stack */ + for (size_t i =3D 0; i < depth; ++i) { + if (frame_pointer =3D=3D unwind[i].frame_pointer) { + break; + } + } + CallstackEntry e =3D {.frame_pointer =3D frame_pointer, .pc =3D pc= }; + unwind[depth] =3D e; + depth++; + if (frame_pointer) { + frame_pointer =3D cpu_read_memory64(cpu, frame_pointer); + } + pc =3D cpu_read_memory64(cpu, frame_pointer + 8); /* read previous= lr */ + } while (frame_pointer && pc && depth < UNWIND_STACK_MAX_DEPTH); + #undef UNWIND_STACK_MAX_DEPTH + + /* push it from bottom to top */ + while (depth) { + callstack_push(cpu->cs, unwind[depth - 1]); + --depth; + } +} + static struct qemu_plugin_register *plugin_find_register(const char *name) { g_autoptr(GArray) regs =3D qemu_plugin_get_registers(); @@ -102,6 +221,43 @@ static CpuOps aarch64_ops =3D { =20 static void track_callstack(unsigned int cpu_index, void *udata) { + uint64_t pc =3D (uintptr_t) udata; + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, cpu_index); + Callstack *cs =3D cpu->cs; + + uint64_t fp =3D cpu->ops.get_frame_pointer(cpu); + if (!fp && callstack_empty(cs)) { + /* + * We simply push current pc. Note that we won't detect symbol cha= nge as + * long as a proper call does not happen. + */ + callstack_push(cs, (CallstackEntry){.frame_pointer =3D fp, .pc =3D= pc}); + return; + } + + CallstackEntry top =3D callstack_top(cs); + if (fp =3D=3D top.frame_pointer) { + /* same function */ + return; + } + + CallstackEntry caller =3D callstack_caller(cs); + if (fp =3D=3D caller.frame_pointer) { + /* return */ + callstack_pop(cs); + return; + } + + uint64_t caller_fp =3D fp ? cpu_read_memory64(cpu, fp) : 0; + if (caller_fp =3D=3D top.frame_pointer) { + /* call */ + callstack_push(cs, (CallstackEntry){.frame_pointer =3D fp, .pc =3D= pc}); + return; + } + + /* discontinuity, exit current stack and unwind new one */ + callstack_clear(cs); + cpu_unwind_stack(cpu, fp, pc); } =20 static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) @@ -140,12 +296,16 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned i= nt vcpu_index) =20 cpu->ops.init(cpu); cpu->buf =3D g_byte_array_new(); + + cpu->cs =3D callstack_new(); } =20 static void vcpu_end(unsigned int vcpu_index) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); g_byte_array_free(cpu->buf, true); + + callstack_free(cpu->cs); memset(cpu, 0, sizeof(Cpu)); } =20 --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685818; cv=none; d=zohomail.com; s=zohoarc; b=fYKIOtF/AOaTQFUdy2zoCvqS6HjBr3tVQFwAZuDB6IfIUzpKCs2rqOBICoxFHjPKFeA7B5N0hH9mPBWsRCmZX/mr4wqzQ1NYZGSiTqjRWaV4CNgGsivxHX1Omi8z91lj1WUSkUN8xTvhB14CoieuwenwZuWe3Gt4WrIg99TPeaw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685818; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TvPW1DllqOy9ROzoZ8zi7sSea4PVBOE0TTlSJsOQt4Y=; b=YQPTXbwO8cvnLjg59Snx79sAe4PKL4EF2seJnsLsDxef0bO+46Bpx8vlCX3qys588/9ttx7fPJsa9sxZXqB7DjjKNUCOGlSEduS5LNX6+mWK7FumxmbdtlglrUka8a5Wvo8rRL/9tw4D2HtLYdNchvrG0TzQxfl+ZhUBs7LLHQk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685818290502.302164917603; Fri, 8 Aug 2025 13:43:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTut-00030V-FP; Fri, 08 Aug 2025 16:42:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTuo-0002xc-Vx for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:16 -0400 Received: from mail-pf1-x42f.google.com ([2607:f8b0:4864:20::42f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTum-0003Cw-M5 for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:14 -0400 Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-76bd6e84eddso3417050b3a.0 for ; Fri, 08 Aug 2025 13:42:11 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685731; x=1755290531; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TvPW1DllqOy9ROzoZ8zi7sSea4PVBOE0TTlSJsOQt4Y=; b=YBPM9DfskFjKumem7+Q01z7pg6ZPEmKB99mXeL2Cjq5TagcUI1InJvxrep2vG1IADi 0PKJ4DnRROmRDa6ieHjynEJynyBxpJbxIGRiAAQSxfgZWrqk/FtK5DY2oFMwd9fhQXMo DX4xQxGW/hZnFTshYWnlZzbNYvGf3pjScNqzc5uU+gInanLaByYDEdHzzC1tcJWPw3GC dNnu/+gx/NWFZVwFmO4WX0ti9+0nKUaSdcFwIUTusTpY953752JjS7qDNTFQOixJslf+ 5OPIRDt9I5mcpro5xixCoSqqEZh8rzEYM0orfjzNAIa4kqRMGMIPzGngWseuDh/6z7SJ 4V3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685731; x=1755290531; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TvPW1DllqOy9ROzoZ8zi7sSea4PVBOE0TTlSJsOQt4Y=; b=tk2eXkuSC6LqxqlZGbiuWc5L0nj31VATUOPfYLG7KM/j5QNelU/UvsHJ/WR0BIAFMa FIRSQc+uQmeusbhLgSbd+EmpdprKlVCtsqLKPNqDIdwC6ooeF+JMkxoiFYtbU/TuBxy8 b+III7kRwMCFieemEZGfsS87ua2Imcp3DZMrnB1LXF5LGEr79BGHNhBRv077qdBigDya 3WAd4vVurnU/qiQxjD1x7RMeP1O4ed7qqTiZL9UDdIxrTTPKjiyWqvwxaa989MyQQlsH Rn3nOaORSgDRn3w5kVXn8OgqbJP26DSp0FSLFDJo6T5rxGYBK5zoIj15cICmeCp/lgX7 47ZQ== X-Gm-Message-State: AOJu0YwjHhVrk3/KCl6V05ElPC51dBJjG9pkazMm7PegjmpFUkOOawK/ /XG++orduECbeqO0jNFjD1K1runbpgrPPArj5q60LmHRY9BrN8aISt4erFfX0oplqnnT6pLiXYm ALDpJIjkAzA== X-Gm-Gg: ASbGncs7IfBpuANDUBttrequrnG5SlgBTWB90ZMsjnjD+11w+4iiEG2yRtfRtPi8+zT 40l6CbM+lS5ajqNA3T7P5LbGT/tGy5jLBfk2QlrP277DBVWQTaZMOeWqQYjY9QjsSbMxlFwYVD4 3mNd8BGBQsWPQVgEI1JxURatWFX9dSrv40UIKuJ4pen5DcjQm7fJkyLCfZqA/KN2A9PJfylP+YV /hgJ0nYCzLIAb6HOna9sMgGScjgW+A8GzemQQGstoMweHWFCH5OlJKxnoOaYF/hb7olvlD2xqAq ipxoXf133G2jt1b76dgnAj2KFcYteQJfOha2E+fveLpvLK+1ip2kSrzfI0A5Rb5JlWObN1NJ8Qj cQDXXnV18Nw5LPyxJv2wilA== X-Google-Smtp-Source: AGHT+IEQt/jLD4Lbwp35OLWf7JpfxjMnGx7tXojzmOpwiCqG6EwwhPItkka7VHHIPY/lqSZCkWzLiA== X-Received: by 2002:a17:902:e552:b0:21f:1202:f2f5 with SMTP id d9443c01a7336-242c2070acdmr59894065ad.8.1754685730739; Fri, 08 Aug 2025 13:42:10 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 4/9] contrib/plugins/uftrace: implement tracing Date: Fri, 8 Aug 2025 13:41:51 -0700 Message-ID: <20250808204156.659715-5-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::42f; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x42f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685821163124100 Content-Type: text/plain; charset="utf-8" We implement tracing, following uftrace format. Trace is flushed every 32 MB, so file operations don't impact performance at runtime. A different trace is generated per cpu, and we ensure they have a unique name, based on vcpu_index, while keeping room for privilege level coming in next commit. Uftrace format is not officially documented, but it can be found here: https://github.com/namhyung/uftrace/blob/v0.18/libmcount/record.c#L909 Signed-off-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- contrib/plugins/uftrace.c | 150 +++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index bb775916270..830967c215b 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -12,6 +12,13 @@ #include #include #include +#include +#include +#include +#include + +#define MiB (INT64_C(1) << 20) +#define NANOSECONDS_PER_SECOND 1000000000LL =20 QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; =20 @@ -24,6 +31,13 @@ typedef struct { uint64_t frame_pointer; } CallstackEntry; =20 +typedef struct { + GArray *t; + GString *path; + GString *name; + uint32_t id; +} Trace; + typedef struct Cpu Cpu; =20 typedef struct { @@ -34,6 +48,7 @@ typedef struct { } CpuOps; =20 typedef struct Cpu { + Trace *trace; Callstack *cs; GByteArray *buf; CpuOps ops; @@ -44,9 +59,41 @@ typedef struct { struct qemu_plugin_register *reg_fp; } Aarch64Cpu; =20 +typedef struct { + uint64_t timestamp; + uint64_t data; +} UftraceEntry; + +typedef enum { + UFTRACE_ENTRY, + UFTRACE_EXIT, + UFTRACE_LOST, + UFTRACE_EVENT +} UftraceRecordType; + static struct qemu_plugin_scoreboard *score; static CpuOps arch_ops; =20 +static uint64_t gettime_ns(void) +{ +#ifdef _WIN32 + /* + * On Windows, timespec_get is available only with UCRT, but not with + * MinGW64 environment. Simplify by using only gettimeofday on this + * platform. This may result in a precision loss. + */ + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t now_ns =3D tv.tv_sec * NANOSECONDS_PER_SECOND + tv.tv_usec * = 1000; +#else + /* We need nanosecond precision for short lived functions. */ + struct timespec ts; + timespec_get(&ts, TIME_UTC); + uint64_t now_ns =3D ts.tv_sec * NANOSECONDS_PER_SECOND + ts.tv_nsec; +#endif + return now_ns; +} + static Callstack *callstack_new(void) { Callstack *cs =3D g_new0(Callstack, 1); @@ -112,6 +159,86 @@ static CallstackEntry callstack_pop(Callstack *cs) return e; } =20 +static Trace *trace_new(uint32_t id, GString *name) +{ + Trace *t =3D g_new0(Trace, 1); + t->t =3D g_array_new(false, false, sizeof(UftraceEntry)); + t->path =3D g_string_new(NULL); + g_string_append_printf(t->path, "./uftrace.data/%"PRIu32".dat", id); + t->name =3D g_string_new(name->str); + t->id =3D id; + return t; +} + +static void trace_free(Trace *t) +{ + g_assert(t->t->len =3D=3D 0); + g_array_free(t->t, true); + t->t =3D NULL; + g_string_free(t->path, true); + t->path =3D NULL; + g_string_free(t->name, true); + t->name =3D NULL; + g_free(t); +} + +static void trace_flush(Trace *t, bool append) +{ + int create_dir =3D g_mkdir_with_parents("./uftrace.data", + S_IRWXU | S_IRWXG | S_IRWXO); + g_assert(create_dir =3D=3D 0); + FILE *dat =3D fopen(t->path->str, append ? "a" : "w"); + g_assert(dat); + GArray *data =3D t->t; + if (data->len) { + size_t wrote =3D fwrite(data->data, sizeof(UftraceEntry), data->le= n, dat); + g_assert(wrote =3D=3D data->len); + } + fclose(dat); + g_array_set_size(data, 0); +} + +static void trace_add_entry(Trace *t, uint64_t timestamp, uint64_t pc, + size_t depth, UftraceRecordType type) +{ + /* https://github.com/namhyung/uftrace/blob/v0.18/libmcount/record.c#L= 909 */ + const uint64_t record_magic =3D 0x5; + uint64_t data =3D type | record_magic << 3; + data +=3D depth << 6; + data +=3D pc << 16; + UftraceEntry e =3D {.timestamp =3D timestamp, .data =3D data}; + g_array_append_val(t->t, e); + if (t->t->len * sizeof(UftraceEntry) > 32 * MiB) { + trace_flush(t, true); + } +} + +static void trace_enter_function(Trace *t, uint64_t timestamp, + uint64_t pc, size_t depth) +{ + trace_add_entry(t, timestamp, pc, depth, UFTRACE_ENTRY); +} + +static void trace_exit_function(Trace *t, uint64_t timestamp, + uint64_t pc, size_t depth) +{ + trace_add_entry(t, timestamp, pc, depth, UFTRACE_EXIT); +} + +static void trace_enter_stack(Trace *t, Callstack *cs, uint64_t timestamp) +{ + for (size_t depth =3D 1; depth <=3D callstack_depth(cs); ++depth) { + trace_enter_function(t, timestamp, callstack_at(cs, depth)->pc, de= pth); + } +} + +static void trace_exit_stack(Trace *t, Callstack *cs, uint64_t timestamp) +{ + for (size_t depth =3D callstack_depth(cs); depth > 0; --depth) { + trace_exit_function(t, timestamp, callstack_at(cs, depth)->pc, dep= th); + } +} + static uint64_t cpu_read_register64(Cpu *cpu, struct qemu_plugin_register = *reg) { GByteArray *buf =3D cpu->buf; @@ -223,7 +350,9 @@ static void track_callstack(unsigned int cpu_index, voi= d *udata) { uint64_t pc =3D (uintptr_t) udata; Cpu *cpu =3D qemu_plugin_scoreboard_find(score, cpu_index); + uint64_t timestamp =3D gettime_ns(); Callstack *cs =3D cpu->cs; + Trace *t =3D cpu->trace; =20 uint64_t fp =3D cpu->ops.get_frame_pointer(cpu); if (!fp && callstack_empty(cs)) { @@ -232,6 +361,7 @@ static void track_callstack(unsigned int cpu_index, voi= d *udata) * long as a proper call does not happen. */ callstack_push(cs, (CallstackEntry){.frame_pointer =3D fp, .pc =3D= pc}); + trace_enter_function(t, timestamp, pc, callstack_depth(cs)); return; } =20 @@ -244,7 +374,8 @@ static void track_callstack(unsigned int cpu_index, voi= d *udata) CallstackEntry caller =3D callstack_caller(cs); if (fp =3D=3D caller.frame_pointer) { /* return */ - callstack_pop(cs); + CallstackEntry e =3D callstack_pop(cs); + trace_exit_function(t, timestamp, e.pc, callstack_depth(cs)); return; } =20 @@ -252,12 +383,16 @@ static void track_callstack(unsigned int cpu_index, v= oid *udata) if (caller_fp =3D=3D top.frame_pointer) { /* call */ callstack_push(cs, (CallstackEntry){.frame_pointer =3D fp, .pc =3D= pc}); + trace_enter_function(t, timestamp, pc, callstack_depth(cs)); return; } =20 /* discontinuity, exit current stack and unwind new one */ + trace_exit_stack(t, cs, timestamp); callstack_clear(cs); + cpu_unwind_stack(cpu, fp, pc); + trace_enter_stack(t, cs, timestamp); } =20 static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) @@ -297,6 +432,16 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned in= t vcpu_index) cpu->ops.init(cpu); cpu->buf =3D g_byte_array_new(); =20 + g_assert(vcpu_index < UINT32_MAX / 100); + /* trace_id is: cpu_number * 100 */ + uint32_t trace_id =3D (vcpu_index + 1) * 100; + + g_autoptr(GString) trace_name =3D g_string_new(NULL); + g_string_append_printf(trace_name, "cpu%u", vcpu_index); + cpu->trace =3D trace_new(trace_id, trace_name); + /* create/truncate trace file */ + trace_flush(cpu->trace, false); + cpu->cs =3D callstack_new(); } =20 @@ -305,6 +450,7 @@ static void vcpu_end(unsigned int vcpu_index) Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); g_byte_array_free(cpu->buf, true); =20 + trace_free(cpu->trace); callstack_free(cpu->cs); memset(cpu, 0, sizeof(Cpu)); } @@ -312,6 +458,8 @@ static void vcpu_end(unsigned int vcpu_index) static void at_exit(qemu_plugin_id_t id, void *data) { for (size_t i =3D 0; i < qemu_plugin_num_vcpus(); ++i) { + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, i); + trace_flush(cpu->trace, true); vcpu_end(i); } =20 --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685807; cv=none; d=zohomail.com; s=zohoarc; b=ZFdl9ZkTIhwE37u6atVkmWa5rB9n/7kQ5pXZqRtudT+WG9y69uGmXHfpGYSey+UT4ySqe4KC40ayTFWwc9xCuECYGMTFpbrIRRpZlGqG+5aLeeLMWRmyNsShQf/IuZm+FSS3I3k6Wxwv06lDKI0BlN+5bRGPSbrmYZZigyQWJfw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685807; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=OC+nkp19eW2UdCXP3rejFdZ2iytq7Q0eqZRk2l9Xu90=; b=LudIuoiOPmY2xcsvIVQFfCNL0S+gS469oMHLVdGLCeb30y8PgPp52byUPBnHHm4A6hTlvkdO/StliiJw08eKiVzkSd8CgXt16gSIUN+J5KSbZ+tNoC1ujvbYL39TBvAznHVmNav2UKhoh5j/vs7zTv/QShBP4iZ3Z+Ev/lkKFyE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685807353549.6925235519429; Fri, 8 Aug 2025 13:43:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTus-0002zj-QN; Fri, 08 Aug 2025 16:42:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTup-0002xj-Lj for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:16 -0400 Received: from mail-pl1-x629.google.com ([2607:f8b0:4864:20::629]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTun-0003D6-BW for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:15 -0400 Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-23c8f179e1bso35145535ad.1 for ; Fri, 08 Aug 2025 13:42:12 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685732; x=1755290532; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=OC+nkp19eW2UdCXP3rejFdZ2iytq7Q0eqZRk2l9Xu90=; b=Lfz7BHKjiQ7xgSDgZ4Rs8lM7PkncWRGPJrgUrCLJyn+65Np+T6/65m1ahQWsmtXm1G eMV6rPJIJ0EESX+fe0ywfX8KjtW0kTAzSeiKgC8l6tyKJFiAlma1LhR4t2dbd09cG89Q XD513qSTuDdG8MxTuYfRhyO8JAlU8EdlZaDcVjuI4iElmMXzXh0m4+sz46H8dFLiKFNz BG88DDeZ1ZqvTdItRd2sqete7xKmKF8atsUl0j5o/58N2d7d+4x5CIOGxiUi8QGi23T+ mnyX6zWyxitB4+yaSHwNdMtVdoKO19q+qQKWdX0AeW6XtYu3VpSs+c4tx0m/oppGV1ta u2gA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685732; x=1755290532; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OC+nkp19eW2UdCXP3rejFdZ2iytq7Q0eqZRk2l9Xu90=; b=RRddMHTodvq6lgmlSngsiN+vp8iE6i38dAvEbM6tRSYVI1X/lCTOsLp9Q6LfuoyDrW 2DKS5/9s2IYxiL7ioqqMXPBYWqfRWHNofztPPs8mqZx2zPOUclrJQIDbZpfk37jJQeip 036/UGWIQ8OfB834UxYZUce+P3CyDoQBIxGCDjH6+eOtQ+O+3iXis9Un8XbSqdk6q5M7 3/uWI4gcLc/GhEzrLm4S5RLDP0Yo4jDlA8XxdTwHlqKZOs09c/Vq4uPE3ydo5NOu6rq4 xv3UG73gdlAPda/e/Cd9/tZXkaBIgGOAM16BMwVLBeZm7AZO4NC2sPrISD28fEo9Jnd+ XdFg== X-Gm-Message-State: AOJu0YyvTfC7YYa9LgK3jTj3SRRB5LP9sh5x9PFDOLYUcYVVNgnTpMis i/Wdy27j+hcZFdjuiD8np+JECeyHQF9M5+LHvWuXs/56p8w8PexCRC792ublG3GLQ2thoxRGgIK OjM1OU9EHQQ== X-Gm-Gg: ASbGnctRHAi/IcFf94HcKe439HJmbzeMPBtQlHbtHhw0E3EdDjS+pzdn/3TfYoQe8wz v3Tk4Z05mav0ClaQgIo/Ru5R8HPkydnoLkmr+6rIe8GvlPbBEQTwhi+qUfX1QGKuA7QQPLYhgiL Ld/w7UKL3LMQvALkR3N5ng3lZqyX1URi+IYBo073Dwr14kS5VWJ2WmIS7H6UxBQXe5BzBljJNP1 MvYP0qoIbgvpROs71UjYzMZ68uC7mdcVk3TAcSJe+GUBbZsRc3KoFDjxnnbl1fmxvaunSKQGCe7 4vwsqOjUDG2stTdtqdT0x2vVzabfd/R9rW7uzxDRywTXvCfyRdGGzhmhAITv9mMtK+YY0reQnA7 I8z41HwTJyL0xTXJrWx9beA== X-Google-Smtp-Source: AGHT+IH+rGpbRZWr8M2Dv8iop1vwOjsJXgnlECovkR9Wn+ZY18yjv39nTE5JJSg5IGEn1sYuDs7fqQ== X-Received: by 2002:a17:903:3b87:b0:242:9bbc:c775 with SMTP id d9443c01a7336-242c2295bd6mr51591725ad.56.1754685731695; Fri, 08 Aug 2025 13:42:11 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 5/9] contrib/plugins/uftrace: implement privilege level tracing Date: Fri, 8 Aug 2025 13:41:52 -0700 Message-ID: <20250808204156.659715-6-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::629; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pl1-x629.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685809656116600 Content-Type: text/plain; charset="utf-8" We add new option trace-privilege-level=3Dbool, which will create a separate trace for each privilege level. This allows to follow changes of privilege during execution. We implement aarch64 operations to track current privilege level accordingly. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 190 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 182 insertions(+), 8 deletions(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 830967c215b..fa95341b8b9 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -44,19 +44,40 @@ typedef struct { void (*init)(Cpu *cpu); void (*end)(Cpu *cpu); uint64_t (*get_frame_pointer)(Cpu *cpu); + uint8_t (*get_privilege_level)(Cpu *cpu); + uint8_t (*num_privilege_levels)(void); + const char *(*get_privilege_level_name)(uint8_t pl); bool (*does_insn_modify_frame_pointer)(const char *disas); } CpuOps; =20 typedef struct Cpu { Trace *trace; Callstack *cs; + uint8_t privilege_level; + GArray *traces; /* Trace *traces [] */ GByteArray *buf; CpuOps ops; void *arch; } Cpu; =20 +typedef enum { + AARCH64_EL0_SECURE, + AARCH64_EL0_NONSECURE, + AARCH64_EL0_REALM, + AARCH64_EL1_SECURE, + AARCH64_EL1_NONSECURE, + AARCH64_EL1_REALM, + AARCH64_EL2_SECURE, + AARCH64_EL2_NONSECURE, + AARCH64_EL2_REALM, + AARCH64_EL3, + AARCH64_PRIVILEGE_LEVEL_MAX, +} Aarch64PrivilegeLevel; + typedef struct { struct qemu_plugin_register *reg_fp; + struct qemu_plugin_register *reg_cpsr; + struct qemu_plugin_register *reg_scr_el3; } Aarch64Cpu; =20 typedef struct { @@ -72,6 +93,7 @@ typedef enum { } UftraceRecordType; =20 static struct qemu_plugin_scoreboard *score; +static bool trace_privilege_level; static CpuOps arch_ops; =20 static uint64_t gettime_ns(void) @@ -249,6 +271,16 @@ static uint64_t cpu_read_register64(Cpu *cpu, struct q= emu_plugin_register *reg) return *((uint64_t *) buf->data); } =20 +static uint32_t cpu_read_register32(Cpu *cpu, struct qemu_plugin_register = *reg) +{ + GByteArray *buf =3D cpu->buf; + g_byte_array_set_size(buf, 0); + size_t sz =3D qemu_plugin_read_register(reg, buf); + g_assert(sz =3D=3D 4); + g_assert(buf->len =3D=3D 4); + return *((uint32_t *) buf->data); +} + static uint64_t cpu_read_memory64(Cpu *cpu, uint64_t addr) { g_assert(addr); @@ -306,6 +338,68 @@ static struct qemu_plugin_register *plugin_find_regist= er(const char *name) return NULL; } =20 +static uint8_t aarch64_num_privilege_levels(void) +{ + return AARCH64_PRIVILEGE_LEVEL_MAX; +} + +static const char *aarch64_get_privilege_level_name(uint8_t pl) +{ + switch (pl) { + case AARCH64_EL0_SECURE: return "S-EL0"; + case AARCH64_EL0_NONSECURE: return "NS-EL0"; + case AARCH64_EL0_REALM: return "R-EL0"; + case AARCH64_EL1_SECURE: return "S-EL1"; + case AARCH64_EL1_NONSECURE: return "NS-EL1"; + case AARCH64_EL1_REALM: return "R-EL1"; + case AARCH64_EL2_SECURE: return "S-EL2"; + case AARCH64_EL2_NONSECURE: return "NS-EL2"; + case AARCH64_EL2_REALM: return "R-EL2"; + case AARCH64_EL3: return "EL3"; + default: + g_assert_not_reached(); + } +} + +static uint8_t aarch64_get_privilege_level(Cpu *cpu_) +{ + Aarch64Cpu *cpu =3D cpu_->arch; + /* + * QEMU gdbstub does not provide access to CurrentEL, + * so we use CPSR instead. + */ + uint8_t el =3D cpu_read_register32(cpu_, cpu->reg_cpsr) >> 2 & 0b11; + + if (el =3D=3D 3) { + return AARCH64_EL3; + } + + uint8_t ss =3D AARCH64_EL0_SECURE; + if (!cpu->reg_scr_el3) { + ss =3D AARCH64_EL0_NONSECURE; + } + uint64_t scr_el3 =3D cpu_read_register64(cpu_, cpu->reg_scr_el3); + uint64_t ns =3D (scr_el3 >> 0) & 0b1; + uint64_t nse =3D (scr_el3 >> 62) & 0b1; + switch (nse << 1 | ns) { + case 0b00: + ss =3D AARCH64_EL0_SECURE; + break; + case 0b01: + ss =3D AARCH64_EL0_NONSECURE; + break; + case 0b11: + ss =3D AARCH64_EL0_REALM; + break; + default: + g_assert_not_reached(); + } + + const uint8_t num_ss =3D 3; + Aarch64PrivilegeLevel pl =3D el * num_ss + ss; + return pl; +} + static uint64_t aarch64_get_frame_pointer(Cpu *cpu_) { Aarch64Cpu *cpu =3D cpu_->arch; @@ -322,6 +416,10 @@ static void aarch64_init(Cpu *cpu_) "available. Please use an AArch64 cpu (or -cpu max= ).\n"); g_abort(); } + cpu->reg_cpsr =3D plugin_find_register("cpsr"); + g_assert(cpu->reg_cpsr); + cpu->reg_scr_el3 =3D plugin_find_register("SCR_EL3"); + /* scr_el3 is optional */ } =20 static void aarch64_end(Cpu *cpu) @@ -343,9 +441,34 @@ static CpuOps aarch64_ops =3D { .init =3D aarch64_init, .end =3D aarch64_end, .get_frame_pointer =3D aarch64_get_frame_pointer, + .get_privilege_level =3D aarch64_get_privilege_level, + .num_privilege_levels =3D aarch64_num_privilege_levels, + .get_privilege_level_name =3D aarch64_get_privilege_level_name, .does_insn_modify_frame_pointer =3D aarch64_does_insn_modify_frame_poi= nter, }; =20 +static void track_privilege_change(unsigned int cpu_index, void *udata) +{ + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, cpu_index); + uint8_t new_pl =3D cpu->ops.get_privilege_level(cpu); + + if (new_pl =3D=3D cpu->privilege_level) { + return; + } + + uint64_t pc =3D (uintptr_t) udata; + uint64_t timestamp =3D gettime_ns(); + + trace_exit_stack(cpu->trace, cpu->cs, timestamp); + callstack_clear(cpu->cs); + + cpu->privilege_level =3D new_pl; + cpu->trace =3D g_array_index(cpu->traces, Trace*, new_pl); + + cpu_unwind_stack(cpu, cpu->ops.get_frame_pointer(cpu), pc); + trace_enter_stack(cpu->trace, cpu->cs, timestamp); +} + static void track_callstack(unsigned int cpu_index, void *udata) { uint64_t pc =3D (uintptr_t) udata; @@ -398,6 +521,13 @@ static void track_callstack(unsigned int cpu_index, vo= id *udata) static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { size_t n_insns =3D qemu_plugin_tb_n_insns(tb); + uintptr_t tb_pc =3D qemu_plugin_tb_vaddr(tb); + + if (trace_privilege_level) { + qemu_plugin_register_vcpu_tb_exec_cb(tb, track_privilege_change, + QEMU_PLUGIN_CB_R_REGS, + (void *) tb_pc); + } =20 /* * Callbacks and inline instrumentation are inserted before an instruc= tion. @@ -431,18 +561,36 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned i= nt vcpu_index) =20 cpu->ops.init(cpu); cpu->buf =3D g_byte_array_new(); + cpu->traces =3D g_array_new(0, 0, sizeof(Trace *)); =20 g_assert(vcpu_index < UINT32_MAX / 100); - /* trace_id is: cpu_number * 100 */ + g_assert(cpu->ops.num_privilege_levels() < 100); + /* trace_id is: cpu_number * 100 + privilege_level */ uint32_t trace_id =3D (vcpu_index + 1) * 100; =20 - g_autoptr(GString) trace_name =3D g_string_new(NULL); - g_string_append_printf(trace_name, "cpu%u", vcpu_index); - cpu->trace =3D trace_new(trace_id, trace_name); - /* create/truncate trace file */ - trace_flush(cpu->trace, false); + if (trace_privilege_level) { + for (uint8_t pl =3D 0; pl < cpu->ops.num_privilege_levels(); ++pl)= { + g_autoptr(GString) trace_name =3D g_string_new(NULL); + g_string_append_printf(trace_name, "cpu%u %s", vcpu_index, + cpu->ops.get_privilege_level_name(pl)); + Trace *t =3D trace_new(trace_id + pl, trace_name); + g_array_append_val(cpu->traces, t); + } + } else { + g_autoptr(GString) trace_name =3D g_string_new(NULL); + g_string_append_printf(trace_name, "cpu%u", vcpu_index); + Trace *t =3D trace_new(trace_id, trace_name); + g_array_append_val(cpu->traces, t); + } + + for (size_t i =3D 0; i < cpu->traces->len; ++i) { + /* create/truncate trace files */ + Trace *t =3D g_array_index(cpu->traces, Trace*, i); + trace_flush(t, false); + } =20 cpu->cs =3D callstack_new(); + cpu->trace =3D g_array_index(cpu->traces, Trace*, cpu->privilege_level= ); } =20 static void vcpu_end(unsigned int vcpu_index) @@ -450,7 +598,12 @@ static void vcpu_end(unsigned int vcpu_index) Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); g_byte_array_free(cpu->buf, true); =20 - trace_free(cpu->trace); + for (size_t i =3D 0; i < cpu->traces->len; ++i) { + Trace *t =3D g_array_index(cpu->traces, Trace*, i); + trace_free(t); + } + + g_array_free(cpu->traces, true); callstack_free(cpu->cs); memset(cpu, 0, sizeof(Cpu)); } @@ -459,7 +612,13 @@ static void at_exit(qemu_plugin_id_t id, void *data) { for (size_t i =3D 0; i < qemu_plugin_num_vcpus(); ++i) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, i); - trace_flush(cpu->trace, true); + for (size_t j =3D 0; j < cpu->traces->len; ++j) { + Trace *t =3D g_array_index(cpu->traces, Trace*, j); + trace_flush(t, true); + } + } + + for (size_t i =3D 0; i < qemu_plugin_num_vcpus(); ++i) { vcpu_end(i); } =20 @@ -470,6 +629,21 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin= _id_t id, const qemu_info_t *info, int argc, char **argv) { + for (int i =3D 0; i < argc; i++) { + char *opt =3D argv[i]; + g_auto(GStrv) tokens =3D g_strsplit(opt, "=3D", 2); + if (g_strcmp0(tokens[0], "trace-privilege-level") =3D=3D 0) { + if (!qemu_plugin_bool_parse(tokens[0], tokens[1], + &trace_privilege_level)) { + fprintf(stderr, "boolean argument parsing failed: %s\n", o= pt); + return -1; + } + } else { + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; + } + } + if (!strcmp(info->target_name, "aarch64")) { arch_ops =3D aarch64_ops; } else { --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685795; cv=none; d=zohomail.com; s=zohoarc; b=D8G53IE9rJj8xSvWOLVvWUuErvEfWEpUPCC0cGLTjaRfQFXh29wPVy+fbN7/YTyieznm8kjowtj9nCq6m2HUdnKI5KFee7QIKwe/3uJLQE/sXMpKxw6zb3SsqKrJuZLPJIEuBnp7I1Pk6NToREJXyWdvO5gFzzviXNI1L1gAqCE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685795; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Qof9Qj78VVSEid4N6FOGHfZkZXIU0Ub5qskH0ZkOHjU=; b=T1TG11eusJOz9rp4mYp74hH3Ts2q0EdgQSI5Oj1ONEicbxMhngNT7VFpPwrLnZqXKpvRRlWIKJG6jZsknUUvB/QUD4nBAaZMmHCENUKIkRje7coZQq2JikYyBrars/aj/DLCAovQhukAV01gt2fn0AGJKc4n9kfNN+MKDEF4qtk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685795752478.1038749272815; Fri, 8 Aug 2025 13:43:15 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTus-000308-Uq; Fri, 08 Aug 2025 16:42:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTur-0002yV-4A for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:17 -0400 Received: from mail-pl1-x62e.google.com ([2607:f8b0:4864:20::62e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTuo-0003DO-PB for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:16 -0400 Received: by mail-pl1-x62e.google.com with SMTP id d9443c01a7336-23dc5bcf49eso29792755ad.2 for ; Fri, 08 Aug 2025 13:42:13 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685733; x=1755290533; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Qof9Qj78VVSEid4N6FOGHfZkZXIU0Ub5qskH0ZkOHjU=; b=UrsuynZ2vwS+m1TJa43As9CYaX5v3PD00pkVGT31sXa/LgCpoGFgR07tHcSMuxatAk RJC7ghU/teH2SiKoXx2Arv78asYsawcXoRGcCeh3LjbhMFAZaX6CltTUikFz/Nms65Cl zbkPHOOWwQ1i5d1z6keRMIVV2m3eM2xPFcFZR7+yCUQLcdCoVVnZ+TePmTgTYcl/bfLC Ha1Ua8LKEjd3eupUdT74kjqh1mkPnnm2ij0NKE00rjbeW644wbUDEHrDRwHvHkzvsADu 1mvsS8HN2nrmsghAXw5M79ZUuc+c+CPc7oLDFIO/Ok/EkeEhkZrVBR67rFv3Bpl5Smpe /LpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685733; x=1755290533; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Qof9Qj78VVSEid4N6FOGHfZkZXIU0Ub5qskH0ZkOHjU=; b=CjQJEdLpaxbz0Hn5dVdSw8099wgL/ohbKAdLZkF9VKR3K83geuKDRG6TtVNLMNTkVl wYpYk+zTIfhknUCw5QiwDHSW8wl+cRtBIqDPJT3FXCbRB6uw9BESIFj3V4g9QqiN9QOV BpZ8Dp/qX76kUK5xLNwm6M++BwRhXd9NIOnaeuydHkNxWlRrB8UdIChzzKQX37wDZkSj E1yZiSOBZrLHPK3zs/90zcwdoMzEqhIEg4q2WHvGODHNPqFS4jI8gDUU3Gh0AOM2+G8V CocHe4HaieDn/C7sy9pihYhA092bCrklgC+ICAqYwOF/Pz0+GtinTcYQTe7zKUYATpqO /kiQ== X-Gm-Message-State: AOJu0YzwsjVjiDU7Sid+VtZK8MuST8WNS+uA5oGGP6zjRsrJE0yLl98V LycSWkfsfj6dx5dptCna7v8hZZduSdJIgliS4md5WaeNSs98grHGCrjVmdXn45m0kQG20UlkuyD mrbPfteDkvg== X-Gm-Gg: ASbGncuETAfy1BLvXlZnZ6R4H5EwZXR4beu7gRaFtf+65tsBst8T4Ml7hfxTtnhI70t C7CASGC76eODzyRxDAv5YVbRVOi2us5q3KojPZLhr1SeCLkPiV1D/FivhYKDL8JWpGVi8bpHHYQ 1dxI7APPjqQRBHQlYBYnOtS2CJZEfdE3ieUkeJJsMapS+eQ/zv4NmYMe7x8AtqpUxO0NZzbadeJ ygk+6gfR3egr2xDYxtYuqSM46tTr6TBWUkS54obKqBu7UT1gbTPBfcux780q1U8+TrK6TcTn9JL B14u+v/iOx7VvhyY4Bkra2szn++mJofE5Tr0/AAClFcm96U4r0DBKtZEpF1/ZJfJo5Co92euBj5 zN3+kxpNXYWNoNAwJBi3yNJECEujj7vLH X-Google-Smtp-Source: AGHT+IGKygQORO9yAFr0wkyzD+psRcNYqUfG2u3yqCb36r3HaWeW8WYcW599TRN7Iy0SP/pXu/IPeA== X-Received: by 2002:a17:903:2b06:b0:242:9be2:f67a with SMTP id d9443c01a7336-242c1fdce56mr64910355ad.11.1754685732695; Fri, 08 Aug 2025 13:42:12 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 6/9] contrib/plugins/uftrace: generate additional files for uftrace Date: Fri, 8 Aug 2025 13:41:53 -0700 Message-ID: <20250808204156.659715-7-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::62e; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pl1-x62e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685797511116600 Content-Type: text/plain; charset="utf-8" Beyond traces per cpu, uftrace expect to find some specific files. - info: contains information about machine/program run those values are not impacting uftrace behaviour (only reported by uftrace info), and we simply added empty strings. - memory mapping: how every binary is mapped in memory. For system mode, we generate an empty mapping (uftrace_symbols.py, coming in future commit, will take care of that). For user mode, we copy current /proc/self/maps. We don't need to do any special filtering, as reported addresses will necessarily concern guest program, and not QEMU and its libraries. - task: list of tasks. We present every vcpu/privilege level as a separate process, as it's the best view we can have when generating a (visual) chrome trace. Using threads is less convenient in terms of UI. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 131 +++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index fa95341b8b9..290e40ee390 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -116,6 +116,127 @@ static uint64_t gettime_ns(void) return now_ns; } =20 +static void uftrace_write_map(bool system_emulation) +{ + const char *path =3D "./uftrace.data/sid-0.map"; + + if (system_emulation && access(path, F_OK) =3D=3D 0) { + /* do not erase existing map in system emulation, as a custom one = might + * already have been generated by uftrace_symbols.py */ + return; + } + + FILE *sid_map =3D fopen(path, "w"); + g_assert(sid_map); + + if (system_emulation) { + fprintf(sid_map, + "# map stack on highest address possible, to prevent uftra= ce\n" + "# from considering any kernel address\n"); + fprintf(sid_map, + "ffffffffffff-ffffffffffff rw-p 00000000 00:00 0 [stack]\n"); + } else { + /* in user mode, copy /proc/self/maps instead */ + FILE *self_map =3D fopen("/proc/self/maps", "r"); + g_assert(self_map); + for (;;) { + int c =3D fgetc(self_map); + if (c =3D=3D EOF) { + break; + } + fputc(c, sid_map); + } + fclose(self_map); + } + fclose(sid_map); +} + +static void uftrace_write_task(const GArray *traces) +{ + FILE *task =3D fopen("./uftrace.data/task.txt", "w"); + g_assert(task); + for (int i =3D 0; i < traces->len; ++i) { + Trace *t =3D g_array_index(traces, Trace*, i); + fprintf(task, "SESS timestamp=3D0.0 pid=3D%"PRIu32" sid=3D0 exenam= e=3D\"%s\"\n", + t->id, t->name->str); + fprintf(task, "TASK timestamp=3D0.0 tid=3D%"PRIu32" pid=3D%"PRIu32= "\n", + t->id, t->id); + } + fclose(task); +} + +static void uftrace_write_info(const GArray *traces) +{ + g_autoptr(GString) taskinfo_tids =3D g_string_new("taskinfo:tids=3D"); + for (int i =3D 0; i < traces->len; ++i) { + Trace *t =3D g_array_index(traces, Trace*, i); + const char *delim =3D i > 0 ? "," : ""; + g_string_append_printf(taskinfo_tids, "%s%"PRIu32, delim, t->id); + } + + g_autoptr(GString) taskinfo_nr_tid =3D g_string_new("taskinfo:nr_tid= =3D"); + g_string_append_printf(taskinfo_nr_tid, "%d", traces->len); + + FILE *info =3D fopen("./uftrace.data/info", "w"); + g_assert(info); + /* + * $ uftrace dump --debug + * uftrace file header: magic =3D 4674726163652100 + * uftrace file header: version =3D 4 + * uftrace file header: header size =3D 40 + * uftrace file header: endian =3D 1 (little) + * uftrace file header: class =3D 2 (64 bit) + * uftrace file header: features =3D 0x1263 (PLTHOOK | ... + * uftrace file header: info =3D 0x7bff (EXE_NAME | ... + * <0000000000000000>: 46 74 72 61 63 65 21 00 04 00 00 00 28 00 01 = 02 + * <0000000000000010>: 63 12 00 00 00 00 00 00 ff 7b 00 00 00 00 00 = 00 + * <0000000000000020>: 00 04 00 00 00 00 00 00 + */ + const uint8_t header[] =3D {0x46, 0x74, 0x72, 0x61, 0x63, 0x65, 0x21, = 0x00, + 0x04, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x= 02, + 0x63, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x= 00, + 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x= 00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x= 00}; + size_t wrote =3D fwrite(header, sizeof(header), 1, info); + g_assert(wrote =3D=3D 1); + const char *info_data[] =3D { + "exename:", + "build_id:0000000000000000000000000000000000000000", + "exit_status:", + "cmdline:", + "cpuinfo:lines=3D2", + "cpuinfo:nr_cpus=3D", + "cpuinfo:desc=3D", + "meminfo:", + "osinfo:lines=3D3", + "osinfo:kernel=3D", + "osinfo:hostname=3D", + "osinfo:distro=3D", + "taskinfo:lines=3D2", + taskinfo_nr_tid->str, + taskinfo_tids->str, + "usageinfo:lines=3D6", + "usageinfo:systime=3D", + "usageinfo:usrtime=3D", + "usageinfo:ctxsw=3D", + "usageinfo:maxrss=3D", + "usageinfo:pagefault=3D", + "usageinfo:iops=3D", + "loadinfo:", + "record_date:", + "elapsed_time:", + "pattern_type:regex", + "uftrace_version:", + "utc_offset:", + 0}; + const char **info_data_it =3D info_data; + while (*(info_data_it)) { + fprintf(info, "%s\n", *info_data_it); + ++info_data_it; + } + fclose(info); +} + static Callstack *callstack_new(void) { Callstack *cs =3D g_new0(Callstack, 1); @@ -610,14 +731,22 @@ static void vcpu_end(unsigned int vcpu_index) =20 static void at_exit(qemu_plugin_id_t id, void *data) { + bool system_emulation =3D (bool) data; + g_autoptr(GArray) traces =3D g_array_new(0, 0, sizeof(Trace *)); + for (size_t i =3D 0; i < qemu_plugin_num_vcpus(); ++i) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, i); for (size_t j =3D 0; j < cpu->traces->len; ++j) { Trace *t =3D g_array_index(cpu->traces, Trace*, j); trace_flush(t, true); + g_array_append_val(traces, t); } } =20 + uftrace_write_map(system_emulation); + uftrace_write_info(traces); + uftrace_write_task(traces); + for (size_t i =3D 0; i < qemu_plugin_num_vcpus(); ++i) { vcpu_end(i); } @@ -654,7 +783,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, =20 score =3D qemu_plugin_scoreboard_new(sizeof(Cpu)); qemu_plugin_register_vcpu_init_cb(id, vcpu_init); - qemu_plugin_register_atexit_cb(id, at_exit, NULL); + qemu_plugin_register_atexit_cb(id, at_exit, (void *) info->system_emul= ation); qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); =20 return 0; --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685818; cv=none; d=zohomail.com; s=zohoarc; b=gm6tx86ctHMbdOABUvz4j+KnMsO/AKVipJR54Ep4srcQ3k2WNz2MntxJK1KiazJ+iiqeJgMX5wMc45zUtkXAHR+K2eBPjhxmkWoUSwjqg1G3CmmEDTS4CJpWe9ZYP6zekwd5rcMgQjn7Tr9atU44WNERL563Vd6npp47mnTJvGM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685818; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=2RkF9BIocl4i6I0VbIlztg88We7hPlBDy2e1enRmrPU=; b=Y/0MAKH8PcpIFaGKyK8JiDwuN07TLQBsAb6o+owFVaarklrpAJgbAENvwva3Yh9DBjivDb/wbFvKcvwEHf0N25i5bqTBQ0pvg/N30xQ8YQ/+l/+W1WrX50k3gSt8uQycOV/+1BST0zc7bc+rEjNFpsfKw6yzUSXNrIOky+dcaEE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685818226285.7425975935723; Fri, 8 Aug 2025 13:43:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTut-00030Q-Az; Fri, 08 Aug 2025 16:42:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTur-0002yT-3U for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:17 -0400 Received: from mail-pl1-x633.google.com ([2607:f8b0:4864:20::633]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTup-0003DX-Eh for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:16 -0400 Received: by mail-pl1-x633.google.com with SMTP id d9443c01a7336-23dc5bcf49eso29792865ad.2 for ; Fri, 08 Aug 2025 13:42:14 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685733; x=1755290533; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2RkF9BIocl4i6I0VbIlztg88We7hPlBDy2e1enRmrPU=; b=zk371KLxppmNvygkt/LCVrOWv8CHI4TdkQwVThuUqKJ3nZNtr7b+NvxI0fxTRnPcwQ dcgf2UBbRxV/Ei5jWz6MFeYbn8J8+jjedPU2PLxAAJQf9uQlLbEwdLJ6CpraN0+feZOu x2mwqmwEPBDdsVT23M7alrbfxcmCSk2iHXaGlWe2OVUE3tqvD4vJadK/olFx+2WJ2tXQ pkBEBECZ96mCLHJr5Ue0Nm+e/i8644A2g6pAAga8lgQNr4IrczKPUrZL6GQgd9bRFfio WJvYq64pe8Fheq0tTctU0D/Bejh8U6EBboWqX4Il4+C6zjb2rNUy142P2j2oGLInzbW9 rfMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685733; x=1755290533; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2RkF9BIocl4i6I0VbIlztg88We7hPlBDy2e1enRmrPU=; b=jiq6c4YbwYpRWM/zXy+F/+yFs2QODBIfJZrd3yyRfdpkwkirJ6fFstSgQxN9NCNKG4 u1wBV8KxkXK3UirDiXMru2UF1bUS5I+FmL0GhqyMPjdYBXPjjeobCgOCQUpq7VcUyF3s 8dhsM4+UPNIxA31qSxlFWk5Mhxlcxr8sfbbLF0v3J5dAwrUVLXLV8eepMGQCzu9NjA4d TXHGLGFSj6oeyvCW2IqfOrCjVdShQY5nlboS+hfccvwt+5h+7fcMuH7Zmr8r75wyLKQ/ rDC61/8zic1TgPSgSMjNWeIOpLXyAFJ3WVxBiTr6GYZg8AhocdIPKIrC0HK5viNbnunJ 3+6Q== X-Gm-Message-State: AOJu0YymAOIjH9YauoNAa6FCdU4VNRQwcp5+uT1EWQ706UpM5vR23nlN 3OH8yAV5K0xOUKUOkewYndOUhtSbGxPk8MxdO0lxvrhCn+qWXPV+bAsinsFZjrv69OFKqVUOL7w VNtFGNTnb+Q== X-Gm-Gg: ASbGncuA2NgOsUoGrzg6k3MKzUL0bG7gPhLBxLwxheNmchQRrRQZUP0k7rRhEp3OKxj LXr0Z6zLV4afgqUPtmXxTUS/T526LijPM1kReE5xoXb0OwY9TQakxQDOL7V/dS4WZajcCtSvxGO AJoosNcMTDrmaf+noUtqXQV69kefwMhzIGbCLCGXVfS6TBEMSIS5AcPPg9+DxH4RM6wEDlzPH6p WAm4mY+0b/70ch733YhLCn+cfpL8jxxkvgdTu9CkE9Tddl+WJSmB7HHqBufy2RFO9E3rUvlTyMo Vkhz7zE0DMBQ/lLPOOfXm063+V++NEUH5lbPwIawNuXCL6B1DBgSM9QkwMTSBQ89v9fzk7/OMoi 28iehM3E6HOzifjhQIQtu1Q== X-Google-Smtp-Source: AGHT+IG+iKvLMgriWVJfoaweeLzPkqbcF+SHH6NhT5P3zHGg0PJ1KX3q/3oefabGKzJsyuzVv052ew== X-Received: by 2002:a17:902:da91:b0:234:d292:be7a with SMTP id d9443c01a7336-242c1fdca31mr70883275ad.1.1754685733612; Fri, 08 Aug 2025 13:42:13 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 7/9] contrib/plugins/uftrace: implement x64 support Date: Fri, 8 Aug 2025 13:41:54 -0700 Message-ID: <20250808204156.659715-8-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::633; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pl1-x633.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685821058124100 Content-Type: text/plain; charset="utf-8" It's trivial to implement x64 support, as it's the same stack layout as aarch64. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 290e40ee390..e4b5308e0d7 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -80,6 +80,21 @@ typedef struct { struct qemu_plugin_register *reg_scr_el3; } Aarch64Cpu; =20 +typedef enum { + X64_RING0, + X64_RING1, + X64_RING2, + X64_RING3, + X64_REAL_MODE, + X64_PRIVILEGE_LEVEL_MAX, +} X64PrivilegeLevel; + +typedef struct { + struct qemu_plugin_register *reg_rbp; + struct qemu_plugin_register *reg_cs; + struct qemu_plugin_register *reg_cr0; +} X64Cpu; + typedef struct { uint64_t timestamp; uint64_t data; @@ -568,6 +583,75 @@ static CpuOps aarch64_ops =3D { .does_insn_modify_frame_pointer =3D aarch64_does_insn_modify_frame_poi= nter, }; =20 +static uint8_t x64_num_privilege_levels(void) +{ + return X64_PRIVILEGE_LEVEL_MAX; +} + +static const char *x64_get_privilege_level_name(uint8_t pl) +{ + switch (pl) { + case X64_RING0: return "Ring0"; + case X64_RING1: return "Ring1"; + case X64_RING2: return "Ring2"; + case X64_RING3: return "Ring3"; + case X64_REAL_MODE: return "RealMode"; + default: + g_assert_not_reached(); + } +} + +static uint8_t x64_get_privilege_level(Cpu *cpu_) +{ + X64Cpu *cpu =3D cpu_->arch; + uint64_t cr0 =3D cpu_read_register64(cpu_, cpu->reg_cr0); + uint64_t protected_mode =3D (cr0 >> 0) & 0b1; + if (!protected_mode) { + return X64_REAL_MODE; + } + uint32_t cs =3D cpu_read_register32(cpu_, cpu->reg_cs); + uint32_t ring_level =3D (cs >> 0) & 0b11; + return ring_level; +} + +static uint64_t x64_get_frame_pointer(Cpu *cpu_) +{ + X64Cpu *cpu =3D cpu_->arch; + return cpu_read_register64(cpu_, cpu->reg_rbp); +} + +static void x64_init(Cpu *cpu_) +{ + X64Cpu *cpu =3D g_new0(X64Cpu, 1); + cpu_->arch =3D cpu; + cpu->reg_rbp =3D plugin_find_register("rbp"); + g_assert(cpu->reg_rbp); + cpu->reg_cs =3D plugin_find_register("cs"); + g_assert(cpu->reg_cs); + cpu->reg_cr0 =3D plugin_find_register("cr0"); + g_assert(cpu->reg_cr0); +} + +static void x64_end(Cpu *cpu) +{ + g_free(cpu->arch); +} + +static bool x64_does_insn_modify_frame_pointer(const char *disas) +{ + return strstr(disas, "rbp"); +} + +static CpuOps x64_ops =3D { + .init =3D x64_init, + .end =3D x64_end, + .get_frame_pointer =3D x64_get_frame_pointer, + .get_privilege_level =3D x64_get_privilege_level, + .num_privilege_levels =3D x64_num_privilege_levels, + .get_privilege_level_name =3D x64_get_privilege_level_name, + .does_insn_modify_frame_pointer =3D x64_does_insn_modify_frame_pointer, +}; + static void track_privilege_change(unsigned int cpu_index, void *udata) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, cpu_index); @@ -775,6 +859,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, =20 if (!strcmp(info->target_name, "aarch64")) { arch_ops =3D aarch64_ops; + } else if (!strcmp(info->target_name, "x86_64")) { + arch_ops =3D x64_ops; } else { fprintf(stderr, "plugin uftrace: %s target is not supported\n", info->target_name); --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685827; cv=none; d=zohomail.com; s=zohoarc; b=OnPd8CH7wqXe+GakdlDj2ydUXAROdDaexBHRVmDhowSE4cLVOVfi2dUvaVMOEfb6CW3y8Av1pD1kNgcBd8PhEGQELxIrU8eOpxT1Pd1e+yKTk/ND/u2n9W6vlAmaX6130VR/Lc/ma7XqEOt7f3vUhOqeBTDScPC2HwfUKzQOOjE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685827; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=6LQZIHbBuXid8iCd4uQRcE8cD4Q27Dve1/07zd+zCHI=; b=ZR5VMAvBGeyU/X5g3EZGUfnK17lfjmRsqgKsMBo8697st3wUG+A8vYcUqdkVoEVAf5IuNcZYDgbA2xMbkKch2XojUWQjv43UEaStqknu0Fp94AgzxTHpy1qMCwQFpM54GotO2vS7JFS+ZmZVdJEsnYuorh3o26uAYuM/l8QHAV8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685827970917.8813913635727; Fri, 8 Aug 2025 13:43:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTuy-00033r-NQ; Fri, 08 Aug 2025 16:42:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTuu-000326-Py for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:20 -0400 Received: from mail-pf1-x430.google.com ([2607:f8b0:4864:20::430]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTuq-0003Dr-4a for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:20 -0400 Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-76bd7676e60so2428895b3a.0 for ; Fri, 08 Aug 2025 13:42:15 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685734; x=1755290534; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6LQZIHbBuXid8iCd4uQRcE8cD4Q27Dve1/07zd+zCHI=; b=t4co8GGigj1mZbr7FcUbP4Zf0D+ObOygB8EUz2Y2K4jmDbQwL6M8abCCEHfh3Mw+Gk 2aFYAR0Nb9YD4b82w5fzIdHh6VgRBnq0bJA7IdZTqkLBcegM1nFKC882XrUaWsHBSNhj iEDWanocTx/+MTcaSAeVCKUbsAF4l9KL82s+uwvx1i0BZSUgYT27g7c4+eomANIFOiWT AMcBkVSOqKqctVMEIrN1+FKuboSrfdMKsU6kGW1GOKk7utt19RpnQvEw+F/r9sqwB11W eMZsEXWEPYKZfJ+6YiN9ZRnrzS2bKI/tpEtxSF8zqxjATVFC2BUQDkYWypMiubchSLn2 WAtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685734; x=1755290534; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6LQZIHbBuXid8iCd4uQRcE8cD4Q27Dve1/07zd+zCHI=; b=OlmFEOjfu1HTnk5w2EE5dJ5Vhry9vDZfCcjjkgbX1rXVCJuRxCIphJdy1d4KorpQjJ tV9K0JLjzaqJzfg+dL/2cVAKZpAG8Z+T2Axj0ZwsQb/Ks9rs8pedWPdZOJxar9LmHgEa 2JIipT1nJpcqPIpU5+EIGDZP9gCnE6djmEmSI7+SiKGyftLH/3gPJ7J/lR63XpZRgw1z 4ZmNc/SsXPmB4zJOufFeOOpUKscidWp8JLZkkJHigJoluJebXJHiDKWCutKubQyiF2AP WlBK0M4sNAyrn3nMtmiGsZ6yQuTvVyzwJiNTGzFq6cQZttN1xn7FBrFKOyoEfvuh5UmL NOuQ== X-Gm-Message-State: AOJu0Yx9QwCKu8gxDeugvwRssJ0HdvJN0wLWHLUnGTIrJbyid1GQXi+V mJY1CK3ycBy3wDWhY8BORQmFI3W3ntVsx4f8V5GyVd7IuNvHeApYqsnuhL5FuFfikv1udXm1E7w DS0lMht8xKA== X-Gm-Gg: ASbGncsfHbG3rCQEdzdT719conA+l04RcNTsvDGPPQgm1L+00EVd6INPk9bn9+eulF8 ZJ47MLCJoikf97kYU8wl6RH7Z6oytR4JvmRwCCa8pEvTs0qHhncY2JVXi0VFtmaDjtGHqMinv7Z i/20ZRvwX2uXX8ONCbkpAHZnIaiOdNIFUr4qhahIqNANx9Qi+GfJqlFWy+zGuXw8jSCNiNejo9V 5MWSI8W/jzGuobvl3exI5ttHUf5JA4qFVAAd6POJy7bhGCt5xuiq6zyqv3udP3wGVSzFs/EtLgf LZXMV/VO6mAd580n4bgXLwkGxmZwVMVSXTHvj8ID7dM1F7B3TeyjMAL85lRa+v6LC9vFKDq4ioH E/TUGSkMcynSosBq6FslZDw== X-Google-Smtp-Source: AGHT+IHj6gwY2zo5ICmEogzVhAcOZtBl77ez8wE5acGDQDJ3IDg7J1C4YGyEz873EiTzbkwHXbZdhg== X-Received: by 2002:a17:902:e890:b0:242:a3fc:5917 with SMTP id d9443c01a7336-242c1ffb633mr76719945ad.2.1754685734574; Fri, 08 Aug 2025 13:42:14 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 8/9] contrib/plugins/uftrace_symbols.py Date: Fri, 8 Aug 2025 13:41:55 -0700 Message-ID: <20250808204156.659715-9-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::430; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x430.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685831264124100 Content-Type: text/plain; charset="utf-8" usage: contrib/plugins/uftrace_symbols.py \ --prefix-symbols \ arm-trusted-firmware/build/qemu/debug/bl1/bl1.elf \ arm-trusted-firmware/build/qemu/debug/bl2/bl2.elf \ arm-trusted-firmware/build/qemu/debug/bl31/bl31.elf \ u-boot/u-boot:0x60000000 \ u-boot/u-boot.relocated:0x000000023f6b6000 \ linux/vmlinux Will generate symbols and memory mapping files for uftrace, allowing to have an enhanced trace, instead of raw addresses. It takes a collection of elf files, and automatically find all their symbols, and generate an ordered memory map based on that. This script uses the python (native) pyelftools module. Signed-off-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- contrib/plugins/uftrace_symbols.py | 152 +++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100755 contrib/plugins/uftrace_symbols.py diff --git a/contrib/plugins/uftrace_symbols.py b/contrib/plugins/uftrace_s= ymbols.py new file mode 100755 index 00000000000..b49e03203c8 --- /dev/null +++ b/contrib/plugins/uftrace_symbols.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Create symbols and mapping files for uftrace. +# +# Copyright 2025 Linaro Ltd +# Author: Pierrick Bouvier +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import argparse +import elftools # pip install pyelftools +import os + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + +def elf_func_symbols(elf): + symbol_tables =3D [(idx, s) for idx, s in enumerate(elf.iter_sections(= )) + if isinstance(s, SymbolTableSection)] + symbols =3D [] + for _, section in symbol_tables: + for _, symbol in enumerate(section.iter_symbols()): + if symbol_size(symbol) =3D=3D 0: + continue + type =3D symbol['st_info']['type'] + if type =3D=3D 'STT_FUNC' or type =3D=3D 'STT_NOTYPE': + symbols.append(symbol) + symbols.sort(key =3D lambda x: symbol_addr(x)) + return symbols + +def symbol_size(symbol): + return symbol['st_size'] + +def symbol_addr(symbol): + addr =3D symbol['st_value'] + # clamp addr to 48 bits, like uftrace entries + return addr & 0xffffffffffff + +def symbol_name(symbol): + return symbol.name + +class BinaryFile: + def __init__(self, path, map_offset): + self.fullpath =3D os.path.realpath(path) + self.map_offset =3D map_offset + with open(path, 'rb') as f: + self.elf =3D ELFFile(f) + self.symbols =3D elf_func_symbols(self.elf) + + def path(self): + return self.fullpath + + def addr_start(self): + return self.map_offset + + def addr_end(self): + last_sym =3D self.symbols[-1] + return symbol_addr(last_sym) + symbol_size(last_sym) + self.map_of= fset + + def generate_symbol_file(self, prefix_symbols): + binary_name =3D os.path.basename(self.fullpath) + sym_file_path =3D f'./uftrace.data/{binary_name}.sym' + print(f'{sym_file_path} ({len(self.symbols)} symbols)') + with open(sym_file_path, 'w') as sym_file: + # print hexadecimal addresses on 48 bits + addrx =3D "0>12x" + for s in self.symbols: + addr =3D symbol_addr(s) + addr =3D f'{addr:{addrx}}' + size =3D f'{symbol_size(s):{addrx}}' + name =3D symbol_name(s) + if prefix_symbols: + name =3D f'{binary_name}:{name}' + print(addr, size, 'T', name, file=3Dsym_file) + +def parse_parameter(p): + s =3D p.split(":") + path =3D s[0] + if len(s) =3D=3D 1: + return path, 0 + if len(s) > 2: + raise ValueError('only one offset can be set') + offset =3D s[1] + if not offset.startswith('0x'): + err =3D f'offset "{offset}" is not an hexadecimal constant. ' + err +=3D 'It should starts with "0x".' + raise ValueError(err) + offset =3D int(offset, 16) + return path, offset + +def is_from_user_mode(map_file_path): + if os.path.exists(map_file_path): + with open(map_file_path, 'r') as map_file: + if not map_file.readline().startswith('# map stack on'): + return True + return False + +def generate_map(binaries): + map_file_path =3D './uftrace.data/sid-0.map' + + if is_from_user_mode(map_file_path): + print(f'do not overwrite {map_file_path} generated from qemu-user') + return + + mappings =3D [] + + # print hexadecimal addresses on 48 bits + addrx =3D "0>12x" + + mappings +=3D ['# map stack on highest address possible, to prevent uf= trace'] + mappings +=3D ['# from considering any kernel address'] + mappings +=3D ['ffffffffffff-ffffffffffff rw-p 00000000 00:00 0 [stack= ]'] + + for b in binaries: + m =3D f'{b.addr_start():{addrx}}-{b.addr_end():{addrx}}' + m +=3D f' r--p 00000000 00:00 0 {b.path()}' + mappings.append(m) + + with open(map_file_path, 'w') as map_file: + print('\n'.join(mappings), file=3Dmap_file) + print(f'{map_file_path}') + print('\n'.join(mappings)) + +def main(): + parser =3D argparse.ArgumentParser(description=3D + 'generate symbol files for uftrace') + parser.add_argument('elf_file', nargs=3D'+', + help=3D'path to an ELF file. ' + 'Use /path/to/file:0xdeadbeef to add a mapping off= set.') + parser.add_argument('--prefix-symbols', + help=3D'prepend binary name to symbols', + action=3Dargparse.BooleanOptionalAction) + args =3D parser.parse_args() + + if not os.path.exists('./uftrace.data'): + os.mkdir('./uftrace.data') + + binaries =3D [] + for file in args.elf_file: + path, offset =3D parse_parameter(file) + b =3D BinaryFile(path, offset) + binaries.append(b) + binaries.sort(key =3D lambda b: b.addr_end()); + + for b in binaries: + b.generate_symbol_file(args.prefix_symbols) + + generate_map(binaries) + +if __name__ =3D=3D '__main__': + main() --=20 2.47.2 From nobody Sun Dec 14 02:14:14 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1754685777; cv=none; d=zohomail.com; s=zohoarc; b=HRflK69LeuG4gudJLD9UWwxuFLK1tqx26mLmK8TJC1fQUgQWn0auiDWtj3sKsENVJ8GQLVQZHvDBHBaX0r2VAdisX2QHoxw5jxgK3UleA3gNzb98/NHJNkL8QWpZCWyWj6mynGJAqSUyUiJmCkJVQBNyOWjbEfJVbGenaomPHrs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754685777; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=DBrgRzoZK/flg18sYa71Nd0Qxl3OyImP8+lDbDt1BL8=; b=ZmNF+rEWydNr+IrVekrz/0ThLAUwngL4Cy6AGhWu3TzxUXL/uZXCQaAQo8KHLSwZ4UDLr/+Iqtm08heGGnPlmQOLEnm7Y9I2V0XnmU9oK6dh2RW57ZVBf6jp+07n+9SKhTRL/tGjRE5jjPZ/MlRc0YS+WqT5bH84ek0QIBTaaFQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754685777497989.7141790947477; Fri, 8 Aug 2025 13:42:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukTuw-00032p-Bh; Fri, 08 Aug 2025 16:42:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ukTut-00030X-Jt for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:19 -0400 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukTur-0003E2-4K for qemu-devel@nongnu.org; Fri, 08 Aug 2025 16:42:19 -0400 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-74264d1832eso3127097b3a.0 for ; Fri, 08 Aug 2025 13:42:16 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-241e899a814sm217789945ad.117.2025.08.08.13.42.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Aug 2025 13:42:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754685735; x=1755290535; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DBrgRzoZK/flg18sYa71Nd0Qxl3OyImP8+lDbDt1BL8=; b=KMLc3gXhpRxfE27Vri4Rj/kcpN/dfj9H7nPkc7ag7iHhm5DJ1NO0QfS3qQUaeIHWEG bVXh0ORqxEQt4UC1hP7ATWnKhJWTna2gObkxQOtGJJ+HYOaDKcwCBfaw7lBorDwMSs6M yuSo+aAv9wdrHe+QfboKnTVgqR/0Yv7Dl258hrG2w+VGhlBEAhcNzJUPTrJjPH7Uqhwy RSZULyXS83SuaUjPFW1AuXLoh9ra1X8w/Fu1UBpQxqgWJTQsJVqsA0z9P4DVPrTKKdY5 2tNyJrr3COxFzbkGp42nGW1eJIi5BlrQl956IywSbdXZERZKbogEMlO3PI+KNfwRaFvs +TmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754685735; x=1755290535; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DBrgRzoZK/flg18sYa71Nd0Qxl3OyImP8+lDbDt1BL8=; b=Vn+CY5LNVATNZgnjyzNMQA2Fo7E0Y7w5XkTW0DJMEbkT4ZDut8xDCAobsWIumErXfp sVVeCLfV9A+mIK2o9I3eiDmyMzoQwF9llXBMZwvLvpoBtCUztEQC6p6kzKg8faqAyGpq gu+nK4jE6arSe59tJGPNnaTY1zk0xzp0xLZ+1v29F+rc9WZ+ASKkN2VOupTX20EYGlYw f7fgNVAbqC4Fc6Jv5ZbJ+EUg6ymMNSvsUvseza48oAJYUxcDIfs7tfh91MptjTtJ+neP J3mjbta8JtdoJokkP9aiGSda3bhBjoOVqjAnh/Wds98k4KElTuohu3iIrf70AK6R/70O SfcQ== X-Gm-Message-State: AOJu0YxfXDceo+pkB8XiaVYdSaPXN2R+DlbxqVfz6/DosY6q7hvdFBV3 GxSwGBlhtGapUrjOjcMkRuaJy/kiAk92dWHKE7kxwIM18hZnRBAN36Sqjy1gJGtItSpw9ioLpN/ OjJIXUPIDrg== X-Gm-Gg: ASbGncvzW1gsD5/vgSOe1c//VdKnDtoXpJRnonKiDxzj/4o6wbFAzHhhWIP9j1MWeJj 2QEjVFQD8vWCD/0kUZ0N2pU/4nVa8/0SHSLWLLNqMJf8w4Pb3gSzlGNoKkNgjtBDj/ndfghepoj CgdG6WcoFrdplucCNfS+0hlZuwk0BdW/8WvNSrY19kaFWUTGZgUaHzn8UUSYNCuIVlixweOxx7v e/ybJqUwOS/Gy7a61gMmZPdvTXRumNXF6mo9DuuN13m1B5V3M3sDeVLqGomc0UWTg+LbswxVIO2 /JNAWvBpJ0fGNLvayoJX3PClmb5/WHCBH8iPLj47ekBlfft+BsUABDsDW2EJWLAv1xqNdrI4Odx D+4EAorGhpqq8/H1dNiVNwYS6F8mGUiob X-Google-Smtp-Source: AGHT+IF7UcVgLxvOp9+Ku41zFxfGi/9ehGrc/hJoGFDp15lJcH/HVvIHagevNXWPh+26SeCTJ4d+ng== X-Received: by 2002:a17:902:fc48:b0:242:b103:18e with SMTP id d9443c01a7336-242c226035amr64644015ad.50.1754685735474; Fri, 08 Aug 2025 13:42:15 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org, pierrick.bouvier@linaro.org Cc: Manos Pitsidianakis , Peter Maydell , rowan Hart , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Gustavo Romero , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Richard Henderson Subject: [PATCH v6 9/9] contrib/plugins/uftrace: add documentation Date: Fri, 8 Aug 2025 13:41:56 -0700 Message-ID: <20250808204156.659715-10-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808204156.659715-1-pierrick.bouvier@linaro.org> References: <20250808204156.659715-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::429; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x429.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1754685779807116600 Content-Type: text/plain; charset="utf-8" This documentation summarizes how to use the plugin, and present two examples of the possibilities offered by it, in system and user mode. As well, it explains how to rebuild and reproduce those examples. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- docs/about/emulation.rst | 199 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/docs/about/emulation.rst b/docs/about/emulation.rst index 456d01d5b08..8a5e128f677 100644 --- a/docs/about/emulation.rst +++ b/docs/about/emulation.rst @@ -816,6 +816,205 @@ This plugin can limit the number of Instructions Per = Second that are executed:: The lower the number the more accurate time will be, but the less ef= ficient the plugin. Defaults to ips/10 =20 +Uftrace +....... + +``contrib/plugins/uftrace.c`` + +This plugin generates a binary trace compatible with +`uftrace `_. + +Plugin supports aarch64 and x64, and works in user and system mode, allowi= ng to +trace a system boot, which is not something possible usually. + +In user mode, the memory mapping is directly copied from ``/proc/self/maps= `` at +the end of execution. Uftrace should be able to retrieve symbols by itself, +without any additional step. +In system mode, the default memory mapping is empty, and you can generate +one (and associated symbols) using ``contrib/plugins/uftrace_symbols.py``. +Symbols must be present in ELF binaries. + +It tracks the call stack (based on frame pointer analysis). Thus, your pro= gram +and its dependencies must be compiled using ``-fno-omit-frame-pointer +-mno-omit-leaf-frame-pointer``. In 2024, `Ubuntu and Fedora enabled it by +default again on x64 +`_. +On aarch64, this is less of a problem, as they are usually part of the ABI, +except for leaf functions. That's true for user space applications, but not +necessarily for bare metal code. You can read this `section +` to easily build a system with frame pointe= rs. + +When tracing long scenarios (> 1 min), the generated trace can become very= long, +making it hard to extract data from it. In this case, a simple solution is= to +trace execution while generating a timestamped output log using +``qemu-system-aarch64 ... | ts "%s"``. Then, ``uftrace --time-range=3Dstar= t~end`` +can be used to reduce trace for only this part of execution. + +Performance wise, overhead compared to normal tcg execution is around x5-x= 15. + +.. list-table:: Uftrace plugin arguments + :widths: 20 80 + :header-rows: 1 + + * - Option + - Description + * - trace-privilege-level=3D[on|off] + - Generate separate traces for each privilege level (Exception Level + + Security State on aarch64, Rings on x64). + +.. list-table:: uftrace_symbols.py arguments + :widths: 20 80 + :header-rows: 1 + + * - Option + - Description + * - elf_file [elf_file ...] + - path to an ELF file. Use /path/to/file:0xdeadbeef to add a mapping o= ffset. + * - --prefix-symbols + - prepend binary name to symbols + +Example user trace +++++++++++++++++++ + +As an example, we can trace qemu itself running git:: + + $ ./build/qemu-aarch64 -plugin \ + build/contrib/plugins/libuftrace.so \ + ./build/qemu-aarch64 /usr/bin/git --help + + # and generate a chrome trace directly + $ uftrace dump --chrome | gzip > ~/qemu_aarch64_git_help.json.gz + +For convenience, you can download this trace `qemu_aarch64_git_help.json.gz +`_. +Download it and open this trace on https://ui.perfetto.dev/. You can zoom = in/out +using :kbd:`W`, :kbd:`A`, :kbd:`S`, :kbd:`D` keys. +Some sequences taken from this trace: + +- Loading program and its interpreter + +.. image:: https://fileserver.linaro.org/s/fie8JgX76yyL5cq/preview + :height: 200px + +- open syscall + +.. image:: https://fileserver.linaro.org/s/rsXPTeZZPza4PcE/preview + :height: 200px + +- TB creation + +.. image:: https://fileserver.linaro.org/s/GXY6NKMw5EeRCew/preview + :height: 200px + +It's usually better to use ``uftrace record`` directly. However, tracing +binaries through qemu-user can be convenient when you don't want to recomp= ile +them (``uftrace record`` requires instrumentation), as long as symbols are +present. + +Example system trace +++++++++++++++++++++ + +A full trace example (chrome trace, from instructions below) generated fro= m a +system boot can be found `here +`_. +Download it and open this trace on https://ui.perfetto.dev/. You can see c= ode +executed for all privilege levels, and zoom in/out using +:kbd:`W`, :kbd:`A`, :kbd:`S`, :kbd:`D` keys. You can find below some seque= nces +taken from this trace: + +- Two first stages of boot sequence in Arm Trusted Firmware (EL3 and S-EL1) + +.. image:: https://fileserver.linaro.org/s/kkxBS552W7nYESX/preview + :height: 200px + +- U-boot initialization (until code relocation, after which we can't track= it) + +.. image:: https://fileserver.linaro.org/s/LKTgsXNZFi5GFNC/preview + :height: 200px + +- Stat and open syscalls in kernel + +.. image:: https://fileserver.linaro.org/s/dXe4MfraKg2F476/preview + :height: 200px + +- Timer interrupt + +.. image:: https://fileserver.linaro.org/s/TM5yobYzJtP7P3C/preview + :height: 200px + +- Poweroff sequence (from kernel back to firmware, NS-EL2 to EL3) + +.. image:: https://fileserver.linaro.org/s/oR2PtyGKJrqnfRf/preview + :height: 200px + +Build and run system example +++++++++++++++++++++++++++++ + +.. _uftrace_build_system_example: + +Building a full system image with frame pointers is not trivial. + +We provide a `simple way `= _ to +build an aarch64 system, combining Arm Trusted firmware, U-boot, Linux ker= nel +and debian userland. It's based on containers (``podman`` only) and +``qemu-user-static (binfmt)`` to make sure it's easily reproducible and do= es not depend +on machine where you build it. + +You can follow the exact same instructions for a x64 system, combining edk= 2, +Linux, and Ubuntu, simply by switching to +`x86_64 `_ bra= nch. + +To build the system:: + + # Install dependencies + $ sudo apt install -y podman qemu-user-static + + $ git clone https://github.com/pbo-linaro/qemu-linux-stack + $ cd qemu-linux-stack + $ ./build.sh + + # system can be started using: + $ ./run.sh /path/to/qemu-system-aarch64 + +To generate a uftrace for a system boot from that:: + + # run true and poweroff the system + $ env INIT=3Dtrue ./run.sh path/to/qemu-system-aarch64 \ + -plugin path/to/contrib/plugins/libuftrace.so,trace-privilege-level= =3Don + + # generate symbols and memory mapping + $ path/to/contrib/plugins/uftrace_symbols.py \ + --prefix-symbols \ + arm-trusted-firmware/build/qemu/debug/bl1/bl1.elf \ + arm-trusted-firmware/build/qemu/debug/bl2/bl2.elf \ + arm-trusted-firmware/build/qemu/debug/bl31/bl31.elf \ + u-boot/u-boot:0x60000000 \ + linux/vmlinux + + # inspect trace with + $ uftrace replay + +Uftrace allows to filter the trace, and dump flamegraphs, or a chrome trac= e. +This last one is very interesting to see visually the boot process:: + + $ uftrace dump --chrome > boot.json + # Open your browser, and load boot.json on https://ui.perfetto.dev/. + +Long visual chrome traces can't be easily opened, thus, it might be +interesting to generate them around a particular point of execution:: + + # execute qemu and timestamp output log + $ env INIT=3Dtrue ./run.sh path/to/qemu-system-aarch64 \ + -plugin path/to/contrib/plugins/libuftrace.so,trace-privilege-level= =3Don |& + ts "%s" | tee exec.log + + $ cat exec.log | grep 'Run /init' + 1753122320 [ 11.834391] Run /init as init process + # init was launched at 1753122320 + + # generate trace around init execution (2 seconds): + $ uftrace dump --chrome --time-range=3D1753122320~1753122322 > init.js= on + Other emulation features ------------------------ =20 --=20 2.47.2