From nobody Sat Sep 26 01:51:50 2026 Received: from mail-yw1-f171.google.com (mail-yw1-f171.google.com [209.85.128.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECB203B2FC6 for ; Sat, 5 Sep 2026 22:54:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788648858; cv=none; b=qc69U2q0J0PEKPc/zt8lgIkrN+M1StGmXtUB7LHArAzeSLDkvko0vQCX0YM08vN6i8Erf6Mn7kF82LpYgc2kjL03DN8L3Ale7HwKxE2MEMfqQ8xEIXsfpG8w9OQ/3zIchdS4j+s2P6+RdAQtpOHlL0tWjcjIwZzzZe8ZIOEUVVU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788648858; c=relaxed/simple; bh=sKKHS2HS6UTzwjY9EozcnrCXoQy26cS3HBrm1gFaNaw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WlZfAGl4cioD8shYs8ryF4HUE346uIW97PBa496VUBiEjbTSuDrWtvn/OIJ9SJpzSE43kb9ash+M0d6AdwyE0SBX28imvRUG0i109dCNaLuMnyUziGKJrgg4eOzl/bCHIRKdhzGrx9SDkVEiUP66sJjAePO8q2Nm47rEZaPSaco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bj8dH8sG; arc=none smtp.client-ip=209.85.128.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bj8dH8sG" Received: by mail-yw1-f171.google.com with SMTP id 00721157ae682-86e7f44b773so25157157b3.2 for ; Sat, 05 Sep 2026 15:54:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788648856; x=1789253656; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=vXw8Ug5yYOUTbLigrOAI+34wLiaUYUCdVkEC3NguuEA=; b=bj8dH8sGCBczySjqdYvBRgqyPJCGjHFhB7JPBVay61ks5YTSk8Ea8ROkz8AfJ3DQ8Y D7KjhfBxMqpFnE5VAtAdHtujQP50b17/aF3lCI4xLcdvqomTLnCIqpaKjIPfS1s3WgrB G0/n19LXCwzuLjmlmwbGAaHtkDhlshHZoVWz6aIT6OUltVkQccqq8lFjkf6888RYXHT/ RIREmYO3fjByJ0a0FTJM04eZik0MJp3MW3GB4/1IsyeXzF/ikN8vnKjnBFlLn52pnY8o /wXDBBz3a1VZF+Z9KSHm6p3T7zUnqKlsSQmHBKBPkins0iUW5GbVXJFgbgP5yYo0MTgR bJfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788648856; x=1789253656; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=vXw8Ug5yYOUTbLigrOAI+34wLiaUYUCdVkEC3NguuEA=; b=INLvMaVcNm1/iR3VWBr2KXVzZJyQvrKtH2uc+V5XQgqBzz4OIVOPOOikl4GRS3pRwb +Ba7zhtfG2ZG9DrDjLvniq9Vr2hvvzOJfz3t+/2kLFVvEcgnz4sRxmP+W+e5JnueyhBT XI+/Wg3yDrPOqLSuOZYJqvPjVSaAOZnxpYWKsBnyRPrhM8D4/8hrEeL2df3GM3plllhK Y8f3WQpqD9DFgibub46zlDc1Q9nPROcYMUbn4rkWvaWzUhX2vOImaIi57Nq8bJUqMF7Z iVfDzEicv4kjVFLVvqUSS+1V+lnukoy1aV7b6mwbY2zyPPFBM28ZFdgllPaN2rEK3Wpi AuYw== X-Forwarded-Encrypted: i=1; AKwUvByTyIdPHuMTyl6tY5DeWZMSwqVhjZlkjJ5/uJ1g7quytZgw1mYqJeE4C2MJHgQpGJe57og+9vP1ZD5c5kI=@vger.kernel.org X-Gm-Message-State: AFuF++maVHw0JgLNiFxMqt1DZZCHbxsebzKn8MRni07TanwHLPev+ITK 9fsvYk32BlAQyi7Na1evx4XhpH5+Gq4YQcZI4Wlg+h+eb6sTp8RX3IA4 X-Gm-Gg: AYBFou0HrDRDoLgacxCClwZlGHjKLbCavwsWKqeM30WPBICu9PGRqJ3OXEh1YZ5Q4M8 ZKOtNLaFErm0/0gUEguKpvlSGn9YZGmCzitYmP42MSIkb3WLrnip2tBVRIhDgYFR3tRbF4XzuaO Mbz1NuoUpenx1jjW44j0EcX7xSi0F1410ykO89SA8kUaVCwiSGLxolrmw+nCfWY2sPE7+/MNaWU eWpBZyWUO6Aen5W+/VpoR9iadMXHH2YaV67Hq3LGQLt1StbyDuERH2Q+buZ7RP8gtxG8lcP7vxx 19J+wkXEEWjj0v7qRWoHKy+gngUBYKUeG6On+g0Bb9Bh8c5+489rSNTNN3dMKfvLUZOynr7C58B uPYXDOcQ2w/7JSky2NkRNVvJt9IyNr4MHzAbQAahAjxNesNvq5st9KO6bzV4mWi6RZOcPDRviGB guUeTRyT+ZRoUXb8ZPihigKQA4114QFcZfu7Tota9GkV1bymJ57WoJNtG5R0x+ X-Received: by 2002:a05:690c:f04:b0:863:e8cb:7773 with SMTP id 00721157ae682-87128faf717mr58602377b3.32.1788648855812; Sat, 05 Sep 2026 15:54:15 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 00721157ae682-871493168dasm45817017b3.11.2026.09.05.15.54.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 05 Sep 2026 15:54:15 -0700 (PDT) From: Matt Turner Date: Sat, 05 Sep 2026 18:54:11 -0400 Subject: [PATCH 1/2] perf thread: Fix live-session detection in thread__e_machine() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260905-perf-alpha-annotate-v1-1-97380433ccb6@gmail.com> References: <20260905-perf-alpha-annotate-v1-0-97380433ccb6@gmail.com> In-Reply-To: <20260905-perf-alpha-annotate-v1-0-97380433ccb6@gmail.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Matt Turner X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3292; i=mattst88@gmail.com; h=from:subject:message-id; bh=sKKHS2HS6UTzwjY9EozcnrCXoQy26cS3HBrm1gFaNaw=; b=owGbwMvMwCW25rVmCc8sv+mMp9WSGLLmzJ30LvujJItxmM/WZWtv/YjR5mKSn3ckevMRqx9bL N7selyS3fGRhUGMi2GmmCJL3HpFllltO5b6nJb+BTOHlQlkiLRIAwMQsDDw5SbmlRrpGOmZahvq GQIZOkbxEDk9Bo3M4uLS1CLdtIIih7z8ksSSzPy8Yr38gtS8gvQCvbTMtJKMjPyi4lSgEXp5qSW mro5uRoYGJpaOFmZOFo6mJs7OToZObo6Ozq5ORpbmJgbOlo4mrpbmDFycAjDXGD5lZOhyEt893V zUsPPqF30Hk7gCnW6Wih0O8pdcfKy7lW5GczEy7Eu/671fUNenginE0HHNn82Lj/wt3+Dk5rI0S lz/mf8dZgA= X-Developer-Key: i=mattst88@gmail.com; a=openpgp; fpr=3BB639E56F861FA2E86505690FDD682D974CA72A When the per-thread e_machine cannot be determined from the DSOs in the thread's maps, thread__e_machine_endian() decides between reading /proc//exe and falling back to the recorded session environment: bool is_live =3D machine->machines =3D=3D NULL; if (!is_live) { /* Check if the session has a data file. */ struct perf_session *session =3D container_of(...); is_live =3D !!session->data; } Neither half of that works. The back pointer added by commit a088031c4998 ("perf tools: Add machine to machines back pointer") is set by machines__add(), which only ever adds guests; the host machine never gets one. Host-machine threads, which is to say almost all of them, therefore see machine->machines =3D=3D NULL and are declared live before the session is consulted at all. The session test is also inverted. A session with a perf_data attached is one being read from a perf.data file, i.e. exactly the case that is not live, while a live session such as 'perf top' passes data=3DNULL to __perf_session__new(). So a file-based session takes the live path and reads /proc//exe on the analysing host, which at best describes an unrelated process that has since been given the recorded pid, and normally just fails, leaving e_machine as EM_NONE. The perf_env fallback that would have supplied the recorded architecture is never reached, and thread__e_machine() returns EM_HOST. For a same-architecture recording this is invisible, since EM_HOST is the right answer anyway. Cross-architecture it is not: annotating an Alpha perf.data on an x86_64 host selects the x86 struct arch, so the Alpha disassembly is matched against the x86 instruction table. Alpha's 'ret' collides with x86's and gets ret_ops, while its calls and branches match nothing and are left unparsed, so no call target is resolved and no jump arrows are drawn. Set the back pointer for the host machine and correct the session test. The new back pointer does not disturb the other reader of the field, machine__findnew_guest_code(), which machine__resolve() only calls when !machine__is_host(machine). Fixes: 70351029b556 ("perf thread: Add support for reading the e_machine ty= pe for a thread") Signed-off-by: Matt Turner Reviewed-by: Ian Rogers --- tools/perf/util/machine.c | 1 + tools/perf/util/thread.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index f86b3b7df742..a1288fbed833 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -237,6 +237,7 @@ int machines__init(struct machines *machines) { int err =3D machine__init(&machines->host, "", HOST_KERNEL_ID); =20 + machines->host.machines =3D machines; machines->guests =3D RB_ROOT_CACHED; return err; } diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index e483ffcb5d93..f0d3773d87db 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -536,7 +536,7 @@ uint16_t thread__e_machine_endian(struct thread *thread= , struct machine *machine struct perf_session, machines); =20 - is_live =3D !!session->data; + is_live =3D !session->data; } /* Read from /proc/pid/exe if live. */ if (is_live) { --=20 2.54.0 From nobody Sat Sep 26 01:51:50 2026 Received: from mail-yw1-f169.google.com (mail-yw1-f169.google.com [209.85.128.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA7923A0E8D for ; Sat, 5 Sep 2026 22:54:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788648860; cv=none; b=OGbHQ5WlQ0n+PN7/r7Hl8iNqddRBxQEJlmwj7A4bTSnpqvEU++tI3WMSeHaA+gUaYx53RcU5Y79j71GMR36s262XKQf8msSb+97AxEhoBpfyqfp35G6EMBIjcI+xxSECKKbf6sB7aTbePFbsrLMOLX/SdJ75cS1j+TiMhxhApoU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788648860; c=relaxed/simple; bh=/58G8eUDsOzZ2bOuezTjemWkfnT0icE7T2bofe6pu8I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oDPGQLJe0LOh+RqYV3V8E6WhADh3jM0A7sKZjaH+viLVomuAHLSxUIw+jusT3WBaweJ3Ei5RHr6YAT6Gn9qrQjoECptvFClAzQVMOoyeIz3YiRybHahkt8KeP+NuIJa290n+TJLSr67XQ7amCqTgghCctUOwnaubm8bwEtbXKVY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Wq5uwBws; arc=none smtp.client-ip=209.85.128.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Wq5uwBws" Received: by mail-yw1-f169.google.com with SMTP id 00721157ae682-8588583a7c3so23557907b3.2 for ; Sat, 05 Sep 2026 15:54:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788648858; x=1789253658; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Si/NxKj3MUw1ND7afSQVGNXR4y19pRWNSVZzgFbIzjE=; b=Wq5uwBws1LmKxiRRWl71DiqCFKR62+/P5a7AI02hpVbIEQB4GsyPMbQMr6A1Nn04lH 5zBZhwIJzpsuhWX/YSaE/33L6ZkMEEN29D/fulSJC7KI6UySUzYZiOFp2LxoaZxPgTD+ pDYF+Eg1SP7m/c0e/DQUTNwaFenlH5i/QtikWG0e4dQPxBnn7UKcGeA4w4W+smmYqSuO Y1nAkZXqVVdgcEpFjlarwshIjoeV/K1dSABSqRy4J89+JHUm+gaotWv2fSsgfG6FqZ6N aF2TbM6Py55uMyEzZGq6A7VkBcVi4TTyIWeWXfqyCO6K/4lsa4RVfXKUvhxSbeIvf+XD ncBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788648858; x=1789253658; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Si/NxKj3MUw1ND7afSQVGNXR4y19pRWNSVZzgFbIzjE=; b=N0/p5QeGlkpvG0TpI873T4pazckgepgJBIZh6hd50G+VUbrtY+8wWYIg/QF3V5aOMQ S7wx4zzV1vXfOJO+29E+BY3hnvIO9QT+OzDNcT0c0z+rqNN2G9MNFL3STLqruzpgIML2 VPAqz3QQeIXaS58AiuSw6SYYLLkZcxMzRpipHmmo0CqMiSbQ8ri/xIpmeb/Ot604A+oO 6Km17RWrDJmhJT/OnxF09CAb8XY5pVIaGnt/pL+/D+isbTVZP8veeyKZISj7Luyjbqc4 viB+e/hbhRbEjeOrY6FGBul61IS6/JpeubBTRZ2ek7oovjJxy16McFnhiOFfgAK2pxvX MEfg== X-Forwarded-Encrypted: i=1; AKwUvBzr83RLILQ9KOsuQL0kM4iTc9HQmgaipl/lyM9rVViVtJrzJmU0MHrSwLiot9wsPL6j9HUq66tO9CBzUlU=@vger.kernel.org X-Gm-Message-State: AFuF++modaJeDqEi2fu6dJK2igb4ROJG5394q7x/XyTL48Ws500+f5qB /pc9xb6/AF5uknxJRUExGFGmbSAeB/DNIwiSWgMKo2+PIReMS9F55a4R X-Gm-Gg: AYBFou050pO0bSnxbSS9FrIa9RlXgcPNXLEhakBU+eYHYniPgFN6PJtv4ea8hlfDWX5 FQWlLiDSAmvLg9G7+eB9hWfwQF8WRCNYV7qp4cx6iv4HUs3WDaDlWKU6u9bXB/cJskN8uPnRhVr QC3SZLnk09ZWCJ8urPys0sTM/TRE84Kor1B6kn+Woyz9P45XTqd+LkJhhOr5D3ztgYEjy5BiTIk u7Do5jsmIq4k06lQ61Mnkfhdc/vwn12azu6KZtUgOm3y1nW2EZyJb+i1EBTAdsXwfIqK8CuAkVB rUmKlQc8HsFkQyudZDJuG+ej5E+P50aFT81gSxZqlGJKR81B1aHqwqlS/ZjUdT6Rvw25hjUEIIB yrYtdVLBSEU6ps87HBXimkRgbm6S1wc7XLEPdlq1KiW9QmzW9VnmW6ggkFVY3k5V0mbeaOI5Fj5 rB23cLjeFVaad/1q8njGy3cgdgLn3SaIYuPprfAK4Pqbw9t8zgZwyiV9FIeUwN X-Received: by 2002:a05:690c:e3ea:b0:873:5bb2:6bfa with SMTP id 00721157ae682-8735bb26d93mr25233117b3.36.1788648857604; Sat, 05 Sep 2026 15:54:17 -0700 (PDT) Received: from localhost ([2600:1702:7a90:6f9f:8bc4:8aec:108d:7a04]) by smtp.gmail.com with ESMTPSA id 00721157ae682-8714931516dsm46273517b3.17.2026.09.05.15.54.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 05 Sep 2026 15:54:16 -0700 (PDT) From: Matt Turner Date: Sat, 05 Sep 2026 18:54:12 -0400 Subject: [PATCH 2/2] perf annotate: add Alpha instruction support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260905-perf-alpha-annotate-v1-2-97380433ccb6@gmail.com> References: <20260905-perf-alpha-annotate-v1-0-97380433ccb6@gmail.com> In-Reply-To: <20260905-perf-alpha-annotate-v1-0-97380433ccb6@gmail.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Matt Turner X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=12016; i=mattst88@gmail.com; h=from:subject:message-id; bh=/58G8eUDsOzZ2bOuezTjemWkfnT0icE7T2bofe6pu8I=; b=owGbwMvMwCW25rVmCc8sv+mMp9WSGLLmzJ08U+1f0EfHzc1neffkza0orrszf9+eI87npDik0 o+9Pycr1fGRhUGMi2GmmCJL3HpFllltO5b6nJb+BTOHlQlkiLRIAwMQsDDw5SbmlRrpGOmZahvq GQIZOkbxEDk9Bo3M4uLS1CLdtIIih7z8ksSSzPy8Yr38gtS8gvQCvbTMtJKMjPyi4lSgEXp5qSW mro5uRoYGJpaOFmZOFo6mJs7OToZObo6Ozq5ORpbmJgbOlo4mrpbmDFycAjDXSLIx/A9MDf2wkM F7WveBhr0Zn2zeOxyK8JSyNtYpyDvq+GfBQUGG/zWX3S4fct2+8GrFD932FT1p63O2dy3X0VqgO X3h65V3JvIAAA== X-Developer-Key: i=mattst88@gmail.com; a=openpgp; fpr=3BB639E56F861FA2E86505690FDD682D974CA72A Teach perf annotate about the Alpha control-transfer instructions, so that an Alpha perf.data gets call and jump arrows and resolved call targets, whether it is read on Alpha or on another host. Add tools/perf/util/annotate-arch/annotate-alpha.c with arch__new_alpha() and an associate_instruction_ops() that classifies: call: bsr, plus jsr and jcr as indirect calls ret: ret jump: br, the conditional branches beq/bne/blt/ble/bgt/bge/blbc/blbs and fbeq/fbne/fblt/fble/fbgt/fbge, plus jmp as an indirect jump mov: mov, fmov (objdump pseudos) That is every mnemonic binutils can print for the branch and JSR formats. jcr rather than jsr_coroutine, because both name the same MBR(0x1a,3) encoding and print_insn_alpha() takes the first match in the table, where the jcr alias has come first since the sources were imported in 1999. bsr needs an Alpha-specific parse routine. The generic call__parse() expects the operand string to begin with the target address, but a bsr prints its return-address register first: bsr t0,fffffc0001031dc0 strtoull() then stops on the leading register name, leaving the target address as 0, which makes call__scnprintf() fall back to printing the raw operands and leaves target.sym unresolved so the browser cannot follow the call. alpha_call__parse() takes the address from after the comma instead, as s390_call__parse() does for the same reason. The PC-relative branches need no such handling, as jump__parse() already skips up to two operands. jsr and jmp get ins_ops that resolve no target at all. They transfer control to a register, and their trailing operand is only a branch prediction hint: jsr ra,(t12),fffffc0001014ee8 <_printk> binutils extracts that hint as a 14-bit signed field scaled by four and prints it relative to the next instruction (extract_jhint() in alpha-opc.c, print_insn_alpha() in alpha-dis.c), so it can name the callee only when the callee lies within the resulting +-32KB. It also defaults to zero, which prints as the next instruction. Of the 213750 jsr in a vmlinux built from this tree, only 23093 hints land on a symbol; 157204 point into the middle of an unrelated function and 33453 are that default. Parsing the hint would therefore invent a call target for the majority of calls, so these keep their operands, as an indirect call does elsewhere. EM_ALPHA is 0x9026, far too large to index the e_machine-keyed arch_new_fn[] table in arch__find(), so select arch__new_alpha explicitly before the table lookup. Declare it in disasm.h and add the object to the annotate-arch Build. Disassembly itself comes from objdump/binutils, which already supports Alpha; this provides perf's instruction-class metadata for annotation. Tested on an EV7 Marvel, both natively and by annotating its perf.data on an x86_64 host, over bsr to a local function, jsr through the PLT and kernel-mode jsr; the two hosts produce identical output. Signed-off-by: Matt Turner Reviewed-by: Ian Rogers --- tools/perf/util/annotate-arch/Build | 1 + tools/perf/util/annotate-arch/annotate-alpha.c | 185 +++++++++++++++++++++= ++++ tools/perf/util/disasm.c | 15 +- tools/perf/util/disasm.h | 1 + 4 files changed, 200 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/annotate-arch/Build b/tools/perf/util/annotate= -arch/Build index 23316743fdc5..0a74e1a9f17b 100644 --- a/tools/perf/util/annotate-arch/Build +++ b/tools/perf/util/annotate-arch/Build @@ -1,3 +1,4 @@ +perf-util-y +=3D annotate-alpha.o perf-util-y +=3D annotate-arc.o perf-util-y +=3D annotate-arm.o perf-util-y +=3D annotate-arm64.o diff --git a/tools/perf/util/annotate-arch/annotate-alpha.c b/tools/perf/ut= il/annotate-arch/annotate-alpha.c new file mode 100644 index 000000000000..ccb13e2338a2 --- /dev/null +++ b/tools/perf/util/annotate-arch/annotate-alpha.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include "../../util/disasm.h" +#include "../../util/map.h" +#include "../../util/maps.h" +#include "../../util/symbol.h" +#include "../../util/thread.h" + +/* + * Alpha control-transfer instructions, as printed by objdump: + * + * PC-relative (opcode group 0x30-0x3f), 21-bit displacement: + * br, bsr unconditional / to-subroutine + * beq bne blt ble bgt bge blbc blbs integer conditional + * fbeq fbne fblt fble fbgt fbge floating conditional + * + * Register-indirect (JSR group, opcode 0x1a): + * jmp, jsr, ret, jcr + * + * bsr/jsr (and jcr, the coroutine form, which binutils prints in preferen= ce to + * the jsr_coroutine spelling) save a return address, so they are calls; r= et + * returns; everything else that transfers control is a jump. + * + * Alpha has no machine "mov"; objdump prints "mov"/"fmov" as pseudos for + * bis/cpys, so map them to mov_ops when present. The no-ops are delibera= tely + * left alone: nop_ops would let delete_last_nop() trim the padding gcc le= aves + * at the end of a function, but its scnprintf() prints the literal "nop",= and + * Alpha pads with unop (ldq_u $31) rather than nop. + */ + +/* + * The generic call__parse() expects the target address to be the first th= ing + * in the operand string, but a bsr prints its return-address register fir= st: + * + * bsr t0,fffffc0001031dc0 + * + * so take the address from after the comma. Without this the address com= es + * out as 0, and neither the callee symbol nor the annotation browser's + * "go to target" work. + */ +static int alpha_call__parse(const struct arch *arch, struct ins_operands = *ops, + struct map_symbol *ms, + struct disasm_line *dl __maybe_unused) +{ + char *endptr, *tok, *name; + struct map *map =3D ms->map; + struct addr_map_symbol target; + + tok =3D strchr(ops->raw, ','); + if (tok =3D=3D NULL) + return -1; + + ops->target.addr =3D strtoull(tok + 1, &endptr, 16); + if (endptr =3D=3D tok + 1) + return -1; + + /* A stripped object has no "" to name the target with. */ + name =3D strchr(endptr, '<'); + if (name =3D=3D NULL) + goto find_target; + + name++; + + if (arch->objdump.skip_functions_char && + strchr(name, arch->objdump.skip_functions_char)) + return -1; + + tok =3D strchr(name, '>'); + if (tok =3D=3D NULL) + return -1; + + *tok =3D '\0'; + ops->target.name =3D strdup(name); + *tok =3D '>'; + + if (ops->target.name =3D=3D NULL) + return -1; + +find_target: + target =3D (struct addr_map_symbol) { + .ms =3D { .map =3D map__get(map), }, + .addr =3D map__objdump_2mem(map, ops->target.addr), + }; + + if (maps__find_ams(thread__maps(ms->thread), &target) =3D=3D 0 && + map__rip_2objdump(target.ms.map, + map__map_ip(target.ms.map, target.addr)) =3D=3D ops->target.addr) + ops->target.sym =3D target.ms.sym; + + addr_map_symbol__exit(&target); + return 0; +} + +static const struct ins_ops alpha_call_ops =3D { + .parse =3D alpha_call__parse, + .scnprintf =3D call__scnprintf, + .is_call =3D true, +}; + +/* + * jsr and jmp transfer control to a register, and their trailing operand = is + * only a branch prediction hint: + * + * jsr ra,(t12),fffffc0001014ee8 <_printk> + * + * binutils extracts that hint as a 14-bit signed field scaled by four and + * prints it relative to the next instruction (extract_jhint() in alpha-op= c.c, + * print_insn_alpha() in alpha-dis.c), so it can name the callee only when= the + * callee lies within the resulting +-32KB. It also defaults to zero, whi= ch + * prints as the next instruction. Most hints are therefore not the calle= e at + * all, and parsing one would invent a call target, so these resolve no ta= rget + * and keep their operands, as an indirect call does elsewhere. The hint = on + * jcr is not even an address. + */ +static const struct ins_ops alpha_indirect_call_ops =3D { + .scnprintf =3D ins__raw_scnprintf, + .is_call =3D true, +}; + +static const struct ins_ops alpha_indirect_jump_ops =3D { + .scnprintf =3D ins__raw_scnprintf, + .is_jump =3D true, +}; + +static int is_alpha_cond_branch(const char *name) +{ + static const char *const branches[] =3D { + "beq", "bne", "blt", "ble", "bgt", "bge", "blbc", "blbs", + "fbeq", "fbne", "fblt", "fble", "fbgt", "fbge", + }; + unsigned int i; + + for (i =3D 0; i < ARRAY_SIZE(branches); i++) { + if (!strcmp(name, branches[i])) + return 1; + } + return 0; +} + +static const struct ins_ops *alpha__associate_instruction_ops(struct arch = *arch, const char *name) +{ + const struct ins_ops *ops =3D NULL; + + if (!strcmp(name, "bsr")) { + ops =3D &alpha_call_ops; + } else if (!strcmp(name, "jsr") || + !strcmp(name, "jcr")) { + ops =3D &alpha_indirect_call_ops; + } else if (!strcmp(name, "ret")) { + ops =3D &ret_ops; + } else if (!strcmp(name, "jmp")) { + ops =3D &alpha_indirect_jump_ops; + } else if (!strcmp(name, "br") || + is_alpha_cond_branch(name)) { + ops =3D &jump_ops; + } else if (!strcmp(name, "mov") || + !strcmp(name, "fmov")) { + ops =3D &mov_ops; + } + + if (ops) + arch__associate_ins_ops(arch, name, ops); + + return ops; +} + +const struct arch *arch__new_alpha(const struct e_machine_and_e_flags *id, + const char *cpuid __maybe_unused) +{ + struct arch *arch =3D zalloc(sizeof(*arch)); + + if (!arch) + return NULL; + + arch->name =3D "alpha"; + arch->id =3D *id; + arch->associate_instruction_ops =3D alpha__associate_instruction_ops; + /* objdump emits no comments for Alpha; '#' is what the assembler uses. */ + arch->objdump.comment_char =3D '#'; + return arch; +} diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c index 6cfdbabbb8c7..49c206a88eec 100644 --- a/tools/perf/util/disasm.c +++ b/tools/perf/util/disasm.c @@ -161,6 +161,8 @@ const struct arch *arch__find(uint16_t e_machine, uint3= 2_t e_flags, const char * .e_flags =3D e_flags, }; const struct arch *result =3D NULL, **tmp; + const struct arch *(*new_fn)(const struct e_machine_and_e_flags *id, + const char *cpuid) =3D NULL; =20 if (num_archs > 0) { tmp =3D bsearch(&key, archs, num_archs, sizeof(*archs), arch__key_cmp); @@ -171,7 +173,16 @@ const struct arch *arch__find(uint16_t e_machine, uint= 32_t e_flags, const char * if (result) return result; =20 - if (e_machine >=3D ARRAY_SIZE(arch_new_fn) || arch_new_fn[e_machine] =3D= =3D NULL) { + /* + * EM_ALPHA (0x9026) is far too large to index arch_new_fn[], so it is + * selected explicitly; everything else uses the e_machine-indexed table. + */ + if (e_machine =3D=3D EM_ALPHA) + new_fn =3D arch__new_alpha; + else if (e_machine < ARRAY_SIZE(arch_new_fn)) + new_fn =3D arch_new_fn[e_machine]; + + if (new_fn =3D=3D NULL) { errno =3D ENOTSUP; return NULL; } @@ -182,7 +193,7 @@ const struct arch *arch__find(uint16_t e_machine, uint3= 2_t e_flags, const char * =20 archs =3D tmp; =20 - result =3D arch_new_fn[e_machine](&key, cpuid); + result =3D new_fn(&key, cpuid); if (!result) { pr_err("%s: failed to initialize %u arch priv area\n", __func__, e_machine); diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h index 25756e3f47e4..adbdbf8f1f35 100644 --- a/tools/perf/util/disasm.h +++ b/tools/perf/util/disasm.h @@ -122,6 +122,7 @@ extern const struct ins_ops ret_ops; =20 int arch__associate_ins_ops(struct arch *arch, const char *name, const str= uct ins_ops *ops); =20 +const struct arch *arch__new_alpha(const struct e_machine_and_e_flags *id,= const char *cpuid); const struct arch *arch__new_arc(const struct e_machine_and_e_flags *id, c= onst char *cpuid); const struct arch *arch__new_arm(const struct e_machine_and_e_flags *id, c= onst char *cpuid); const struct arch *arch__new_arm64(const struct e_machine_and_e_flags *id,= const char *cpuid); --=20 2.54.0