From patchwork Fri Feb 2 22:04:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 196063 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp732961dyc; Fri, 2 Feb 2024 14:31:16 -0800 (PST) X-Google-Smtp-Source: AGHT+IHxJP6K4DvmJkwSlT4dhewLP57THw812JCAmQlXXfyYaHIo3pPpgNtemSw54Dwbxvfuxv6n X-Received: by 2002:a17:906:a888:b0:a37:21cb:f3fc with SMTP id ha8-20020a170906a88800b00a3721cbf3fcmr8544ejb.9.1706913075750; Fri, 02 Feb 2024 14:31:15 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706913075; cv=pass; d=google.com; s=arc-20160816; b=K70LpqHUZwW7zuFFllcVav1tXWCWqeGWAtJZESqcp6COjvMw3KcKivrzmGLIUpK4bK TLT7YqLAJb4I4umVu7HmKagmOYY7L+G71YNjn7DEgoPqIFQPYPsFOHDQ6qoUaDCfYb6c Juo4fT4H1WbN6T1uAY4su6yBsKuqfsr4VUHMrcqSkxRd+5nCRC4LoCvDJSjLR5WvG6wW Qd70auTD5ibDU0rQTp9HYlpaVrkZKbujZlI/xfYNSJKZo5Pu11hQ83KIJRKN9Xt1payp E5wA1VHOgG1yiOqLc9UBsyhpl4R8ysDnGIGNMaTcoMwYVZG8jsAtNLPOuuSClTwy0SVv pQPg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=x2DL2UveeLpLuMsEbdteBN2ifTTjqB6/QPkHXz4u9aA=; fh=1JxWv9fMrOG8nRCB3voAngGvC37qtsRktANVPyWADfI=; b=v1SxyjmFSgyPJEJdeNql9DoERqBsALtMi83CElVTzlutdyC8kKu+QXOZXj9RsK1ilB t7vXMyQHfXFAQIUjvuPwtnt7g8n6QDcPuBI+eE1ufAVIPl5B6kHUmIqM2CCj+hPaMECT 8b2QROOC9r/oIx5rler7vSWpgDQquYYVH40fyNq+74bMP9J97v9JP3SDQBYUVln6f+ja O4rUYZJHYo2+tC75EGVc4fQWiHj3EUUHYxzMfLKYzlG3PQ5bNx7RThNZY+76r0bUOEEL 7Edd0286JfMRNXyPTWncOCaT0Bfb34x3iYsKty85CDyQIY7xy4m9GQ7uscg3zCJ2OZp3 4IFA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="P/QlBZOV"; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-50635-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-50635-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org X-Forwarded-Encrypted: i=1; AJvYcCXBOeJrZ8TrDvq7qxoLeNo/ykBKJiS0+onQfcTsm49y3zGzI7nD5oLfqnyQjScVvVXjiyffaZiW0NyTryMz6e0ZufGQBQ== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id f15-20020a17090624cf00b00a35c1f2ea3esi1245577ejb.992.2024.02.02.14.31.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 14:31:15 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-50635-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="P/QlBZOV"; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-50635-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-50635-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 823E81F2A170 for ; Fri, 2 Feb 2024 22:06:28 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A6E2C12D742; Fri, 2 Feb 2024 22:05:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="P/QlBZOV" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A4CC85935; Fri, 2 Feb 2024 22:05:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706911503; cv=none; b=p38cHaLGICu61442RyIBsVwb425sigdTe4Rqw6/eJcZFYp+YS/XS68Gmzh9DRwKFxChtC3aK9aWq4VeQLVrmPyWoLtE+mrrt3YIgkBh4U9gPep3gI69DPbhFCqiPPKOY+aw+lOE2p4dGPkbmQwtgwBgNIqpE68PrZw+qbvxk9v8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706911503; c=relaxed/simple; bh=jmdfikaTg6ynLFAg/Mk8pHeUzgNbVHrf3IL/djBhCOo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aULANspnAOHviM3ZwXldvbCxw6RMnyBrBcjfNOlhqDsfIPs+wJoRvUnXmuxDXtlx7kIGP+uH4qzFyvFedYparS3H1HtannLf7wyBESzw2VizL4KmSrDQEshjrpbOPqr7413mHTplF/h4Qg2zXuJ3t866Z9icw7t9PDBkVTmcSDk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=P/QlBZOV; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 72704C43390; Fri, 2 Feb 2024 22:05:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1706911502; bh=jmdfikaTg6ynLFAg/Mk8pHeUzgNbVHrf3IL/djBhCOo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P/QlBZOVURwJt2W/TTEwL1Dvui8C5poLRMPdhqanzuhMTyxGyNpoIidnOWhm774cC D8EhZH5bODyzLHfCDSHvgzbdqQQnk2Oz0qE5uEhp3jhx8/21TyVAH9foX5SuWTOXY4 XwlY/acsoBI7vPjTSOEZk8SW1sUm2p8a31KAY8QX8dsOBPLLgQ8T+s8wZv+mIlMFlP DldTqmONWIWvdSzH6j5TCbx+1d3lvY78BQcWcMlMA4liRCJ36Lxn1tMb0dqgY4+yyV LXyHM+gYg2uf2or0IJJ6MZmsJpqSZ0l1uCH0q+tWyxXfNrmGULnlBjyf1KW9mkqh1R pqiUhm12vR1dg== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, Linus Torvalds , Stephane Eranian , Masami Hiramatsu , linux-toolchains@vger.kernel.org, linux-trace-devel@vger.kernel.org Subject: [PATCH 02/14] perf dwarf-aux: Handle type transfer for memory access Date: Fri, 2 Feb 2024 14:04:47 -0800 Message-ID: <20240202220459.527138-3-namhyung@kernel.org> X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog In-Reply-To: <20240202220459.527138-1-namhyung@kernel.org> References: <20240202220459.527138-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789828085523141313 X-GMAIL-MSGID: 1789828085523141313 We want to track type states as instructions are executed. Each instruction can access compound types like struct or union and load/ store its members to a different location. The die_deref_ptr_type() is to find a type of memory access with a pointer variable. If it points to a compound type like struct, the target memory is a member in the struct. The access will happen with an offset indicating which member it refers. Let's follow the DWARF info to figure out the type of the pointer target. For example, say we have the following code. struct foo { int a; int b; }; struct foo *p = malloc(sizeof(*p)); p->b = 0; The last pointer access should produce x86 asm like below: mov 0x0, 4(%rbx) And we know %rbx register has a pointer to struct foo. Then offset 4 should return the debug info of member 'b'. Also variables of compound types can be accessed directly without a pointer. The die_get_member_type() is to handle a such case. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Namhyung Kim --- tools/perf/util/dwarf-aux.c | 110 ++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 6 ++ 2 files changed, 116 insertions(+) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index f878014c9e27..39851ff1d5c4 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1841,3 +1841,113 @@ int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes) *scopes = data.scopes; return data.nr; } + +static int __die_find_member_offset_cb(Dwarf_Die *die_mem, void *arg) +{ + Dwarf_Die type_die; + Dwarf_Word size, loc; + Dwarf_Word offset = (long)arg; + int tag = dwarf_tag(die_mem); + + if (tag != DW_TAG_member) + return DIE_FIND_CB_SIBLING; + + /* Unions might not have location */ + if (die_get_data_member_location(die_mem, &loc) < 0) + loc = 0; + + if (offset == loc) + return DIE_FIND_CB_END; + + die_get_real_type(die_mem, &type_die); + + if (dwarf_aggregate_size(&type_die, &size) < 0) + size = 0; + + if (loc < offset && offset < (loc + size)) + return DIE_FIND_CB_END; + + return DIE_FIND_CB_SIBLING; +} + +/** + * die_get_member_type - Return type info of struct member + * @type_die: a type DIE + * @offset: offset in the type + * @die_mem: a buffer to save the resulting DIE + * + * This function returns a type of a member in @type_die where it's located at + * @offset if it's a struct. For now, it just returns the first matching + * member in a union. For other types, it'd return the given type directly + * if it's within the size of the type or NULL otherwise. + */ +Dwarf_Die *die_get_member_type(Dwarf_Die *type_die, int offset, + Dwarf_Die *die_mem) +{ + Dwarf_Die *member; + Dwarf_Die mb_type; + int tag; + + tag = dwarf_tag(type_die); + /* If it's not a compound type, return the type directly */ + if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { + Dwarf_Word size; + + if (dwarf_aggregate_size(type_die, &size) < 0) + size = 0; + + if ((unsigned)offset >= size) + return NULL; + + *die_mem = *type_die; + return die_mem; + } + + mb_type = *type_die; + /* TODO: Handle union types better? */ + while (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) { + member = die_find_child(&mb_type, __die_find_member_offset_cb, + (void *)(long)offset, die_mem); + if (member == NULL) + return NULL; + + if (die_get_real_type(member, &mb_type) == NULL) + return NULL; + + tag = dwarf_tag(&mb_type); + + if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) { + Dwarf_Word loc; + + /* Update offset for the start of the member struct */ + if (die_get_data_member_location(member, &loc) == 0) + offset -= loc; + } + } + *die_mem = mb_type; + return die_mem; +} + +/** + * die_deref_ptr_type - Return type info for pointer access + * @ptr_die: a pointer type DIE + * @offset: access offset for the pointer + * @die_mem: a buffer to save the resulting DIE + * + * This function follows the pointer in @ptr_die with given @offset + * and saves the resulting type in @die_mem. If the pointer points + * a struct type, actual member at the offset would be returned. + */ +Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset, + Dwarf_Die *die_mem) +{ + Dwarf_Die type_die; + + if (dwarf_tag(ptr_die) != DW_TAG_pointer_type) + return NULL; + + if (die_get_real_type(ptr_die, &type_die) == NULL) + return NULL; + + return die_get_member_type(&type_die, offset, die_mem); +} diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index efafd3a1f5b6..ad4d7322fcbf 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -144,6 +144,12 @@ struct die_var_type { int offset; }; +/* Return type info of a member at offset */ +Dwarf_Die *die_get_member_type(Dwarf_Die *type_die, int offset, Dwarf_Die *die_mem); + +/* Return type info where the pointer and offset point to */ +Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset, Dwarf_Die *die_mem); + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT /* Get byte offset range of given variable DIE */