From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94070C4167B for ; Fri, 11 Feb 2022 10:35:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349052AbiBKKf0 (ORCPT ); Fri, 11 Feb 2022 05:35:26 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:32820 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349030AbiBKKfH (ORCPT ); Fri, 11 Feb 2022 05:35:07 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 77D4AEB0 for ; Fri, 11 Feb 2022 02:35:06 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id g205-20020a2552d6000000b0061e1843b8edso16801842ybb.18 for ; Fri, 11 Feb 2022 02:35:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=zI7UttEId1m8qD/b8dbgmy1+n+4tYzA6No79RQaEvJg=; b=c95z3s6HerUsvP/6fia6eJdMvptjfAevj7eDXrXgwIk+/Yf1znUfb9oQkMdkukkGxo /NqRN6P/TR/OZgj3LaDZza8AEC1H/0xz/5VKrU72Vfaeze5e9ZGStAeEN7V7WuzLKfU5 WOU5qYZ7Q2y0t3BDkFPJ1BMwqNwqlVaVTolLTpGlPMdSst9KaiBCS5Ls0CGq9NIKrkLD skEflOenO7ka0YxTJqL2cSVyBut2gJDQLX9m7BfEhm+xP4MPnl6Yx+ONFzEsTmdYiRT5 NdgL+/eiQFsuP5u/4IRBw2MLSecRQ8PbLZlhXTmcvRh8w8NIRYAB2aiK+PXuK4zZ+Rc2 zJ6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=zI7UttEId1m8qD/b8dbgmy1+n+4tYzA6No79RQaEvJg=; b=ZlQsTTK4UIQt67QJN5uItkWCMUDmt365kgOp4jtHBoHnhxDoZ+Ql9imIOxuD+gp6Wl +c+GJmSH7JuDRdllRMBuGchNAtOiprdeC983QaVRQ93WhSsM5P61xUhzFPBtYEp5yCJz tx1dhNuseawqNls8b3ixaBQ9r/C+n/rr0aZRtQX/MZHI6VjPD3DWibitErgnW/49G8B8 E6sCdVG1GmBwiKv+UiosVW0xek49AP4RJw9RrBXc2H7bjSP4kojQCpPOXiPWg9Lsehuq 1N8GR8vqd/B9VPscelj2kGrvBWC/bfGAN2XT5piK5AWT5r/XKE4cCfZQ6VL5ETlFo3Bq 2o8A== X-Gm-Message-State: AOAM5304ES1FG3pfsMnDBKvqewbx5cJBWpjmGvOLsXzfhQOcGGBcu0DN y4wSsFSYTECI1l/AFGB0XBtU+yr/Ny3+ X-Google-Smtp-Source: ABdhPJyR3EAY6q+MUpkB9EnOpbAkDmuicacRDgwQL12qDtgndGv3SRuWrd0G2nqwMG5XhpypEUcVLVx/mWE5 X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:2d98:3ad9:1d8a:fb9b]) (user=irogers job=sendgmr) by 2002:a81:3350:: with SMTP id z77mr859862ywz.281.1644575705706; Fri, 11 Feb 2022 02:35:05 -0800 (PST) Date: Fri, 11 Feb 2022 02:34:11 -0800 In-Reply-To: <20220211103415.2737789-1-irogers@google.com> Message-Id: <20220211103415.2737789-19-irogers@google.com> Mime-Version: 1.0 References: <20220211103415.2737789-1-irogers@google.com> X-Mailer: git-send-email 2.35.1.265.g69c8d7142f-goog Subject: [PATCH v3 18/22] libperf: Add reference count checking macros. From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Darren Hart , Davidlohr Bueso , "=?UTF-8?q?Andr=C3=A9=20Almeida?=" , James Clark , John Garry , Riccardo Mancini , Yury Norov , Andy Shevchenko , Andrew Morton , Jin Yao , Adrian Hunter , Leo Yan , Andi Kleen , Thomas Richter , Kan Liang , Madhavan Srinivasan , Shunsuke Nakamura , Song Liu , Masami Hiramatsu , Steven Rostedt , Miaoqian Lin , Stephen Brennan , Kajol Jain , Alexey Bayduraev , German Gomez , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Dmitry Vyukov , Hao Luo Cc: eranian@google.com, Ian Rogers Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-perf-users@vger.kernel.org The macros serve as a way to debug use of a reference counted struct. The macros add a memory allocated pointer that is interposed between the reference counted original struct at a get and freed by a put. The pointer replaces the original struct, so use of the struct name via APIs remains unchanged. Signed-off-by: Ian Rogers --- tools/lib/perf/include/internal/rc_check.h | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tools/lib/perf/include/internal/rc_check.h diff --git a/tools/lib/perf/include/internal/rc_check.h b/tools/lib/perf/include/internal/rc_check.h new file mode 100644 index 000000000000..30d12f9c7b52 --- /dev/null +++ b/tools/lib/perf/include/internal/rc_check.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_INTERNAL_RC_CHECK_H +#define __LIBPERF_INTERNAL_RC_CHECK_H + +#include +#include + +/* + * Shared reference count checking macros. + * + * Reference count checking is an approach to sanitizing the use of reference + * counted structs. It leverages address and leak sanitizers to make sure gets + * are paired with a put. Reference count checking adds a malloc-ed layer of + * indirection on a get, and frees it on a put. A missed put will be reported as + * a memory leak. A double put will be reported as a double free. Accessing + * after a put will cause a use-after-free and/or a segfault. + */ + +#ifndef REFCNT_CHECKING +/* Replaces "struct foo" so that the pointer may be interposed. */ +#define DECLARE_RC_STRUCT(struct_name) \ + struct struct_name + +/* Declare a reference counted struct variable. */ +#define RC_STRUCT(struct_name) struct struct_name + +/* + * Interpose the indirection. Result will hold the indirection and object is the + * reference counted struct. + */ +#define ADD_RC_CHK(result, object) (result = object, object) + +/* Strip the indirection layer. */ +#define RC_CHK_ACCESS(object) object + +/* Frees the object and the indirection layer. */ +#define RC_CHK_FREE(object) free(object) + +/* A get operation adding the indirection layer. */ +#define RC_CHK_GET(result, object) ADD_RC_CHK(result, object) + +/* A put operation removing the indirection layer. */ +#define RC_CHK_PUT(object) {} + +#else + +/* Replaces "struct foo" so that the pointer may be interposed. */ +#define DECLARE_RC_STRUCT(struct_name) \ + struct original_##struct_name; \ + struct struct_name { \ + struct original_##struct_name *orig; \ + }; \ + struct original_##struct_name + +/* Declare a reference counted struct variable. */ +#define RC_STRUCT(struct_name) struct original_##struct_name + +/* + * Interpose the indirection. Result will hold the indirection and object is the + * reference counted struct. + */ +#define ADD_RC_CHK(result, object) \ + ( \ + object ? (result = malloc(sizeof(*result)), \ + result ? (result->orig = object, result) \ + : (result = NULL, NULL)) \ + : (result = NULL, NULL) \ + ) + +/* Strip the indirection layer. */ +#define RC_CHK_ACCESS(object) object->orig + +/* Frees the object and the indirection layer. */ +#define RC_CHK_FREE(object) \ + do { \ + zfree(&object->orig); \ + free(object); \ + } while(0) + +/* A get operation adding the indirection layer. */ +#define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL)) + +/* A put operation removing the indirection layer. */ +#define RC_CHK_PUT(object) \ + do { \ + if (object) { \ + object->orig = NULL; \ + free(object); \ + } \ + } while(0) + +#endif + +#endif /* __LIBPERF_INTERNAL_RC_CHECK_H */ -- 2.35.1.265.g69c8d7142f-goog