From nobody Sun Sep 28 16:37:05 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=1756799547; cv=none; d=zohomail.com; s=zohoarc; b=Y+ejkteygn/k/A6YGyHrMspx6bbJUhqgmEcbzJL0OtF3I+6K4CvxrqKDtDQ4GqL7nYxtZdyrYqPwEGb/54RdCjaP5hLUXO1+gM7oyD4btIeWJGDh2t2wJC1ZcVkZzGtYF6DN62aa6wlonmBJ8PlbZfTAdzlwftC45+vktPBpqjA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799547; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KsrgAwcfXPf60wLi3R10FjsXpsAPM+d7uJ0mGFTRCRw=; b=N7PmjDfmtR10rtdgGpliM3YqKuhxs5hfYZ009G0gIgQplgo3b4+cY0sx2tpoUvgJeBRYuWsnpdMIdleqHIa8jjU7oV4TD8/1/Z4JWEqnegvIVjbeuBa9Ar6nzRHs2py8lGElt52HFFiR3VXxHVUPpIxv/HNLwXU/U7doD1ZW67E= 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 17567995472531013.717959480197; Tue, 2 Sep 2025 00:52:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnP-00077P-AN; Tue, 02 Sep 2025 03:51:15 -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 1utLnH-00074d-JN for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:09 -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 1utLnB-0001uc-F6 for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:07 -0400 Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-7722f8cf9adso3484609b3a.0 for ; Tue, 02 Sep 2025 00:50:58 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.50.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:50:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799457; x=1757404257; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KsrgAwcfXPf60wLi3R10FjsXpsAPM+d7uJ0mGFTRCRw=; b=tMSX8xRRGdeOatBYYgof1RALpPvJFmxCpaQDoY6FaqwGyl/fj9dIPU4NiwpiL1iW3n B+tW+fLVXyYP7APyOOHimtxtyaeFZnrtvo3y1JD1MjfYfHp8Xv5gx/zrVXYAATkIMExj lunPRAA14JuympQWFmUu9s2nzVxgAbcSxi0zDrwwdET+UalonnKBrWUiGmTxHfyUQGGp tFTyE+PaJLWkzeLcG3P+n2/OP99OaxJI2tfPYpitadXtUmpoW9W/Uy/OQ4n8OqNKuzg/ bI2nmkL9g6i1YD1DZVNtvyHaLbfUS3UpOGMDPHfgIf4NHIxuX9bT3PWUCMGYpXjAjBkV ZZ/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799457; x=1757404257; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KsrgAwcfXPf60wLi3R10FjsXpsAPM+d7uJ0mGFTRCRw=; b=TvRvnhCd8XtTEXtic82lg5Lnin2F88ObumbMCLIrd7TXuOWBhjjOgGUQPxomUB//lI m/EXGahcJy90U/aYer0ablMWtQhMLoqBjtMb7SLFtpvS1e/MTz5K46muM4/rkgD1JCzy Qp5McMNXvQW3pJZ4NiIQmWOaHRXFLjZ3D/q0/hgojx7In8ChxI/oyZ9+okRifuQTLew1 qtJaqtWu4PGNmVtwzyWMpTJGINZRIJav23J5iHfptIbifADnseYrAYwZVgnEKrLLfGHh tRPHAqSQIqu06Y3hIjXFWsBm2xYUkRILU66yzHp8f5+eqF7ZedQnGzdJ7gI3Gpc49taa yUaw== X-Forwarded-Encrypted: i=1; AJvYcCUxcBLP6iTqVGwlQn/XoIuCYCVnViS3F7KE+PFo6Dpy9Tm/orslDD7f6N7S41VEpKFIrjnDPTxwUFhQ@nongnu.org X-Gm-Message-State: AOJu0YyiY4Im3axeuhVMMAf06BQk8bk3CzXC+alW34KDNER7hYa980Hf YDv+NXXcIX5k+eqZqEqXiBrxH2yaGPO52IQJXySaJWMmBj44bFiRBTmPv+vIvixwJn8= X-Gm-Gg: ASbGncunnH++rZVRP9K1PdDvfiBf+Kx5ost8MTiHF4xFrzNyEMrgjxlxdFytrefyGfm OTpNrnzGPDC21enZsfF2JSxTofBhkLfK22V0KMoMo2hXU4C5MFNHqw4mkQSL71LmE5YsKYJ1Pa4 XpRnAwIWTN/KjOzYwc4yE1nLn0I/tmmT8Wbfbo4kWcHHl6aV3+ST5l2EvHMP3MfWVbTPihTJol7 lLqGFcVNOXMQcTLfR0ZVcewDfGm+07TbMjUSr7CgVUC55+bR7RExyApS9/5sHIzhnDQ6PXZP6Jh pusVBTVIhmfHN4Wxfl54ZfyHb3avJdp8wYgsNSfUCFJsugHRC89+8dS0NZBR6URsTeiE+lZP7gn CpsMnK5Da0wetuyeyEE26ZF8wEwILuhQZ2X9n2XMGPVc= X-Google-Smtp-Source: AGHT+IEnwkRQyoajQ+wzO1OBiSDoxbHYacNaBxleMIW05ToiFEKgPiq2iScaYZJlnmLRKoKx53Yw3Q== X-Received: by 2002:a05:6a21:33a8:b0:243:9b4e:281b with SMTP id adf61e73a8af0-243d6f40ef6mr14322782637.49.1756799457122; Tue, 02 Sep 2025 00:50:57 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 1/9] contrib/plugins/uftrace: skeleton file Date: Tue, 2 Sep 2025 00:50:34 -0700 Message-ID: <20250902075042.223990-2-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-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: 1756799549555116600 Content-Type: text/plain; charset="utf-8" We define a scoreboard that will hold our data per cpu. As well, we define a buffer per cpu that will be used to read registers and memories in a thread-safe way. For now, we just instrument all instructions with an empty callback. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 73 +++++++++++++++++++++++++++++++++++++ contrib/plugins/meson.build | 3 +- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 contrib/plugins/uftrace.c diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c new file mode 100644 index 00000000000..4af0130b159 --- /dev/null +++ b/contrib/plugins/uftrace.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2025, Pierrick Bouvier + * + * Generates a trace compatible with uftrace (similar to uftrace record). + * https://github.com/namhyung/uftrace + * + * See docs/about/emulation.rst|Uftrace for details and examples. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; + +typedef struct Cpu { + GByteArray *buf; +} Cpu; + +static struct qemu_plugin_scoreboard *score; + +static void track_callstack(unsigned int cpu_index, void *udata) +{ +} + +static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) +{ + size_t n_insns =3D qemu_plugin_tb_n_insns(tb); + + for (size_t i =3D 0; i < n_insns; i++) { + struct qemu_plugin_insn *insn =3D qemu_plugin_tb_get_insn(tb, i); + + uintptr_t pc =3D qemu_plugin_insn_vaddr(insn); + qemu_plugin_register_vcpu_insn_exec_cb(insn, track_callstack, + QEMU_PLUGIN_CB_R_REGS, + (void *) pc); + } +} + +static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) +{ + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); + cpu->buf =3D g_byte_array_new(); +} + +static void vcpu_end(unsigned int vcpu_index) +{ + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); + g_byte_array_free(cpu->buf, true); + memset(cpu, 0, sizeof(Cpu)); +} + +static void at_exit(qemu_plugin_id_t id, void *data) +{ + for (size_t i =3D 0; i < qemu_plugin_num_vcpus(); ++i) { + vcpu_end(i); + } + + qemu_plugin_scoreboard_free(score); +} + +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, + const qemu_info_t *info, + int argc, char **argv) +{ + score =3D qemu_plugin_scoreboard_new(sizeof(Cpu)); + qemu_plugin_register_vcpu_init_cb(id, vcpu_init); + qemu_plugin_register_atexit_cb(id, at_exit, NULL); + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); + + return 0; +} diff --git a/contrib/plugins/meson.build b/contrib/plugins/meson.build index 1876bc78438..7eb3629c95d 100644 --- a/contrib/plugins/meson.build +++ b/contrib/plugins/meson.build @@ -1,5 +1,6 @@ contrib_plugins =3D ['bbv', 'cache', 'cflow', 'drcov', 'execlog', 'hotbloc= ks', - 'hotpages', 'howvec', 'hwprofile', 'ips', 'stoptrigger'] + 'hotpages', 'howvec', 'hwprofile', 'ips', 'stoptrigger', + 'uftrace'] if host_os !=3D 'windows' # lockstep uses socket.h contrib_plugins +=3D 'lockstep' --=20 2.47.2 From nobody Sun Sep 28 16:37:05 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=1756799535; cv=none; d=zohomail.com; s=zohoarc; b=D1Le+bK5guMaQyVxcX5CZ/C0AqrbE4FuPZtWongLiGFIr3/Fe6Nk0e8c+CC+9mK8XVh/qkXi8ww+TP/NYB3CieAwcf+txVLlXBgqVDF1deHjvK22RlnlTKyiakQ3Jv6Kk65y6/LFS7WaPglAPVUTgf2nBK9YDR6ByfY10K4AxcY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799535; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=UCnnXWfvqtRCVbfN0E52T8SkudA5RqZI+yQNyvWP9uU=; b=Rt6hTO2F5AwRWCvWQPsI3kcjsywYe19tiITvWefngQkvQv2mTrwQqo1uGbSnm1BH5cdtMBhNY+QgY+qxicjOnLwwbbQt0ehZ7C/N/Rk+oqJFrUHYZ+dZEm308uanoEjn8ZeDWgDNax6jfxKMr25ElYmreR2cSTU4oNGd+JRLbE4= 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 175679953558148.72881452294314; Tue, 2 Sep 2025 00:52:15 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnS-00078A-Cd; Tue, 02 Sep 2025 03:51:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1utLnF-000746-MI for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:06 -0400 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1utLnB-0001uj-F5 for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:05 -0400 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-7724fe9b24dso1321260b3a.2 for ; Tue, 02 Sep 2025 00:50:59 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.50.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:50:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799458; x=1757404258; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UCnnXWfvqtRCVbfN0E52T8SkudA5RqZI+yQNyvWP9uU=; b=u91A5c6mTBnXlzyPcpFEK89nx9DpqbO7cMZMPnfLGU0agHKeJ1sZZLxOc57lOnNqCq BM1K10hI1Mr+5KjFBvEV6HR9RLC20RXUc0US0M4GZTJ6ZKnlw5WtmiAjBVMeMStqaPRS j88FL8UeRUWrPZBEyu06RJNHLJCN9P4XUlM2mmcNGKz1XJj7usdGVfKTD1zy9VxpUp9L UZcaGOhrJbdZEbbsqmGvHhi48hXBUrq30O1KQfr/rXIk2grcRD2BxJnkaQdrCyR+eCLt vffzf06Bev8ne7GwBeq7CgW/4r8Yxr/3B+TofVu5FsYhYUzUbaLSZ7w676au8UUPEQk5 MwVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799458; x=1757404258; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UCnnXWfvqtRCVbfN0E52T8SkudA5RqZI+yQNyvWP9uU=; b=s+yFwckHlFa+x+i28S+7E+PbEVIR+lQxQoqjkSgY+XXuF1Dm+SD6aqQ/m7O7HSPZVz NQvKQng8tvQ0xW5XPymgDTDnwGVzcThpMdFzYoKDTKNoVW4nb9puwmYKA0Yq5j0xsTy0 KNo9Che60Y/MtdLkzyE6OJz85oYKk388hoepirpmyyR5IMf5FqfoFsdPfg4wqPn4Xc2S 7A8Ec6FmwJzlsbhEjxxFxuF2GSU85+6NMSNWnHmxQW0hfLzZ8Y+23GtMbGB1fmlzPHjq kDJNvGsnCu6izTkIz56TQIxMwUYrnzVjmr/uDyhjB6Y/T7G+Us0QEuhLZ2bY414e52gm 6jgQ== X-Forwarded-Encrypted: i=1; AJvYcCUOJr4xTvPcF87fi/yyDVWOzbvQP2FXeZGpVgVh4yv6FU9mlUbM2+MhSXgkenVtU5dJIIniqS+9vkct@nongnu.org X-Gm-Message-State: AOJu0YwpO2TKSOJn41U1/0iqHP9B9ng++V5rg82fYLQ0ZWtaULxs2EGY U1tDI/ctRr9c5584RuGf3NUqCGuPCfNo43HcwqyhbRN7D8TQmoeGC4mW4vTdAGAFF0k= X-Gm-Gg: ASbGncu2o3qhvxyZW9dKG5BIVJ6Tl1pRBZ3OxfEK3G/ROFR7snSJ+absufwJB0PyrtO YWKqnEefM8unSgvArdSPS72sgxhDEdQIXKivmDAppcN8DmF7WUFkxCWVqvjpUixy6yuD5wYNGj3 OxfwpZt5VrykrVOJEUivfAwp7OVOTfDacqH6VtFUY5hfSVkxCqrKu8GKncC0SMsftrxwXuErtrO E7OhMIC/ytTaIDasez319/QYkmqaHcqTGEeTOqam50vyjaCTmsi4Evl3bjYeZC9OHwtCm4gO3pZ LHiNvFhjDNDWAZzJq+HWEa9meJVgDXn8S78PnFsFZMAlkGarMR8/r58YZS00F+W+LvKivaP3wMl co2FCRQ25fdLlk6Whj9PRg5+7LdGdLedlD3VJcbzOQxg= X-Google-Smtp-Source: AGHT+IEXH6812YMC6JXK/8H0qgo14yZvWDYyItBrePQ1REDgL2+4/WWr38CWEXmUCZ7bxz5eGXfzLw== X-Received: by 2002:a05:6a20:9144:b0:243:c6d1:777a with SMTP id adf61e73a8af0-243d6e5fb90mr16019365637.26.1756799457959; Tue, 02 Sep 2025 00:50:57 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 2/9] contrib/plugins/uftrace: define cpu operations and implement aarch64 Date: Tue, 2 Sep 2025 00:50:35 -0700 Message-ID: <20250902075042.223990-3-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::429; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x429.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1756799537521116600 Content-Type: text/plain; charset="utf-8" We define a new CpuOps structure that will be used to implement tracking independently of guest architecture. As well, we now instrument only instructions following ones that might have touched the frame pointer. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 114 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 4 deletions(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 4af0130b159..d060513446c 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -11,14 +11,94 @@ =20 #include #include +#include =20 QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; =20 +typedef struct Cpu Cpu; + +typedef struct { + void (*init)(Cpu *cpu); + void (*end)(Cpu *cpu); + uint64_t (*get_frame_pointer)(Cpu *cpu); + bool (*does_insn_modify_frame_pointer)(const char *disas); +} CpuOps; + typedef struct Cpu { GByteArray *buf; + CpuOps ops; + void *arch; } Cpu; =20 +typedef struct { + struct qemu_plugin_register *reg_fp; +} Aarch64Cpu; + static struct qemu_plugin_scoreboard *score; +static CpuOps arch_ops; + +static uint64_t cpu_read_register64(Cpu *cpu, struct qemu_plugin_register = *reg) +{ + GByteArray *buf =3D cpu->buf; + g_byte_array_set_size(buf, 0); + size_t sz =3D qemu_plugin_read_register(reg, buf); + g_assert(sz =3D=3D 8); + g_assert(buf->len =3D=3D 8); + return *((uint64_t *) buf->data); +} + +static struct qemu_plugin_register *plugin_find_register(const char *name) +{ + g_autoptr(GArray) regs =3D qemu_plugin_get_registers(); + for (int i =3D 0; i < regs->len; ++i) { + qemu_plugin_reg_descriptor *reg; + reg =3D &g_array_index(regs, qemu_plugin_reg_descriptor, i); + if (!strcmp(reg->name, name)) { + return reg->handle; + } + } + return NULL; +} + +static uint64_t aarch64_get_frame_pointer(Cpu *cpu_) +{ + Aarch64Cpu *cpu =3D cpu_->arch; + return cpu_read_register64(cpu_, cpu->reg_fp); +} + +static void aarch64_init(Cpu *cpu_) +{ + Aarch64Cpu *cpu =3D g_new0(Aarch64Cpu, 1); + cpu_->arch =3D cpu; + cpu->reg_fp =3D plugin_find_register("x29"); + if (!cpu->reg_fp) { + fprintf(stderr, "uftrace plugin: frame pointer register (x29) is n= ot " + "available. Please use an AArch64 cpu (or -cpu max= ).\n"); + g_abort(); + } +} + +static void aarch64_end(Cpu *cpu) +{ + g_free(cpu->arch); +} + +static bool aarch64_does_insn_modify_frame_pointer(const char *disas) +{ + /* + * Check if current instruction concerns fp register "x29". + * We add a prefix space to make sure we don't match addresses dump + * in disassembly. + */ + return strstr(disas, " x29"); +} + +static CpuOps aarch64_ops =3D { + .init =3D aarch64_init, + .end =3D aarch64_end, + .get_frame_pointer =3D aarch64_get_frame_pointer, + .does_insn_modify_frame_pointer =3D aarch64_does_insn_modify_frame_poi= nter, +}; =20 static void track_callstack(unsigned int cpu_index, void *udata) { @@ -28,19 +108,37 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct = qemu_plugin_tb *tb) { size_t n_insns =3D qemu_plugin_tb_n_insns(tb); =20 + /* + * Callbacks and inline instrumentation are inserted before an instruc= tion. + * Thus, to see instruction effect, we need to wait for next one. + * Potentially, the last instruction of a block could modify the frame + * pointer. Thus, we need to always instrument first instruction in a = tb. + */ + bool instrument_insn =3D true; for (size_t i =3D 0; i < n_insns; i++) { struct qemu_plugin_insn *insn =3D qemu_plugin_tb_get_insn(tb, i); =20 - uintptr_t pc =3D qemu_plugin_insn_vaddr(insn); - qemu_plugin_register_vcpu_insn_exec_cb(insn, track_callstack, - QEMU_PLUGIN_CB_R_REGS, - (void *) pc); + if (instrument_insn) { + uintptr_t pc =3D qemu_plugin_insn_vaddr(insn); + qemu_plugin_register_vcpu_insn_exec_cb(insn, track_callstack, + QEMU_PLUGIN_CB_R_REGS, + (void *) pc); + instrument_insn =3D false; + } + + char *disas =3D qemu_plugin_insn_disas(insn); + if (arch_ops.does_insn_modify_frame_pointer(disas)) { + instrument_insn =3D true; + } } } =20 static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); + cpu->ops =3D arch_ops; + + cpu->ops.init(cpu); cpu->buf =3D g_byte_array_new(); } =20 @@ -64,6 +162,14 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_= id_t id, const qemu_info_t *info, int argc, char **argv) { + if (!strcmp(info->target_name, "aarch64")) { + arch_ops =3D aarch64_ops; + } else { + fprintf(stderr, "plugin uftrace: %s target is not supported\n", + info->target_name); + return 1; + } + score =3D qemu_plugin_scoreboard_new(sizeof(Cpu)); qemu_plugin_register_vcpu_init_cb(id, vcpu_init); qemu_plugin_register_atexit_cb(id, at_exit, NULL); --=20 2.47.2 From nobody Sun Sep 28 16:37:05 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=1756799543; cv=none; d=zohomail.com; s=zohoarc; b=OMbewQqkp+2i54ukUd4qyNvosy/EdywrbydVLutb2OQvnPT+v7i6Pzpq4Uqo2+GA3VxZSyOQ1VYrsE6pYpwHdfVCv3YB6kP2u76sjAYU+tJ9ONK59vS607xc5FwQKwCHo/XdSGVqVBh0kdx43mtda9z3FfmOdQknxnnyplEpsGQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799543; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=n8jo0LSSh8lJpsdcimtvOxocpTr/cr5eTG3kdaxxUXg=; b=YqFPqH1I8rtB+kNMkhj3KLC86KHTaEo+jpNAYoKJloVNea2I/gBzga5JI7Q6cB6HeJUKm+QUyfLzkrSky/HvtvFmFIUyHNzsZn+UXRyja+Qv8K91ZfSdp50i+22V8xQNCOXChq9ozrhMCb1Viv8updBClS21djmH2eRFoDOkVGU= 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 1756799543560149.12023037435188; Tue, 2 Sep 2025 00:52:23 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnP-00077J-Ar; Tue, 02 Sep 2025 03:51:15 -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 1utLnG-000749-8O for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:06 -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 1utLnB-0001un-F6 for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:06 -0400 Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-76e2ea933b7so4174311b3a.1 for ; Tue, 02 Sep 2025 00:50:59 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.50.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:50:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799459; x=1757404259; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=n8jo0LSSh8lJpsdcimtvOxocpTr/cr5eTG3kdaxxUXg=; b=DqCN0h6YmYXM/ZmVGyYIy0OHoaFD3f6Uz3BX2WBSkCWvxAZ+kqGMZuuKcqmnYo/X8x sXojiVeglqcmsPj/v4qB98Ju0diVhne2E4ynwNNwH0aw3oXU0rBq+kBXckqWLFHVzU8A dhmQToWJB3D1RYTPvz8mFv+7gg4lyHqsWF0peH1jFNVx59alcVY7c7UrAa5MuZoRbyK3 Ei0PtO9BEiJgTf80nD7BDpaIlh/RuuRNww3VA/P7O4XHR8bMrZkEGUk7hxv7AsK1bIzP o8sPLWDnNyqvA5JI+r2X7BfdseTwKbh+WB7MuFCPyvFCwDEIksOHXijhnFBHrNV9yCAV klBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799459; x=1757404259; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=n8jo0LSSh8lJpsdcimtvOxocpTr/cr5eTG3kdaxxUXg=; b=pK702/HXJxFut9nyDqAwjt0G0TZq1w7rY/RPT4+0IsQvRHA+xBMOGZt3hc6A2etTHT meKKCTCB8AdXjs/nUcWNkMkRxcBgE40PNs9rS34KhVnIk8jG8jnLTktZukzJTDMkwBhV 8suN4ZSCOFtG/9flY7KtlL7/grkT/52+E+feuYQyZ0BVinGgXjp9JPs3jwqAoEYe8K11 XaFnYdrzaBjhhdh9lNVaxVzPDhrY9JsW8/1cNHZ0AuivMmkuutTMl6J+B6xA6xNYRCTL ibao4tXtvxUxQ7X5iDUp1zz8ZOszzcvc/BmYz6wZOXF+IO/od677ZQQj8xXV/WdCJW30 bN9Q== X-Forwarded-Encrypted: i=1; AJvYcCXGsRB+bUXBedneI0rVT5AZryerehnSbgAG5QqfnWlS5Xkgh5bKxgQG6TQ/GeGk5vkfS1jQHjXCR7ww@nongnu.org X-Gm-Message-State: AOJu0YzifOsbakYOy0Tpb5PryL1eIqYwCaAwynzmhhjO/reqAfaH+Qaa +c1SkWHVYAZfpcC6t9T4565SfJbkmWCrG12H+OtMwUAiPIiuFx2oY9eMlrPylE3AdGc= X-Gm-Gg: ASbGncsTwzK4AQQbkz9dL2kNOcvFEsfIcaIY4xd28BqjluxZ8JEp2cwi095RYWEz0Iu nf0PykleDprr+23hzS7mTcDXYouqSTyb2aoFyKsZiNCwSmhpDjCDXnaB+xTdEjh+1Qd3/Jt72hv xelP98oa9Jg8cRQsy7p/8ioxPr0PiT88/kbHQPbirDbzAavO3z8/elaM1tS4yk7LtRTXluLLkAf OPZ1V/HvpE9VrfOdgUGaZyYU5zB0WzS9alN9tLnSF9dvYNlj2dpLg220T6Qfhklim18PkoG+J+S j6O0pgX3zSGMCvnHX3mL2kaXMV2w78LWuped6jW9733OAvpV9T4UovRXBPGDeovlIxHtjUU8yXj uSM5zWpGUOnO9SDkuf1os5NhUT69S+YnPV7vACAyRgaw= X-Google-Smtp-Source: AGHT+IHZPc12v5wUMl4IagFfd4ZJIviALA2uvv6Etzy1rXPfhLTYsmFNpgm3aASFqDx0xeiRN7u/YA== X-Received: by 2002:a05:6a00:5a:b0:772:44c4:4e23 with SMTP id d2e1a72fcca58-77244c45955mr8476062b3a.6.1756799458839; Tue, 02 Sep 2025 00:50:58 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 3/9] contrib/plugins/uftrace: track callstack Date: Tue, 2 Sep 2025 00:50:36 -0700 Message-ID: <20250902075042.223990-4-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-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: 1756799544711124100 Content-Type: text/plain; charset="utf-8" We now track callstack, based on frame pointer analysis. We can detect function calls, returns, and discontinuities. We implement a frame pointer based unwinding that is used for discontinuities. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 160 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index d060513446c..bb775916270 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -15,6 +15,15 @@ =20 QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; =20 +typedef struct { + GArray *s; +} Callstack; + +typedef struct { + uint64_t pc; + uint64_t frame_pointer; +} CallstackEntry; + typedef struct Cpu Cpu; =20 typedef struct { @@ -25,6 +34,7 @@ typedef struct { } CpuOps; =20 typedef struct Cpu { + Callstack *cs; GByteArray *buf; CpuOps ops; void *arch; @@ -37,6 +47,71 @@ typedef struct { static struct qemu_plugin_scoreboard *score; static CpuOps arch_ops; =20 +static Callstack *callstack_new(void) +{ + Callstack *cs =3D g_new0(Callstack, 1); + cs->s =3D g_array_new(false, false, sizeof(CallstackEntry)); + return cs; +} + +static void callstack_free(Callstack *cs) +{ + g_array_free(cs->s, true); + cs->s =3D NULL; + g_free(cs); +} + +static size_t callstack_depth(const Callstack *cs) +{ + return cs->s->len; +} + +static size_t callstack_empty(const Callstack *cs) +{ + return callstack_depth(cs) =3D=3D 0; +} + +static void callstack_clear(Callstack *cs) +{ + g_array_set_size(cs->s, 0); +} + +static const CallstackEntry *callstack_at(const Callstack *cs, size_t dept= h) +{ + g_assert(depth > 0); + g_assert(depth <=3D callstack_depth(cs)); + return &g_array_index(cs->s, CallstackEntry, depth - 1); +} + +static CallstackEntry callstack_top(const Callstack *cs) +{ + if (callstack_depth(cs) >=3D 1) { + return *callstack_at(cs, callstack_depth(cs)); + } + return (CallstackEntry){}; +} + +static CallstackEntry callstack_caller(const Callstack *cs) +{ + if (callstack_depth(cs) >=3D 2) { + return *callstack_at(cs, callstack_depth(cs) - 1); + } + return (CallstackEntry){}; +} + +static void callstack_push(Callstack *cs, CallstackEntry e) +{ + g_array_append_val(cs->s, e); +} + +static CallstackEntry callstack_pop(Callstack *cs) +{ + g_assert(!callstack_empty(cs)); + CallstackEntry e =3D callstack_top(cs); + g_array_set_size(cs->s, callstack_depth(cs) - 1); + return e; +} + static uint64_t cpu_read_register64(Cpu *cpu, struct qemu_plugin_register = *reg) { GByteArray *buf =3D cpu->buf; @@ -47,6 +122,50 @@ static uint64_t cpu_read_register64(Cpu *cpu, struct qe= mu_plugin_register *reg) return *((uint64_t *) buf->data); } =20 +static uint64_t cpu_read_memory64(Cpu *cpu, uint64_t addr) +{ + g_assert(addr); + GByteArray *buf =3D cpu->buf; + g_byte_array_set_size(buf, 0); + bool read =3D qemu_plugin_read_memory_vaddr(addr, buf, 8); + if (!read) { + return 0; + } + g_assert(buf->len =3D=3D 8); + return *((uint64_t *) buf->data); +} + +static void cpu_unwind_stack(Cpu *cpu, uint64_t frame_pointer, uint64_t pc) +{ + g_assert(callstack_empty(cpu->cs)); + + #define UNWIND_STACK_MAX_DEPTH 1024 + CallstackEntry unwind[UNWIND_STACK_MAX_DEPTH]; + size_t depth =3D 0; + do { + /* check we don't have an infinite stack */ + for (size_t i =3D 0; i < depth; ++i) { + if (frame_pointer =3D=3D unwind[i].frame_pointer) { + break; + } + } + CallstackEntry e =3D {.frame_pointer =3D frame_pointer, .pc =3D pc= }; + unwind[depth] =3D e; + depth++; + if (frame_pointer) { + frame_pointer =3D cpu_read_memory64(cpu, frame_pointer); + } + pc =3D cpu_read_memory64(cpu, frame_pointer + 8); /* read previous= lr */ + } while (frame_pointer && pc && depth < UNWIND_STACK_MAX_DEPTH); + #undef UNWIND_STACK_MAX_DEPTH + + /* push it from bottom to top */ + while (depth) { + callstack_push(cpu->cs, unwind[depth - 1]); + --depth; + } +} + static struct qemu_plugin_register *plugin_find_register(const char *name) { g_autoptr(GArray) regs =3D qemu_plugin_get_registers(); @@ -102,6 +221,43 @@ static CpuOps aarch64_ops =3D { =20 static void track_callstack(unsigned int cpu_index, void *udata) { + uint64_t pc =3D (uintptr_t) udata; + Cpu *cpu =3D qemu_plugin_scoreboard_find(score, cpu_index); + Callstack *cs =3D cpu->cs; + + uint64_t fp =3D cpu->ops.get_frame_pointer(cpu); + if (!fp && callstack_empty(cs)) { + /* + * We simply push current pc. Note that we won't detect symbol cha= nge as + * long as a proper call does not happen. + */ + callstack_push(cs, (CallstackEntry){.frame_pointer =3D fp, .pc =3D= pc}); + return; + } + + CallstackEntry top =3D callstack_top(cs); + if (fp =3D=3D top.frame_pointer) { + /* same function */ + return; + } + + CallstackEntry caller =3D callstack_caller(cs); + if (fp =3D=3D caller.frame_pointer) { + /* return */ + callstack_pop(cs); + return; + } + + uint64_t caller_fp =3D fp ? cpu_read_memory64(cpu, fp) : 0; + if (caller_fp =3D=3D top.frame_pointer) { + /* call */ + callstack_push(cs, (CallstackEntry){.frame_pointer =3D fp, .pc =3D= pc}); + return; + } + + /* discontinuity, exit current stack and unwind new one */ + callstack_clear(cs); + cpu_unwind_stack(cpu, fp, pc); } =20 static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) @@ -140,12 +296,16 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned i= nt vcpu_index) =20 cpu->ops.init(cpu); cpu->buf =3D g_byte_array_new(); + + cpu->cs =3D callstack_new(); } =20 static void vcpu_end(unsigned int vcpu_index) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); g_byte_array_free(cpu->buf, true); + + callstack_free(cpu->cs); memset(cpu, 0, sizeof(Cpu)); } =20 --=20 2.47.2 From nobody Sun Sep 28 16:37:05 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=1756799575; cv=none; d=zohomail.com; s=zohoarc; b=a0R5HbHtZjK63oPZD/S0PkrIeDpbdBrZF5ZTwOGoOWHhTlbb3224A3NJbmODox1wRyCUxdn22zg6lHf2cRZEprN6QxkLB2NSpkz1SKjE6WEfkt3o6ZdxgH7shMWPhcO3mHeS0B/W2iHFpbIOHaQRAlMc/BRrN+RgYaNFoogb0RQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799575; h=Content-Type: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=GSfyk/HqfC8n0v5Y6ucX/C1jK6jRJAOoqt5Ytsqhg8I=; b=DIG9slabQTvxAXDfvl7B43zQmYGoSiyCVKviMr4oq8Ag9Gs0uzYzjV9wdq15ep14wWhsi8p2Mv/JO8wLejGVBpS96Mmd5TtPgJda0ZJ+hj7iA2Yyil5Xy0UFw6W+JoZF3nJrFbKqqbIc+lEgvtUIzLjDxB/89jrS7C2ynvQBlzI= 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 1756799575402431.6643323861755; Tue, 2 Sep 2025 00:52:55 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnT-00079O-EI; Tue, 02 Sep 2025 03:51:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1utLnF-000748-OQ for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:06 -0400 Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1utLnB-0001uv-FJ for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:05 -0400 Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-7725fb32e1bso1662428b3a.1 for ; Tue, 02 Sep 2025 00:51:00 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.50.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:50:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799460; x=1757404260; 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=GSfyk/HqfC8n0v5Y6ucX/C1jK6jRJAOoqt5Ytsqhg8I=; b=hIj2zzeqoztzjoH6De5HCvwOmM8gKx6oE3l71L9QYPgHCK3NZx6alJZTLlfArBt4aF mNES1aNfNzDJT9I+423aMYovkVEnHLUelrC0DpFQQEqjCqeOQFmb4wSVt2QQNaHEKfNv 6noI2T0ve35N+EwoQYTiyM1fft16GkkHzVXWdTSysMlDUFG4IovSlWTG69kfEPQL9env tpeB4LM5wtigjlRNfPb4FW6QTNl+TYRbNofKxKtzUwIsQ+SF2leiwC/GyJcCwg9v6uGX SeOmmfIw2Inqf9fuw3X/f/JsLP1KbhSI4csWabrqCcCDE1NqaSX0FKH/v/YROsPZCId1 4bOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799460; x=1757404260; 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=GSfyk/HqfC8n0v5Y6ucX/C1jK6jRJAOoqt5Ytsqhg8I=; b=Y2njTo8s8CjPIk9/2sIcxK3LVFJ+WTom603Sk4cTZIdSJLXd8ZeC0BwMMNwiB5c4vP b0vVugL//sOw5hLCnxeezXPM0ehMNYPdlITaNMdcsAofYWyp++E7qjkh2N0UCvUdmtMV qHcQbuCZrQ7fq8+M2ALSRviUUg038K+EVlEgyMU7ffUSPe2Yd9BVIbL53CNwcySboN5e HvzXhQH4WRvYr6yZokSUXboiUt/JqrLZDJhFiQA+/BdiWcfrEltXIdApSaaNSAqgCnUR 1xn3oIaYu8v7GJbyfN46EghE1ohdVUrheoqX0NTlj00YT9uoqMUPA/OSB7vt0ym2pHU5 g7vw== X-Forwarded-Encrypted: i=1; AJvYcCW+w2iI6TQPCMctcLpAGo1r12R+09U3Zlw8CR2y2luvJt+dymzLs9OZH86ROyz45kSV1F6S3N7RnXLy@nongnu.org X-Gm-Message-State: AOJu0YyZfi4jFQUTF22t+UtX+ZI4/W3D10c0mCPVA/QcR6GB1rZbVQ1B Fc2rx8l5P/AN60D7o3g+l0xzLRMKfhtJ5raAjxiCSNWbDfAI25zXyevDgOB6mDls0Qc= X-Gm-Gg: ASbGncsDkTOl3jLzi8soV4ZdbB4SThj8eGgmHrzAD4muaXm26wUvVXpaDU50SR06sS3 nlh03GE87xSG0tKwkDvqP79+RI82pglmZ8cYSFMHggVDDzkyKM371e8ZDI5zhXHc1o1Q6x8Qxbc ZletQZZosCK4GkmvjZKDrp/JZAYYwRs/aszlkePMU56rU2B/FpXZw2JbFUMQq6tcki69du66A7v /NFEiJqAdbh41pcpE+DEgSdWGS/zfu++9QfXJzHf8hGf6YLhOwGPgQ57zaOp6RDoePOWJmTqmxo 3b5TY3pcz4I+O4y71di90JTvFP6RmZtU7AEwDnsOLVlLHf9/l3AUnRUfdI3nRojMt39AQF3gtOd VatSkCpv0pMlCNO0g/cM8o8tElC2eRigL3g4Arvt4TzP3QnET9I8DGg== X-Google-Smtp-Source: AGHT+IHVgHvKowN7epw1lJQIRwVAyrPE2dXskSXU0sXIDANUX0/5LF+Kp5EdXHxPwV/MQzN5DQSYYg== X-Received: by 2002:a05:6a00:2e08:b0:76b:f8ee:4eaa with SMTP id d2e1a72fcca58-7723e24ff0cmr12199348b3a.9.1756799459811; Tue, 02 Sep 2025 00:50:59 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 4/9] contrib/plugins/uftrace: implement tracing Date: Tue, 2 Sep 2025 00:50:37 -0700 Message-ID: <20250902075042.223990-5-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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::42d; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x42d.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: 1756799577361124100 We implement tracing, following uftrace format. Trace is flushed every 32 MB, so file operations don't impact performance at runtime. A different trace is generated per cpu, and we ensure they have a unique name, based on vcpu_index, while keeping room for privilege level coming in next commit. Uftrace format is not officially documented, but it can be found here: https://github.com/namhyung/uftrace/blob/v0.18/libmcount/record.c#L909 Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 152 +++++++++++++++++++++++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index bb775916270..b9dcd531987 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -12,6 +12,15 @@ #include #include #include +#include +#include +#include +#include + +#define MiB (INT64_C(1) << 20) +#define NANOSECONDS_PER_SECOND 1000000000LL +#define TRACE_FLUSH_SIZE (32 * MiB) +#define TRACE_ID_SCALE 100 =20 QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; =20 @@ -24,6 +33,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 +50,7 @@ typedef struct { } CpuOps; =20 typedef struct Cpu { + Trace *trace; Callstack *cs; GByteArray *buf; CpuOps ops; @@ -44,9 +61,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 +161,86 @@ static CallstackEntry callstack_pop(Callstack *cs) return e; } =20 +static Trace *trace_new(uint32_t id, GString *name) +{ + Trace *t =3D g_new0(Trace, 1); + t->t =3D g_array_new(false, false, sizeof(UftraceEntry)); + t->path =3D g_string_new(NULL); + g_string_append_printf(t->path, "./uftrace.data/%"PRIu32".dat", id); + t->name =3D g_string_new(name->str); + t->id =3D id; + return t; +} + +static void trace_free(Trace *t) +{ + g_assert(t->t->len =3D=3D 0); + g_array_free(t->t, true); + t->t =3D NULL; + g_string_free(t->path, true); + t->path =3D NULL; + g_string_free(t->name, true); + t->name =3D NULL; + g_free(t); +} + +static void trace_flush(Trace *t, bool append) +{ + int create_dir =3D g_mkdir_with_parents("./uftrace.data", + S_IRWXU | S_IRWXG | S_IRWXO); + g_assert(create_dir =3D=3D 0); + FILE *dat =3D fopen(t->path->str, append ? "a" : "w"); + g_assert(dat); + GArray *data =3D t->t; + if (data->len) { + size_t wrote =3D fwrite(data->data, sizeof(UftraceEntry), data->le= n, dat); + g_assert(wrote =3D=3D data->len); + } + fclose(dat); + g_array_set_size(data, 0); +} + +static void trace_add_entry(Trace *t, uint64_t timestamp, uint64_t pc, + size_t depth, UftraceRecordType type) +{ + /* https://github.com/namhyung/uftrace/blob/v0.18/libmcount/record.c#L= 909 */ + const uint64_t record_magic =3D 0x5; + uint64_t data =3D type | (record_magic << 3); + data +=3D depth << 6; + data +=3D pc << 16; + UftraceEntry e =3D {.timestamp =3D timestamp, .data =3D data}; + g_array_append_val(t->t, e); + if (t->t->len * sizeof(UftraceEntry) > TRACE_FLUSH_SIZE) { + 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 +352,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 +363,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 +376,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 +385,16 @@ static void track_callstack(unsigned int cpu_index, v= oid *udata) if (caller_fp =3D=3D top.frame_pointer) { /* call */ callstack_push(cs, (CallstackEntry){.frame_pointer =3D fp, .pc =3D= pc}); + trace_enter_function(t, timestamp, pc, callstack_depth(cs)); return; } =20 /* discontinuity, exit current stack and unwind new one */ + trace_exit_stack(t, cs, timestamp); callstack_clear(cs); + cpu_unwind_stack(cpu, fp, pc); + trace_enter_stack(t, cs, timestamp); } =20 static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) @@ -297,6 +434,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 / TRACE_ID_SCALE); + /* trace_id is: cpu_number * TRACE_ID_SCALE */ + uint32_t trace_id =3D (vcpu_index + 1) * TRACE_ID_SCALE; + + g_autoptr(GString) trace_name =3D g_string_new(NULL); + g_string_append_printf(trace_name, "cpu%u", vcpu_index); + cpu->trace =3D trace_new(trace_id, trace_name); + /* create/truncate trace file */ + trace_flush(cpu->trace, false); + cpu->cs =3D callstack_new(); } =20 @@ -305,6 +452,7 @@ static void vcpu_end(unsigned int vcpu_index) Cpu *cpu =3D qemu_plugin_scoreboard_find(score, vcpu_index); g_byte_array_free(cpu->buf, true); =20 + trace_free(cpu->trace); callstack_free(cpu->cs); memset(cpu, 0, sizeof(Cpu)); } @@ -312,6 +460,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 Sep 28 16:37:05 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=1756799567; cv=none; d=zohomail.com; s=zohoarc; b=XAjY2kHLY0zs4wGy3pp9srk2noMLgI/H4n/sXK5Io79CPNIMyPlulsalaz6qR+NtSEoudyyso+Tchxm3PGO4lbLPUeUeRc7hb7fi7Au5j9Oc8+E0H4Q5jD8LIKZUgAuzngaBD8uGu+TU16D5svgxyYFPQTJ+mBHgLqwwkzJMELI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799567; 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=er0+oHSby1SsX9Z+9EWvUqCthwUwJ7qhNzavtkJi6RU=; b=f1VWr5sAeDb/l4xAayVILbO0AxomVpypnFggOXymvuLtY9ZrOiUiHnSkbq0iIqWqjs3uschrhUKsmBbKpqnesLE20a2omSlwOdOqM8o8JVMvtb0v1KzkGLz0lNjkI9Yfm8yBV4SKFvIyty1KKZBasO67wezviss2cY6tGaLpQTo= 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 1756799567469436.58403827500365; Tue, 2 Sep 2025 00:52:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnR-00077s-LU; Tue, 02 Sep 2025 03:51:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1utLnH-00074W-C4 for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:08 -0400 Received: from mail-pf1-x435.google.com ([2607:f8b0:4864:20::435]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1utLnC-0001v3-78 for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:06 -0400 Received: by mail-pf1-x435.google.com with SMTP id d2e1a72fcca58-77238a3101fso1891644b3a.0 for ; Tue, 02 Sep 2025 00:51:01 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.50.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:51:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799461; x=1757404261; 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=er0+oHSby1SsX9Z+9EWvUqCthwUwJ7qhNzavtkJi6RU=; b=nHGEVe6Ev5DTBIPbOab80sT+VKvGzksH7C6eGnAtixhLP43vjfN1db2OWpCLAd/N71 4cvZzL4XnREfDt7P4BObLIDZ/toVzUcVgwvhHw9lEAg+MWkgacuRgjL09vOcLQEYgYOv yxnwHQUHifmCuTiKWwKXBcrB/mvFexxiCUuQq1kMprH16u/7dLw3SiaoAZdzBfRJMc5M tlmr+3OP0oHcGLYnTQYfCqNM7BdXNctQiTY5qZWp/55/C53+ahHqsrkiJ67C+L4QsGfe igDoseX/+urePUQh+9WcpLiCEc9eSarEtdHUeOySDHWb0tZsO2wktY6WIz/9IJX9OH7d nooQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799461; x=1757404261; 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=er0+oHSby1SsX9Z+9EWvUqCthwUwJ7qhNzavtkJi6RU=; b=TXySyBUkXwJgvYNg1epwUqKqDlQAfKiBa9FQQ+MoaIfO2PpdRZbpxv6Cs7GzCTufye +xF+TlZ9zkN7YVJ1/A3c+qtw+YFdsKwN6QUkfX9eHFPc2ES5GDwQQy9D/Ci2cPRoMVUA EOViHayUBgc1Tp0yInt1nVik4rlAnxvB8Ibvwv5lIPx3nKXABVhVQOyQitRol7IdYU0R IKaUfQuS+G8yIZbGpO8/fDBsNYp/6hh3bRYQg5bgKqOUxf619F4qpeTY0+7sQIBx/iP6 VwIH2qT5r6cyYRfyIc17UDZssfob9zhzI3TZABDnmDh7sXinp5gEGqRafMV+y+Q75wLk G1qw== X-Forwarded-Encrypted: i=1; AJvYcCUtesT3EcIRCxLj8mfl9w97u3/tU4Ih9LThhUhp3kwkujZ+M9Y8g7ULZRKx5kp3th7aZJ5RYUeJvXot@nongnu.org X-Gm-Message-State: AOJu0YysGoIMSQgzBSvnWPyTKhxAcHsV7x2+DdhEdlDZJc1tZ55fqdQx zxoUArPsbUwYoYvx4ACZdzJalnusXrHGwzbLkCjHHoVVr1t0CPOBjfeFCYiJn0Nb/Ug= X-Gm-Gg: ASbGncsiEpEW98a7mj/tOInhAsIeFq1naC0VqhM+TttKYgXrtOjQ30jWo/9bk4o3pjV rv8Ht7zogHggThSl00lkKuMkuHMn41G5pM4GF8q4E7Zg/kZcGv7RQNI48z4StPQ5OlL0bHnymW0 9TiTQFhUM7xg1Lrd1iSQl/1JXGqVN3s4b2o6QxNDqJKW13jVozhwICwXqRrZyrbDzMLZEaWQa/c YupoU9nYwoM4tf6mVpxSrx6v4AMZM72K3zRHBzHsAjRbCEjFiKf5Y7s56xUb6WUwi85CJh02eLk JE5CPZ/76uNuu/gx5vKbF/ZsWFSNU6rz/jY/rXARJ6lsjB8mUOgA4Ub6jLKhfr76gPg5h5jBYNa MRyUYaUzU/Ajv6IOjf/xtmGfI6YAA324coHgWx356ARvOMlzmTCSR3g== X-Google-Smtp-Source: AGHT+IHgS9VCui+a/c3yg/ET5SeXynWWo0EUdVnnfbFCHb8qyBQT7KJ//VkI1pSnMzMToyQosv482w== X-Received: by 2002:a05:6300:210d:b0:243:a7e0:5113 with SMTP id adf61e73a8af0-243d6f39371mr14868436637.51.1756799460732; Tue, 02 Sep 2025 00:51:00 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 5/9] contrib/plugins/uftrace: implement privilege level tracing Date: Tue, 2 Sep 2025 00:50:38 -0700 Message-ID: <20250902075042.223990-6-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-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::435; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x435.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: 1756799569218124100 Content-Type: text/plain; charset="utf-8" We add new option trace-privilege-level=3Dbool, which will create a separate trace for each privilege level. This allows to follow changes of privilege during execution. We implement aarch64 operations to track current privilege level accordingly. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 190 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 182 insertions(+), 8 deletions(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index b9dcd531987..10abad0673c 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -46,19 +46,40 @@ typedef struct { void (*init)(Cpu *cpu); void (*end)(Cpu *cpu); uint64_t (*get_frame_pointer)(Cpu *cpu); + uint8_t (*get_privilege_level)(Cpu *cpu); + uint8_t (*num_privilege_levels)(void); + const char *(*get_privilege_level_name)(uint8_t pl); bool (*does_insn_modify_frame_pointer)(const char *disas); } CpuOps; =20 typedef struct Cpu { Trace *trace; Callstack *cs; + uint8_t privilege_level; + GArray *traces; /* Trace *traces [] */ GByteArray *buf; CpuOps ops; void *arch; } Cpu; =20 +typedef enum { + AARCH64_EL0_SECURE, + AARCH64_EL0_NONSECURE, + AARCH64_EL0_REALM, + AARCH64_EL1_SECURE, + AARCH64_EL1_NONSECURE, + AARCH64_EL1_REALM, + AARCH64_EL2_SECURE, + AARCH64_EL2_NONSECURE, + AARCH64_EL2_REALM, + AARCH64_EL3, + AARCH64_PRIVILEGE_LEVEL_MAX, +} Aarch64PrivilegeLevel; + typedef struct { struct qemu_plugin_register *reg_fp; + struct qemu_plugin_register *reg_cpsr; + struct qemu_plugin_register *reg_scr_el3; } Aarch64Cpu; =20 typedef struct { @@ -74,6 +95,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) @@ -251,6 +273,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); @@ -308,6 +340,68 @@ static struct qemu_plugin_register *plugin_find_regist= er(const char *name) return NULL; } =20 +static uint8_t aarch64_num_privilege_levels(void) +{ + return AARCH64_PRIVILEGE_LEVEL_MAX; +} + +static const char *aarch64_get_privilege_level_name(uint8_t pl) +{ + switch (pl) { + case AARCH64_EL0_SECURE: return "S-EL0"; + case AARCH64_EL0_NONSECURE: return "NS-EL0"; + case AARCH64_EL0_REALM: return "R-EL0"; + case AARCH64_EL1_SECURE: return "S-EL1"; + case AARCH64_EL1_NONSECURE: return "NS-EL1"; + case AARCH64_EL1_REALM: return "R-EL1"; + case AARCH64_EL2_SECURE: return "S-EL2"; + case AARCH64_EL2_NONSECURE: return "NS-EL2"; + case AARCH64_EL2_REALM: return "R-EL2"; + case AARCH64_EL3: return "EL3"; + default: + g_assert_not_reached(); + } +} + +static uint8_t aarch64_get_privilege_level(Cpu *cpu_) +{ + Aarch64Cpu *cpu =3D cpu_->arch; + /* + * QEMU gdbstub does not provide access to CurrentEL, + * so we use CPSR instead. + */ + uint8_t el =3D cpu_read_register32(cpu_, cpu->reg_cpsr) >> 2 & 0b11; + + if (el =3D=3D 3) { + return AARCH64_EL3; + } + + uint8_t ss =3D AARCH64_EL0_SECURE; + if (!cpu->reg_scr_el3) { + ss =3D AARCH64_EL0_NONSECURE; + } + uint64_t scr_el3 =3D cpu_read_register64(cpu_, cpu->reg_scr_el3); + uint64_t ns =3D (scr_el3 >> 0) & 0b1; + uint64_t nse =3D (scr_el3 >> 62) & 0b1; + switch (nse << 1 | ns) { + case 0b00: + ss =3D AARCH64_EL0_SECURE; + break; + case 0b01: + ss =3D AARCH64_EL0_NONSECURE; + break; + case 0b11: + ss =3D AARCH64_EL0_REALM; + break; + default: + g_assert_not_reached(); + } + + const uint8_t num_ss =3D 3; + Aarch64PrivilegeLevel pl =3D el * num_ss + ss; + return pl; +} + static uint64_t aarch64_get_frame_pointer(Cpu *cpu_) { Aarch64Cpu *cpu =3D cpu_->arch; @@ -324,6 +418,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) @@ -345,9 +443,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; @@ -400,6 +523,13 @@ static void track_callstack(unsigned int cpu_index, vo= id *udata) static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { size_t n_insns =3D qemu_plugin_tb_n_insns(tb); + uintptr_t tb_pc =3D qemu_plugin_tb_vaddr(tb); + + if (trace_privilege_level) { + qemu_plugin_register_vcpu_tb_exec_cb(tb, track_privilege_change, + QEMU_PLUGIN_CB_R_REGS, + (void *) tb_pc); + } =20 /* * Callbacks and inline instrumentation are inserted before an instruc= tion. @@ -433,18 +563,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 / TRACE_ID_SCALE); - /* trace_id is: cpu_number * TRACE_ID_SCALE */ + g_assert(cpu->ops.num_privilege_levels() < TRACE_ID_SCALE); + /* trace_id is: cpu_number * TRACE_ID_SCALE + privilege_level */ uint32_t trace_id =3D (vcpu_index + 1) * TRACE_ID_SCALE; =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) @@ -452,7 +600,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)); } @@ -461,7 +614,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 @@ -472,6 +631,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 Sep 28 16:37:05 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=1756799520; cv=none; d=zohomail.com; s=zohoarc; b=kjggHS/jNkfgVgV7qPH8FVhxNqV7RtD3QLcP8jrTTuQPnW6rHdARjKB0y6zylsemj5LU7FFLE6fiIbpDIH76exbjxFyvsX35GEIL/hzI9Co6lCWJUvbNe0UpQbi5D/gmS3RCS0mqolFFvJnqpKyWN7HsHW9IGJcLopvMRGrdGGo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799520; 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=3getHXPYzZdqMEOFGjHe0lrB5ynIJa8/W9r/FOOowbk=; b=dwbF2gFr1euMMXdKpP1/QpFWQls3niZ4DGz4gKDJccDfGUQBJdJa3QpkGfFmBPzTj9Oi8qFBRjVjX0YbC/IGWLa7dAXpPiYMl6Fvfp6gtFsKrFZmaxCFCJ6Uf8vwLwcU9dZjJypNfPjcERdE30q11wq1mhS5+baSVxTtfbkQU8I= 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 1756799520315418.95961287658724; Tue, 2 Sep 2025 00:52:00 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnQ-00077j-Vs; Tue, 02 Sep 2025 03:51:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1utLnH-00074c-GK for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:08 -0400 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1utLnD-0001vB-98 for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:07 -0400 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-7722f8cf9adso3484723b3a.0 for ; Tue, 02 Sep 2025 00:51:02 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.51.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:51:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799462; x=1757404262; 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=3getHXPYzZdqMEOFGjHe0lrB5ynIJa8/W9r/FOOowbk=; b=hrvQSo3oZyRmaB2RHoutWICRA5qnaMK2TyLVQ81d6qYkk60QGj5CmV09BgRhzwrvLY Y6NavD3dqO2lfsmk16rH2M5JGDuODAPiczTfulYLfRzntQAntJwFz1ZOkSwz7yM69HjG Ux4RYBwkSbQ+5CQZEK9EyO4l5BiJyMH3DjAEXmYeD9ETMjAkd35scht2iUNFr8QEUmyL RPzWYEZtaCGx9Io4TbO4dqBY6ulThScl7dGAJUZ0/wM0EuxoF8v6cz52gOpFKK/xxjvv kQRirsmc77K7ZDkOfk3iOffY4kHTxDC+7ZENzB7jx1ZpXtJK5m9/FqAPPqjoxBT3jpQz cHBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799462; x=1757404262; 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=3getHXPYzZdqMEOFGjHe0lrB5ynIJa8/W9r/FOOowbk=; b=m40lMZyyOLCqEEsyM4xigP4C+jz9q4aDQbNTNlmbS3pSTUZ1hAaejtnqxnOSO0pWsw vK8/Uq9TJicZ+ETF8vXko2y+USZAkVk4YmMqf1Zcu2/qlqiiLk1qgBj2S6S/4wL6e8v4 dek/G62RRniQDwlXx9E0+R3B2lbE+SamXFNmaQ9RLQAjt1HCLhPwpgYQ1QUOkuUg24j6 W+mY2c8f8U4ZIXFFJ6vEXemN8fONuDVJ+2emfKP6GSrxQFyKpNbSSaIMrC0+gLKLsTt3 i2YMrulq0LPECwgWXGoKrlWMM/ExcygSc3+bw+gBAkKxx7YYLs53QJAgp66VGucjWGrX Hm4g== X-Forwarded-Encrypted: i=1; AJvYcCUZbEyB/B8MebXDnDNebGSwOHPMLtkDkWX1+drH31/Vp/oVJ5SXc3KbNBdd5E+Xr+LXAnmOw8jioajy@nongnu.org X-Gm-Message-State: AOJu0YxHxdg/zDC4KHnESOs5lL3AYR0vSgKCYY594H0fdTQYLDcblUc/ 0PDqpslVWeiSA/M3hqrQDjw7PcRTU+C/MTiZCV44KhFF47Q4Uo4lvHM8pWDvjeG3DJU= X-Gm-Gg: ASbGncv462cVMC8m2WTyE/SOaD2MGMkx+eWg+ZnNOwL5Qya1NrZFcOvrv4qHk95caWD IdHBbi+9UNT3/Z8LZHfg9baFFDkGz12w1TVZHcpXVq5O/MrhdoQxKxgCxX59lsDC+UWQ84vpRRT HEF/FpZwVq31FhdRDJibyyDIJjeYnLmFpnxnprv6xug5YyN4UlPxraoT0fZq1T2tlmahRE/b8dp ieu3uJl75blBMLEKNHTmzM8aBCqpExasWIRYD1NowDLvK+/FJxnD3E+W/J3rqdB5HlDjyb+7Yl3 TbJwuKE8CgewKeyOkTHB17QSGGgNj0XQXJoIDZBPmZJMXKyFE+6UfQbLsftWVslnKbuhBT3rILS f8gB3+vhT8kBDq532bVV6KH2qJ4GQh6CCr2nf0aXmLO7daQuOBj5sbg== X-Google-Smtp-Source: AGHT+IGiTBgQxeNEmWqERms56y9rXFvnzRtkpdJYa0TS8dzbNI4n0oxkeYhR4EfNBacukrCIzqN6zg== X-Received: by 2002:a05:6a00:4fc3:b0:772:6493:7e77 with SMTP id d2e1a72fcca58-77264938033mr4459128b3a.5.1756799461622; Tue, 02 Sep 2025 00:51:01 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 6/9] contrib/plugins/uftrace: generate additional files for uftrace Date: Tue, 2 Sep 2025 00:50:39 -0700 Message-ID: <20250902075042.223990-7-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-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::432; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x432.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: 1756799522588124100 Content-Type: text/plain; charset="utf-8" Beyond traces per cpu, uftrace expect to find some specific files. - info: contains information about machine/program run those values are not impacting uftrace behaviour (only reported by uftrace info), and we simply added empty strings. - memory mapping: how every binary is mapped in memory. For system mode, we generate an empty mapping (uftrace_symbols.py, coming in future commit, will take care of that). For user mode, we copy current /proc/self/maps. We don't need to do any special filtering, as reported addresses will necessarily concern guest program, and not QEMU and its libraries. - task: list of tasks. We present every vcpu/privilege level as a separate process, as it's the best view we can have when generating a (visual) chrome trace. Using threads is less convenient in terms of UI. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 131 +++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 10abad0673c..2386cc723bc 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -118,6 +118,127 @@ static uint64_t gettime_ns(void) return now_ns; } =20 +static void uftrace_write_map(bool system_emulation) +{ + const char *path =3D "./uftrace.data/sid-0.map"; + + if (system_emulation && access(path, F_OK) =3D=3D 0) { + /* do not erase existing map in system emulation, as a custom one = might + * already have been generated by uftrace_symbols.py */ + return; + } + + FILE *sid_map =3D fopen(path, "w"); + g_assert(sid_map); + + if (system_emulation) { + fprintf(sid_map, + "# map stack on highest address possible, to prevent uftra= ce\n" + "# from considering any kernel address\n"); + fprintf(sid_map, + "ffffffffffff-ffffffffffff rw-p 00000000 00:00 0 [stack]\n"); + } else { + /* in user mode, copy /proc/self/maps instead */ + FILE *self_map =3D fopen("/proc/self/maps", "r"); + g_assert(self_map); + for (;;) { + int c =3D fgetc(self_map); + if (c =3D=3D EOF) { + break; + } + fputc(c, sid_map); + } + fclose(self_map); + } + fclose(sid_map); +} + +static void uftrace_write_task(const GArray *traces) +{ + FILE *task =3D fopen("./uftrace.data/task.txt", "w"); + g_assert(task); + for (int i =3D 0; i < traces->len; ++i) { + Trace *t =3D g_array_index(traces, Trace*, i); + fprintf(task, "SESS timestamp=3D0.0 pid=3D%"PRIu32" sid=3D0 exenam= e=3D\"%s\"\n", + t->id, t->name->str); + fprintf(task, "TASK timestamp=3D0.0 tid=3D%"PRIu32" pid=3D%"PRIu32= "\n", + t->id, t->id); + } + fclose(task); +} + +static void uftrace_write_info(const GArray *traces) +{ + g_autoptr(GString) taskinfo_tids =3D g_string_new("taskinfo:tids=3D"); + for (int i =3D 0; i < traces->len; ++i) { + Trace *t =3D g_array_index(traces, Trace*, i); + const char *delim =3D i > 0 ? "," : ""; + g_string_append_printf(taskinfo_tids, "%s%"PRIu32, delim, t->id); + } + + g_autoptr(GString) taskinfo_nr_tid =3D g_string_new("taskinfo:nr_tid= =3D"); + g_string_append_printf(taskinfo_nr_tid, "%d", traces->len); + + FILE *info =3D fopen("./uftrace.data/info", "w"); + g_assert(info); + /* + * $ uftrace dump --debug + * uftrace file header: magic =3D 4674726163652100 + * uftrace file header: version =3D 4 + * uftrace file header: header size =3D 40 + * uftrace file header: endian =3D 1 (little) + * uftrace file header: class =3D 2 (64 bit) + * uftrace file header: features =3D 0x1263 (PLTHOOK | ... + * uftrace file header: info =3D 0x7bff (EXE_NAME | ... + * <0000000000000000>: 46 74 72 61 63 65 21 00 04 00 00 00 28 00 01 = 02 + * <0000000000000010>: 63 12 00 00 00 00 00 00 ff 7b 00 00 00 00 00 = 00 + * <0000000000000020>: 00 04 00 00 00 00 00 00 + */ + const uint8_t header[] =3D {0x46, 0x74, 0x72, 0x61, 0x63, 0x65, 0x21, = 0x00, + 0x04, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x= 02, + 0x63, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x= 00, + 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x= 00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x= 00}; + size_t wrote =3D fwrite(header, sizeof(header), 1, info); + g_assert(wrote =3D=3D 1); + const char *info_data[] =3D { + "exename:", + "build_id:0000000000000000000000000000000000000000", + "exit_status:", + "cmdline:", + "cpuinfo:lines=3D2", + "cpuinfo:nr_cpus=3D", + "cpuinfo:desc=3D", + "meminfo:", + "osinfo:lines=3D3", + "osinfo:kernel=3D", + "osinfo:hostname=3D", + "osinfo:distro=3D", + "taskinfo:lines=3D2", + taskinfo_nr_tid->str, + taskinfo_tids->str, + "usageinfo:lines=3D6", + "usageinfo:systime=3D", + "usageinfo:usrtime=3D", + "usageinfo:ctxsw=3D", + "usageinfo:maxrss=3D", + "usageinfo:pagefault=3D", + "usageinfo:iops=3D", + "loadinfo:", + "record_date:", + "elapsed_time:", + "pattern_type:regex", + "uftrace_version:", + "utc_offset:", + 0}; + const char **info_data_it =3D info_data; + while (*(info_data_it)) { + fprintf(info, "%s\n", *info_data_it); + ++info_data_it; + } + fclose(info); +} + static Callstack *callstack_new(void) { Callstack *cs =3D g_new0(Callstack, 1); @@ -612,14 +733,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); } @@ -656,7 +785,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 Sep 28 16:37:05 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=1756799514; cv=none; d=zohomail.com; s=zohoarc; b=PsWW5nyCSOzlLsL8jh8FPSIVFVEfSwOJH66Rc0rIoAxUnaTwFRlNAJM7kgM7zYxpG3qwcnF8S4X9xutXBcVIzKQL3pnbgj0hReqD5DDcEtokWgnFNvXll5lL9U7Suc7k4RzLIhDCwiH5EIgcKwGV7d/oWsX0ir7yo8PvniF/dPk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799514; 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=JF7wvMHp6QGg+A1XjfDgDm08vP8DadjlUvjQUOqc8Gw=; b=dHjKhTWPol8Z23azxbdVrZXgubgPaAv2Hj2gkLi7/137FmFahzQltajD7LTni9eYlKn2wA1D5HWm6FmpjUbyL56mXkIS8bC4mOtgVnpn1KADhSBNTo0mosVbLpiUb7SnDm3zZFHUU91duUvduig4oEII29AXm/OjAeHM/QMYFSo= 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 175679951469585.0604841716472; Tue, 2 Sep 2025 00:51:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnV-0007BT-45; Tue, 02 Sep 2025 03:51:21 -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 1utLnH-00074e-Nk for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:09 -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 1utLnE-0001vF-2U for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:07 -0400 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-7725de6b57dso1821124b3a.0 for ; Tue, 02 Sep 2025 00:51:03 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.51.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:51:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799462; x=1757404262; 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=JF7wvMHp6QGg+A1XjfDgDm08vP8DadjlUvjQUOqc8Gw=; b=jqqRF6W0MJuCu2Uc22EGKtFURteO7MF35e1RCcyYFJsYvTZyzZdsuRAr1JDR7noDwY /UFvdmqQkA+UJF92hXY1q929ZQbFPf8Z95FKlihQpf8NgT5FjlaTL6Zpj1YC4pFp3IaX o/tz5hp3vC22cQLGaGbdmyslArKq+btQkPY7lYVwXmsgsJi9EIAimoya1JWt9FLeWfWJ dnS5PCj5Z2l34wDn0GXnLggNCUEgHAnB9+TCP4jjX6DkLmVMcfGrgZj9Xh5ojEGWZ5Bz 6dqA8IVf3FV+soCQwG34tRh58R3E7FuhUPHhV6T/g0szfPrNulBPhZD1rfAhHzJTVrnr dBRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799462; x=1757404262; 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=JF7wvMHp6QGg+A1XjfDgDm08vP8DadjlUvjQUOqc8Gw=; b=E1vEtlpmtSSU2UhnWe+qKbImfoBZMyJ6MGSX3nqauAkipZKF04tZplSA+MBvpHXeyh sdgxHWsjFZN8w7VjyeB1eTtaXOyaB3rBTNXcV9niYEUjKDaOImgsn79zzjDYm6VvRp2d RPs43zm/PLYHFUCjOkM8o3tu8txrHyBzSjkp9bZStXGfq5saYtCnuEiQ5z6HxL5bkjaq vj48SeTLmiJCOy96arVVhnGXaI0JLmeTeA5idKow4v0zjHU/A9/a5A+hGrtY6lzz/q90 +aLsqHhspVuCi1z1SPxiLDDRYPTjbeR2GSWyPqz7p5WUXO0hpnAGz1FUUhFHyE6cKQMX PKFg== X-Forwarded-Encrypted: i=1; AJvYcCURW7yr4LkOkvrRTmhHUnSEV/8wO1H/Z7f5FqxklkhAYoGhyfkBJJoVFJbx7mLCiUa2VkTSR+8hSp6B@nongnu.org X-Gm-Message-State: AOJu0YxvcTYsMfz+3b6TXF1da8DFNDgJSN8X/6CGzCBDEmshhSyVRZGh +fY1cC5IabbmtpMQWh2pMVpfgEsuweMZJg4GFoAmZSNPsbqpZPNvH2jvhcR7MqrqGsg= X-Gm-Gg: ASbGncvUmo0GFqwXWwWqs5HxkP8t5e0OBNA9HiQqqBVvBvs3NiMgtSZ6/H5MH/bfzJJ evYYlt7XPFhbL0RozFCGb/lJmXTQ4mX1qePo0NNt+rh0URT15jpr+JiaHbcTLOLJXuwaXLcgDdi Cr9Bd3gmae+KzesCs6tm++rhR4iAe1yP5y4mrsI4RvOOFa5iOU7B5jTaJMSBJLRYAzeu2Na4ZSO SIu9qcgszT+Atd+sY8H806HvH8GNVYtQtslCke6XfTx9c1mcObCmP/xaYjy9pHL7OShAldpbXQS JIZmtdqyAxpo+6fcXaXh+edHRQ0Gz7QTeQCSQKjjRGIyF8wPMktatauHOpIa+1QDMZJtVnDII7e wgWMuQBgv5P36JaSPxDJFONNrbN6qWkt/ElePU/PVDiZHnFslCpdrDA== X-Google-Smtp-Source: AGHT+IEFd0bzmxs49ftcNLfKyXUu9LuUM7GjvR9Fe7tRGOJouvt1tnqn1NFGNrAoEgHJ9TVPVuYhkA== X-Received: by 2002:a05:6a00:39a0:b0:757:ca2b:48a3 with SMTP id d2e1a72fcca58-7723e259561mr11901971b3a.9.1756799462583; Tue, 02 Sep 2025 00:51:02 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 7/9] contrib/plugins/uftrace: implement x64 support Date: Tue, 2 Sep 2025 00:50:40 -0700 Message-ID: <20250902075042.223990-8-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-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: 1756799515113116600 Content-Type: text/plain; charset="utf-8" It's trivial to implement x64 support, as it's the same stack layout as aarch64. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- contrib/plugins/uftrace.c | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/contrib/plugins/uftrace.c b/contrib/plugins/uftrace.c index 2386cc723bc..b7d6124d2f5 100644 --- a/contrib/plugins/uftrace.c +++ b/contrib/plugins/uftrace.c @@ -82,6 +82,21 @@ typedef struct { struct qemu_plugin_register *reg_scr_el3; } Aarch64Cpu; =20 +typedef enum { + X64_RING0, + X64_RING1, + X64_RING2, + X64_RING3, + X64_REAL_MODE, + X64_PRIVILEGE_LEVEL_MAX, +} X64PrivilegeLevel; + +typedef struct { + struct qemu_plugin_register *reg_rbp; + struct qemu_plugin_register *reg_cs; + struct qemu_plugin_register *reg_cr0; +} X64Cpu; + typedef struct { uint64_t timestamp; uint64_t data; @@ -570,6 +585,75 @@ static CpuOps aarch64_ops =3D { .does_insn_modify_frame_pointer =3D aarch64_does_insn_modify_frame_poi= nter, }; =20 +static uint8_t x64_num_privilege_levels(void) +{ + return X64_PRIVILEGE_LEVEL_MAX; +} + +static const char *x64_get_privilege_level_name(uint8_t pl) +{ + switch (pl) { + case X64_RING0: return "Ring0"; + case X64_RING1: return "Ring1"; + case X64_RING2: return "Ring2"; + case X64_RING3: return "Ring3"; + case X64_REAL_MODE: return "RealMode"; + default: + g_assert_not_reached(); + } +} + +static uint8_t x64_get_privilege_level(Cpu *cpu_) +{ + X64Cpu *cpu =3D cpu_->arch; + uint64_t cr0 =3D cpu_read_register64(cpu_, cpu->reg_cr0); + uint64_t protected_mode =3D (cr0 >> 0) & 0b1; + if (!protected_mode) { + return X64_REAL_MODE; + } + uint32_t cs =3D cpu_read_register32(cpu_, cpu->reg_cs); + uint32_t ring_level =3D (cs >> 0) & 0b11; + return ring_level; +} + +static uint64_t x64_get_frame_pointer(Cpu *cpu_) +{ + X64Cpu *cpu =3D cpu_->arch; + return cpu_read_register64(cpu_, cpu->reg_rbp); +} + +static void x64_init(Cpu *cpu_) +{ + X64Cpu *cpu =3D g_new0(X64Cpu, 1); + cpu_->arch =3D cpu; + cpu->reg_rbp =3D plugin_find_register("rbp"); + g_assert(cpu->reg_rbp); + cpu->reg_cs =3D plugin_find_register("cs"); + g_assert(cpu->reg_cs); + cpu->reg_cr0 =3D plugin_find_register("cr0"); + g_assert(cpu->reg_cr0); +} + +static void x64_end(Cpu *cpu) +{ + g_free(cpu->arch); +} + +static bool x64_does_insn_modify_frame_pointer(const char *disas) +{ + return strstr(disas, "rbp"); +} + +static CpuOps x64_ops =3D { + .init =3D x64_init, + .end =3D x64_end, + .get_frame_pointer =3D x64_get_frame_pointer, + .get_privilege_level =3D x64_get_privilege_level, + .num_privilege_levels =3D x64_num_privilege_levels, + .get_privilege_level_name =3D x64_get_privilege_level_name, + .does_insn_modify_frame_pointer =3D x64_does_insn_modify_frame_pointer, +}; + static void track_privilege_change(unsigned int cpu_index, void *udata) { Cpu *cpu =3D qemu_plugin_scoreboard_find(score, cpu_index); @@ -777,6 +861,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 Sep 28 16:37:05 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=1756799521; cv=none; d=zohomail.com; s=zohoarc; b=oE9J80fHZtbAsRuKMIkMNThFh5NoPxlgJcx5qq6zHBJ4nSr1QoOwjOsqiJhIqB09xFJr1eu3BtR4J9KQ9SlHfXV6c3rm9zUiXtXwcehX0jUnsS04FqrwLPwnl/8cSDKB4hA74de0Fb4wVXbRmf0smbquZnwNYw3WdzsolbHUFWU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799521; h=Content-Type: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=LRefeMWyZSYaeV5SOh3x+t98m3lhnIbtiTK21kQRzUM=; b=GfDja/4UH4joZxwGNCRd9gr01Vwr3aFL52yf0DLXpZ1AfCL7WTOjsdaFOWJZcOeZS119OV3DgXPv7KyossnqbU2WVmMkSOt8JruAxRV8V1TSTBz4Ogk5NHPZYtS5mzEN3JKNUY7sXL5GamJR/54YSA6cP8RbKj6UyC1PSC8RoJs= 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 1756799521263634.4834362206706; Tue, 2 Sep 2025 00:52:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnS-00078T-Iu; Tue, 02 Sep 2025 03:51:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1utLnK-00076M-Bx for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:12 -0400 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1utLnF-0001vT-FK for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:10 -0400 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-7722bcb989aso2689364b3a.1 for ; Tue, 02 Sep 2025 00:51:04 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.51.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:51:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799464; x=1757404264; 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=LRefeMWyZSYaeV5SOh3x+t98m3lhnIbtiTK21kQRzUM=; b=nrLxsOL7q7LwoquFu9ql+E4plwOTRmpjo2c/Ar8XrHSkq1OTAKa2zyygO9p16ZzKOc 2Q+LNlZBc+MUo3zkS6Chzq4cOMarcHkJJu8m2WvyD+E7E7Fgfrjz5kFjZVP3mWt6Aqpb VgD/A9E+1WPjiCJCSvxwZULeE920aGH2G8xNHX+tfFhDjmmDvoug1wRIYHucvw/OMsui fNE9jkXJA5hH0bDn4lBSgtU/iFECp5XAzfmEwVPAwf34LyDHJXnI7LLHgrIDJo+5U10V zWJYSO5N9TNhhjadMo9kZVijCVzDSAM6gTLcrUnUyxAJL5PfO4HUmYe+VgT7brqbWGqA 48ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799464; x=1757404264; 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=LRefeMWyZSYaeV5SOh3x+t98m3lhnIbtiTK21kQRzUM=; b=hCDuxCu09pGHc1OAjg85edXm01KF5YjpaZVPE3SY9N72uG4YnPShsJ3q9xqgz86Uz+ oUlAtuEsQPwuGwlyzhPTKlyu0qagCorL/+XO958eQOObYIxPlaQpGc7gATiNgkxlgh7O YroKCKz3+g7d8kyQP4v64Fenkex/kDCqq+hUIPNutwwLp9nC3WTTm0uUBw6JrbP87Iws 2q4BbDidZudFMP4N477P77UHs/44LuauMymUTBBnAViOGFcXavBDsSoqA0ZiuF6KXl0b cCoMHvmlrc57FD853ZFBOqBcQ2vApaYeQiWx+Hwjz/Rvgvq7u2yY5PrbyY+LuF/Z9TXI Z65g== X-Forwarded-Encrypted: i=1; AJvYcCUyKvYq3X1oA/SMRltyo4/+qk2r28XTSEdwPWMg5rAJwu/kkL3jUfYpxLmtDfrfAxlUHP6RCpDWP891@nongnu.org X-Gm-Message-State: AOJu0YynfOxEnSMevfQYDWGpbFRtLs1Hjy+kYszXhMLpHPqyyI1+74b5 5sicKc2NcPzLc8wGgQxyV3N39wub2SzYTPThKp9sZ0UKFV7OVeuAABwIoZWPqeh50xg= X-Gm-Gg: ASbGnct7rH6g1OGtc+jkQaBCHrpHImZtqMbUK/CrYGle69B5XleVUuX5MfyxXzI8VqQ z8FgOYZqMtyYXdGiaYaHDkM0ZmJtUtrPVBxLBZRwvIAc+usIeJ9412F21W8mHFHfhqWg6e3obWp NGAl3LKVkCsGj2WbKFo3WCGCq4LY5ZKhfuQLTZP+W7efmlJ1PNtoUweYvsFKEF50iJVFMyEKhUQ 4aurss1Syld1wE6k/1hZdxRC6IU9BSFIfdLj361Xqd5vDGJtKTVoG7vmU1EClOlJU0XLFo5bdOu pkpz2BVCVJHCFGiy6yRmnJyBpsT5KSqAj13jiuoF2w5WEv+NOsbz7Uai2bSTMi4VuyZnnQGuB1Q yHFSAfTVZO2schdO8nSkQBjsZP3ORa/xbnt40o2mQ0Xw= X-Google-Smtp-Source: AGHT+IExxrXndfd/JyQJFZnzp3ZN0WaxLY4BSggEb9KpmfCvlMW6vbZLhcgzC36eW4IHebD6U2FcTA== X-Received: by 2002:a05:6a00:4b03:b0:748:e5a0:aa77 with SMTP id d2e1a72fcca58-7723e276b6dmr11388698b3a.13.1756799463623; Tue, 02 Sep 2025 00:51:03 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 8/9] contrib/plugins/uftrace_symbols.py Date: Tue, 2 Sep 2025 00:50:41 -0700 Message-ID: <20250902075042.223990-9-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-1-pierrick.bouvier@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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::432; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x432.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: 1756799523408116600 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. Reviewed-by: Philippe Mathieu-Daud=C3=A9 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 Sep 28 16:37:05 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=1756799506; cv=none; d=zohomail.com; s=zohoarc; b=AS8WXDPQpT8MaW4PaAzhr+lNZILprjAQbJ/5cX5wareJcj19YTfZ0ZwdHxdX+D6Ecm2uK5tmRzuajH7cRlO5ymv/lQRp8bgm6zK+Dyjh7UTWGW56TglQmQnGKL1ZGaTUE3Bjxnw2DJd2NeS/2xOl/wgdHtBNOY+RPSDis7CzYwc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756799506; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=DBrgRzoZK/flg18sYa71Nd0Qxl3OyImP8+lDbDt1BL8=; b=d2WueuHKYL31k1wAFnvi3shrUHahZiNZtu2QJxixQhAztAUe2omb3I/LhO4VVwWsyo44d8xQVh8EZ5/nCluveFzsaAWBv/1YynY6yhL2JNj9gU6LXfakKwU8zEKH7j0d4vQOQFVUuS7Na7zB1RioY2mVftg4FosvjGRSFcfm2DI= 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 1756799506168438.2347125866655; Tue, 2 Sep 2025 00:51:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1utLnQ-00077T-F4; Tue, 02 Sep 2025 03:51:16 -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 1utLnJ-00075t-GW for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:11 -0400 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1utLnH-0001vh-4q for qemu-devel@nongnu.org; Tue, 02 Sep 2025 03:51:09 -0400 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-77256200f1bso1374371b3a.3 for ; Tue, 02 Sep 2025 00:51:06 -0700 (PDT) Received: from pc.taild8403c.ts.net ([38.41.223.211]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7723d79fcfesm9642766b3a.16.2025.09.02.00.51.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Sep 2025 00:51:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756799465; x=1757404265; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DBrgRzoZK/flg18sYa71Nd0Qxl3OyImP8+lDbDt1BL8=; b=or3t34lKPfugCa+JELM6RBKRqzPsSwbhyTMPldUrNADEq4MlYE3OVZXm8cRUoPNR5j fKEkKCV0IVgvPxlBiCYn9BYNWv0Cq/yw3bKrL8B89RawiyCKEn0HQwmXtAgU7mbzcSrS E7Hh2nrCU8gXscnGQZIIgcb/jyYziqYq5g/tFJdA3NyxjooBeaFXoPs3h5oKmFRSnA1t NvCwQ1Eko/sdbeRLlZrSJBA+WyRl96lrfTn/jasmcrEazHYMAlD8y9mDjWmkzQmzFJW5 wpt2Q4pPsnJOM9ogRQs6m4dWyWSrXDHlVxNSwc0FHu/sdX+nPEePfyq4ZB48v1xpy16A 9eEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756799465; x=1757404265; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DBrgRzoZK/flg18sYa71Nd0Qxl3OyImP8+lDbDt1BL8=; b=kVYl4CUmS7aTdTBWfWSyRaIOccIX0dxghngf8UKvYdzuhdOiFEsu/P2kgCUNUkqAS4 dcn1aYnzqhVgNJX+G132lXz1SF7Tz3H4WrQnS5KgUFwsY1XU4gfI8pUY4sXEqVisH8p6 HmgZtfJGLSZkUKkyb3ViDmiixCP9LtmItgBWI1QW6bOdC5carxjXs0dyGuG71s44kday ZiGh3Kfv3GoEAPwsRrQYNT42QSzH6GFkZbIB3QHPl6nKW2HSWIZog9QBHlJoGFIPqTBd bsmUzqUx+444jZU8sVlXKq08wZjP158ngGUGE0woWMaxLoW4WJQfHAcMvzLpzR7zMSr8 8oAg== X-Forwarded-Encrypted: i=1; AJvYcCUbnnkLE2C1+8K8uhDAeqQSG4kC4vaoDrPAZSMjrhFSN4oSYxLxVZj6dK9qDkq4TKmJP0oDU3biGVdz@nongnu.org X-Gm-Message-State: AOJu0Yx9jphbv/4YLwGMUugEraF3dIK/11gAr7WMXRjYZlvAruYAsk9t kZo3ikiutL3M/wg1PxW7GnSZRbY/EEIRG1ZxoSpdjG+dU+4g388QswLKq+kkSVKuyfI= X-Gm-Gg: ASbGncuudiJ9bCWlVXlfYFIJwQRWXvO5c4P9EHiYqZfGdvKrLOtPnvl8toKaa6L565P FdXC9sN/sSNqm+kO0tq14jpqPAQVMkGbTQs+r1aQxpSBc0WTst0ciDZudPllm8HQ5BGJrSdFGku CnMT95F59CnOKkt3PHEqXPVEZKrhCUqvugwl/heuTIlcsoCd2VTy7gXIeoJLPfBESiJZII4q9Wr OjyZzQOGAojT6TY883AdbLux9k8/5XaB7RUwA1WkVnx8Zm7Hb1tgfn8WIfIkHaoGfLfDklMXf9k wz8LmoouI5QHXblMtDJHcNVV366P61Rz7gguKUWd6wDRmQ5lCAyrceRSvh8fwTg3Ypc5377wIxO /hgN+YtT/YEWkgScGrhz7ut6YrPmGHOmkxOp4g7XO0tA= X-Google-Smtp-Source: AGHT+IGR4sHy8t2PnRVc23rwX8Q8qGI/pwUIR6Ijnt7tTtygvwtYy8LNLkv5rohjxEjfuAmQ+Pw0Jg== X-Received: by 2002:a05:6a00:2306:b0:748:eedb:902a with SMTP id d2e1a72fcca58-7723e362814mr13297381b3a.17.1756799464561; Tue, 02 Sep 2025 00:51:04 -0700 (PDT) From: Pierrick Bouvier To: pierrick.bouvier@linaro.org, qemu-devel@nongnu.org Cc: Peter Maydell , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis , Alexandre Iooss , Gustavo Romero , Mahmoud Mandour , rowan Hart Subject: [PATCH v7 9/9] contrib/plugins/uftrace: add documentation Date: Tue, 2 Sep 2025 00:50:42 -0700 Message-ID: <20250902075042.223990-10-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250902075042.223990-1-pierrick.bouvier@linaro.org> References: <20250902075042.223990-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::432; envelope-from=pierrick.bouvier@linaro.org; helo=mail-pf1-x432.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: 1756799507566116600 Content-Type: text/plain; charset="utf-8" This documentation summarizes how to use the plugin, and present two examples of the possibilities offered by it, in system and user mode. As well, it explains how to rebuild and reproduce those examples. Reviewed-by: Manos Pitsidianakis Signed-off-by: Pierrick Bouvier --- docs/about/emulation.rst | 199 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/docs/about/emulation.rst b/docs/about/emulation.rst index 456d01d5b08..8a5e128f677 100644 --- a/docs/about/emulation.rst +++ b/docs/about/emulation.rst @@ -816,6 +816,205 @@ This plugin can limit the number of Instructions Per = Second that are executed:: The lower the number the more accurate time will be, but the less ef= ficient the plugin. Defaults to ips/10 =20 +Uftrace +....... + +``contrib/plugins/uftrace.c`` + +This plugin generates a binary trace compatible with +`uftrace `_. + +Plugin supports aarch64 and x64, and works in user and system mode, allowi= ng to +trace a system boot, which is not something possible usually. + +In user mode, the memory mapping is directly copied from ``/proc/self/maps= `` at +the end of execution. Uftrace should be able to retrieve symbols by itself, +without any additional step. +In system mode, the default memory mapping is empty, and you can generate +one (and associated symbols) using ``contrib/plugins/uftrace_symbols.py``. +Symbols must be present in ELF binaries. + +It tracks the call stack (based on frame pointer analysis). Thus, your pro= gram +and its dependencies must be compiled using ``-fno-omit-frame-pointer +-mno-omit-leaf-frame-pointer``. In 2024, `Ubuntu and Fedora enabled it by +default again on x64 +`_. +On aarch64, this is less of a problem, as they are usually part of the ABI, +except for leaf functions. That's true for user space applications, but not +necessarily for bare metal code. You can read this `section +` to easily build a system with frame pointe= rs. + +When tracing long scenarios (> 1 min), the generated trace can become very= long, +making it hard to extract data from it. In this case, a simple solution is= to +trace execution while generating a timestamped output log using +``qemu-system-aarch64 ... | ts "%s"``. Then, ``uftrace --time-range=3Dstar= t~end`` +can be used to reduce trace for only this part of execution. + +Performance wise, overhead compared to normal tcg execution is around x5-x= 15. + +.. list-table:: Uftrace plugin arguments + :widths: 20 80 + :header-rows: 1 + + * - Option + - Description + * - trace-privilege-level=3D[on|off] + - Generate separate traces for each privilege level (Exception Level + + Security State on aarch64, Rings on x64). + +.. list-table:: uftrace_symbols.py arguments + :widths: 20 80 + :header-rows: 1 + + * - Option + - Description + * - elf_file [elf_file ...] + - path to an ELF file. Use /path/to/file:0xdeadbeef to add a mapping o= ffset. + * - --prefix-symbols + - prepend binary name to symbols + +Example user trace +++++++++++++++++++ + +As an example, we can trace qemu itself running git:: + + $ ./build/qemu-aarch64 -plugin \ + build/contrib/plugins/libuftrace.so \ + ./build/qemu-aarch64 /usr/bin/git --help + + # and generate a chrome trace directly + $ uftrace dump --chrome | gzip > ~/qemu_aarch64_git_help.json.gz + +For convenience, you can download this trace `qemu_aarch64_git_help.json.gz +`_. +Download it and open this trace on https://ui.perfetto.dev/. You can zoom = in/out +using :kbd:`W`, :kbd:`A`, :kbd:`S`, :kbd:`D` keys. +Some sequences taken from this trace: + +- Loading program and its interpreter + +.. image:: https://fileserver.linaro.org/s/fie8JgX76yyL5cq/preview + :height: 200px + +- open syscall + +.. image:: https://fileserver.linaro.org/s/rsXPTeZZPza4PcE/preview + :height: 200px + +- TB creation + +.. image:: https://fileserver.linaro.org/s/GXY6NKMw5EeRCew/preview + :height: 200px + +It's usually better to use ``uftrace record`` directly. However, tracing +binaries through qemu-user can be convenient when you don't want to recomp= ile +them (``uftrace record`` requires instrumentation), as long as symbols are +present. + +Example system trace +++++++++++++++++++++ + +A full trace example (chrome trace, from instructions below) generated fro= m a +system boot can be found `here +`_. +Download it and open this trace on https://ui.perfetto.dev/. You can see c= ode +executed for all privilege levels, and zoom in/out using +:kbd:`W`, :kbd:`A`, :kbd:`S`, :kbd:`D` keys. You can find below some seque= nces +taken from this trace: + +- Two first stages of boot sequence in Arm Trusted Firmware (EL3 and S-EL1) + +.. image:: https://fileserver.linaro.org/s/kkxBS552W7nYESX/preview + :height: 200px + +- U-boot initialization (until code relocation, after which we can't track= it) + +.. image:: https://fileserver.linaro.org/s/LKTgsXNZFi5GFNC/preview + :height: 200px + +- Stat and open syscalls in kernel + +.. image:: https://fileserver.linaro.org/s/dXe4MfraKg2F476/preview + :height: 200px + +- Timer interrupt + +.. image:: https://fileserver.linaro.org/s/TM5yobYzJtP7P3C/preview + :height: 200px + +- Poweroff sequence (from kernel back to firmware, NS-EL2 to EL3) + +.. image:: https://fileserver.linaro.org/s/oR2PtyGKJrqnfRf/preview + :height: 200px + +Build and run system example +++++++++++++++++++++++++++++ + +.. _uftrace_build_system_example: + +Building a full system image with frame pointers is not trivial. + +We provide a `simple way `= _ to +build an aarch64 system, combining Arm Trusted firmware, U-boot, Linux ker= nel +and debian userland. It's based on containers (``podman`` only) and +``qemu-user-static (binfmt)`` to make sure it's easily reproducible and do= es not depend +on machine where you build it. + +You can follow the exact same instructions for a x64 system, combining edk= 2, +Linux, and Ubuntu, simply by switching to +`x86_64 `_ bra= nch. + +To build the system:: + + # Install dependencies + $ sudo apt install -y podman qemu-user-static + + $ git clone https://github.com/pbo-linaro/qemu-linux-stack + $ cd qemu-linux-stack + $ ./build.sh + + # system can be started using: + $ ./run.sh /path/to/qemu-system-aarch64 + +To generate a uftrace for a system boot from that:: + + # run true and poweroff the system + $ env INIT=3Dtrue ./run.sh path/to/qemu-system-aarch64 \ + -plugin path/to/contrib/plugins/libuftrace.so,trace-privilege-level= =3Don + + # generate symbols and memory mapping + $ path/to/contrib/plugins/uftrace_symbols.py \ + --prefix-symbols \ + arm-trusted-firmware/build/qemu/debug/bl1/bl1.elf \ + arm-trusted-firmware/build/qemu/debug/bl2/bl2.elf \ + arm-trusted-firmware/build/qemu/debug/bl31/bl31.elf \ + u-boot/u-boot:0x60000000 \ + linux/vmlinux + + # inspect trace with + $ uftrace replay + +Uftrace allows to filter the trace, and dump flamegraphs, or a chrome trac= e. +This last one is very interesting to see visually the boot process:: + + $ uftrace dump --chrome > boot.json + # Open your browser, and load boot.json on https://ui.perfetto.dev/. + +Long visual chrome traces can't be easily opened, thus, it might be +interesting to generate them around a particular point of execution:: + + # execute qemu and timestamp output log + $ env INIT=3Dtrue ./run.sh path/to/qemu-system-aarch64 \ + -plugin path/to/contrib/plugins/libuftrace.so,trace-privilege-level= =3Don |& + ts "%s" | tee exec.log + + $ cat exec.log | grep 'Run /init' + 1753122320 [ 11.834391] Run /init as init process + # init was launched at 1753122320 + + # generate trace around init execution (2 seconds): + $ uftrace dump --chrome --time-range=3D1753122320~1753122322 > init.js= on + Other emulation features ------------------------ =20 --=20 2.47.2