From nobody Sun Dec 14 20:30:53 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=1754618938; cv=none; d=zohomail.com; s=zohoarc; b=fGIMjUXKhVv/Y8My7+lfdt6U00XJSyFl/IBLdSGKOgPVdn/dA2aDvRbmeJWrq6poBpejD8/sgn+MBMGR6PF9RlxFz96CneExe3/UrjHwMMwws+sD/FVWrNvzUzKa1mZyB4d/Jf1eL0Vft3EecsFdqov3nUtXNN+v6IbECDnKmRA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754618938; 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=+bVGAocy/p30cRQnSJIEIdT0YYjPWtKW5vU1A6Z7uqE=; b=J5tFcifSY8W5vAXhGgRj179CeWpizr/IT+EGqsSv+dTp/1vtreQcDQbW17MIMSiINdp9GhBTeEp+2aK14Z71xlT5mOPXd8Itbyez30Cc94652i2SJRPCDsxDzDTFhlM6SCOjw915xENb9uledxg/Pw8GKtVsZSxf3fBqRp/ROe8= 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 1754618938430870.0532317457153; Thu, 7 Aug 2025 19:08:58 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCVz-0008Ie-Gb; Thu, 07 Aug 2025 22:07:27 -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 1ukCVr-00087U-8T for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:21 -0400 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukCVl-0003Tq-3I for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:16 -0400 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-76bfd457607so1856124b3a.0 for ; Thu, 07 Aug 2025 19:07:10 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618830; x=1755223630; 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=+bVGAocy/p30cRQnSJIEIdT0YYjPWtKW5vU1A6Z7uqE=; b=omhLPQc9EqfPjm5RzTkoNa5NQFSV2XzQbihRG6bWXxWstRRCM8pfBEzRmHxP3Pb8Vp uhHBKJt3vO1cPkYpMnkK851nrGwen6LaYMT6mn+4fY4Q5b2z0A1rTRdioU8dOqkn4ymm JglkqDuwb+r7zfywESq9MHXWhvys09eg0BwHMVUcM1am4GdR2/2Z4S47Q4vPOfcCiOcq hW8ynFOFJV5Wz60WOCbNhQNm6EI7nFseoI+DFiEiL+awunAYMwBDq2P7CsyQuAAUAJ5k b/Mn5AGmoSd6uFwHd921gpNwgRqmXf1C2+IQJ9AXyKXFgq/8W3UJF4FcVMsCwwNS9t5r iPxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618830; x=1755223630; 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=+bVGAocy/p30cRQnSJIEIdT0YYjPWtKW5vU1A6Z7uqE=; b=Zd1CIxvq78gk8n15VHNuCSE07i7zDlDJlpAUK5v4iJbPf9P5XkuZ6EjRRFPP5bOS0N hEcBH5/9wz1Jp5C409skk4LpVSgaUX/mTudDuJzodqeN55k9QaBmSppKXYRRPPceq4RW lKaf7j2TbQ9c6xMscaGuNc5LXfbwFokbalBQd7Tp9zDd38Yjo1cLcd+5dXm6yC3hxoIw VIGsa621CY/mSo3bcY2dShId17WC0WR6NsNmmuvI886gO7pJMi4EEzStq/V7xZHTHvTf nUHoV3Yq7mDy9jKqH9jRDKS/FaWDT/DKJcs63Y0J7FlmNY9nCtWsnFCcTKKrnGAULdhL 4IBw== X-Forwarded-Encrypted: i=1; AJvYcCX6ELKsAEGya4J28YLYCNcxbBLwde9wWv/xuL3RByy+eLMrVXxnLDuYvZY6wL3Vx1eaxlWFYP6ZSKEx@nongnu.org X-Gm-Message-State: AOJu0YxFn6iFX+fYWgNxFdgfTcU6YzAFepJCfmH2LTZAeRfwHa+hVsFF suGomU3fV3F0S4G/pqQZp2kqD0T0Djm76CeOwE1viw8GbgsL6aQjC+e/Os69MTlnoTc= X-Gm-Gg: ASbGncucBS1V/bNG3aVeJq5zz1mmz7Uj/31/RB87Zd4DnQKVphZ20M9xrPG9LTa8ge6 DTU/y17sMdeTZxtHyBTjTZdS8+q3+9aqwUDO0fILo7gBIiChtDoStgwnlshgfbUznlmB6qd00Hy FxMt1Bh7MblhhouBAdDH2cMVXLZ0SjDrCxuGwm2BIlgdBeXm4UpF47xOeMb7wZHBd7xVs7gfZ06 fwBWyxUnuBVjKxY0YqFFcfFf8AXWCCEu7tmg8DLwu9lLqzinvGH0Bfzce9IH7lC+noaQD0IvYD8 OyJYXm4CBSDDTdUxvF2VLNyU7b6CTEVzAr2NOK6kyDO4giYE8mBHLRhQZ4CIrrSh1liv2BQ2IyA VNoAh/LbXdqyftq0YYozq16Uhupi+i0nD X-Google-Smtp-Source: AGHT+IH3Be9dZzteoUcJfUbVf8jV8IrOozBi+ocNCD/eIP27gXSCLuyIzmuTXFg1JoYVlDQ+vt7Llg== X-Received: by 2002:a05:6a21:6d96:b0:23f:52dd:2d13 with SMTP id adf61e73a8af0-240551f8755mr1785483637.39.1754618829825; Thu, 07 Aug 2025 19:07:09 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 1/9] contrib/plugins/uftrace: skeleton file Date: Thu, 7 Aug 2025 19:06:54 -0700 Message-ID: <20250808020702.410109-2-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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::42b; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x42b.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: 1754618969972124100 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. Signed-off-by: Pierrick Bouvier Reviewed-by: Manos Pitsidianakis --- contrib/plugins/uftrace.c | 74 +++++++++++++++++++++++++++++++++++++ contrib/plugins/meson.build | 3 +- 2 files changed, 76 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..d60c1077496 --- /dev/null +++ b/contrib/plugins/uftrace.c @@ -0,0 +1,74 @@ +/* + * 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 (int 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 20:30:53 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=1754618996; cv=none; d=zohomail.com; s=zohoarc; b=NP1a2eXTftZE9+QGqDAUjRT/mO98Sflpf0s2v1j4IxEvYszQsoOqXRnhGhHl3ErjejRLbkxQ6AeXCCQR9/e6ghz2vncKrre4fOhGPvT5uipui355WTU7CZ5Nyo29TKUddewQTOYvYeFCaIDSnlm9WhFgr3P3cI227EXlUJ6rMvw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754618996; 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=Mz5cEembi0r5EM31bY2UE3YFcscP1MIRJopPm7hW/tY=; b=nkmYRragXFjNgjLGRTncFnUHVKHf3bLudPEBEYBDXGYD3kIOumVmYCYHbaLf0YSEH+kALrtERo3FKGPt9OExy+GWlwzBXG10jstQPhSW8vITpNPF8MqIhhOitxjDzC28UrQ7NEK1kh3qUx+vO2kgabWMkR5I9RuJUTgfNresAl0= 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 1754618996165757.3712377373756; Thu, 7 Aug 2025 19:09:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCVx-0008Cn-0L; Thu, 07 Aug 2025 22:07:25 -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 1ukCVs-00087T-8k for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:21 -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 1ukCVl-0003Tx-7A for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:15 -0400 Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-76aea119891so2788010b3a.1 for ; Thu, 07 Aug 2025 19:07:11 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618831; x=1755223631; 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=Mz5cEembi0r5EM31bY2UE3YFcscP1MIRJopPm7hW/tY=; b=xNlcI4D5m6aARLMGVf2FD7ut12ItKahUgqOwtNGek7/E0NGpNKRhRJAOmrqVFuztft XfVRcU2OUuHbIbpsga7QRrKi6llJJ8waqjM7ptE3KkxUvFLMZqZ7XMnPWE1uJchxFxne ezILOIq559y3dIxbQkE7j+kgedipEtg7kA+RWrRpy+kDosLr0CcbpLZNf8nv07R6zEd1 TKqBzwsUYPXCyw9LC1hRpA1QPqCCDpsSYmCGHkhtZs66o0UedBEYUkZfHgMJGMRiFNkg wvhEyzlLguA78NQ/6j/XC+a5B7a3LN8hkmgfPj30pFKvgbIDsdBzAs5Vgj30Uy70lHp6 7UUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618831; x=1755223631; 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=Mz5cEembi0r5EM31bY2UE3YFcscP1MIRJopPm7hW/tY=; b=B6IQ6jbjuMoysAs/hT6GbQZYYQX538SoD3XwhBMQZLWzY/r1OoIb3TXoSWnrLWFbyd pb1pPqHx8DAYj6uoPdyAdXi5T1BQQuC0A4xdH7q5crTTrhAMytYE1SNX101FlBA264gc pPWPSm2bkG0+6UEvHXA74kd0PVX1ZzssyaZtMQ1rnFQ7dYXXCXXZ2ENE1c1bLNGCAeUz T8dBST2qOr9Lxta/vSPtluxDY4A23UpaTH4RLOln+MXMwOUjGRdtDhh8QmSZOgiUX8cs SqDuVOsOi4TM6NrJl0wFxvz3GLS7cD1kBlYMNSMDmd1s/K/NP76iZyqwEbWFN2sKNxN+ QC4Q== X-Forwarded-Encrypted: i=1; AJvYcCW7kOYD2MroePLxu7Nvp3sHb7d3rEix6aCI/bqsisYne2k4HUoxdsOvvWHeaZbhjwM3vJjbLdZVJS29@nongnu.org X-Gm-Message-State: AOJu0YwD9j9Ci2rrC/uRJly8fHUFskrwt2PoGAZE8C4PF/1SmipADCdj ckDRftbjXGr0y1lJL5ENqEmxjl8Jcscc1Q8AAZr3bxc5dtjKvO48jcvlSrcCqIiCl2k= X-Gm-Gg: ASbGncvI/Nmwx0RbktXAJrLrlgYEAzfsvM3JmGmkWFVYWS2LmMSTFylkCEFwJrWBy9s eSPFm3+NLvYXh66dcyUDZHIZsunvfVrj89QhwdfEnNlO2SBSc9ctQ3+hSLNTGP7aBcmz3SsE02Z slSGBybYmK8aXjs8F6NHnggP+CWvCpALwfPfzc0RyO1dteEYW8+2pthr/w6j5EGRMb8ftbSeQbO GS5hL6n6J1y8S9TfiX7Zai3Y2GdITH1Qyv6KYZnnTO3EMk+tXcL4sfD4k8hQ7CECpxnm0HzNsa9 oTQgLSZkwwo+4bKBl7m4lIOHB5UiG9C1Z/i9TsmXg0TP1RJrcxSqTXwAyWiR04JTjJKb6CqfoTa HdIk8s8ysQua1hNf75PR6Hg== X-Google-Smtp-Source: AGHT+IEaNwVJK/tKNCXRGKFQaOaM7TCB5Tqy3IhB7JUAypFAcv9AVzUyi4miuRkUNEy0LJ6hfxFRWA== X-Received: by 2002:a05:6a20:7286:b0:23f:fa35:d0b1 with SMTP id adf61e73a8af0-2404117c03fmr10489717637.3.1754618830731; Thu, 07 Aug 2025 19:07:10 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 2/9] contrib/plugins/uftrace: define cpu operations and implement aarch64 Date: Thu, 7 Aug 2025 19:06:55 -0700 Message-ID: <20250808020702.410109-3-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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: 1754618997206116600 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 touch the frame pointer. Signed-off-by: Pierrick Bouvier Reviewed-by: Manos Pitsidianakis --- contrib/plugins/uftrace.c | 112 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 4 deletions(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index d60c1077496..4b1a2f38143 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,20 +108,36 @@ 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 + /* + * We instrument all instructions following one that might have updated + * the frame pointer. We always instrument first instruction in block,= as + * last executed instruction, in previous tb, may have modified it. + */ + bool instrument_insn =3D true; for (int 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; + } =20 + 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 @@ -65,6 +161,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 20:30:53 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=1754618941; cv=none; d=zohomail.com; s=zohoarc; b=XDk+T2gsMTDWhwixNdFG8afWsthILeRGCrIkkFex+yVx+vhEGJFDMVZeXBInZWEckL7VxkkBHEGXht+mank8utd/dvd7QOp6/olsER0hvjdLWVPjHl8imq7SO0Cu4UBl4coYowvEsFTvTxOIDNWO/YWiQAVEeHwbRCJkQTF+MI4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754618941; 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=lB76hTGMecyehi/uoRAfInFa2pW6hNBiyLO8Wo7oktk=; b=cWsPhyUJRy3v3nlcAjaONJZ1fTQhGTiwAlo7+EttGnM1kU847Vxi75OK4m+7wXlwi0VjZ8P76rfIbg+OIHR230XQS43bfK7yPWhcZ2+emnKSbeASMNAZiIDP6TV4AxWPGcDSJ41rPQN4KFcfiyqh+wLG3V7YIjyBjy0C7thPYM8= 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 1754618941321713.3861801282778; Thu, 7 Aug 2025 19:09:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCW2-0008Qc-GN; Thu, 07 Aug 2025 22:07:31 -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 1ukCVr-00087V-8L for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:21 -0400 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukCVl-0003U9-Va for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:18 -0400 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-76bde897110so1439753b3a.3 for ; Thu, 07 Aug 2025 19:07:12 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618832; x=1755223632; 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=lB76hTGMecyehi/uoRAfInFa2pW6hNBiyLO8Wo7oktk=; b=EwICLwvqJGYcVwYSy8DZl+1LtGpoJhfkcaLtwjEeFDRWd3XagB4oGju9EL5rohoRkV RyCdgreSPDMCVY57EY6ViaWwarFVPnpVu5A9O/ipLHZX4ZWz6rUyCjVPE4kJj/PfCb2E 56pY8ezTp3Ts9dyoV1DiLhCKFtSxc1urs07dy+at/+TR/C++/tTW60Ks46vxTQjt36pA AViSBX6oXwzGAOVd2d/QhD3c3MqP0vKMR2OV85SHMNwpsfa4oll2lQDqS3Ptpkmw3not mNDc61qEM5tyqqQpF0ZeR840e9zwYYLXG09tfVLx6xKsJZdPtfTr+9c5o74IQQhHD4DJ wV0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618832; x=1755223632; 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=lB76hTGMecyehi/uoRAfInFa2pW6hNBiyLO8Wo7oktk=; b=c+ufeP123PDtcCtf41D/4xo2jHkamSUp12NEJ3a9FgtfDCur7f6XzbKvj7YSvz5CwF uLKHKydbH4sSijuD7xhdBoqOJSDJXRgtq1ReU6j4kR2w21NW4Xk8SBa/sdtvHGxLaKnf 4OvBZq/CQNfDtDjoZeNSErSoM1diNA87dfsQpk6FAS98TzWPc799fsbFqVV9b4iiBISH xbBPWMZk1jEN7/hNFUH8R59aNXq2bdQZwh6wcGgOfZv31X2dvmu11Ip2gfBN717XODJ8 wo4f5vqZ0LGSr7ufVNIJoysEdlGwUEe0VNfo2LG2nglpmAX5b1H4+LDgzS0FKfpDFIl+ 8k0g== X-Forwarded-Encrypted: i=1; AJvYcCXIRzYdeS42fVhMOboAn242zzGLp3yPU1KsgMth+wJK1q5UOyKwRkzgXeViPY7cJBsZqMWKYSqfrqnU@nongnu.org X-Gm-Message-State: AOJu0YyyGCsamITRBth6sdPRa6GXboZDexYrqHWOwRFL5mEZt3/sbb5B DYKq9EYz8hItA3GpyB9PArtaLzRJ1vTQWfUho4DGP5JE4Y9T4yLk0/kZMLg1aqBCT14= X-Gm-Gg: ASbGnct7ubkQljBcAlTs+edBNsDyzcg58gNbStYzfKsocYMApQHzwbanVMBFyYLLu6E wtDXmcTE2W82ZsPv6Sg1R27Mn7zKZAsnNh5kmekD8rmCKX8mrBc2nmC0NZ8+Cj9Qjt/AHKJlYm4 v/0qi8xnydRiF+VLup+gHDVK3Pdr7FeY4k3e6mHR+iEo5rvnAPQbBE6a3JDj8E/oZ6RcCoEPk36 21N30s+mZ1C/eZMMWPxUh1gfizy/rRVzqL+JM3QmYbVn5NxOzjpCm7EdAtMpVWxRj8YB45iH7/6 MsqRFQEo2/8nutYYuCo1BDavoFFbwmkfSn0C/Itu699FEBuisy49PVKwNzAMUcdXiZmkv16oALk 0nDWgLTm6z5avxJeMZwgCZg== X-Google-Smtp-Source: AGHT+IFowEEQjtGcmFoCey0zjA5Em8028eEBDLhC1NKGOlC53Snv+cAPRcMVIl6lXbqH+6M6rjyYQA== X-Received: by 2002:a05:6a20:748b:b0:235:4a12:6adb with SMTP id adf61e73a8af0-240551c9f2bmr1789399637.33.1754618831769; Thu, 07 Aug 2025 19:07:11 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 3/9] contrib/plugins/uftrace: track callstack Date: Thu, 7 Aug 2025 19:06:56 -0700 Message-ID: <20250808020702.410109-4-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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::42b; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x42b.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: 1754618943192124100 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. Signed-off-by: Pierrick Bouvier Reviewed-by: Manos Pitsidianakis --- contrib/plugins/uftrace.c | 160 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 4b1a2f38143..d51faceb344 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) @@ -139,12 +295,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 20:30:53 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=1754619038; cv=none; d=zohomail.com; s=zohoarc; b=Bf+is3QJ5DjZiP9r9hKER+WnAdTHCpRUzfoc3w05KrIjWArpphxyqmDAeoxfvUCUWcTD3P/WvfPabmqV4x27AdrXaMCdDsGpS6lcDM0/07izkf0I8UvJyOIKC1cWl7smeGi/LrnztbIUTLaOtBXsHKzXg5NNqYofbUkgHu/q1Pw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754619038; 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=co5Pn4vXxl2xGepzoq0rmC9u8lz8ngf1vfiSXSUCvG8=; b=euDfBcG0zyc6tQK31mCQjZeRaNJNFpTGYCUiuxaMDp7i8022gmuuuAODD9EuPIMtMBnEpN/E/13SazB/1uKF+7EdGqrJU9J0gkc+f6qOvywvMT0RiefyXrFB47f6xiWpGNvsVbdksgU+fwpKMau7bV+xDHYowyk5DNYYmZK1qjI= 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 175461903856723.98555193331447; Thu, 7 Aug 2025 19:10:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCVy-0008GD-HR; Thu, 07 Aug 2025 22:07:26 -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 1ukCVt-00087o-7y for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:23 -0400 Received: from mail-pj1-x102f.google.com ([2607:f8b0:4864:20::102f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukCVn-0003UL-Qt for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:20 -0400 Received: by mail-pj1-x102f.google.com with SMTP id 98e67ed59e1d1-32117db952aso1548821a91.0 for ; Thu, 07 Aug 2025 19:07:14 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618833; x=1755223633; 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=co5Pn4vXxl2xGepzoq0rmC9u8lz8ngf1vfiSXSUCvG8=; b=XBZmjdfSROgWc7iUcQMERZWGioCMqIq/DKf1uPbALaT3KoJrqFWt6Kpch6emUrdhYo LC8WDnmLWwLXu16hlCC7neI5dALGfTAtPUyiBcgqSW/V/Pz5jcEu3mFtgTUDlB40iztc /wVXL4Ze4vaw8p6mIyw3dAMOcP9AvSFXuL3vehcYu9TUTs5hPiTDYvrpvRutcxnVpcis YwcVqq1Fq/NtwSXfZ/dwRvM3EWu+rfF9C48jpxQ9Mnsk3YPBTv4PPI1sOUhUPyF7JDoW 8S2RYaM8kIZ0J0uDZYwcQ96PFwv4ZoAmiKL9XvcQrZf35IeHQ4g/kElExtwUzeSMelRm vsrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618833; x=1755223633; 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=co5Pn4vXxl2xGepzoq0rmC9u8lz8ngf1vfiSXSUCvG8=; b=gxumFNvNN/7GiK/axYA8WZVihGad+wTTWSWld2bByoi2eR9ridneCkNyp9C3aFHR+E 7MsZQu6pYcSDgCZl35VBxYkg5HDjPw1zojszABWvF4jptmefR3jOnAyLi87tJABT1+Sx 1yNrrNpco4CqmKGq1OiqIPZ5lYavDLAaHMLOAR/8GJWqp4UHG8lJW8gBePR3LyR9JPzu yu3CcEfB58Lnra44gbTQE/GaXxoe8VVUOFfnxfGnXB9cx+zkbq1uyZNJzVG9RYcOQOB6 RpnNedHQ8pq0zXM/CiL/m9vbfrzQF9eUfBTXIVNmAnRhkeS91Z0/Uh3QNmqYIjSezZhP oeQg== X-Forwarded-Encrypted: i=1; AJvYcCXQOWT/yFrS5jjejgW1FSlk20Pz1TW045PDZvy+9XjtCPE9Esw3f8JyDAzP8GbMGOihYqaopjAUQn+J@nongnu.org X-Gm-Message-State: AOJu0YzwXF4mZAdAt5Kr8rlTjc3F8hcM9vkE4PjYX4DcRXPZjBbPE5t4 BukDWXShqpB56AKFQOPFVzqCuyEcE/7xvUkJJB8zZTEAvt6yXJg6U851Ox14Wjqtfmo= X-Gm-Gg: ASbGncsQKmZMRZv8SpW+x1lcjNykFJ3bhMEaFQ2iO0nqu0pth5MuMIt+eO47iYVfEv5 pK0gD7Nmfd3ezbZHNFvZRfcE+yrwkEEpl0DMyiAl1tqbp/Nnp132UQHUaZib342oJdkHWicF/PP zCWWeJoUhmEnkncJA7gLQA39Djx1rSV1cv9vSDhj9Gw6yqk8aXaOy9kyyKc9Tcv+BLBnzu2HXuz ukSg1nqSZJ6C/yXMgLU5Sqnfr7G5TPvHfDYN57ddIrczqd89uxbbuWpg1XJWX/9X+u1l9hFFTHl UdGYrlXaV4zlPjk2i6gJXWCL2dM7x3EgjIaY81wnbrw2DEbfY6HhPpCVbFr5VYmud2jVel0+MdQ dGgGT/fu7/HXEbgk4M4g1Ug== X-Google-Smtp-Source: AGHT+IGhdg2jqJpyG8AyVPo6vT1FWqETi+LzEUAlo92PQifS6LiHWVcb6mcEju8fksSiEJS0IgVHCA== X-Received: by 2002:a17:90b:224e:b0:31f:210e:e34a with SMTP id 98e67ed59e1d1-321839f0c96mr1723085a91.8.1754618832853; Thu, 07 Aug 2025 19:07:12 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 4/9] contrib/plugins/uftrace: implement tracing Date: Thu, 7 Aug 2025 19:06:57 -0700 Message-ID: <20250808020702.410109-5-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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::102f; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pj1-x102f.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: 1754619040367124100 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. Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 149 +++++++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index d51faceb344..402a242433e 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,85 @@ 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) { + fwrite(data->data, data->len, sizeof(UftraceEntry), dat); + } + 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) +{ + /* libmcount/record.c:record_event */ + 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 +349,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 +360,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 +373,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 +382,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) @@ -296,6 +430,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 @@ -304,6 +448,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)); } @@ -311,6 +456,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 20:30:53 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=1754619006; cv=none; d=zohomail.com; s=zohoarc; b=JVvm6HKeOMKuYJoKw0d2gw3RnkhqF0PhICFRl40IDo1IcHoYUhf79Mau+poF10b8aUs/phqdyI17A/Zwk/AKSGZP+Mc+W1vKSv4kzSWVW3sE52Cwm7y3NfAtyL3igWtAMJ8buYMgTqB3kZgiAPD3G0ShgAkWJE5cFPcdUAWPNIs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754619006; 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=zf0uMACDaQ+15NSJd7SLPaCaPXIKJs8f85jw+2sFri8=; b=MA8BwN0i7UYduavf8BtXNiHh5JDBJpf9N8OE1G/seuV1cvnD8klkcMxI8Sbx7b2Hgkq9erc2N4aQppwW0vscFXj02xddfT5HIdzNqh0rQQTN3vnJjNoisybP3ciBiR8beR5B29HCv0kdV+HXttjG/30b2Q6lr4NCSwIkLL+7PG4= 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 1754619006768532.695482193245; Thu, 7 Aug 2025 19:10:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCW4-0008SE-FH; Thu, 07 Aug 2025 22:07:32 -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 1ukCVw-0008BG-7U for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:24 -0400 Received: from mail-pf1-x431.google.com ([2607:f8b0:4864:20::431]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukCVp-0003UR-JQ for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:23 -0400 Received: by mail-pf1-x431.google.com with SMTP id d2e1a72fcca58-76bd050184bso2318491b3a.2 for ; Thu, 07 Aug 2025 19:07:14 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618834; x=1755223634; 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=zf0uMACDaQ+15NSJd7SLPaCaPXIKJs8f85jw+2sFri8=; b=oHtNW/dDrtebOoZfZLRYK5aYo1DdXwptPSACHBn7YgMHZuTVeAQgWc2NnLDUx/aoHH Vbtopj3kXt4gOC2JsZ+7YciF6rcbHBqQ7jFiPBndPXyry8G6r6zuxDezutkHSbyQtSl+ 69bshINAsftcazYe60LOBaIBZ3OLiGQLxakOycdqleW4veSm9/0urOQnbzEPidmFsHd5 OEEDkNfzjvbhnayMaxIreWlvoecrTxKWEUKv9TJOoI2EAP5zOoYK66saN6jh7yMT0Qlv e6TmpOeXAYIY8zpf4bQpLlEP/TLBY0r5Ikbp8GybDFCWyUQYk5LWGWrnfb0Dit7ylrKh anig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618834; x=1755223634; 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=zf0uMACDaQ+15NSJd7SLPaCaPXIKJs8f85jw+2sFri8=; b=rm264NpOE7ojSxNf3YhyZrNOCsMdegVXsQE1kNtp9q7tLycDM/gAo2nQaYZl4H+cBq fQny5YydWAjQSxi/kdTvGlth5ikury4L+fEOKUdIac9709O54mXSBBB/r4n8Je139CMj 1RU3MkVXjTuuDwZn3RD+Ng+135X/Z6ilrMfU/5JHiwIJEa9cnAl7GcQIhouCZ4Mp+Aol cn6me/mYRgqD6XYPUwPYRplMiVx78HIIBzOueqbcsEqluxk1gfwg5FZ1vR1GaygmqqSt 6tBYVCbMCJwf4NF4rAWzTQgIWDKfCOER3j4vzcu1LaoM5298rOPFobMZvl8+HNWsNoyG E5WQ== X-Forwarded-Encrypted: i=1; AJvYcCW8v0i5B8g5iRr9xrpYTWnCn7ZnvP9N/+p4w9dT60Ul7s1pUlVfezzzRIfJcOgBLrAj9ZtUrI0zio0b@nongnu.org X-Gm-Message-State: AOJu0YzIDLU4ZrUhsnHt38dJXIYBzaAReCtbubJM/bkSgSvS3uG7UMy+ +w2Sk6XzrzrRO5lHTYpUxpxql/4ucrtCVCPlZXDlKCDVEBKw3ah5bMPhLKCz67GsoUo= X-Gm-Gg: ASbGnctgdGUDWPbwh1w4nPylO/ahFmsSDdhW2AfmIXblF2B8k1t8AZlEHbJGU7xnrxt o/wvOVU2D++/iBN5oNmTWPFy5vo/uiFTOx7YWkygCX0yRL9IUo9MONDjcD0frokusnXgq/BaTln MVOK+O8MmbL/xRKyfK8yFNMy6Yl7TjwZmygDxNK4qs6PGcDU/XEuE3mVrHrrOPGcEEq3RjstEXG M7bB0q5JDWsQNvCD7kKxV5Blj8CZG0URq7pPYxO+u9GC+pG9Os32Kwz8dpevt9Kqgja2L4zh7ky lW66OzgrluddFXDn5sUhp3M/Lr5o931j38+Yrtw3hy0+cSJ/8Y+7/8YB3Hj6U+OhgG0QDeCklyO s2RFWjxSE2zingaawEvzi5Q== X-Google-Smtp-Source: AGHT+IHqFxmYV0SU3Nczq178U9qDVe4dVh7JYKHStJ20Dw9y4AXHGG6prMrbUU2t4BFYC/f700IXHA== X-Received: by 2002:a05:6300:2189:b0:23f:f4df:6ce3 with SMTP id adf61e73a8af0-24055030a22mr1746186637.18.1754618833839; Thu, 07 Aug 2025 19:07:13 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 5/9] contrib/plugins/uftrace: implement privilege level tracing Date: Thu, 7 Aug 2025 19:06:58 -0700 Message-ID: <20250808020702.410109-6-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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::431; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x431.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_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 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: 1754619007458116600 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. Signed-off-by: Pierrick Bouvier Reviewed-by: Manos Pitsidianakis --- contrib/plugins/uftrace.c | 189 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 181 insertions(+), 8 deletions(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 402a242433e..7737626da2f 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -44,19 +44,39 @@ 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, +} 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 +92,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) @@ -248,6 +269,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); @@ -305,6 +336,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_EL3 + 1; +} + +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; @@ -321,6 +414,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) @@ -342,9 +439,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; @@ -397,6 +519,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 /* * We instrument all instructions following one that might have updated @@ -429,18 +558,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) @@ -448,7 +595,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)); } @@ -457,7 +609,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 @@ -468,6 +626,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 20:30:53 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=1754619008; cv=none; d=zohomail.com; s=zohoarc; b=HofDGUCxGfsPR1ZNJNHGv/z/Cank2VLC7RXHTbbK3KeL/BotQQvhsHyHxMOraFqbaHURowyU79wiPUJf9VRwVX1z4OrVOIvS7XwaZoDA6GqWrM653KhT0qQVnsaESlBtNPmHX19+qjkSZbaFYRQIiius5AJOEWnx6lzNoZ5UEFc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754619008; 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=+XhHp4ICBhZSJpQEoZ4selXDuu2CQ0EBUbhnnEXKkzM=; b=blSwEVtKS77RA3ydihp45V/WdbBGnPSsEhxQfSaaZjNCMWDBYhU2PZmZsFMdIWBBEOVA+6tJFwkwp33EJXr7leY+khdS61HFG55KDR42Glx34uSAho6j/4Nfp5D0nSdCeWGMr0a8EZTxEFbW5DLi5GC4BCwzLlffyW5Q81HYwiU= 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 1754619008838106.81910837992427; Thu, 7 Aug 2025 19:10:08 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCVy-0008GA-Fz; Thu, 07 Aug 2025 22:07:26 -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 1ukCVt-00087n-8E for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:23 -0400 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukCVq-0003Uh-AP for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:20 -0400 Received: by mail-pj1-x102d.google.com with SMTP id 98e67ed59e1d1-32129c4e9a4so1486382a91.1 for ; Thu, 07 Aug 2025 19:07:16 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618835; x=1755223635; 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=+XhHp4ICBhZSJpQEoZ4selXDuu2CQ0EBUbhnnEXKkzM=; b=EaXlO9dcbqHjqh0AIoxEKpX0iSPdLFaH+eQmcFcvEnUX3gHUfTuIrMArSuTPpDZKV2 JI53iFKRfxjtciwlb11+UvQMRxgEar0wMepBtt5EefSAciWIcPHNVDL16b3RfGR9OLE8 Ns7iBVpn17vIaphVYuTRVe88DHiZDTX6mpX6MRfQAucSEEYCUutIwZ3rIE2kRWTYqcVP s4lsN0vjfRPhid1+6CkFQgFfciPGAk4mqAkmC4qbu+j4rikOkEUbh4IhjXiMsTRtswYe IZzpAK4tbQ0YhqGPXMj5NUlj4gsJ9tELNfF2i6vVGOLgX6u//KqdAU5lxRyr2Xvbj9aG GIYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618835; x=1755223635; 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=+XhHp4ICBhZSJpQEoZ4selXDuu2CQ0EBUbhnnEXKkzM=; b=OFM83ojMj6IUFbr0bt4g6CQ2dhsfjeZLBZ2v4M9Xhwc3tveWvWxItXHq8x36E7WLS+ SLb/wV+DV8vbfuDyVzQvNxQR0e6ey8fT03TVZySM6CShY9SizmyQuFlYJpifIJfcoEfk UX8MzctI2qJ83BW7gV63Zo2VgGRFQc7sNEk5Yz6htYliEb2mokiymBCWphYLfo46cX+L I8w87dFI0+BMl1f9kOI+Ib4DbUCPMQYCK4cvioPGyWARw4qQUQgQVWYpXazFO0ZQgWFD Y7O7OhENPx+yZdIN0FKpi4EMiHglkK6hhHGoStNZNs9ZAQrFd4H8zesPN18PEACh44xq p7dw== X-Forwarded-Encrypted: i=1; AJvYcCXX/O5pPWEJowi42LYVrwzSvMwQWr8IaC/HcPqmn7z7kSyBs+IkpEQ2b0STtaFiJ6JQT5eTXHq88p0b@nongnu.org X-Gm-Message-State: AOJu0Yy3ZWgUJXSGaofjalwCFbnfB3XhVldoWhyLlO8L4hsbjhgqa4Em GY+IPgfQzp1OkgA7SwTamgTjPxQQV3DtLVUaGAy3MR0kH9HcQF9vodigvKfasK6M9r8= X-Gm-Gg: ASbGnctc5chmskMjg+c97dk9/dIlLgOURX8fjUeYCqjhRuydbdiKJo6cPghIgcwfeXt EdedMDobbpu7Rc67R8haYD9GXCB2DNFmEKfHh6ciwhkA1Tl6SZmSjjfmBIBG1CJj7dGaU1+SHcd jtxLPZX+ptojYRwWdBc2eGkysArHfu9capD+aT8CE5bCOiJP3MMP0T9M06pnSl4XCRm21r17f37 WTPbiyxsdtVoFxyKKtkVQ65bSDOomyE0sPhK5j+2DwyLfAcPd5l2ass68VQr0/QFxcV57FcqhoH zkLqKtRsG5j9VD8x5kHrBDUrbtQOciztaPA73cw5XLqKgaaw0FXPTnldBV5skG4uXFHM6dyOHC0 eI1DXTIHSNnZgBaFcmlSg6Q== X-Google-Smtp-Source: AGHT+IEo4NbfBL4sQ1pkIKyfPFTDOzxAVZRDrLqP+SKbmFYHLVSJzcS3A4Ubx9XAAzfqCH1HdV7HOw== X-Received: by 2002:a17:90b:3d8f:b0:31f:2bd7:a4d2 with SMTP id 98e67ed59e1d1-32183e82581mr1845756a91.35.1754618835044; Thu, 07 Aug 2025 19:07:15 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 6/9] contrib/plugins/uftrace: generate additional files for uftrace Date: Thu, 7 Aug 2025 19:06:59 -0700 Message-ID: <20250808020702.410109-7-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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::102d; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pj1-x102d.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: 1754619012208124100 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, and we simply copied a random example to keep things simple. - 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. Signed-off-by: Pierrick Bouvier Reviewed-by: Manos Pitsidianakis --- contrib/plugins/uftrace.c | 130 +++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 7737626da2f..6628b4256fd 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -115,6 +115,126 @@ 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}; + fwrite(header, sizeof(header), 1, info); + const char *info_data[] =3D { + "exename:from_qemu", + "build_id:0123456789abcdef0123456789abcdef01234567", + "exit_status:0", + "cmdline:uftrace record qemu", + "cpuinfo:lines=3D2", + "cpuinfo:nr_cpus=3D1 / 1 (online/possible)", + "cpuinfo:desc=3DIntel 8086", + "meminfo:1.0 / 1.0 GB (free / total)", + "osinfo:lines=3D3", + "osinfo:kernel=3DLinux 6.12.33", + "osinfo:hostname=3Dpc", + "osinfo:distro=3D\"Debian GNU/Linux 13 (trixie)\"", + "taskinfo:lines=3D2", + taskinfo_nr_tid->str, + taskinfo_tids->str, + "usageinfo:lines=3D6", + "usageinfo:systime=3D0.000000", + "usageinfo:usrtime=3D0.000000", + "usageinfo:ctxsw=3D0 / 0 (voluntary / involuntary)", + "usageinfo:maxrss=3D8016", + "usageinfo:pagefault=3D0 / 0 (major / minor)", + "usageinfo:iops=3D0 / 0 (read / write)", + "loadinfo:0.0 / 0.0 / 0.0", + "record_date:Mon Jan 1 00:00:00 2025", + "elapsed_time:1000000000000.0 sec", + "pattern_type:regex", + "uftrace_version:v0.17 ( x86_64 dwarf python3 luajit tui perf sche= d dynamic kernel )", + "utc_offset:1751552954", + 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); @@ -607,14 +727,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); } @@ -651,7 +779,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 20:30:53 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=1754619001; cv=none; d=zohomail.com; s=zohoarc; b=k9Qxf9AupTCHd2WIuEVzAaxmg0fovoDx4bUe6o97EiT3Cvd/Bjk2ZB8oVXrt9Eh8zV8b9OXLsdFfzUgzPLwO05keuf6sRzWo2RWmKWkBalktek1MF2FQk+7fcneOoZNyXS6dYpVbywog29dhd764KKGWuZdN6wxcs1RuAQiqiXk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754619001; 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=dcx/SXeVPZrEb+bZtbiVnjd582rVKcmddr3/xl05bmI=; b=ak+1oWAh6E/DCCIWvingu40kzhMtFtEGaAK29/0d8d6Og8Vs4qaiclHb11XytyU3tVeLPOE0naq37LtFOw6Na0dUuxxFbtq+cjPTb+a+7n4+yzVnzpDzscdKKvARsLcn9QogudK1tissEYXU2Np+Bxk5SASy/fVuykpAKrCgIA8= 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 1754619001429637.2385366017786; Thu, 7 Aug 2025 19:10:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCVx-0008Cp-11; Thu, 07 Aug 2025 22:07:25 -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 1ukCVt-000889-Un for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:23 -0400 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukCVr-0003Ur-1J for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:21 -0400 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-76bc5e68e26so1721607b3a.0 for ; Thu, 07 Aug 2025 19:07:17 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618836; x=1755223636; 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=dcx/SXeVPZrEb+bZtbiVnjd582rVKcmddr3/xl05bmI=; b=CAarvhqM1BGK6KHqZ3gy7fpFXPrSaY89zCfQBkfE8pb/Xu6EMcUKYq5bm6H3APmKD0 IKDC1HZBtrU52nnnJGqixQ5b47k0LLULsN1ER1svlRXgJ3CALGUWdDJQvsBJw1+W92c2 Hmv52ITP0Tc8xlAccVlJUwz3JiZtISAT4a9AxIUMGX62+RTftapzPTLh6oupw//mO76R fn2esimtEngAqwRoQIglSxGAKZIK0HKbdexD/e5HBA0sEGPK0m8jYe0HgF+0y2WcyVDi pkvgA2tyczMOT0aSKwPGF7aUEh/k8PzCKdqfMPSnUiwumbrpXAtx1jecKloF9K1QJs5Y ETYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618836; x=1755223636; 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=dcx/SXeVPZrEb+bZtbiVnjd582rVKcmddr3/xl05bmI=; b=CKfW/7qp2DxumGnPTHc4O85/mCsxrxp8m4tyfM+yPxEzgt7eahSSt5Djveqq23NQYK annbClZGnLhaaE9CxzWieuJAfU09Ck4T3KSzWW82c16tFwfbliLNEVppZT+/D6BRZKDG zWpT/MzNara0Vc92zib5iY8P14F9Qeh1YCeEiPL3E8S1imHyMMjSUdbULKgirqQrE9Yf RpHGqyb2iL4ozAXuA0i9jNpYe9ZlkCPS9yx5hhXBb5hif5FyL3SwsY6FA+8id5flT7UL BFwzP5m9jyx9k7fxbuqWWLdjJtVpxGS5YfZqSLGwMHO/w2FhRbQK9AiBym6C+6xgyFK/ JfAA== X-Forwarded-Encrypted: i=1; AJvYcCVjailiNfYXOSi13qf5Pq72/zLOxpri2KjbYgXZQK2AOx3u692+M5IVhcNb6c+KDgbvTw3hj+24CtIF@nongnu.org X-Gm-Message-State: AOJu0YxvCkwIAFTW6OLipJS4ln+FaYv7s9/ODcK1iZ8r9QCJuWHr1tkz BC3RWSxLXWq00282dbu0Jr484VAveFHLyY69GSVzsnodtXS/qVlsJY0h9HBaLXH2T0c= X-Gm-Gg: ASbGncvskmwTrKjLxjVTOmtBCSdWqsQvg3PCN8VQgNdECHO7Iff53Qeq+yIPYyYlhTy 8FoMrhiuzFbCM5Fwbh+PBreOqwEsmf/OOMZ5mkt1EjVfU4xxhrrHFwr31Dbj81pwW56ShYO9niR CHIhh8N/6l1rHL4ssQ1A6N3X26w124SlP/BNH9E1krfI0wuCzp2SSyYLWDFZugBKc3aeA0Gopnb 1IgF8wVQ5urRFyQSFVmS5/5hU3VFprfWVCwShDLkRTmfG/dupVdFMz9kp4dyepln+kkD8DH/QFZ n3WrEaJR1ZyvrDuOb3IVu7CNaRzPIyhLLAWKFzqsB+pOVU2CF/AVRV6XVAICU037jWIp5am4P6G ZCVrOOYzauEJocgvgUrn+OQ== X-Google-Smtp-Source: AGHT+IF8XLaBIVTx/8gadg/Iq9ZQ7ERVwOg8wBFmMm5548X2y+Mpn2CxkUktlhSDYjR3OGuolT/UhA== X-Received: by 2002:a05:6a20:6a1c:b0:23f:fbb1:c229 with SMTP id adf61e73a8af0-24054d788a7mr1720360637.0.1754618836075; Thu, 07 Aug 2025 19:07:16 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 7/9] contrib/plugins/uftrace: implement x64 support Date: Thu, 7 Aug 2025 19:07:00 -0700 Message-ID: <20250808020702.410109-8-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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::42c; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x42c.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: 1754619003893124100 Content-Type: text/plain; charset="utf-8" It's trivial to implement x64 support, as it's the same stack layout than aarch64. Signed-off-by: Pierrick Bouvier Reviewed-by: Manos Pitsidianakis --- contrib/plugins/uftrace.c | 85 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 6628b4256fd..f10172eed10 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -79,6 +79,20 @@ typedef struct { struct qemu_plugin_register *reg_scr_el3; } Aarch64Cpu; =20 +typedef enum { + X64_RING0, + X64_RING1, + X64_RING2, + X64_RING3, + X64_REAL_MODE, +} 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; @@ -565,6 +579,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_REAL_MODE + 1; +} + +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); @@ -771,6 +854,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 20:30:53 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=1754618981; cv=none; d=zohomail.com; s=zohoarc; b=WVk+gyABH6QteMo18IgPnUvh2KlQWoXsrL8YZsIFjuutQjT0HA1VJwdvFFjPjkUfwYUYeWT1yZlJ64kTKcNeQjqDvKmzO4mAaxfa6ZVJ8q5cUTY2K3pjU42A9CBnLys6vxPAsFdSUxveCB2Ub5QTFNQc2EpFx/2jRhENUS9zwHs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754618981; 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=hD67TGPiV1SbF8y9AkKRT7bufL7Q5fsfSFADPbgLilZyEyJhcoxpdau3As/DTrS16rU8tQH5BK1PQtq8Ei3Kz1XGRNhXPK7odvLJtdQtzsEnxe19ki5Ii1ymwCLJPjfo//YQyKaIiLcs8II6JE6mXyI+1lSnTtMuZWoZ/Jef//s= 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 1754618981731335.5820283930401; Thu, 7 Aug 2025 19:09:41 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCW3-0008R6-E5; Thu, 07 Aug 2025 22:07:31 -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 1ukCVw-0008Ap-0Q for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:24 -0400 Received: from mail-pf1-x433.google.com ([2607:f8b0:4864:20::433]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ukCVq-0003V5-Vm for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:23 -0400 Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-76bd050184bso2318546b3a.2 for ; Thu, 07 Aug 2025 19:07:17 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618837; x=1755223637; 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=Mv01FUgQ8IYifXnLJ+dl5fnuMnKQ6s1xrJz89jBVamUZ1C/Ci6lgBbwYFQrFpllHD3 F6NZL1WoorRPtUwTru+7aaaRm4oW6a/o5rCCd+4niLP2X43mR23jI+a8FjL9nEuYt6WC oUHJ/wkw4umv9XNjqXIBjaGFb67/NCgHdEct0uMldP9tio4IIi381H/lN/qdLitKNzhs 1vqQMpmDRv507pA85r6sJEkTDZ1jH1Yg13MtxTakpCRhG6kPMHcz3VpxlpPW9QYOI0a1 UeJOCfPH6awGS+UWxgCfOf1rawxFuwKix5n4C5S3xU0YRg/I49pRhKNlbLOHHQzIUUsv 0I6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618837; x=1755223637; 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=P1UqV/sFO9Dq9yxRd01OIblyUCGVatZEBkvhocVy3oRGEL+vWqB9w5DHCtOMvfI3hL UnNtX+W3JzCaSSJmBWdCBmHWln+Q8KpadKKtTShIYAL7DPSnura/BjvPfNZYxdL3SxBx PpRgykiVovzSW/xDRqykU1eGoQtr7R1fVfplBB5dy2QtBXnGjCK9LN7RdlkZZMT1rCr8 z/BxHbAlphbLKAJr/y8lgIqXOFsOZ07icFdueg93kxX+zTFgQXB+6z4LeLQbhVYPdbxl K98M7XA0BTkJ3U6Sg9zcScVf5WvuC0hmJbhZDpoEPDgecfn3gAd3ed6+RNIZkYIgIm7q o+vg== X-Forwarded-Encrypted: i=1; AJvYcCW0YC5wbJ9eLRox+3bX4O8NeCdsl/hmJyW4dupmKk5957UlUqQhyNkfwbrD3MlSHsjwRW63Asw4RgUU@nongnu.org X-Gm-Message-State: AOJu0Yy1bAcDev34xPaW8QTMhpFTiczzLTEz62iClAVp53Qani6v3+nS vK/pPEtBwSW5YuJ0Hcf3IAylkKfydpC8qm8EAvMirFPlSm31BLDTf0pGA7ScsTPhVcQ= X-Gm-Gg: ASbGncsZKfOYDFS7xtzV3VYiI/1+9EEdWiBWH3DeO5hyMSDCD4l8Y/+nQpyJFj34q5I yGQVD+zgMaE2dP+aftBpa5KiC63tLzbJ64gy0Tk3/jBvTH8pnwIgHwh9t7ZNMogHuMeq7AtWjpJ tl1sAQWzLOqubVUHDfAnxJzL5nL3u3OhzkRmVVHcKT+N6uDivflODy2xfgNvSEtn5aB54YJJ034 wp4iQPmxlF66fhd8kO0rBoiSW1IDniet0VclxwqEgV3PLZiJ9I1PllIHBEA81AA/fOR97aqMQVY MteIoSnRieJNg2ps3DjDI6yVeU0RQLF2UkCo/xoO42pGTcyeQkrpcQ2ulJnc8Ij/O2Z3/GvWhkP DPiYIGPR8IMpgG6mdKfgOnQ== X-Google-Smtp-Source: AGHT+IFOUEdu9PZYbRGs3tt6e+xSTPwYWTlZoRejyJo6Urx05EmonMbZCpV2bOHWEGp5uzOhnMuCLg== X-Received: by 2002:a05:6a20:5493:b0:231:a5f3:4d0c with SMTP id adf61e73a8af0-240551321eemr1815974637.26.1754618837001; Thu, 07 Aug 2025 19:07:17 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 8/9] contrib/plugins/uftrace_symbols.py Date: Thu, 7 Aug 2025 19:07:01 -0700 Message-ID: <20250808020702.410109-9-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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::433; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x433.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: 1754618983110116600 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 --- 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 20:30:53 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=1754618939; cv=none; d=zohomail.com; s=zohoarc; b=Qnxprqu6MHAlTFJCufZZpGCLV1NcEvDfFfnv8Obe8HeiC0DgHkT9zxVzjyNkEV6Kwo2PLRgX9u5ffPqh03nqHjCOPBR+082SDak230qez0c7rWA43wBUtrg1N6z23YMckoBQTYLY7BiAvBL6Mo0c8KCjZRcorwpgiG+6Nsu8ErA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754618939; 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=3ARdLG0RyBcqXqMc7SaUdtHrarx6Ntm3n+KKS568/t4=; b=LPftKPBWGVtnvrRTLBn+tY5BTJiLrUYsrC8bK4TPllC6gRARTd/lIis8ctT2q3F7ys56zKwNriD/yiZHXjwB9SgqqvyNYf1vnHs9oo0udctAR4p46Mwtv1+Nsge2Ikh8INtcfWzIfddrqeSPRJi4UwVo0+Sr9HqeiDBZ5LEZ0wo= 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 175461893944621.063686975068663; Thu, 7 Aug 2025 19:08:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ukCVz-0008JS-QB; Thu, 07 Aug 2025 22:07:27 -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 1ukCVv-0008A5-Ab for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:23 -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 1ukCVt-0003VK-0R for qemu-devel@nongnu.org; Thu, 07 Aug 2025 22:07:23 -0400 Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-7682560a2f2so1861081b3a.1 for ; Thu, 07 Aug 2025 19:07:19 -0700 (PDT) Received: from pc.. ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b428ba4cf35sm3705433a12.14.2025.08.07.19.07.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Aug 2025 19:07:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1754618838; x=1755223638; 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=3ARdLG0RyBcqXqMc7SaUdtHrarx6Ntm3n+KKS568/t4=; b=sZMC7yu408y5I/brtnkx58T8cQsz9g65j029wbKUOSzRM4XnLfiUy6QbRjIe+S+N/H 0T8RuJfRaCmkSCoC/a18sudSIRR9d2T2CJxx4earurrXzW/ag0BvrZKprq709pWt8fkK kpB+bPs1UKhmFDk6QXe2KmG/ttqIcrOhYvwmU//Ihd3ONwnD/C8gAJ4xuM/RlHCNX+FF zh9CQq6eRNtPz36sq+qH0Jhe+D3DTZZBiuoF9lX3Zw+chSDsGOc3eytHFlq4hZm3HsKv +eLotnl90M3Hh6dJvOjGGghoVmSU+1bERZVA9GyKSe5beAPKfcByDge+Cirxfr0WIzv/ FHtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754618838; x=1755223638; 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=3ARdLG0RyBcqXqMc7SaUdtHrarx6Ntm3n+KKS568/t4=; b=tVjlVmf3UEopTbeHocO6hTD6GMosOfLj9hwSewFLJ6hQVIMeZGjsAY1j1luuC2MIFk kKhk8g74sSZ5MgcZJA//f/Adlqg/kV6I1ZYTQrgvqe28lIKHptOvI7aQCOskWX6j8xrB KwleC8T6c2TyhG37AKAE5F1WXflBjV/T5gP7V9ZiudEFns8ZcHh9CxH3eYvnIYJSmx5F bEGCEn4LH14dO9xb/kz8SvivdhNhwU4I5LAODD/LYIZD1zQX2mngALkWwI9znoDhuzab c+/C9iD83sRjyH1ASdN4xRqx42jQt/xXzkybwl7wPw14ubnbMsFzrpauuzd/7Xxfkds1 9gHw== X-Forwarded-Encrypted: i=1; AJvYcCUgoteLelM5Dcvw444pIhPXfGx1+kDJP3kSq4GGsChJfGxiY344ptJPEi7t8lCvbaGH7PNnF9sn/R2h@nongnu.org X-Gm-Message-State: AOJu0YxZKDTJHRcGhCWv2RAhhaCb3Psh2sIB4n2XNysCM/8byDy23s/l 1pRIn5yGZHV43ZT3MAxMZ5UcYB051IMRXmhhNQuYAEs2JuLl14FksVsiniBIpil9reE= X-Gm-Gg: ASbGncuCIyZH9gpMmtUpEY9TlPQ1F6+Cf2yTZqWwvdbnPlC1Rs+9k6xz6MYlOtIXgjE AlwljbEndReIUONEQOou6k5Ou0dU1MKMfpjjJmLqz0ThwSrkWiMQbvN4mGxA7HNPz8bkR6em9qQ ID4mSHx19Hs44yrYI+7VRfdo/1ulOwyon4CoIXKqg30zn49ZYqSwLJy+9JCwqqvxhwyq1gDIyMx KX9oURA1Cw5hRj5pgDlXdqDSPcWvXZlL1a+YsoOr1Ydq0eitGAJJaHWcXVXnSAcqER7FGLoo9Xw 9qmFS4dqXGbUsAiGFO/PlLaOdKBUIWiwJvtJkj8acH74Z30QhlBTLWLVoMtX69CMeYZJqM5x6ew LT53vkohEUNZFv3MXVNT51A== X-Google-Smtp-Source: AGHT+IHd3ivCqaR1MQax7iSHr8Y+34lWcIn9f7N4VqL28+f0ITqBaF1B1eiktZmQ3uw5aUkiJcK77A== X-Received: by 2002:a05:6a20:258c:b0:240:f4c:cde6 with SMTP id adf61e73a8af0-2404117b827mr8617498637.5.1754618837922; Thu, 07 Aug 2025 19:07:17 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Mahmoud Mandour , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , rowan Hart , Gustavo Romero , Manos Pitsidianakis , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Peter Maydell , Richard Henderson Subject: [PATCH v5 9/9] contrib/plugins/uftrace: add documentation Date: Thu, 7 Aug 2025 19:07:02 -0700 Message-ID: <20250808020702.410109-10-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250808020702.410109-1-pierrick.bouvier@linaro.org> References: <20250808020702.410109-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: 1754618941762124100 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. Signed-off-by: Pierrick Bouvier Reviewed-by: Manos Pitsidianakis --- docs/about/emulation.rst | 197 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/docs/about/emulation.rst b/docs/about/emulation.rst index 456d01d5b08..9ce47ac2712 100644 --- a/docs/about/emulation.rst +++ b/docs/about/emulation.rst @@ -816,6 +816,203 @@ 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 w,a,s,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 w,a,s,d keys. You= can +find below some sequences 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