From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (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 681A21A070C for ; Mon, 23 Sep 2024 18:19:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115550; cv=none; b=sOMWyBjSW/jvCxYFm4DKkK8zBdU80egFsRHZjudS9mv0WxP168w66/DRTiPSHgb7DAJ//sPIN5GshcoyfCGCGbUvHL8Y51xnraBXjN/q7On4anMK6bpBrOZMtOBXhk/am+LqHrceIAd79b6kOEAA56FJ+hUVrRUJCdndR+5UjJ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115550; c=relaxed/simple; bh=oXNzm4MZb0k/XXfQMZMx6410zG4bTNO8FdzpKDFiStc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=CqCn0GYJUnAuOtWcpJF20huszQy34CG5g14BpE1zMnI4r/x1GqzEXJQOv3NJ5TI3yxeU5blmwq2CvG+66HmywuQM/8OJTYjQVxlJNrVePIXgRe6F3klFEnIu72SH+HME1HKSnfWCwYbZo0xPRtKgInuybXT+mVXwM7xjmlgrgws= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=VRVB5urv; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="VRVB5urv" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-6d4f52a4069so81084377b3.3 for ; Mon, 23 Sep 2024 11:19:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115547; x=1727720347; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=7d86bJdCRGCypNEWHvJnM+7Kig6RbYD9GxfCLKVtKPE=; b=VRVB5urvPjGP3zha/Hv7jptCgmXOto7ufx3KghcIIDTbHo2ZsXLPvVgbu9WVKWYGes Rkd1/1nNmRjsQkz04gabvDbs35b7HeyCywxp6THtswN4iz8LmhmORpOsAHihy6czQfd1 ys4JxqAfKzsqhgrRBPQa8hj7VxJfWHfIuPAoExoI9SKzXGSbuGwPrAD8aw9pUgPpl3Nw CJiif3qm3gVZkOhFFVaf//PynTCt/YjouDuquTblhJdoSSIfKe+K7I8aXYuxONZXESan 7sXY4EKR1YRacWHbBS6ayE6n5Kr9qtT07hBQZrTGeZm7azvpzsvpErKBCgA85cg3gJSb xr+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115547; x=1727720347; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=7d86bJdCRGCypNEWHvJnM+7Kig6RbYD9GxfCLKVtKPE=; b=Y6ulJwfrKL0dS8HJO9YcEzGuq1yFnYkXVWE1dbGXMB3ueyCRjRf4glBCBe7M30h2DL /E+9cu3qKYe5JW2fmBI0t7+SPuPxZtOdl28X47GAZ/HlVRovwJCWNGd5CSypk6WlxFkl 43UobEHF7g3goFOhAmEtjnM9KlEVxgOLpGNkn/WUYqXMEwtHQmdiuCZ0oi+D3sLa1Zql y0LJnbYhfQhDQKVo4Mu0OI9BM80yb/+CTtDvKlglORMte5oviP5Oo4/3zouVx+Do8Wt5 LJCYzjZIPyU/W5v7wbtWbCTm8UZ7sDa8Pq8orcv5xAoWUdBYguRhCEFQ+hc8S5TCdNSe eyzA== X-Forwarded-Encrypted: i=1; AJvYcCUR8EozGu/0HJoPWLhiVSTvZL7N3AOOj003Fae20YAvEfx67i/p3E70EKqaaQAP/BsIU5SEbY2D1UxGnT8=@vger.kernel.org X-Gm-Message-State: AOJu0Yxw6mkKucjZeYZkFsKPro+vMyo4k65AlNJpPCuVLPSMrWqDtgih HiDQtC8HlkrAw3tfqWHRjupphlTQTw+kXbxha4sElGDi4zclYdzX6ogISVIy9EZWn9VHt5bXfRY jD8t8Q8WS1goFbAmlKO0DPYddvw== X-Google-Smtp-Source: AGHT+IHm2Anof1qGJ9R1CvWT3pkt5SNmdiVkAOQ5LZRBMwdvknPsZ+Wqwa1ekbtEl+NQeccCrcS1Kq2JDKfyTFFeZVE= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a25:690e:0:b0:e1d:21ae:3b95 with SMTP id 3f1490d57ef6-e2252fe2127mr32035276.10.1727115547235; Mon, 23 Sep 2024 11:19:07 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:47 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=2207; i=samitolvanen@google.com; h=from:subject; bh=oXNzm4MZb0k/XXfQMZMx6410zG4bTNO8FdzpKDFiStc=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN7IpMgaalZt/ZdNgMn5hGFUwv/f5BSflZZ//L7YV2 au9/cPfjlIWBjEOBlkxRZaWr6u37v7ulPrqc5EEzBxWJpAhDFycAjCR3leMDFfk1WPEjs9IzO6Y ry/OH+RzXaBp+eTWuw8rJO47lKz1us/wP0xmVZtejIrC77VzTjnVp3f196efPWzpckN52UR/ucQ 8DgA= X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-23-samitolvanen@google.com> Subject: [PATCH v3 01/20] scripts: import more list macros From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Import list_is_first, list_is_last, list_replace, and list_replace_init. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/include/list.h | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/scripts/include/list.h b/scripts/include/list.h index fea1e2b79063..8bdcaadca709 100644 --- a/scripts/include/list.h +++ b/scripts/include/list.h @@ -127,6 +127,36 @@ static inline void list_del(struct list_head *entry) entry->prev =3D LIST_POISON2; } =20 +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next =3D old->next; + new->next->prev =3D new; + new->prev =3D old->prev; + new->prev->next =3D new; +} + +/** + * list_replace_init - replace old entry by new one and initialize the old= one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + /** * list_move - delete from one list and add as another's head * @list: the entry to move @@ -150,6 +180,26 @@ static inline void list_move_tail(struct list_head *li= st, list_add_tail(list, head); } =20 +/** + * list_is_first -- tests whether @list is the first entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_first(const struct list_head *list, const struct= list_head *head) +{ + return list->prev =3D=3D head; +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, const struct = list_head *head) +{ + return list->next =3D=3D head; +} + /** * list_is_head - tests whether @list is the list @head * @list: the entry to test --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yb1-f202.google.com (mail-yb1-f202.google.com [209.85.219.202]) (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 5AE031A070E for ; Mon, 23 Sep 2024 18:19:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115552; cv=none; b=uu+0a80pENJQ1IwhwhE8svYe3VRJlsCLlfToAeIlVa47SPejwRebLTESRa9t/j0jly+MGX7/b+HCPBaazWAo5ipMHeSvaPf4eyqdzpYKhKXgvSS7Cst1zuU/zAahp7UVEsdDDToUZx1mEqwYcLXe1FnW+w08P9lSkn/B8rDPxRM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115552; c=relaxed/simple; bh=IuiawhuG+zoJYUxi2uk0F1cVV4B1nwmNk/wnSiaWDTw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=VDvKZ0j34Db8BAY29XyCcfNKRdAMGTP6PnxzKhKuM83rddO5citafHyd8nJ/gFlsL2woTAh7shsD70Sk4zen5L2uM2u3B7NE95kASc6VHxxDzHF9OboGjLzn+onAPNbwdvaBe19WADsfwFZ1216z5RVWQMBHc7Twa3HUkmgwIeA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=lXm5YTgI; arc=none smtp.client-ip=209.85.219.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="lXm5YTgI" Received: by mail-yb1-f202.google.com with SMTP id 3f1490d57ef6-e1e275db7faso6929973276.2 for ; Mon, 23 Sep 2024 11:19:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115549; x=1727720349; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=3IHLt1IdfyTQ2hGd6XvMfjpE0ppk6XCfD4SQxUE62ug=; b=lXm5YTgI2Rf0t1kqKNZ50482NPLwq/eb30KTQ+vTVH+DSg+Z+dVwGGSOwA4sJe4GQv +k50/hmb7ocoW5p4mX1Q249raFDm31CHSp5bGoDVnk5GFM+hL+ngIIKTtbMwuquZO4oY /PDGv66ugPOeHFKL0duY22g3zU+68OqHz9rN+zg5rS78JFpleD2WhAkIBXIwXqAiYBwe fBjf2DNWV6r16FliYziYEbxR3XIFsVUd1YUABEj1+wKZN75UHHA54snU5iPCoBJ0XEm2 YaXjJ5AsTgku2LwEcrjxw9Dr3ycU3MOWLGV6xJcKheAvrxEDKwziA0bdf1bOItNr2ILF 1X9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115549; x=1727720349; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3IHLt1IdfyTQ2hGd6XvMfjpE0ppk6XCfD4SQxUE62ug=; b=FLlbDb2b1cJQlOYg7RLoAtVqOK0Tj7tFiINXHG2VrF+zCKCPFqcEoGc03iO65mScJE g+Ai4dQsDPUAftZn+Z5fcTF4y5j9L6+lql8rbienLP0qV1IhxK7ZVLdZRZbxCqmcGzgQ NebxaEgm4E2ptqhph/H85wgaB75HIK6flUcTveKX/17G27e7myCXu/3rOD6Buc+nEQHt iwmFp6rc4ImKlE0+EaRsGnhGVbNmdYRUFrKCHLNww6vIqcA1t8C4vKqMZM6h9Fk0qC/M DAXL14ZonX1DusaFp4tMZ/CjGnePkbwg+F87jdz2gGxLmAuIA8KW4ubW/rDfxosDYtyO hhOQ== X-Forwarded-Encrypted: i=1; AJvYcCUeIM3hNeRr5b4dkmQA+OEeLU/pgJQuL3MjLdiVditFJAzwMfJEoZ+k62JiqjlSK/4ftfwzYMQwWDSNuNc=@vger.kernel.org X-Gm-Message-State: AOJu0YyUeVNu6I1hDU6yPawbHiRE1uCjMM7FLJq34o228YctKO7v9qJV 6fIMVt+a5AEZQqniur/XFGhb1ANHo8kHH1fTNEdqFF+liSv5RFtbbEgTLfnxue+9+LAO+w8EP/W 8fhLWW/Tj4dLUhuENjGzAg36Owg== X-Google-Smtp-Source: AGHT+IERTGgOAFWFV3F4mZ5DsUTVPlGgpEHV9tQ0c3M91Yl5SUu/hfCh9Ur9j2hFiLFhTcot3pChDd0QgbyKME2socs= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a25:dcc7:0:b0:e20:25f5:a889 with SMTP id 3f1490d57ef6-e2250c42fd4mr9764276.5.1727115549078; Mon, 23 Sep 2024 11:19:09 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:48 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=9955; i=samitolvanen@google.com; h=from:subject; bh=IuiawhuG+zoJYUxi2uk0F1cVV4B1nwmNk/wnSiaWDTw=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN7L/33u1U0rFUVnHiHX3hE+VD7znfW/OXLatSm59u ZvAur8pHaUsDGIcDLJiiiwtX1dv3f3dKfXV5yIJmDmsTCBDGLg4BWAiN2UYGZ4ynJy9NGD9qjXT OZdLf6vWvzTl59bNF+dyGraUeDYw9VxiZJhuI8y2JPqvvsGG87zTNt68MnGpGNeR9RNO1m83kPM 78J4fAA== X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-24-samitolvanen@google.com> Subject: [PATCH v3 02/20] scripts: move genksyms crc32 implementation to a common include From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To avoid duplication between host programs, move the crc32 code to a shared header file. Suggested-by: Petr Pavlu Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/genksyms/genksyms.c | 77 +----------------------------- scripts/include/crc32.h | 93 +++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 76 deletions(-) create mode 100644 scripts/include/crc32.h diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index f3901c55df23..2885bbcb9eec 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -18,6 +18,7 @@ #include #include =20 +#include #include "genksyms.h" /*----------------------------------------------------------------------*/ =20 @@ -58,82 +59,6 @@ static struct string_list *mk_node(const char *string); static void print_location(void); static void print_type_name(enum symbol_type type, const char *name); =20 -/*----------------------------------------------------------------------*/ - -static const unsigned int crctab32[] =3D { - 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, - 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, - 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, - 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, - 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, - 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, - 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, - 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, - 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, - 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, - 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, - 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, - 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, - 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, - 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, - 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, - 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, - 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, - 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, - 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, - 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, - 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, - 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, - 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, - 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, - 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, - 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, - 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, - 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, - 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, - 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, - 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, - 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, - 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, - 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, - 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, - 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, - 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, - 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, - 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, - 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, - 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, - 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, - 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, - 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, - 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, - 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, - 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, - 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, - 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, - 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, - 0x2d02ef8dU -}; - -static unsigned long partial_crc32_one(unsigned char c, unsigned long crc) -{ - return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); -} - -static unsigned long partial_crc32(const char *s, unsigned long crc) -{ - while (*s) - crc =3D partial_crc32_one(*s++, crc); - return crc; -} - -static unsigned long crc32(const char *s) -{ - return partial_crc32(s, 0xffffffff) ^ 0xffffffff; -} - -/*----------------------------------------------------------------------*/ - static enum symbol_type map_to_ns(enum symbol_type t) { switch (t) { diff --git a/scripts/include/crc32.h b/scripts/include/crc32.h new file mode 100644 index 000000000000..06eedd273717 --- /dev/null +++ b/scripts/include/crc32.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * CRC32 implementation. + * + * Moved from scripts/genksyms/genksyms.c, which has the following + * notice: + * + * Generate kernel symbol version hashes. + * Copyright 1996, 1997 Linux International. + * + * New implementation contributed by Richard Henderson + * Based on original work by Bjorn Ekwall + * + * This file was part of the Linux modutils 2.4.22: moved back into the + * kernel sources by Rusty Russell/Kai Germaschewski. + */ + +#ifndef __CRC32_H +#define __CRC32_H + +static const unsigned int crctab32[] =3D { + 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, + 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, + 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, + 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, + 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, + 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, + 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, + 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, + 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, + 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, + 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, + 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, + 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, + 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, + 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, + 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, + 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, + 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, + 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, + 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, + 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, + 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, + 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, + 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, + 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, + 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, + 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, + 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, + 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, + 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, + 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, + 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, + 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, + 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, + 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, + 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, + 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, + 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, + 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, + 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, + 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, + 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, + 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, + 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, + 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, + 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, + 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, + 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, + 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, + 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, + 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, + 0x2d02ef8dU +}; + +static inline unsigned long partial_crc32_one(unsigned char c, unsigned lo= ng crc) +{ + return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); +} + +static inline unsigned long partial_crc32(const char *s, unsigned long crc) +{ + while (*s) + crc =3D partial_crc32_one(*s++, crc); + return crc; +} + +static inline unsigned long crc32(const char *s) +{ + return partial_crc32(s, 0xffffffff) ^ 0xffffffff; +} + +#endif /* __CRC32_H */ --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 326881A08CE for ; Mon, 23 Sep 2024 18:19:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115554; cv=none; b=q/o2SYQmKEioyTKn+Jgj9GRP3bMfx7lTbJV0udDHLmuU8v1fyX5XrJld48Y58mUMV1svYuXdyt0MjSOevCJ/dnave6j95QvCq6C8ND5n7Ta/UffBdI6oLvIIqqD9+RjPDNNac0OsgVjJV4eJ1x8hLw+MZYO5eNfXZ/8Mhy1pKM8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115554; c=relaxed/simple; bh=EIGT9VIHeytq4Cj/C6088281fr/C0yizCn1b3ot2OpU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=gZltxI0u/IX3W4xaTMbj16yfTPngdZOjlBHhKpsZ8ZgmFV/+N9rCyIUOlJ022OTko1xhHZS6ekr0Mg7UJyySh88SoDR4C3yiGBApqz/mBJli5Uevewk0B6/2NyQfbtOE2uUu/CCW7PGhptU4wB8H5dWmvMjG8vufXOWjLDLLl3k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=muGoVXUE; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="muGoVXUE" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-209dc9354c3so16713975ad.0 for ; Mon, 23 Sep 2024 11:19:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115551; x=1727720351; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=r25b93t30NRQDT3mdE01vOqrF861R5sVgc3eWnwIsC4=; b=muGoVXUESNIPguydiDOKb2aiZGAlSOGEIIWneIRIN3fj1+4Gzx9jCKv/boReVHXt+x qFDdOyNiVetg3msc0XJjOKt9Rz7E9TUY5GphQbNv4LzzelfJavq1K0S3Tj2LmHeuiIGx CUXCAlxQBLl9SbAQVcCKfyJru/3zWXgqRNIMIjyHb/HVw1S7o6sKqXjumDunQJYwZtUQ y430kSqFkPvL2eM64Bpf4dnInwZDypWxwMSaIk5jr7FQge0BZ0x5bvZEoR2bTDIhwNj2 9COtauguEIQ5pIwZBpwaQv+brqqQtEWJjE8elpYGinPoWRihQ1UTFSJi6UTBlzfCo6p0 3ztQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115551; x=1727720351; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=r25b93t30NRQDT3mdE01vOqrF861R5sVgc3eWnwIsC4=; b=GU2pNr4LNwmlhxw9Y0htWLSaoDQFmXepgNBN3rf9M2HX4QuuSapIxl/J6LITUQzW68 c6rOZwjUL6a9ffRc9SmpnLStHW6rHvRRbPIl8JkI4kM6lKwJyCBTxrjcm8W5fL8Gerxh 7BbP/AbuW1fZcxsAHT9E9daJo/PDI6cbCzsdtGUFiSVoXt8L/YIiwTnFvLcYTRTo5/hc dhMpcRFnTe18fxyltjefe+jnjcufqFJCuvhbDcEuhk5cvInL6xolHO99OZy0TbSfwUM+ uCX+eSCXTouZhsfG96mfrZuI8Xgo7QruU+S6yP+rOWSjkWTk3rL2/1utMxQjNHcNNmNK XhjQ== X-Forwarded-Encrypted: i=1; AJvYcCVEaxxOolpPrKNDJ8DNbM9d+LZ86f/eDs7NwCXMt8iFqgWsso7/uXbxH60qYYDbBPdWGjZ6JlUa06UHstg=@vger.kernel.org X-Gm-Message-State: AOJu0YzeS65NYhnoGOH6gerFp4eK5N6LNegdv2qvTeu/o7FJby0FABsd H/zkW6OLy47sLvp+d+y7tpyt8t2rh19VHD2Hm791lSphnLtk5/2Dzd0GWCw6c9nb5+PHBVuuBWH +GYVO7ZLMzVb7ugZDz9d5EEcGjA== X-Google-Smtp-Source: AGHT+IHMRrMHpwWxjfNNNbMOMVIr8jGhe2gygLHm8/okL3yLNqEk754NTh7YUpKveVk+VHizpRL/6+H/9e9Ktv9vHAQ= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a17:902:6901:b0:1fb:f1f:19ea with SMTP id d9443c01a7336-20aed0749bfmr5075ad.1.1727115551084; Mon, 23 Sep 2024 11:19:11 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:49 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=14721; i=samitolvanen@google.com; h=from:subject; bh=EIGT9VIHeytq4Cj/C6088281fr/C0yizCn1b3ot2OpU=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN7KndDzqERA62MLYO21BtaGpzeILP5wWqH06cm3WG jsRNbntHaUsDGIcDLJiiiwtX1dv3f3dKfXV5yIJmDmsTCBDGLg4BWAiCWGMDDNTjjWu3Jjp9eNy 5+5bknz8C4z2/ww/VeOyY9/rmXrP/GQZ/ul0LLnddXTTuVt3UtQFP75UK31wpkzNgccx8cMRpmt 2/9gA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-25-samitolvanen@google.com> Subject: [PATCH v3 03/20] tools: Add gendwarfksyms From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a basic DWARF parser, which uses libdw to traverse the debugging information in an object file and looks for functions and variables. In follow-up patches, this will be expanded to produce symbol versions for CONFIG_MODVERSIONS from DWARF. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa Reviewed-by: Petr Pavlu --- kernel/module/Kconfig | 8 ++ scripts/Makefile | 1 + scripts/gendwarfksyms/.gitignore | 2 + scripts/gendwarfksyms/Makefile | 8 ++ scripts/gendwarfksyms/dwarf.c | 166 ++++++++++++++++++++++++++ scripts/gendwarfksyms/gendwarfksyms.c | 132 ++++++++++++++++++++ scripts/gendwarfksyms/gendwarfksyms.h | 97 +++++++++++++++ scripts/gendwarfksyms/symbols.c | 82 +++++++++++++ 8 files changed, 496 insertions(+) create mode 100644 scripts/gendwarfksyms/.gitignore create mode 100644 scripts/gendwarfksyms/Makefile create mode 100644 scripts/gendwarfksyms/dwarf.c create mode 100644 scripts/gendwarfksyms/gendwarfksyms.c create mode 100644 scripts/gendwarfksyms/gendwarfksyms.h create mode 100644 scripts/gendwarfksyms/symbols.c diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index ccdbd1bc12aa..c3a0172a909f 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -168,6 +168,14 @@ config MODVERSIONS make them incompatible with the kernel you are running. If unsure, say N. =20 +config GENDWARFKSYMS + bool + depends on DEBUG_INFO + # Requires full debugging information, split DWARF not supported. + depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT + # Requires ELF object files. + depends on !LTO + config ASM_MODVERSIONS bool default HAVE_ASM_MODVERSIONS && MODVERSIONS diff --git a/scripts/Makefile b/scripts/Makefile index 6bcda4b9d054..d7fec46d38c0 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -54,6 +54,7 @@ targets +=3D module.lds =20 subdir-$(CONFIG_GCC_PLUGINS) +=3D gcc-plugins subdir-$(CONFIG_MODVERSIONS) +=3D genksyms +subdir-$(CONFIG_GENDWARFKSYMS) +=3D gendwarfksyms subdir-$(CONFIG_SECURITY_SELINUX) +=3D selinux subdir-$(CONFIG_SECURITY_IPE) +=3D ipe =20 diff --git a/scripts/gendwarfksyms/.gitignore b/scripts/gendwarfksyms/.giti= gnore new file mode 100644 index 000000000000..0927f8d3cd96 --- /dev/null +++ b/scripts/gendwarfksyms/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +/gendwarfksyms diff --git a/scripts/gendwarfksyms/Makefile b/scripts/gendwarfksyms/Makefile new file mode 100644 index 000000000000..9f8fec4fd39b --- /dev/null +++ b/scripts/gendwarfksyms/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +hostprogs-always-y +=3D gendwarfksyms + +gendwarfksyms-objs +=3D gendwarfksyms.o +gendwarfksyms-objs +=3D dwarf.o +gendwarfksyms-objs +=3D symbols.o + +HOSTLDLIBS_gendwarfksyms :=3D -ldw -lelf diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c new file mode 100644 index 000000000000..81df3e2ad3ae --- /dev/null +++ b/scripts/gendwarfksyms/dwarf.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + */ + +#include "gendwarfksyms.h" + +static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *v= alue) +{ + Dwarf_Attribute da; + + /* dwarf_formref_die returns a pointer instead of an error value. */ + return dwarf_attr(die, id, &da) && dwarf_formref_die(&da, value); +} + +#define DEFINE_GET_STRING_ATTR(attr) \ + static const char *get_##attr##_attr(Dwarf_Die *die) \ + { \ + Dwarf_Attribute da; \ + if (dwarf_attr(die, DW_AT_##attr, &da)) \ + return dwarf_formstring(&da); \ + return NULL; \ + } + +DEFINE_GET_STRING_ATTR(name) +DEFINE_GET_STRING_ATTR(linkage_name) + +static const char *get_symbol_name(Dwarf_Die *die) +{ + const char *name; + + /* rustc uses DW_AT_linkage_name for exported symbols */ + name =3D get_linkage_name_attr(die); + if (!name) + name =3D get_name_attr(die); + + return name; +} + +static bool match_export_symbol(struct state *state, Dwarf_Die *die) +{ + Dwarf_Die *source =3D die; + Dwarf_Die origin; + + /* If the DIE has an abstract origin, use it for type information. */ + if (get_ref_die_attr(die, DW_AT_abstract_origin, &origin)) + source =3D &origin; + + state->sym =3D symbol_get(get_symbol_name(die)); + + /* Look up using the origin name if there are no matches. */ + if (!state->sym && source !=3D die) + state->sym =3D symbol_get(get_symbol_name(source)); + + state->die =3D *source; + return !!state->sym; +} + +/* + * Type string processing + */ +static void process(const char *s) +{ + s =3D s ?: ""; + + if (dump_dies) + fputs(s, stderr); +} + +bool match_all(Dwarf_Die *die) +{ + return true; +} + +int process_die_container(struct state *state, Dwarf_Die *die, + die_callback_t func, die_match_callback_t match) +{ + Dwarf_Die current; + int res; + + res =3D checkp(dwarf_child(die, ¤t)); + while (!res) { + if (match(¤t)) { + /* <0 =3D error, 0 =3D continue, >0 =3D stop */ + res =3D checkp(func(state, ¤t)); + if (res) + return res; + } + + res =3D checkp(dwarf_siblingof(¤t, ¤t)); + } + + return 0; +} + +/* + * Exported symbol processing + */ +static void process_symbol(struct state *state, Dwarf_Die *die, + die_callback_t process_func) +{ + debug("%s", state->sym->name); + check(process_func(state, die)); + if (dump_dies) + fputs("\n", stderr); +} + +static int __process_subprogram(struct state *state, Dwarf_Die *die) +{ + process("subprogram"); + return 0; +} + +static void process_subprogram(struct state *state, Dwarf_Die *die) +{ + process_symbol(state, die, __process_subprogram); +} + +static int __process_variable(struct state *state, Dwarf_Die *die) +{ + process("variable "); + return 0; +} + +static void process_variable(struct state *state, Dwarf_Die *die) +{ + process_symbol(state, die, __process_variable); +} + +static int process_exported_symbols(struct state *unused, Dwarf_Die *die) +{ + int tag =3D dwarf_tag(die); + + switch (tag) { + /* Possible containers of exported symbols */ + case DW_TAG_namespace: + case DW_TAG_class_type: + case DW_TAG_structure_type: + return check(process_die_container( + NULL, die, process_exported_symbols, match_all)); + + /* Possible exported symbols */ + case DW_TAG_subprogram: + case DW_TAG_variable: { + struct state state; + + if (!match_export_symbol(&state, die)) + return 0; + + if (tag =3D=3D DW_TAG_subprogram) + process_subprogram(&state, &state.die); + else + process_variable(&state, &state.die); + + return 0; + } + default: + return 0; + } +} + +void process_cu(Dwarf_Die *cudie) +{ + check(process_die_container(NULL, cudie, process_exported_symbols, + match_all)); +} diff --git a/scripts/gendwarfksyms/gendwarfksyms.c b/scripts/gendwarfksyms/= gendwarfksyms.c new file mode 100644 index 000000000000..096a334fa5b3 --- /dev/null +++ b/scripts/gendwarfksyms/gendwarfksyms.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include "gendwarfksyms.h" + +/* + * Options + */ + +/* Print debugging information to stderr */ +int debug; +/* Dump DIE contents */ +int dump_dies; + +static void usage(void) +{ + fputs("Usage: gendwarfksyms [options] elf-object-file ... < symbol-list\n= \n" + "Options:\n" + " -d, --debug Print debugging information\n" + " --dump-dies Dump DWARF DIE contents\n" + " -h, --help Print this message\n" + "\n", + stderr); +} + +static int process_module(Dwfl_Module *mod, void **userdata, const char *n= ame, + Dwarf_Addr base, void *arg) +{ + Dwarf_Addr dwbias; + Dwarf_Die cudie; + Dwarf_CU *cu =3D NULL; + Dwarf *dbg; + int res; + + debug("%s", name); + dbg =3D dwfl_module_getdwarf(mod, &dwbias); + + do { + res =3D dwarf_get_units(dbg, cu, &cu, NULL, NULL, &cudie, NULL); + if (res < 0) + error("dwarf_get_units failed: no debugging information?"); + if (res =3D=3D 1) + break; /* No more units */ + + process_cu(&cudie); + } while (cu); + + return DWARF_CB_OK; +} + +static const Dwfl_Callbacks callbacks =3D { + .section_address =3D dwfl_offline_section_address, + .find_debuginfo =3D dwfl_standard_find_debuginfo, +}; + +int main(int argc, char **argv) +{ + unsigned int n; + int opt; + + struct option opts[] =3D { { "debug", 0, NULL, 'd' }, + { "dump-dies", 0, &dump_dies, 1 }, + { "help", 0, NULL, 'h' }, + { 0, 0, NULL, 0 } }; + + while ((opt =3D getopt_long(argc, argv, "dh", opts, NULL)) !=3D EOF) { + switch (opt) { + case 0: + break; + case 'd': + debug =3D 1; + break; + case 'h': + usage(); + return 0; + default: + usage(); + return 1; + } + } + + if (optind >=3D argc) { + usage(); + error("no input files?"); + } + + symbol_read_exports(stdin); + + for (n =3D optind; n < argc; n++) { + Dwfl *dwfl; + int fd; + + fd =3D open(argv[n], O_RDONLY); + if (fd =3D=3D -1) { + error("open failed for '%s': %s", argv[n], + strerror(errno)); + return -1; + } + + dwfl =3D dwfl_begin(&callbacks); + if (!dwfl) { + error("dwfl_begin failed for '%s': %s", argv[n], + dwarf_errmsg(-1)); + return -1; + } + + if (!dwfl_report_offline(dwfl, argv[n], argv[n], fd)) { + error("dwfl_report_offline failed for '%s': %s", + argv[n], dwarf_errmsg(-1)); + return -1; + } + + dwfl_report_end(dwfl, NULL, NULL); + + if (dwfl_getmodules(dwfl, &process_module, NULL, 0)) { + error("dwfl_getmodules failed for '%s'", argv[n]); + return -1; + } + + dwfl_end(dwfl); + } + + return 0; +} diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h new file mode 100644 index 000000000000..1a10d18f178e --- /dev/null +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef __GENDWARFKSYMS_H +#define __GENDWARFKSYMS_H + +/* + * Options -- in gendwarfksyms.c + */ +extern int debug; +extern int dump_dies; + +/* + * Output helpers + */ +#define __PREFIX "gendwarfksyms: " +#define __println(prefix, format, ...) \ + fprintf(stderr, prefix __PREFIX "%s: " format "\n", __func__, \ + ##__VA_ARGS__) + +#define debug(format, ...) \ + do { \ + if (debug) \ + __println("", format, ##__VA_ARGS__); \ + } while (0) + +#define warn(format, ...) __println("warning: ", format, ##__VA_ARGS__) +#define error(format, ...) \ + do { \ + __println("error: ", format, ##__VA_ARGS__); \ + exit(1); \ + } while (0) + +/* + * Error handling helpers + */ +#define __check(expr, test) \ + ({ \ + int __res =3D expr; \ + if (test) \ + error("`%s` failed: %d", #expr, __res); \ + __res; \ + }) + +/* Error =3D=3D non-zero values */ +#define check(expr) __check(expr, __res) +/* Error =3D=3D negative values */ +#define checkp(expr) __check(expr, __res < 0) + +/* + * symbols.c + */ + +struct symbol { + const char *name; + struct hlist_node name_hash; +}; + +typedef void (*symbol_callback_t)(struct symbol *, void *arg); + +void symbol_read_exports(FILE *file); +struct symbol *symbol_get(const char *name); + +/* + * dwarf.c + */ + +struct state { + struct symbol *sym; + Dwarf_Die die; +}; + +typedef int (*die_callback_t)(struct state *state, Dwarf_Die *die); +typedef bool (*die_match_callback_t)(Dwarf_Die *die); +bool match_all(Dwarf_Die *die); + +int process_die_container(struct state *state, Dwarf_Die *die, + die_callback_t func, die_match_callback_t match); + +void process_cu(Dwarf_Die *cudie); + +#endif /* __GENDWARFKSYMS_H */ diff --git a/scripts/gendwarfksyms/symbols.c b/scripts/gendwarfksyms/symbol= s.c new file mode 100644 index 000000000000..1809be93d18c --- /dev/null +++ b/scripts/gendwarfksyms/symbols.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + */ + +#include "gendwarfksyms.h" + +#define SYMBOL_HASH_BITS 15 +static HASHTABLE_DEFINE(symbol_names, 1 << SYMBOL_HASH_BITS); + +static int for_each(const char *name, symbol_callback_t func, void *data) +{ + struct hlist_node *tmp; + struct symbol *match; + + if (!name || !*name) + return 0; + + hash_for_each_possible_safe(symbol_names, match, tmp, name_hash, + hash_str(name)) { + if (strcmp(match->name, name)) + continue; + + if (func) + func(match, data); + + return 1; + } + + return 0; +} + +static bool is_exported(const char *name) +{ + return checkp(for_each(name, NULL, NULL)) > 0; +} + +void symbol_read_exports(FILE *file) +{ + struct symbol *sym; + char *line =3D NULL; + char *name =3D NULL; + size_t size =3D 0; + int nsym =3D 0; + + while (getline(&line, &size, file) > 0) { + if (sscanf(line, "%ms\n", &name) !=3D 1) + error("malformed input line: %s", line); + + if (is_exported(name)) { + /* Ignore duplicates */ + free(name); + continue; + } + + sym =3D xcalloc(1, sizeof(struct symbol)); + sym->name =3D name; + + hash_add(symbol_names, &sym->name_hash, hash_str(sym->name)); + ++nsym; + + debug("%s", sym->name); + } + + free(line); + debug("%d exported symbols", nsym); +} + +static void get_symbol(struct symbol *sym, void *arg) +{ + struct symbol **res =3D arg; + + *res =3D sym; +} + +struct symbol *symbol_get(const char *name) +{ + struct symbol *sym =3D NULL; + + for_each(name, get_symbol, &sym); + return sym; +} --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (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 037E41A0BD1 for ; Mon, 23 Sep 2024 18:19:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115555; cv=none; b=dKMuwWW8+wYvwCSLX34oiYDU4qETig+jiHfxbzA1/yM8YcZK2fhYDkcvB/qC8iwLfxplhdCT9SKylZhQH1OKadlBJ5bMjMb2P5o+CwKxrFkx5QxvF08anqZ67HNszZFiN3Y31ZLO96k5A1Lj8WRAxnIBfMxCOfArZJwgBScrR6Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115555; c=relaxed/simple; bh=iSUUW3x5txrloi+7+mdj9ELlZqG3qTNWuRqFbkcBVvs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=uXR1kSkdgmgDNveVeDVDzvzS3xHKKGkyuAQ+7W8j8uW4SiG4oesYMEU3Yn54fjpgsLHahDBbcBcAaGJIrmqvAVgKuJEZSV7hL/7yYxnudguqUDSBqrMYlFw32luX5AqCuqIS2UI5FJYN6MSApYjUKpJCqyYhYzDEt9ox1VjnFTo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=AkgShLJw; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="AkgShLJw" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-718e065f057so5998921b3a.3 for ; Mon, 23 Sep 2024 11:19:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115553; x=1727720353; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=k5E6A6+qtsL2yx6u5QsUJXotC4baF5lnSIeka5+35fc=; b=AkgShLJwMpwUUFB51uVQ56nOFyfDvrUr5+9nO0QxqV4jD3Isxt7cbqH6zSdrJRnUdi 1WZImgLwxtLTip1uozLfOaknYjna0M11b7hNcwZpqwrRi8gDeO6j6mOhXcPC49bcqWm4 DQHvwOpyKb+CTH1tapacFk1VwHdF0ZxzNsw0peY3FrwJgkal3nd9WbW9At5UBlM1KDTj z6c2jriO2JoZKDQF+W2jvrqbjJfLDT1B2eCyVRgUZdlcJ9UvQ2U8WyIeeDOs0sj14Ban DdzzBbjwEuOT4bRSP0qFddU9W9HZvwYe/Evy88GFu3QWEL1eleOZQWLgpwtEO1eBitwI IcaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115553; x=1727720353; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=k5E6A6+qtsL2yx6u5QsUJXotC4baF5lnSIeka5+35fc=; b=QqJ6KSXLIcvdW7rBGUzEdN4Yh//hj++gKpeteL097+8hz36kTZ9MMyg9VI/JkOhHP7 t3K7OVHcoCvfJJawiKtXf/j20jeptcO5sxTawYUIT4anfkBmz8C0IYTiIi4o3JLkcqHv tljdSlvz6aKHhqtty/4oabIXjv+KvktKcmPJn4IZmqRTTMh7XtHyr0ac+UAqyB2kp6/i wKHv0ipucs9mnz2fj4wRK3G148eKNB8NGVlnR6guXsAkLex+RB4fcbSIupwwr9XPJjm8 z+UZv13HM44dyn88GRmFscL3M7RQ71HpKdROFACPnLjnmMZCpmG2S54GfIUzQXMeeOIK GdTg== X-Forwarded-Encrypted: i=1; AJvYcCUfyHKKhFNVyNYIKyYgMxkelWULhvKZepMiI8CVwiCzURzONqaajidtnk0aL67dtiH7gze5U1UM6cl12OI=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/l77Auf++Q5bElHGiIWmBhF8JnG3uoYVqA1gbId4qXUbsH1rz kgd7kyWkDwHtVRCHrzABsNAVyq2J8zOY50GP6OD8SCE7R6NIRR+kMU0iHg1InjM14Qwrr0Ry6xA sp2FzO+7eSUAJLChPORccMW7nMA== X-Google-Smtp-Source: AGHT+IGTT/HJAvXTol3s1CGGiXlpT4QazkYqwtFl5wbZvjyFTJ7aUqw/e69/vdZFngAkYLyFECjGUy2FtIhorJ52z2k= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a05:6a00:6210:b0:717:98ba:fe26 with SMTP id d2e1a72fcca58-7199cb1ed42mr17592b3a.0.1727115552951; Mon, 23 Sep 2024 11:19:12 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:50 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=7147; i=samitolvanen@google.com; h=from:subject; bh=iSUUW3x5txrloi+7+mdj9ELlZqG3qTNWuRqFbkcBVvs=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3JMXqrmeiOMj5179gSLXcXBMps+lS+9n/H3+bIwT i/9esGzHaUsDGIcDLJiiiwtX1dv3f3dKfXV5yIJmDmsTCBDGLg4BWAirv8YGf5NvbvxgW3R656K qMm76/zz/5pvunWn+7UTz8OIxduWm0szMuyuC9Zsur5mhiRTi9SsLykMpWzSHpelTJr8dgqvWHX dhREA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-26-samitolvanen@google.com> Subject: [PATCH v3 04/20] gendwarfksyms: Add address matching From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The compiler may choose not to emit type information in DWARF for all aliases, but it's possible for each alias to be exported separately. To ensure we find type information for the aliases as well, read {section, address} tuples from the symbol table and match symbols also by address. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/gendwarfksyms.c | 2 + scripts/gendwarfksyms/gendwarfksyms.h | 13 +++ scripts/gendwarfksyms/symbols.c | 153 +++++++++++++++++++++++++- 3 files changed, 165 insertions(+), 3 deletions(-) diff --git a/scripts/gendwarfksyms/gendwarfksyms.c b/scripts/gendwarfksyms/= gendwarfksyms.c index 096a334fa5b3..5032ec487626 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.c +++ b/scripts/gendwarfksyms/gendwarfksyms.c @@ -105,6 +105,8 @@ int main(int argc, char **argv) return -1; } =20 + symbol_read_symtab(fd); + dwfl =3D dwfl_begin(&callbacks); if (!dwfl) { error("dwfl_begin failed for '%s': %s", argv[n], diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index 1a10d18f178e..a058647e2361 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -66,14 +66,27 @@ extern int dump_dies; * symbols.c */ =20 +static inline unsigned int addr_hash(uintptr_t addr) +{ + return hash_ptr((const void *)addr); +} + +struct symbol_addr { + uint32_t section; + Elf64_Addr address; +}; + struct symbol { const char *name; + struct symbol_addr addr; + struct hlist_node addr_hash; struct hlist_node name_hash; }; =20 typedef void (*symbol_callback_t)(struct symbol *, void *arg); =20 void symbol_read_exports(FILE *file); +void symbol_read_symtab(int fd); struct symbol *symbol_get(const char *name); =20 /* diff --git a/scripts/gendwarfksyms/symbols.c b/scripts/gendwarfksyms/symbol= s.c index 1809be93d18c..d84b46675dd1 100644 --- a/scripts/gendwarfksyms/symbols.c +++ b/scripts/gendwarfksyms/symbols.c @@ -6,9 +6,41 @@ #include "gendwarfksyms.h" =20 #define SYMBOL_HASH_BITS 15 + +/* struct symbol_addr -> struct symbol */ +static HASHTABLE_DEFINE(symbol_addrs, 1 << SYMBOL_HASH_BITS); +/* name -> struct symbol */ static HASHTABLE_DEFINE(symbol_names, 1 << SYMBOL_HASH_BITS); =20 -static int for_each(const char *name, symbol_callback_t func, void *data) +static inline unsigned int symbol_addr_hash(const struct symbol_addr *addr) +{ + return hash_32(addr->section ^ addr_hash(addr->address)); +} + +static int __for_each_addr(struct symbol *sym, symbol_callback_t func, + void *data) +{ + struct hlist_node *tmp; + struct symbol *match =3D NULL; + int processed =3D 0; + + hash_for_each_possible_safe(symbol_addrs, match, tmp, addr_hash, + symbol_addr_hash(&sym->addr)) { + if (match =3D=3D sym) + continue; /* Already processed */ + + if (match->addr.section =3D=3D sym->addr.section && + match->addr.address =3D=3D sym->addr.address) { + func(match, data); + ++processed; + } + } + + return processed; +} + +static int for_each(const char *name, bool name_only, symbol_callback_t fu= nc, + void *data) { struct hlist_node *tmp; struct symbol *match; @@ -21,9 +53,13 @@ static int for_each(const char *name, symbol_callback_t = func, void *data) if (strcmp(match->name, name)) continue; =20 + /* Call func for the match, and all address matches */ if (func) func(match, data); =20 + if (!name_only && match->addr.section !=3D SHN_UNDEF) + return checkp(__for_each_addr(match, func, data)) + 1; + return 1; } =20 @@ -32,7 +68,7 @@ static int for_each(const char *name, symbol_callback_t f= unc, void *data) =20 static bool is_exported(const char *name) { - return checkp(for_each(name, NULL, NULL)) > 0; + return checkp(for_each(name, true, NULL, NULL)) > 0; } =20 void symbol_read_exports(FILE *file) @@ -55,6 +91,7 @@ void symbol_read_exports(FILE *file) =20 sym =3D xcalloc(1, sizeof(struct symbol)); sym->name =3D name; + sym->addr.section =3D SHN_UNDEF; =20 hash_add(symbol_names, &sym->name_hash, hash_str(sym->name)); ++nsym; @@ -77,6 +114,116 @@ struct symbol *symbol_get(const char *name) { struct symbol *sym =3D NULL; =20 - for_each(name, get_symbol, &sym); + for_each(name, false, get_symbol, &sym); return sym; } + +typedef void (*elf_symbol_callback_t)(const char *name, GElf_Sym *sym, + Elf32_Word xndx, void *arg); + +static void elf_for_each_global(int fd, elf_symbol_callback_t func, void *= arg) +{ + size_t sym_size; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + Elf_Data *xndx_data =3D NULL; + Elf_Scn *scn; + Elf *elf; + + if (elf_version(EV_CURRENT) !=3D EV_CURRENT) + error("elf_version failed: %s", elf_errmsg(-1)); + + elf =3D elf_begin(fd, ELF_C_READ_MMAP, NULL); + if (!elf) + error("elf_begin failed: %s", elf_errmsg(-1)); + + scn =3D elf_nextscn(elf, NULL); + + while (scn) { + shdr =3D gelf_getshdr(scn, &shdr_mem); + + if (shdr && shdr->sh_type =3D=3D SHT_SYMTAB_SHNDX) { + xndx_data =3D elf_getdata(scn, NULL); + break; + } + + scn =3D elf_nextscn(elf, scn); + } + + sym_size =3D gelf_fsize(elf, ELF_T_SYM, 1, EV_CURRENT); + scn =3D elf_nextscn(elf, NULL); + + while (scn) { + shdr =3D gelf_getshdr(scn, &shdr_mem); + + if (shdr && shdr->sh_type =3D=3D SHT_SYMTAB) { + Elf_Data *data =3D elf_getdata(scn, NULL); + unsigned int nsyms; + unsigned int n; + + if (shdr->sh_entsize !=3D sym_size) + error("expected sh_entsize (%lu) to be %zu", + shdr->sh_entsize, sym_size); + + nsyms =3D shdr->sh_size / shdr->sh_entsize; + + for (n =3D 1; n < nsyms; ++n) { + const char *name =3D NULL; + Elf32_Word xndx =3D 0; + GElf_Sym sym_mem; + GElf_Sym *sym; + + sym =3D gelf_getsymshndx(data, xndx_data, n, + &sym_mem, &xndx); + + if (GELF_ST_BIND(sym->st_info) =3D=3D STB_LOCAL) + continue; + + if (sym->st_shndx !=3D SHN_XINDEX) + xndx =3D sym->st_shndx; + + name =3D elf_strptr(elf, shdr->sh_link, + sym->st_name); + + /* Skip empty symbol names */ + if (name && *name) + func(name, sym, xndx, arg); + } + } + + scn =3D elf_nextscn(elf, scn); + } + + check(elf_end(elf)); +} + +static void set_symbol_addr(struct symbol *sym, void *arg) +{ + struct symbol_addr *addr =3D arg; + + if (sym->addr.section =3D=3D SHN_UNDEF) { + sym->addr =3D *addr; + hash_add(symbol_addrs, &sym->addr_hash, + symbol_addr_hash(&sym->addr)); + + debug("%s -> { %u, %lx }", sym->name, sym->addr.section, + sym->addr.address); + } else { + warn("multiple addresses for symbol %s?", sym->name); + } +} + +static void elf_set_symbol_addr(const char *name, GElf_Sym *sym, + Elf32_Word xndx, void *arg) +{ + struct symbol_addr addr =3D { .section =3D xndx, .address =3D sym->st_val= ue }; + + /* Set addresses for exported symbols */ + if (addr.section !=3D SHN_UNDEF) + for_each(name, true, set_symbol_addr, &addr); +} + +void symbol_read_symtab(int fd) +{ + elf_for_each_global(fd, elf_set_symbol_addr, NULL); +} --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 C404E1A0BCE for ; Mon, 23 Sep 2024 18:19:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115557; cv=none; b=PCzFaSoDl4qrQPFSHe4xeGI8aKvmlTrHjiEzzVx6t6zkjF4Jy9bcAeFA8IN6kT4eZyfbBApel8DvSrrJO8FKURfP7xQcQSBSq6lSyvEmXb6E7WFb6p5v/GwW4MCVuE9ZpBW5+wqC6jRxiJPM/0ll4UQhC5uGTKJ0eiKr6wgB8G0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115557; c=relaxed/simple; bh=GbyHjS/k/0UBxuQfH5qKmPuM8OYbP33sr4avDOXFg3k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=il4m5tjWvNV73UuaD62piiVRS3A2SH8+1Hf+RIoNJzMTl56f68Z4y1nXYiDiSnMxYzA06fHTJR1Xj/dfoFhdrP0NXdy32g09cPg6kOqh8tOWQ/S2SpBLoQvDDs0mdMKabsphJPQ0h/2cKixMR9aDnyzDra0RM6sAjjN1ptOeaT0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=RiWwqCyh; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="RiWwqCyh" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2d88641e9a8so4887260a91.0 for ; Mon, 23 Sep 2024 11:19:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115555; x=1727720355; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=pPrJDICBXYLS7hoF/6RDIfXDH4cTMyv4XmP564TgqI4=; b=RiWwqCyhu4EuXDUDAkZSkwv/29ms2J33mGwtXC6r8EkkDoSn5/fBz23L0uxcjbyndW S2naHeAQ+8uxsssvupCqc9S/NEYY/OE0z+HoDcuwOYSc27K5PxiHSi7OXas80vl2nDev YBjuLvm8Sc9gjv4sqi/fkoeHOVkYxnXqfVK5MwGBscpyKIeC0pNqSsnKbo13pZI0X8Ef uPwDd9oR+8xbzCVFguGA6u+KhrvfNeEy1yhbKrBhqfgTiZAVeOU9DLjNAeB0ljwT7GvT HKHwKFY7gxkNeas9DYvurubSR0zQu01GU+3fKL7Ew1NC4fLttlwayr33jdZJVnAgGPa7 N4Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115555; x=1727720355; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=pPrJDICBXYLS7hoF/6RDIfXDH4cTMyv4XmP564TgqI4=; b=WDEi126wyv28c1mXX+do4zprm1IBN7XlCmDarlM65wBt4fFWpMKo+CEKn6Vp1f45r0 PIJMa5QHdXBsqo0q0G13gUHY56ylGt13Qdky8h9wXA7NuUQqK76WGLWG/wc6PKztqBEE 5MEb3S9Kit0aGbZ8pfsVg3jBDizCk6qg8zv5sh0j/mxOgyQBR2SljpUP3Om3XuAmHZf2 kBnf71IPfeSPqlphYFnu9N7IoVoasTtkxlmOJE2BXvy3/61pbSsA1G9pVyAPHH6+kpoi SAZ7QKVCmfwTcKn5ow4iMAG6p73AImr9RepjtqsWg6EYNloxqkgkjRs7M0XVouheYDn2 AemA== X-Forwarded-Encrypted: i=1; AJvYcCUhFTVfnYlYupCA0zSdFJY0UlJXv+9u2aj2/ToqxAHnQ44VpGOF4jRlSx760vP4rIWE+f+TapaDb70rN9o=@vger.kernel.org X-Gm-Message-State: AOJu0YxzXX3g3kyBfT3MxAGEL3TKzqdbsAh+gEPza1291Olr7ueHooop r04EAiiNfwqQ7OItwA5DBFHqOom9httFWRHefaqIyaZGcjE6PMWNeq1HPBZb2xto35Q38AFGZcG lWFuf9OjJAqLE8Q9P+he6Kkj1kg== X-Google-Smtp-Source: AGHT+IFWuUmLh9cRh/+AIUM5wokytnEB2uaC2zfDXPBYXdPOKNJd0AL34leCOqvmOWiVODyI1j3o2Kp2PQWysHFMxXc= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a17:902:cecc:b0:206:928c:bfc3 with SMTP id d9443c01a7336-208d97edb36mr549915ad.2.1727115554899; Mon, 23 Sep 2024 11:19:14 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:51 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=5239; i=samitolvanen@google.com; h=from:subject; bh=GbyHjS/k/0UBxuQfH5qKmPuM8OYbP33sr4avDOXFg3k=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3KET7PbXJP06HuxEV8mzzyunPy+Tz85bWbf55paX tEdrn6/o5SFQYyDQVZMkaXl6+qtu787pb76XCQBM4eVCWQIAxenAExk7WqG/z7t5zWFZK8eT1lT KS5uw2SVH1PBsWQ2U/oL51ufdk9J/cbI0LBwwXJuu8TrbsyRHgJnKzjr3u/1vPp/v+LujVu/2St YMwEA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-27-samitolvanen@google.com> Subject: [PATCH v3 05/20] gendwarfksyms: Expand base_type From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Start making gendwarfksyms more useful by adding support for expanding DW_TAG_base_type types and basic DWARF attributes. Example: $ echo loops_per_jiffy | \ scripts/gendwarfksyms/gendwarfksyms \ --debug --dump-dies vmlinux.o ... gendwarfksyms: process_symbol: loops_per_jiffy variable base_type unsigned long byte_size(8) encoding(7) ... Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa Reviewed-by: Petr Pavlu --- scripts/gendwarfksyms/dwarf.c | 157 ++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 81df3e2ad3ae..3e9e8500f448 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -3,8 +3,20 @@ * Copyright (C) 2024 Google LLC */ =20 +#include #include "gendwarfksyms.h" =20 +#define DEFINE_GET_ATTR(attr, type) \ + static bool get_##attr##_attr(Dwarf_Die *die, unsigned int id, \ + type *value) \ + { \ + Dwarf_Attribute da; \ + return dwarf_attr(die, id, &da) && \ + !dwarf_form##attr(&da, value); \ + } + +DEFINE_GET_ATTR(udata, Dwarf_Word) + static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *v= alue) { Dwarf_Attribute da; @@ -67,6 +79,107 @@ static void process(const char *s) fputs(s, stderr); } =20 +#define MAX_FMT_BUFFER_SIZE 128 + +static void process_fmt(const char *fmt, ...) +{ + char buf[MAX_FMT_BUFFER_SIZE]; + va_list args; + + va_start(args, fmt); + + if (checkp(vsnprintf(buf, sizeof(buf), fmt, args)) >=3D sizeof(buf)) + error("vsnprintf overflow: increase MAX_FMT_BUFFER_SIZE"); + + process(buf); + va_end(args); +} + +#define MAX_FQN_SIZE 64 + +/* Get a fully qualified name from DWARF scopes */ +static char *get_fqn(Dwarf_Die *die) +{ + const char *list[MAX_FQN_SIZE]; + Dwarf_Die *scopes =3D NULL; + bool has_name =3D false; + char *fqn =3D NULL; + char *p; + int count =3D 0; + int len =3D 0; + int res; + int i; + + res =3D checkp(dwarf_getscopes_die(die, &scopes)); + if (!res) { + list[count] =3D get_name_attr(die); + + if (!list[count]) + return NULL; + + len +=3D strlen(list[count]); + count++; + + goto done; + } + + for (i =3D res - 1; i >=3D 0 && count < MAX_FQN_SIZE; i--) { + if (dwarf_tag(&scopes[i]) =3D=3D DW_TAG_compile_unit) + continue; + + list[count] =3D get_name_attr(&scopes[i]); + + if (list[count]) { + has_name =3D true; + } else { + list[count] =3D ""; + } + + len +=3D strlen(list[count]); + count++; + + if (i > 0) { + list[count++] =3D "::"; + len +=3D 2; + } + } + + free(scopes); + + if (count =3D=3D MAX_FQN_SIZE) + warn("increase MAX_FQN_SIZE: reached the maximum"); + + if (!has_name) + return NULL; +done: + fqn =3D xmalloc(len + 1); + *fqn =3D '\0'; + + p =3D fqn; + for (i =3D 0; i < count; i++) + p =3D stpcpy(p, list[i]); + + return fqn; +} + +static void process_fqn(Dwarf_Die *die) +{ + process(" "); + process(get_fqn(die) ?: ""); +} + +#define DEFINE_PROCESS_UDATA_ATTRIBUTE(attribute) = \ + static void process_##attribute##_attr(Dwarf_Die *die) \ + { \ + Dwarf_Word value; \ + if (get_udata_attr(die, DW_AT_##attribute, &value)) \ + process_fmt(" " #attribute "(%" PRIu64 ")", value); \ + } + +DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) +DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size) +DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) + bool match_all(Dwarf_Die *die) { return true; @@ -93,6 +206,49 @@ int process_die_container(struct state *state, Dwarf_Di= e *die, return 0; } =20 +static int process_type(struct state *state, Dwarf_Die *die); + +static void process_type_attr(struct state *state, Dwarf_Die *die) +{ + Dwarf_Die type; + + if (get_ref_die_attr(die, DW_AT_type, &type)) { + check(process_type(state, &type)); + return; + } + + /* Compilers can omit DW_AT_type -- print out 'void' to clarify */ + process("base_type void"); +} + +static void process_base_type(struct state *state, Dwarf_Die *die) +{ + process("base_type"); + process_fqn(die); + process_byte_size_attr(die); + process_encoding_attr(die); + process_alignment_attr(die); +} + +#define PROCESS_TYPE(type) \ + case DW_TAG_##type##_type: \ + process_##type##_type(state, die); \ + break; + +static int process_type(struct state *state, Dwarf_Die *die) +{ + int tag =3D dwarf_tag(die); + + switch (tag) { + PROCESS_TYPE(base) + default: + debug("unimplemented type: %x", tag); + break; + } + + return 0; +} + /* * Exported symbol processing */ @@ -119,6 +275,7 @@ static void process_subprogram(struct state *state, Dwa= rf_Die *die) static int __process_variable(struct state *state, Dwarf_Die *die) { process("variable "); + process_type_attr(state, die); return 0; } =20 --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (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 BFD981A2578 for ; Mon, 23 Sep 2024 18:19:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115559; cv=none; b=eAVVEepwaxN/56tY1WMQY4h2+aco0zdY7bdfutnXBU3KIxTmK6CPhflqtsJf9zJ3e9exXTeVZq+UX2yP7DbRlhgsF5Ud4j4CgiUPVVGkMFmddYkFSMLeGey7cSh3JHd8vI/imIKKyBV9+x66Tz3yKHltGw+MxoxPgteeXe3p08Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115559; c=relaxed/simple; bh=lXq6lP22aY/tuXV5y+BvfZowtiMxW5xohBBULQJYl3o=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=uBYFoidniFf/Q5Nla9PQKalyvbGdDCZerNXMAKjozuR5Efkfx7nPUYE4WXGEyDOP8hmT0tz1bqGU94824zfw6NEypbwA6VeP2Hadax+xC/mHMa0h6Pkp2TIlIG3ddN42Xg/FTDWOLvmIVKHyXnn+ifFo4HU+l/WkMrP2YMCHgqc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=0kAvS+SF; arc=none smtp.client-ip=209.85.215.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="0kAvS+SF" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-7163489149fso5546150a12.3 for ; Mon, 23 Sep 2024 11:19:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115557; x=1727720357; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=SghQU1lZYz69X9HH/FZ13dE1oo0DdF62r/uN8ZVxVYU=; b=0kAvS+SFIuJmcAipppEtgVJ6Uq/lnN1doxqey8a/CFr+o6NKCp+yEZ/O7veEb/J6zU BjdDsDg1AmLX7HILPCKSwD7lC3WAVrN3UwNQAKhCzcKExRaNVFuzXaAJTyGjLKKKzCkq HL7azt8/ZWlaNlec2nAM064e6NEI9bzS4+1A4tgCIvy1/BhdD6GFYsltnVXop6AcdUwC jP2vi6vCXxAIEfWkk79grFPe1+vUClnN2hbHrlg+mm6nEjS0m/qfUpuM4RjSAW1w4zbu TczcI+fJIExmlhUBg8F72S7MFB3ogHHHmWEutB6mRgYkcharGYi3qwYaIJAWtJzFMsPY PuKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115557; x=1727720357; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=SghQU1lZYz69X9HH/FZ13dE1oo0DdF62r/uN8ZVxVYU=; b=barMkj2TzaqQKFq5YQn+3fTz22YQGXPCdeu7+9ih5orfLbr4DIiQiVP6CAOlkKeL/l QZei2FOyhxg9o20OV7iYbVydT+GmccecdwwQCJhR+4S8RIuPU+IrpedpA+tjgLLdLquK RpRvuG5mOxx89zmuL1QmK/u43mM321lsnUYUOpAphrX4JrnGmuPMYFknpQY0fmBT1bDP bwlA2639/awakFp+cLojoCAobAz5HJf09zCyAiaCJl3kz1+NnhY6s5OgfYQMFRNCx8jA OEF6kc8TplnX1BqJaP4lPSM+QstphXygf0lvFKHQ263bbstN0Zh5CS9MyRcWKHy4Qyfq wNHg== X-Forwarded-Encrypted: i=1; AJvYcCUqmhhYnmaVL87shmR63BQspoI8GUtEZY5dV/GfSaGZKdGnsUQ3Tzq+uP+Irdd7faz/7DZI0OwoRDahV0w=@vger.kernel.org X-Gm-Message-State: AOJu0Yx+4mZylHXvZIOpe6JdlOJgIr6gM3EypI7MEnj43T862gUund4Y VhX3lTvkCH6KSwqMZVrdARnPjOjp8ZYHW02Lis0BskdWS+Dq2NhQNTfiULmos5W9LzwO7pGv5cX RB7sZQk20HiDQFfQ0U2tmL6By7g== X-Google-Smtp-Source: AGHT+IFo33Eyj6lwns2SzW35RxXeSuXBaoS1fJIRiAgdIunvV4zCbZ1y+iJh7dWbvswKZAxhiaU7qYxPBdXsG/3EuAw= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a63:380c:0:b0:6e5:62bf:f905 with SMTP id 41be03b00d2f7-7dcc69b7e9cmr10388a12.10.1727115556762; Mon, 23 Sep 2024 11:19:16 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:52 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=15390; i=samitolvanen@google.com; h=from:subject; bh=lXq6lP22aY/tuXV5y+BvfZowtiMxW5xohBBULQJYl3o=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3IunKSzejsDp3qNPq+N4HzvGQkpP7bYBq1wS2LWF e2ZdPJ0RykLgxgHg6yYIkvL19Vbd393Sn31uUgCZg4rE8gQBi5OAZjIn2BGhlvpzWaCsU45awNU Fk64cCdfpGTrlVOcx2y+nc+Znpi9t43hf+HFObYJvD9/HmQz43JQu7N3WQBT757rHie3pb+O5M6 KYAYA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-28-samitolvanen@google.com> Subject: [PATCH v3 06/20] gendwarfksyms: Add a cache for processed DIEs From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Basic types in DWARF repeat frequently and traversing the DIEs using libdw is relatively slow. Add a simple hashtable based cache for the processed DIEs. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/Makefile | 1 + scripts/gendwarfksyms/die.c | 143 ++++++++++++++++++++++++++ scripts/gendwarfksyms/dwarf.c | 136 +++++++++++++++++------- scripts/gendwarfksyms/gendwarfksyms.c | 6 ++ scripts/gendwarfksyms/gendwarfksyms.h | 62 ++++++++++- 5 files changed, 307 insertions(+), 41 deletions(-) create mode 100644 scripts/gendwarfksyms/die.c diff --git a/scripts/gendwarfksyms/Makefile b/scripts/gendwarfksyms/Makefile index 9f8fec4fd39b..c0d4ce50fc27 100644 --- a/scripts/gendwarfksyms/Makefile +++ b/scripts/gendwarfksyms/Makefile @@ -2,6 +2,7 @@ hostprogs-always-y +=3D gendwarfksyms =20 gendwarfksyms-objs +=3D gendwarfksyms.o +gendwarfksyms-objs +=3D die.o gendwarfksyms-objs +=3D dwarf.o gendwarfksyms-objs +=3D symbols.o =20 diff --git a/scripts/gendwarfksyms/die.c b/scripts/gendwarfksyms/die.c new file mode 100644 index 000000000000..28d89fce89fc --- /dev/null +++ b/scripts/gendwarfksyms/die.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + */ + +#include +#include "gendwarfksyms.h" + +#define DIE_HASH_BITS 20 + +/* {die->addr, state} -> struct die * */ +static HASHTABLE_DEFINE(die_map, 1 << DIE_HASH_BITS); + +static unsigned int map_hits; +static unsigned int map_misses; + +static inline unsigned int die_hash(uintptr_t addr, enum die_state state) +{ + return hash_32(addr_hash(addr) ^ (unsigned int)state); +} + +static void init_die(struct die *cd) +{ + cd->state =3D DIE_INCOMPLETE; + cd->fqn =3D NULL; + cd->tag =3D -1; + cd->addr =3D 0; + INIT_LIST_HEAD(&cd->fragments); +} + +static struct die *create_die(Dwarf_Die *die, enum die_state state) +{ + struct die *cd; + + cd =3D xmalloc(sizeof(struct die)); + init_die(cd); + cd->addr =3D (uintptr_t)die->addr; + + hash_add(die_map, &cd->hash, die_hash(cd->addr, state)); + return cd; +} + +int __die_map_get(uintptr_t addr, enum die_state state, struct die **res) +{ + struct die *cd; + + hash_for_each_possible(die_map, cd, hash, die_hash(addr, state)) { + if (cd->addr =3D=3D addr && cd->state =3D=3D state) { + *res =3D cd; + return 0; + } + } + + return -1; +} + +struct die *die_map_get(Dwarf_Die *die, enum die_state state) +{ + struct die *cd; + + if (__die_map_get((uintptr_t)die->addr, state, &cd) =3D=3D 0) { + map_hits++; + return cd; + } + + map_misses++; + return create_die(die, state); +} + +static void reset_die(struct die *cd) +{ + struct die_fragment *tmp; + struct die_fragment *df; + + list_for_each_entry_safe(df, tmp, &cd->fragments, list) { + if (df->type =3D=3D FRAGMENT_STRING) + free(df->data.str); + free(df); + } + + if (cd->fqn && *cd->fqn) + free(cd->fqn); + init_die(cd); +} + +void die_map_free(void) +{ + struct hlist_node *tmp; + unsigned int stats[DIE_LAST + 1]; + struct die *cd; + int i; + + memset(stats, 0, sizeof(stats)); + + hash_for_each_safe(die_map, cd, tmp, hash) { + stats[cd->state]++; + reset_die(cd); + free(cd); + } + hash_init(die_map); + + if (map_hits + map_misses > 0) + debug("hits %u, misses %u (hit rate %.02f%%)", map_hits, + map_misses, + (100.0f * map_hits) / (map_hits + map_misses)); + + for (i =3D 0; i <=3D DIE_LAST; i++) + debug("%s: %u entries", die_state_name(i), stats[i]); +} + +static struct die_fragment *append_item(struct die *cd) +{ + struct die_fragment *df; + + df =3D xmalloc(sizeof(struct die_fragment)); + df->type =3D FRAGMENT_EMPTY; + list_add_tail(&df->list, &cd->fragments); + return df; +} + +void die_map_add_string(struct die *cd, const char *str) +{ + struct die_fragment *df; + + if (!cd) + return; + + df =3D append_item(cd); + df->data.str =3D xstrdup(str); + df->type =3D FRAGMENT_STRING; +} + +void die_map_add_die(struct die *cd, struct die *child) +{ + struct die_fragment *df; + + if (!cd) + return; + + df =3D append_item(cd); + df->data.addr =3D child->addr; + df->type =3D FRAGMENT_DIE; +} diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 3e9e8500f448..f0c881bef026 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -71,17 +71,19 @@ static bool match_export_symbol(struct state *state, Dw= arf_Die *die) /* * Type string processing */ -static void process(const char *s) +static void process(struct die *cache, const char *s) { s =3D s ?: ""; =20 if (dump_dies) fputs(s, stderr); + + die_map_add_string(cache, s); } =20 #define MAX_FMT_BUFFER_SIZE 128 =20 -static void process_fmt(const char *fmt, ...) +static void process_fmt(struct die *cache, const char *fmt, ...) { char buf[MAX_FMT_BUFFER_SIZE]; va_list args; @@ -91,7 +93,7 @@ static void process_fmt(const char *fmt, ...) if (checkp(vsnprintf(buf, sizeof(buf), fmt, args)) >=3D sizeof(buf)) error("vsnprintf overflow: increase MAX_FMT_BUFFER_SIZE"); =20 - process(buf); + process(cache, buf); va_end(args); } =20 @@ -162,18 +164,28 @@ static char *get_fqn(Dwarf_Die *die) return fqn; } =20 -static void process_fqn(Dwarf_Die *die) +static void update_fqn(struct die *cache, Dwarf_Die *die) +{ + if (!cache->fqn) + cache->fqn =3D get_fqn(die) ?: ""; +} + +static void process_fqn(struct die *cache, Dwarf_Die *die) { - process(" "); - process(get_fqn(die) ?: ""); + update_fqn(cache, die); + if (*cache->fqn) + process(cache, " "); + process(cache, cache->fqn); } =20 -#define DEFINE_PROCESS_UDATA_ATTRIBUTE(attribute) = \ - static void process_##attribute##_attr(Dwarf_Die *die) \ - { \ - Dwarf_Word value; \ - if (get_udata_attr(die, DW_AT_##attribute, &value)) \ - process_fmt(" " #attribute "(%" PRIu64 ")", value); \ +#define DEFINE_PROCESS_UDATA_ATTRIBUTE(attribute) = \ + static void process_##attribute##_attr(struct die *cache, \ + Dwarf_Die *die) \ + { \ + Dwarf_Word value; \ + if (get_udata_attr(die, DW_AT_##attribute, &value)) \ + process_fmt(cache, " " #attribute "(%" PRIu64 ")", \ + value); \ } =20 DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) @@ -185,8 +197,9 @@ bool match_all(Dwarf_Die *die) return true; } =20 -int process_die_container(struct state *state, Dwarf_Die *die, - die_callback_t func, die_match_callback_t match) +int process_die_container(struct state *state, struct die *cache, + Dwarf_Die *die, die_callback_t func, + die_match_callback_t match) { Dwarf_Die current; int res; @@ -195,7 +208,7 @@ int process_die_container(struct state *state, Dwarf_Di= e *die, while (!res) { if (match(¤t)) { /* <0 =3D error, 0 =3D continue, >0 =3D stop */ - res =3D checkp(func(state, ¤t)); + res =3D checkp(func(state, cache, ¤t)); if (res) return res; } @@ -206,39 +219,78 @@ int process_die_container(struct state *state, Dwarf_= Die *die, return 0; } =20 -static int process_type(struct state *state, Dwarf_Die *die); +static int process_type(struct state *state, struct die *parent, + Dwarf_Die *die); =20 -static void process_type_attr(struct state *state, Dwarf_Die *die) +static void process_type_attr(struct state *state, struct die *cache, + Dwarf_Die *die) { Dwarf_Die type; =20 if (get_ref_die_attr(die, DW_AT_type, &type)) { - check(process_type(state, &type)); + check(process_type(state, cache, &type)); return; } =20 /* Compilers can omit DW_AT_type -- print out 'void' to clarify */ - process("base_type void"); + process(cache, "base_type void"); +} + +static void process_base_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + process(cache, "base_type"); + process_fqn(cache, die); + process_byte_size_attr(cache, die); + process_encoding_attr(cache, die); + process_alignment_attr(cache, die); } =20 -static void process_base_type(struct state *state, Dwarf_Die *die) +static void process_cached(struct state *state, struct die *cache, + Dwarf_Die *die) { - process("base_type"); - process_fqn(die); - process_byte_size_attr(die); - process_encoding_attr(die); - process_alignment_attr(die); + struct die_fragment *df; + Dwarf_Die child; + + list_for_each_entry(df, &cache->fragments, list) { + switch (df->type) { + case FRAGMENT_STRING: + process(NULL, df->data.str); + break; + case FRAGMENT_DIE: + if (!dwarf_die_addr_die(dwarf_cu_getdwarf(die->cu), + (void *)df->data.addr, &child)) + error("dwarf_die_addr_die failed"); + check(process_type(state, NULL, &child)); + break; + default: + error("empty die_fragment"); + } + } } =20 -#define PROCESS_TYPE(type) \ - case DW_TAG_##type##_type: \ - process_##type##_type(state, die); \ +#define PROCESS_TYPE(type) \ + case DW_TAG_##type##_type: \ + process_##type##_type(state, cache, die); \ break; =20 -static int process_type(struct state *state, Dwarf_Die *die) +static int process_type(struct state *state, struct die *parent, Dwarf_Die= *die) { + struct die *cache; int tag =3D dwarf_tag(die); =20 + /* + * If we have the DIE already cached, use it instead of walking + * through DWARF. + */ + cache =3D die_map_get(die, DIE_COMPLETE); + + if (cache->state =3D=3D DIE_COMPLETE) { + process_cached(state, cache, die); + die_map_add_die(parent, cache); + return 0; + } + switch (tag) { PROCESS_TYPE(base) default: @@ -246,6 +298,11 @@ static int process_type(struct state *state, Dwarf_Die= *die) break; } =20 + /* Update cache state and append to the parent (if any) */ + cache->tag =3D tag; + cache->state =3D DIE_COMPLETE; + die_map_add_die(parent, cache); + return 0; } =20 @@ -256,14 +313,15 @@ static void process_symbol(struct state *state, Dwarf= _Die *die, die_callback_t process_func) { debug("%s", state->sym->name); - check(process_func(state, die)); + check(process_func(state, NULL, die)); if (dump_dies) fputs("\n", stderr); } =20 -static int __process_subprogram(struct state *state, Dwarf_Die *die) +static int __process_subprogram(struct state *state, struct die *cache, + Dwarf_Die *die) { - process("subprogram"); + process(cache, "subprogram"); return 0; } =20 @@ -272,10 +330,11 @@ static void process_subprogram(struct state *state, D= warf_Die *die) process_symbol(state, die, __process_subprogram); } =20 -static int __process_variable(struct state *state, Dwarf_Die *die) +static int __process_variable(struct state *state, struct die *cache, + Dwarf_Die *die) { - process("variable "); - process_type_attr(state, die); + process(cache, "variable "); + process_type_attr(state, cache, die); return 0; } =20 @@ -284,7 +343,8 @@ static void process_variable(struct state *state, Dwarf= _Die *die) process_symbol(state, die, __process_variable); } =20 -static int process_exported_symbols(struct state *unused, Dwarf_Die *die) +static int process_exported_symbols(struct state *unused, struct die *cach= e, + Dwarf_Die *die) { int tag =3D dwarf_tag(die); =20 @@ -294,7 +354,7 @@ static int process_exported_symbols(struct state *unuse= d, Dwarf_Die *die) case DW_TAG_class_type: case DW_TAG_structure_type: return check(process_die_container( - NULL, die, process_exported_symbols, match_all)); + NULL, cache, die, process_exported_symbols, match_all)); =20 /* Possible exported symbols */ case DW_TAG_subprogram: @@ -318,6 +378,6 @@ static int process_exported_symbols(struct state *unuse= d, Dwarf_Die *die) =20 void process_cu(Dwarf_Die *cudie) { - check(process_die_container(NULL, cudie, process_exported_symbols, + check(process_die_container(NULL, NULL, cudie, process_exported_symbols, match_all)); } diff --git a/scripts/gendwarfksyms/gendwarfksyms.c b/scripts/gendwarfksyms/= gendwarfksyms.c index 5032ec487626..66806b0936e4 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.c +++ b/scripts/gendwarfksyms/gendwarfksyms.c @@ -43,6 +43,10 @@ static int process_module(Dwfl_Module *mod, void **userd= ata, const char *name, debug("%s", name); dbg =3D dwfl_module_getdwarf(mod, &dwbias); =20 + /* + * Look for exported symbols in each CU, follow the DIE tree, and add + * the entries to die_map. + */ do { res =3D dwarf_get_units(dbg, cu, &cu, NULL, NULL, &cudie, NULL); if (res < 0) @@ -53,6 +57,8 @@ static int process_module(Dwfl_Module *mod, void **userda= ta, const char *name, process_cu(&cudie); } while (cu); =20 + die_map_free(); + return DWARF_CB_OK; } =20 diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index a058647e2361..7df270429c21 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -89,6 +89,60 @@ void symbol_read_exports(FILE *file); void symbol_read_symtab(int fd); struct symbol *symbol_get(const char *name); =20 +/* + * die.c + */ + +enum die_state { + DIE_INCOMPLETE, + DIE_COMPLETE, + DIE_LAST =3D DIE_COMPLETE +}; + +enum die_fragment_type { + FRAGMENT_EMPTY, + FRAGMENT_STRING, + FRAGMENT_DIE +}; + +struct die_fragment { + enum die_fragment_type type; + union { + char *str; + uintptr_t addr; + } data; + struct list_head list; +}; + +#define CASE_CONST_TO_STR(name) \ + case name: \ + return #name; + +static inline const char *die_state_name(enum die_state state) +{ + switch (state) { + default: + CASE_CONST_TO_STR(DIE_INCOMPLETE) + CASE_CONST_TO_STR(DIE_COMPLETE) + } +} + +struct die { + enum die_state state; + char *fqn; + int tag; + uintptr_t addr; + struct list_head fragments; + struct hlist_node hash; +}; + +int __die_map_get(uintptr_t addr, enum die_state state, struct die **res); +struct die *die_map_get(Dwarf_Die *die, enum die_state state); +void die_map_add_string(struct die *pd, const char *str); +void die_map_add_linebreak(struct die *pd, int linebreak); +void die_map_add_die(struct die *pd, struct die *child); +void die_map_free(void); + /* * dwarf.c */ @@ -98,12 +152,14 @@ struct state { Dwarf_Die die; }; =20 -typedef int (*die_callback_t)(struct state *state, Dwarf_Die *die); +typedef int (*die_callback_t)(struct state *state, struct die *cache, + Dwarf_Die *die); typedef bool (*die_match_callback_t)(Dwarf_Die *die); bool match_all(Dwarf_Die *die); =20 -int process_die_container(struct state *state, Dwarf_Die *die, - die_callback_t func, die_match_callback_t match); +int process_die_container(struct state *state, struct die *cache, + Dwarf_Die *die, die_callback_t func, + die_match_callback_t match); =20 void process_cu(Dwarf_Die *cudie); =20 --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (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 A86171A2643 for ; Mon, 23 Sep 2024 18:19:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115561; cv=none; b=t8suptoN2bfnWbyr3dGWpv5tMgoh6IhpO5QTf+i3qmIqvQw7/ARC3SMWP0PlNCkI6QJsM0iOCKRNFelfW0puApMtwzvISRcHF0ZbrdTuCRMUJL90Em1Tic82CesV0d2ZDWbmdYQ/GlITytKKDt9zX7AfcXyLi/TodjEBxKZ77D8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115561; c=relaxed/simple; bh=ymRviO+a5cEV3+mp0Yi0XXSwQOhrRgtOy5SB1olfBDk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=RPBbaz30dsUiJmvE7gqHVTtk8EL/aNkAH89tUFiO2BgSKW7ubohT6La42puKQ0fregOwJKQ1Ni1RF4g8EqWxhGT842RoApLUczJH3v8mvVrJVH4U56oXBNqKiLPQS16wfSozx+JxQIujAVxiAxuJcg/FV0NQKPi/tELOgltkVMg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=tHUwiCD7; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="tHUwiCD7" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6e1fea193a4so13434507b3.0 for ; Mon, 23 Sep 2024 11:19:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115559; x=1727720359; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Lx1zf/KMHWOofjasnauK3EaDfAHFjR3zRo1FGvEVy2g=; b=tHUwiCD7xkxmNWqmgwZfzAY5cBaOsRgxASBDefcrjBHFNKiAZWuinqTkSSdkcqFZZS Q0PdVF6byByl3XHfK7L/3ZITUUcrlfcfLtvPbJ+QcqpGnyp0oTpSaTQa3PvKj/zlN9bE njtr/0SB330F4ZFr1k5xU/+SxcRZTulPPAhUo8AI8DllKcZeKfdFnFd7XJYtUh2/1Jmu Gug+I9SNW0KyfHtVBaLDJFm8Dt2LUWgQuIAVihvJ1//ZCaz1o31NG146Z5u//31rNiZ8 U91zXfQ95RgszL17HF9w+VGKwvnxBfZywLZiQFuLONGXDzG5Jv3lTkWEbXWp3HYtaFCR BrWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115559; x=1727720359; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Lx1zf/KMHWOofjasnauK3EaDfAHFjR3zRo1FGvEVy2g=; b=L5yNEdUYGOd1JnAa0xvpTs9Uc1IfSK0MIaXj70iHbFHfH/84l1/1ZNXO/ZLv5t95HC +Tzhe+Fo49VMlyycMRGF8/T9Ka4ZXhhQWMRw5/08UZQWFuQMDSj0tPBrKBYIeGFQ9ABt L82jXL2pLJ3oo8A/Ohc2akDkAtNTCtc22nopSL34vi3NEWVS/SZDdPC6W1LiEdt3e6Tq YR5+7POKbNjc2GtYo9eGFHyQUhyB+tgyZuMVuPUsVwwXSrUoP2KNYyQPlNoFonNZA2h2 v6K7vDWcM8mptitWINOq5Gi1MrD5YT2XIqP1hYSWuFJFC/U555UnvrWQ3tihAFDoVfTU uxaA== X-Forwarded-Encrypted: i=1; AJvYcCVbNQrQNe8fEQl7rlWBuvowwxAVc8DmjV3fRUoVSbfoVm+a1L5VpI3MUHqoXArUNEQR7m4A7sHAP5EeGO0=@vger.kernel.org X-Gm-Message-State: AOJu0YyropI+K8TUPNuG5eqY3UUMWh6LIxaaifZHsrMz2nhloJ6RjwbM BaWBLO4mW/SnlvGcz2NgDZs1knFnhAIVfu5/Z59gaP1k0VeAzJutMry3FQvZgwkPVpYwB1LzpjJ Bpfvm0fXDrP4dy3sZC9udxq0vlQ== X-Google-Smtp-Source: AGHT+IHIiX0oEVv8/+fATBQ7LD6NBHYzwVtHhVQ0EnnibVqWRuZ/lhL988HpQao5hS9ju6/+Oj1BAws9oo3moFSvy2g= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a25:8751:0:b0:e1a:9ed2:67f4 with SMTP id 3f1490d57ef6-e2250c24608mr11792276.2.1727115558693; Mon, 23 Sep 2024 11:19:18 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:53 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=5378; i=samitolvanen@google.com; h=from:subject; bh=ymRviO+a5cEV3+mp0Yi0XXSwQOhrRgtOy5SB1olfBDk=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3KWySrN/VU7q2rOIjXj7Oglc7pCZk/zeRy/PyuQd aJd5xb9jlIWBjEOBlkxRZaWr6u37v7ulPrqc5EEzBxWJpAhDFycAjCRS4qMDJuXfn3a9lyv8tyO F2syzn/t/leU3GiRriDUXj+H+RCXbT8jw5eunhVXuc68t3im9O2d8YfpHO79rwy3ys/Y1XPotYH FLQ4A X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-29-samitolvanen@google.com> Subject: [PATCH v3 07/20] gendwarfksyms: Expand type modifiers and typedefs From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for expanding DWARF type modifiers, such as pointers, const values etc., and typedefs. These types all have DW_AT_type attribute pointing to the underlying type, and thus produce similar output. Also add linebreaks and indentation to debugging output to make it more readable. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa Reviewed-by: Petr Pavlu --- scripts/gendwarfksyms/die.c | 12 +++++ scripts/gendwarfksyms/dwarf.c | 67 +++++++++++++++++++++++++++ scripts/gendwarfksyms/gendwarfksyms.h | 5 ++ 3 files changed, 84 insertions(+) diff --git a/scripts/gendwarfksyms/die.c b/scripts/gendwarfksyms/die.c index 28d89fce89fc..2829387fd815 100644 --- a/scripts/gendwarfksyms/die.c +++ b/scripts/gendwarfksyms/die.c @@ -130,6 +130,18 @@ void die_map_add_string(struct die *cd, const char *st= r) df->type =3D FRAGMENT_STRING; } =20 +void die_map_add_linebreak(struct die *cd, int linebreak) +{ + struct die_fragment *df; + + if (!cd) + return; + + df =3D append_item(cd); + df->data.linebreak =3D linebreak; + df->type =3D FRAGMENT_LINEBREAK; +} + void die_map_add_die(struct die *cd, struct die *child) { struct die_fragment *df; diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index f0c881bef026..50ef58591c83 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -6,6 +6,17 @@ #include #include "gendwarfksyms.h" =20 +static bool do_linebreak; +static int indentation_level; + +/* Line breaks and indentation for pretty-printing */ +static void process_linebreak(struct die *cache, int n) +{ + indentation_level +=3D n; + do_linebreak =3D true; + die_map_add_linebreak(cache, n); +} + #define DEFINE_GET_ATTR(attr, type) \ static bool get_##attr##_attr(Dwarf_Die *die, unsigned int id, \ type *value) \ @@ -75,6 +86,12 @@ static void process(struct die *cache, const char *s) { s =3D s ?: ""; =20 + if (dump_dies && do_linebreak) { + fputs("\n", stderr); + for (int i =3D 0; i < indentation_level; i++) + fputs(" ", stderr); + do_linebreak =3D false; + } if (dump_dies) fputs(s, stderr); =20 @@ -236,6 +253,40 @@ static void process_type_attr(struct state *state, str= uct die *cache, process(cache, "base_type void"); } =20 +/* Container types with DW_AT_type */ +static void __process_type(struct state *state, struct die *cache, + Dwarf_Die *die, const char *type) +{ + process(cache, type); + process_fqn(cache, die); + process(cache, " {"); + process_linebreak(cache, 1); + process_type_attr(state, cache, die); + process_linebreak(cache, -1); + process(cache, "}"); + process_byte_size_attr(cache, die); + process_alignment_attr(cache, die); +} + +#define DEFINE_PROCESS_TYPE(type) = \ + static void process_##type##_type(struct state *state, \ + struct die *cache, Dwarf_Die *die) \ + { \ + __process_type(state, cache, die, #type "_type"); \ + } + +DEFINE_PROCESS_TYPE(atomic) +DEFINE_PROCESS_TYPE(const) +DEFINE_PROCESS_TYPE(immutable) +DEFINE_PROCESS_TYPE(packed) +DEFINE_PROCESS_TYPE(pointer) +DEFINE_PROCESS_TYPE(reference) +DEFINE_PROCESS_TYPE(restrict) +DEFINE_PROCESS_TYPE(rvalue_reference) +DEFINE_PROCESS_TYPE(shared) +DEFINE_PROCESS_TYPE(volatile) +DEFINE_PROCESS_TYPE(typedef) + static void process_base_type(struct state *state, struct die *cache, Dwarf_Die *die) { @@ -257,6 +308,9 @@ static void process_cached(struct state *state, struct = die *cache, case FRAGMENT_STRING: process(NULL, df->data.str); break; + case FRAGMENT_LINEBREAK: + process_linebreak(NULL, df->data.linebreak); + break; case FRAGMENT_DIE: if (!dwarf_die_addr_die(dwarf_cu_getdwarf(die->cu), (void *)df->data.addr, &child)) @@ -292,7 +346,20 @@ static int process_type(struct state *state, struct di= e *parent, Dwarf_Die *die) } =20 switch (tag) { + /* Type modifiers */ + PROCESS_TYPE(atomic) + PROCESS_TYPE(const) + PROCESS_TYPE(immutable) + PROCESS_TYPE(packed) + PROCESS_TYPE(pointer) + PROCESS_TYPE(reference) + PROCESS_TYPE(restrict) + PROCESS_TYPE(rvalue_reference) + PROCESS_TYPE(shared) + PROCESS_TYPE(volatile) + /* Other types */ PROCESS_TYPE(base) + PROCESS_TYPE(typedef) default: debug("unimplemented type: %x", tag); break; diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index 7df270429c21..81b8989efa22 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -62,6 +62,9 @@ extern int dump_dies; /* Error =3D=3D negative values */ #define checkp(expr) __check(expr, __res < 0) =20 +/* Consistent aliases (DW_TAG__type) for DWARF tags */ +#define DW_TAG_typedef_type DW_TAG_typedef + /* * symbols.c */ @@ -102,6 +105,7 @@ enum die_state { enum die_fragment_type { FRAGMENT_EMPTY, FRAGMENT_STRING, + FRAGMENT_LINEBREAK, FRAGMENT_DIE }; =20 @@ -109,6 +113,7 @@ struct die_fragment { enum die_fragment_type type; union { char *str; + int linebreak; uintptr_t addr; } data; struct list_head list; --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (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 34E191A2876 for ; Mon, 23 Sep 2024 18:19:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115563; cv=none; b=HcSsa5mG7IbY/7H8VHL4P+NHF/nfmfOYzJArAp0F+I5bAXeJ7vLXdcko830zXmvyh41ku+jiqR+AUs5aSWF4w6xup1Lzf4Gm5J8XDC0RcXOH2LuGQNe7irYUFuNo0OkQyaOfZxOMNhxjxyUZNqO+//GtSYAXrH3c7J4nLoWoEE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115563; c=relaxed/simple; bh=YnxRLubYaRu5LmAQuXzMlCDLmcU4MfVwQeLF/vCiIvY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=jz3Wi7WMZQyxkPWhqpt5qekZcPnu9zqya1DAd4PjBgBeaST44RWP0+8uEXuw9YDG4nI4Iq+oq2veudbqY7oWDfWz3jtz/HjFbWSFzNLfmFUxWU+hzf+UumKmv5JpJY/H90YwPaTgnRYBAbhMErO0hMNfAvx0Wn/idkPDFjq/4pI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=mNa6NkvD; arc=none smtp.client-ip=209.85.215.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="mNa6NkvD" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-7b696999c65so2999145a12.3 for ; Mon, 23 Sep 2024 11:19:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115560; x=1727720360; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=0QY5Hy6t2hyco5Zb7/L0lbrSBcXnpHdZW8dyGEzKIpI=; b=mNa6NkvDDYsyzamhyHd7KZK2QiILEoVlXSM+cUxteSGkDk9CSRdt6Ouqw6ZBb9DDxr C8BMP0fYy2n3xsjcFW6NbJv+iCWFEbHCwJVTFRlWAN7fkPPt5GwCulQYlo8N7E8G7Yk4 zPvr9htKiqlTJrpqPWyYM74/eTuAhDxdswIsGJf7BB5K3dd7o7JG5tZjU8Mq7rlp+9q4 mlD5sOs5RBH+beCigRLC9ZZMIKAehKVxwAPnpmD2d8jJkMxarUJczlRCmo+LkKpUij9u cbmom7xeBG3yXJFbfsk0kjZBhDfJ3s8sTBbI4jiqSL7RPsBMZ9Oh2UyFgjrq68lzc5zl 4NcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115560; x=1727720360; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=0QY5Hy6t2hyco5Zb7/L0lbrSBcXnpHdZW8dyGEzKIpI=; b=vsIzy6FutMccRaB4zfuVdDzFd+5fd1Q+VzH5n/1iGAyABymkBZiPR7NY+3CnuPdYYJ Nj6RGA439Kg4tQXOXU2ptmZVv8iX9+4xedi9+i1tDQBrmEIIz2YW7XogJmNleldeNDP1 p9Bom7Vk4caowDfFdFIc0OtikPo3r/dZP5CAD9aQlFRnbpXVbk1RoYAqr4X7PhkdENO5 c29lSMdsB7c87SaA9eM+diQOjzKrQL+Fc21ob1VyiRcOyyhKdbdiM6uKd0alYvdkDST6 GGKUXe0Mon4hxLNk2wNgAB1BKvmdb/plPiobW0lhy2AbehCkNfY1JEzC7QblUBcUnTdN U3fw== X-Forwarded-Encrypted: i=1; AJvYcCXrjXivoYWSyRc5gjYJgglLu4801t712+VkIIB0S4GWcieAq8hKSNo3C2aO5vIdvTkdFqa0Bs8ZS8eel+I=@vger.kernel.org X-Gm-Message-State: AOJu0Ywephb34t4u+LwcjecgNoAONGq1mwltz+3GpIBwRzuNjbcbzYap GXst1bzqj5QeZmsKEf9t2bbCPm8Cl0aPshdlYk9+iBAn4hNlj++t+DkIFkMpo8KF7GPYZKVoHcI 1PdRBtGXEENWcoN+/u9dQhTw6Hw== X-Google-Smtp-Source: AGHT+IF/yPm3Q7gCKUFaoUWev9k41igxQNUBQ8slxggC77S4yv3VXQoOTiBlJiL8f1t8waF428RuZmoZyGvu8Yp1D1o= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a63:b254:0:b0:7db:16b4:7a2a with SMTP id 41be03b00d2f7-7dcd3c474ebmr12955a12.2.1727115560447; Mon, 23 Sep 2024 11:19:20 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:54 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=5712; i=samitolvanen@google.com; h=from:subject; bh=YnxRLubYaRu5LmAQuXzMlCDLmcU4MfVwQeLF/vCiIvY=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3L1la67YPFtm47e9Yi7NkxCfamzy4XMLl5lj5m9K /rKixeLOkpZGMQ4GGTFFFlavq7euvu7U+qrz0USMHNYmUCGMHBxCsBE5r9nZNj8/vKiVccm/U9+ vSH6zSWe6dpHn4hdKnzyTGDmnadP9eYbMDJ8stzpP0lousu3Q983X/VX5Gp0Fm4uvLfoveO/3H0 7CyUZAQ== X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-30-samitolvanen@google.com> Subject: [PATCH v3 08/20] gendwarfksyms: Expand subroutine_type From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for expanding DW_TAG_subroutine_type and the parameters in DW_TAG_formal_parameter. Use this to also expand subprograms. Example output with --dump-dies: subprogram ( formal_parameter pointer_type { const_type { base_type char byte_size(1) encoding(6) } } ) -> base_type unsigned long byte_size(8) encoding(7) Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa Reviewed-by: Petr Pavlu --- scripts/gendwarfksyms/dwarf.c | 84 ++++++++++++++++++++++++++- scripts/gendwarfksyms/gendwarfksyms.h | 4 ++ 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 50ef58591c83..5bdab5b80ca2 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -209,6 +209,15 @@ DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size) DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) =20 +/* Match functions -- die_match_callback_t */ +#define DEFINE_MATCH(type) \ + static bool match_##type##_type(Dwarf_Die *die) \ + { \ + return dwarf_tag(die) =3D=3D DW_TAG_##type##_type; \ + } + +DEFINE_MATCH(formal_parameter) + bool match_all(Dwarf_Die *die) { return true; @@ -221,19 +230,28 @@ int process_die_container(struct state *state, struct= die *cache, Dwarf_Die current; int res; =20 + /* Track the first item in lists. */ + if (state) + state->first_list_item =3D true; + res =3D checkp(dwarf_child(die, ¤t)); while (!res) { if (match(¤t)) { /* <0 =3D error, 0 =3D continue, >0 =3D stop */ res =3D checkp(func(state, cache, ¤t)); if (res) - return res; + goto out; } =20 res =3D checkp(dwarf_siblingof(¤t, ¤t)); } =20 - return 0; + res =3D 0; +out: + if (state) + state->first_list_item =3D false; + + return res; } =20 static int process_type(struct state *state, struct die *parent, @@ -253,6 +271,40 @@ static void process_type_attr(struct state *state, str= uct die *cache, process(cache, "base_type void"); } =20 +static void process_list_comma(struct state *state, struct die *cache) +{ + if (state->first_list_item) { + state->first_list_item =3D false; + } else { + process(cache, " ,"); + process_linebreak(cache, 0); + } +} + +/* Comma-separated with DW_AT_type */ +static void __process_list_type(struct state *state, struct die *cache, + Dwarf_Die *die, const char *type) +{ + const char *name =3D get_name_attr(die); + + process_list_comma(state, cache); + process(cache, type); + process_type_attr(state, cache, die); + if (name) { + process(cache, " "); + process(cache, name); + } +} + +#define DEFINE_PROCESS_LIST_TYPE(type) = \ + static void process_##type##_type(struct state *state, \ + struct die *cache, Dwarf_Die *die) \ + { \ + __process_list_type(state, cache, die, #type " "); \ + } + +DEFINE_PROCESS_LIST_TYPE(formal_parameter) + /* Container types with DW_AT_type */ static void __process_type(struct state *state, struct die *cache, Dwarf_Die *die, const char *type) @@ -287,6 +339,29 @@ DEFINE_PROCESS_TYPE(shared) DEFINE_PROCESS_TYPE(volatile) DEFINE_PROCESS_TYPE(typedef) =20 +static void __process_subroutine_type(struct state *state, struct die *cac= he, + Dwarf_Die *die, const char *type) +{ + process(cache, type); + process(cache, " ("); + process_linebreak(cache, 1); + /* Parameters */ + check(process_die_container(state, cache, die, process_type, + match_formal_parameter_type)); + process_linebreak(cache, -1); + process(cache, ")"); + process_linebreak(cache, 0); + /* Return type */ + process(cache, "-> "); + process_type_attr(state, cache, die); +} + +static void process_subroutine_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + __process_subroutine_type(state, cache, die, "subroutine_type"); +} + static void process_base_type(struct state *state, struct die *cache, Dwarf_Die *die) { @@ -357,8 +432,11 @@ static int process_type(struct state *state, struct di= e *parent, Dwarf_Die *die) PROCESS_TYPE(rvalue_reference) PROCESS_TYPE(shared) PROCESS_TYPE(volatile) + /* Subtypes */ + PROCESS_TYPE(formal_parameter) /* Other types */ PROCESS_TYPE(base) + PROCESS_TYPE(subroutine) PROCESS_TYPE(typedef) default: debug("unimplemented type: %x", tag); @@ -388,7 +466,7 @@ static void process_symbol(struct state *state, Dwarf_D= ie *die, static int __process_subprogram(struct state *state, struct die *cache, Dwarf_Die *die) { - process(cache, "subprogram"); + __process_subroutine_type(state, cache, die, "subprogram"); return 0; } =20 diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index 81b8989efa22..d5186472f705 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -63,6 +63,7 @@ extern int dump_dies; #define checkp(expr) __check(expr, __res < 0) =20 /* Consistent aliases (DW_TAG__type) for DWARF tags */ +#define DW_TAG_formal_parameter_type DW_TAG_formal_parameter #define DW_TAG_typedef_type DW_TAG_typedef =20 /* @@ -155,6 +156,9 @@ void die_map_free(void); struct state { struct symbol *sym; Dwarf_Die die; + + /* List expansion */ + bool first_list_item; }; =20 typedef int (*die_callback_t)(struct state *state, struct die *cache, --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (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 294BA1A2C29 for ; Mon, 23 Sep 2024 18:19:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115564; cv=none; b=fvJE6G+qG0Ib7Vkb2YHg2iFjgi//nmuIykYHvJMOr4bV+B/F8TfxIHseb41xGqC+h8d1VwGMEzY77g28siNjkehfoJAgcd53c0IocJPFvCDAzBiBcCsk4MhtfGl2ZmbadjQf7++dghyr+HN6b5CXjOw46tAeA40l2AXC3wGwBxY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115564; c=relaxed/simple; bh=Ot9dZ9VGfijBFpNN4l2sas7HxFqkXH4N4SfK0aRWMN8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=b4t8Ytv3nYxcU3erkTvoIsISDHrVG1x5bw4NnYmhJ9XD/hdz6j/5JyGroexKEfOzDnBH11EPZw3u0f8MNDPBY++eIM0BKlX+sKqvSu2HgT3qcLRaiGrP3sghYalJz6TPwsw9HAG0R2QBsFXxzPrTgX0aDn+TbltGt8eSvY3N5fg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=wgCz3yM1; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="wgCz3yM1" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-7190c5e73cdso4942087b3a.0 for ; Mon, 23 Sep 2024 11:19:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115562; x=1727720362; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=oaCRsbnNWrRaFere+ELhrZId4GCv9+17KXmOqdHXVow=; b=wgCz3yM1WZEEqRAoiYldouXucyJW7zym6bp1IiEf0byn0GDWa12Y3GBmgotS7h7jtX PsPSBMBAVTOKQyKy19vHq2mXsz/JkTPB76wkYz5byFWYPWEmpEneAQ5dV06bDgiw3P9Q eRKGOUGoPXCEyoAYfGyJdlVauKeaFkQsCBEPQXiF0m9NgBw5peBM/eTuOzX3Pk2ex1ur BuVMsksCT21EJmZjDKXtI/6rJO3WKSRRMfaB7IlIvRLR3Sx7XfWmHxVzIhPQkMNY/55N wa60m9tzz8rQny4tHJPCqibI/fmI2JGOMt5QGIzvvI/a7PBxWPzml2NOKMjtg20S8ec7 IXXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115562; x=1727720362; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=oaCRsbnNWrRaFere+ELhrZId4GCv9+17KXmOqdHXVow=; b=ol7CszRQMdVMmdqzXqZZcOMPesrafjYZv6J4c/gpza3rfJH9lMCErMijOsDyO9Ocmr 2n9OSDquxUAlVZV6Joc82nnhujbbBkA6z1pJoFBr95p9O79UZjVgNVfsrZslBH1wY5KY C7rRwJqPsOBOjo9DrLEVje7u4byZbTHJa9TW19Jv2ICRHnsgVZyFhZvL2IAv3DQP/bgG 5jEWNTODi63eg4CjYlgstxi/F+zLCkayrzRS2LiIuDLyGrEfizPUDsfKPNlWfkcwyk6z YxZgwdZeUUlj8uZMab16lVqhhZWpr52vqyVRgXdNyMmHem2GN93CxnrZRdde6BmzGMet BRRg== X-Forwarded-Encrypted: i=1; AJvYcCXu4ZTdWQ3/t5FAVos/xaMPv++U/8ex0BDw6CF51572e21ArjyY74Ui/40RxKTamKWEE4xk7VEVMPkmIpM=@vger.kernel.org X-Gm-Message-State: AOJu0Yxwc10OHNhyYewzk6OvVtXTylJFhQMO/DKB1llVA6FHcYVloVFO KvECt/6WC0ddg5GPF5MfZo94Q1nmKck4rPCQtYNWgHfeBdT6WKE5+g+qoz8SjfKf7nPUwvVud60 fWdavNe+vB97Juf7CvjPSCsabig== X-Google-Smtp-Source: AGHT+IGgYP6fjgneZDlNtYZaBPXV084hh6eLWrDiE/RaKFs2xYRWbrbifhbSENhjTwFTncb+Fjv3BWnlVd6hjI5gp8c= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a05:6a00:6f5b:b0:70d:1285:bbcf with SMTP id d2e1a72fcca58-7199c6ed0f8mr16986b3a.0.1727115562282; Mon, 23 Sep 2024 11:19:22 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:55 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=2253; i=samitolvanen@google.com; h=from:subject; bh=Ot9dZ9VGfijBFpNN4l2sas7HxFqkXH4N4SfK0aRWMN8=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3KZH3u4/t3F3Van9p6MPLvruFdScYyw8bOVUY+Nc 8zP+ya7d5SyMIhxMMiKKbK0fF29dfd3p9RXn4skYOawMoEMYeDiFICJpLMwMqwqD84o0jhZrtu9 RKqm3jYi/vwblu7Ds/hX3DQUOn/PfgUjQ0Orx6O0KUtk326tsF38Y4XT0YrEN4tPrzZgqtm2ybX iERMA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-31-samitolvanen@google.com> Subject: [PATCH v3 09/20] gendwarfksyms: Expand array_type From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for expanding DW_TAG_array_type, and the subrange type indicating array size. Example source code: const char *s[34]; Output with --dump-dies: variable array_type[34] { pointer_type { const_type { base_type char byte_size(1) encoding(6) } } byte_size(8) } Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa Reviewed-by: Petr Pavlu --- scripts/gendwarfksyms/dwarf.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 5bdab5b80ca2..caf25da0a9b9 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -217,6 +217,7 @@ DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) } =20 DEFINE_MATCH(formal_parameter) +DEFINE_MATCH(subrange) =20 bool match_all(Dwarf_Die *die) { @@ -339,6 +340,33 @@ DEFINE_PROCESS_TYPE(shared) DEFINE_PROCESS_TYPE(volatile) DEFINE_PROCESS_TYPE(typedef) =20 +static void process_subrange_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + Dwarf_Word count =3D 0; + + if (get_udata_attr(die, DW_AT_count, &count)) + process_fmt(cache, "[%" PRIu64 "]", count); + else if (get_udata_attr(die, DW_AT_upper_bound, &count)) + process_fmt(cache, "[%" PRIu64 "]", count + 1); + else + process(cache, "[]"); +} + +static void process_array_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + process(cache, "array_type"); + /* Array size */ + check(process_die_container(state, cache, die, process_type, + match_subrange_type)); + process(cache, " {"); + process_linebreak(cache, 1); + process_type_attr(state, cache, die); + process_linebreak(cache, -1); + process(cache, "}"); +} + static void __process_subroutine_type(struct state *state, struct die *cac= he, Dwarf_Die *die, const char *type) { @@ -434,7 +462,9 @@ static int process_type(struct state *state, struct die= *parent, Dwarf_Die *die) PROCESS_TYPE(volatile) /* Subtypes */ PROCESS_TYPE(formal_parameter) + PROCESS_TYPE(subrange) /* Other types */ + PROCESS_TYPE(array) PROCESS_TYPE(base) PROCESS_TYPE(subroutine) PROCESS_TYPE(typedef) --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (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 3305C1A304A for ; Mon, 23 Sep 2024 18:19:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115567; cv=none; b=dJU0/rH4Jyr354YoeYRI+JDPltv1DU7rCNeqkHUiE4YrWGv4Szo8qOjSm2/d/6b95w49hL4Em6T/Rs/nC0MzLnBLx351xH7BPLcBBTZ0BVuJqaJWznSgkF/7/ekqwBXRW3R2b1EHFqevIR4DG/W9rrp3uDeG7bJBb6mq/uZSz4g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115567; c=relaxed/simple; bh=MygsVSBJnEKAJTK82XRxogqINneL66eGErhMp0pu+UM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=NqpOoy3pvq9YFBaRF3DDcYs2aRSNQdKOuNUz/HEibR0f2qYarHifzQO2dSIv8d4CQuhUXbEDMVHFu/cD6yV0iiMiJveQ6P5EPmzaEGXOYWX7fhkAIPE3FdGoMkWORnnWjXtqZJjJ4rfMV3aYwEQL+PB/WuKeOfcHGn7Te88M/5k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ZXb/X0L5; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ZXb/X0L5" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6ddbcc96984so72919847b3.2 for ; Mon, 23 Sep 2024 11:19:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115564; x=1727720364; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ANlveXiwDoWkXc0H/Y/2WzrB6GWz44bcvCNk+rFBd0Q=; b=ZXb/X0L5uPHlGu/bttGdGVWZgQQ4C6D0HPOrniwHTTaICw7MtvO/RsPvVfoaYYtNrs I8cbxvMMa7SQv8sLYDC4nHHZWOVmn5ZUeait1WNQXREHPrdT+g8r/bsN3Nvoo9xjPyCE ODZ/v7dWsh+/76RSjSG/Heh+ivuyIHoxs2GbVeF3RdclWS2PQTtRc/CRjHAGyjuPw+8M 2AwPXLtrZF32Dkb713KcaqsCjcxs+fB1LyrLK63x8455OXoLJ8hG2ftcrtf6s2L5X5xi gMkN4KqqDz+240i5Fz34PiodAgGvX+Hbz9E4fKK2o3DF1n3QP/kKKEYxIyi/72UQbzm+ o61A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115564; x=1727720364; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ANlveXiwDoWkXc0H/Y/2WzrB6GWz44bcvCNk+rFBd0Q=; b=vPoJ1wlHVPLqRDnFqGrAkKwUzI+o3hKj6CG50J7bNRjpa7l+RGGpgRe0yC6Id3OMgs OnGjI7O3jtv9sd/MlO6817bC9NM6MIPNwYlP/1aQxxEjlbZM4YmA81T1JxNHC3l8aSc9 9+1mT/KOcoDcyMrx0detcBDiDxR1FNjQZXvpFtKo1JHd/fSgOdYbRfgtBaOTOKcIU+7b SFHDkyP2nhuIMEmDzVSSMA7Tb+Ybih2zHh8hu5+yRaKz5WgqnPTQdCOjHfXuhjxQuZDz OT52wRkuUABlLmtYQGNOWehV50EqrrjeqiYzUfAkK3dVv0A8g7JMFOuD6oHdKsujuy36 Hoiw== X-Forwarded-Encrypted: i=1; AJvYcCWmkWLqHOv5hgunl0Ccy47u4WZaHhvDdOI6p6PxSQOJf9ZXIaanUo2grwF8LzPZDUdxK+gxD/1ExMjpytw=@vger.kernel.org X-Gm-Message-State: AOJu0Yx8EueWHahJV0ExYa4zss6fmwd4DDMbevkDMz1rTpyz+Wv1hg5/ Hfe7RxK8ffWgs9g9FbhbnB++2RcEtL0Bmtx/q0qjKzZ2cCEc9Ksion2dpEGTV0xHwpS0beU3mHa 6o+Z8r7Y5Q2JYdT7Mx6+5fvzasA== X-Google-Smtp-Source: AGHT+IE3j8e3jXaBGeJhRI75gJXd4IGAjcxId0osToHNQi+/xv6gI6zHeuvMD11Z6mGijxPTOEdYL9CnbjAsjLkZUkw= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a25:c74b:0:b0:e16:69e2:2028 with SMTP id 3f1490d57ef6-e2250c33deemr10274276.3.1727115564207; Mon, 23 Sep 2024 11:19:24 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:56 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=8385; i=samitolvanen@google.com; h=from:subject; bh=MygsVSBJnEKAJTK82XRxogqINneL66eGErhMp0pu+UM=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3KvnxEocy9tm+P+5buXxe2caJB3K1nl0UfHnfd3c mh0LhBj6yhlYRDjYJAVU2Rp+bp66+7vTqmvPhdJwMxhZQIZwsDFKQATmbOC4X+m6bLNNyTMinLv Llh2+cphqwdr95bOWXL4R4NrSNDm2R+eMDJsVnfgMllQe1pmzvruj99lTr3cU/Hs35zyqbb2O77 3cP9mAQA= X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-32-samitolvanen@google.com> Subject: [PATCH v3 10/20] gendwarfksyms: Expand structure types From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Recursively expand DWARF structure types, i.e. structs, unions, and enums. Also include relevant DWARF attributes in type strings to encode structure layout, for example. Example output with --dump-dies: subprogram ( formal_parameter structure_type &str { member pointer_type { base_type u8 byte_size(1) encoding(7) } data_ptr data_member_location(0) , member base_type usize byte_size(8) encoding(7) length data_member_lo= cation(8) } byte_size(16) alignment(8) msg ) -> base_type void Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/dwarf.c | 137 +++++++++++++++++++++++++- scripts/gendwarfksyms/gendwarfksyms.h | 5 + 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index caf25da0a9b9..b7f1dc29cb9c 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -205,9 +205,13 @@ static void process_fqn(struct die *cache, Dwarf_Die *= die) value); \ } =20 +DEFINE_PROCESS_UDATA_ATTRIBUTE(accessibility) DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) +DEFINE_PROCESS_UDATA_ATTRIBUTE(bit_size) DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size) DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) +DEFINE_PROCESS_UDATA_ATTRIBUTE(data_bit_offset) +DEFINE_PROCESS_UDATA_ATTRIBUTE(data_member_location) =20 /* Match functions -- die_match_callback_t */ #define DEFINE_MATCH(type) \ @@ -216,8 +220,11 @@ DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) return dwarf_tag(die) =3D=3D DW_TAG_##type##_type; \ } =20 +DEFINE_MATCH(enumerator) DEFINE_MATCH(formal_parameter) +DEFINE_MATCH(member) DEFINE_MATCH(subrange) +DEFINE_MATCH(variant) =20 bool match_all(Dwarf_Die *die) { @@ -295,6 +302,10 @@ static void __process_list_type(struct state *state, s= truct die *cache, process(cache, " "); process(cache, name); } + process_accessibility_attr(cache, die); + process_bit_size_attr(cache, die); + process_data_bit_offset_attr(cache, die); + process_data_member_location_attr(cache, die); } =20 #define DEFINE_PROCESS_LIST_TYPE(type) = \ @@ -305,6 +316,7 @@ static void __process_list_type(struct state *state, st= ruct die *cache, } =20 DEFINE_PROCESS_LIST_TYPE(formal_parameter) +DEFINE_PROCESS_LIST_TYPE(member) =20 /* Container types with DW_AT_type */ static void __process_type(struct state *state, struct die *cache, @@ -337,6 +349,7 @@ DEFINE_PROCESS_TYPE(reference) DEFINE_PROCESS_TYPE(restrict) DEFINE_PROCESS_TYPE(rvalue_reference) DEFINE_PROCESS_TYPE(shared) +DEFINE_PROCESS_TYPE(template_type_parameter) DEFINE_PROCESS_TYPE(volatile) DEFINE_PROCESS_TYPE(typedef) =20 @@ -390,6 +403,106 @@ static void process_subroutine_type(struct state *sta= te, struct die *cache, __process_subroutine_type(state, cache, die, "subroutine_type"); } =20 +static void process_variant_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + process_list_comma(state, cache); + process(cache, "variant {"); + process_linebreak(cache, 1); + check(process_die_container(state, cache, die, process_type, + match_member_type)); + process_linebreak(cache, -1); + process(cache, "}"); +} + +static void process_variant_part_type(struct state *state, struct die *cac= he, + Dwarf_Die *die) +{ + process_list_comma(state, cache); + process(cache, "variant_part {"); + process_linebreak(cache, 1); + check(process_die_container(state, cache, die, process_type, + match_variant_type)); + process_linebreak(cache, -1); + process(cache, "}"); +} + +static int ___process_structure_type(struct state *state, struct die *cach= e, + Dwarf_Die *die) +{ + switch (dwarf_tag(die)) { + case DW_TAG_member: + case DW_TAG_variant_part: + return check(process_type(state, cache, die)); + case DW_TAG_class_type: + case DW_TAG_enumeration_type: + case DW_TAG_structure_type: + case DW_TAG_template_type_parameter: + case DW_TAG_union_type: + case DW_TAG_subprogram: + /* Skip non-member types, including member functions */ + return 0; + default: + error("unexpected structure_type child: %x", dwarf_tag(die)); + } +} + +static void __process_structure_type(struct state *state, struct die *cach= e, + Dwarf_Die *die, const char *type, + die_callback_t process_func, + die_match_callback_t match_func) +{ + process(cache, type); + process_fqn(cache, die); + process(cache, " {"); + process_linebreak(cache, 1); + + check(process_die_container(state, cache, die, process_func, + match_func)); + + process_linebreak(cache, -1); + process(cache, "}"); + + process_byte_size_attr(cache, die); + process_alignment_attr(cache, die); +} + +#define DEFINE_PROCESS_STRUCTURE_TYPE(structure) \ + static void process_##structure##_type( \ + struct state *state, struct die *cache, Dwarf_Die *die) \ + { \ + __process_structure_type(state, cache, die, \ + #structure "_type", \ + ___process_structure_type, \ + match_all); \ + } + +DEFINE_PROCESS_STRUCTURE_TYPE(class) +DEFINE_PROCESS_STRUCTURE_TYPE(structure) +DEFINE_PROCESS_STRUCTURE_TYPE(union) + +static void process_enumerator_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + Dwarf_Word value; + + process_list_comma(state, cache); + process(cache, "enumerator"); + process_fqn(cache, die); + + if (get_udata_attr(die, DW_AT_const_value, &value)) { + process(cache, " =3D "); + process_fmt(cache, "%" PRIu64, value); + } +} + +static void process_enumeration_type(struct state *state, struct die *cach= e, + Dwarf_Die *die) +{ + __process_structure_type(state, cache, die, "enumeration_type", + process_type, match_enumerator_type); +} + static void process_base_type(struct state *state, struct die *cache, Dwarf_Die *die) { @@ -400,6 +513,16 @@ static void process_base_type(struct state *state, str= uct die *cache, process_alignment_attr(cache, die); } =20 +static void process_unspecified_type(struct state *state, struct die *cach= e, + Dwarf_Die *die) +{ + /* + * These can be emitted for stand-elone assembly code, which means we + * might run into them in vmlinux.o. + */ + process(cache, "unspecified_type"); +} + static void process_cached(struct state *state, struct die *cache, Dwarf_Die *die) { @@ -460,17 +583,27 @@ static int process_type(struct state *state, struct d= ie *parent, Dwarf_Die *die) PROCESS_TYPE(rvalue_reference) PROCESS_TYPE(shared) PROCESS_TYPE(volatile) + /* Container types */ + PROCESS_TYPE(class) + PROCESS_TYPE(structure) + PROCESS_TYPE(union) + PROCESS_TYPE(enumeration) /* Subtypes */ + PROCESS_TYPE(enumerator) PROCESS_TYPE(formal_parameter) + PROCESS_TYPE(member) PROCESS_TYPE(subrange) + PROCESS_TYPE(template_type_parameter) + PROCESS_TYPE(variant) + PROCESS_TYPE(variant_part) /* Other types */ PROCESS_TYPE(array) PROCESS_TYPE(base) PROCESS_TYPE(subroutine) PROCESS_TYPE(typedef) + PROCESS_TYPE(unspecified) default: - debug("unimplemented type: %x", tag); - break; + error("unexpected type: %x", tag); } =20 /* Update cache state and append to the parent (if any) */ diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index d5186472f705..ad50e35e3351 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -63,8 +63,13 @@ extern int dump_dies; #define checkp(expr) __check(expr, __res < 0) =20 /* Consistent aliases (DW_TAG__type) for DWARF tags */ +#define DW_TAG_enumerator_type DW_TAG_enumerator #define DW_TAG_formal_parameter_type DW_TAG_formal_parameter +#define DW_TAG_member_type DW_TAG_member +#define DW_TAG_template_type_parameter_type DW_TAG_template_type_parameter #define DW_TAG_typedef_type DW_TAG_typedef +#define DW_TAG_variant_part_type DW_TAG_variant_part +#define DW_TAG_variant_type DW_TAG_variant =20 /* * symbols.c --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (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 A94F01A38CE for ; Mon, 23 Sep 2024 18:19:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115568; cv=none; b=RUpmkXKJIT88HKElUE6fL4TMPZuUZ7edOCeO2JLb99oL8HPOGo4/R7LTJknSplTQmL7EK8XjobM7sx6FjI8OQDvr+o+52NfaekEhbFOSY+5X4/BziX0ran5fPFQCyy/gaQAxL3wvvc63ogLyhH2JNmhuLOWrkzNi5hmV9QwupkI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115568; c=relaxed/simple; bh=F+Slq6plceRzR9rmq0FI3V1NpzM62BS5pOj+D4AGsN4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=qzrV6j1CciJxd9Ve3TkpuEm3xB+nP0oVnkQZs6vJiwIPZLNJG2zf3eytmtFAB2w0rYoAJlJb4CWhBfypXDSNHRSvCZ0MAVcTHdH6OjyoroE0bPnJCWGmvtOOugYUKgXMB4O3MDMQ12rjZvaNEtZNsS+d172OKb1lT37a5FuHx/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=3dug4bp8; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="3dug4bp8" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6db7a8c6831so73447487b3.3 for ; Mon, 23 Sep 2024 11:19:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115566; x=1727720366; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=DB+9TXTkpzmpJhLs8qE2orQTUzZeD2kPnUO93xvC9pc=; b=3dug4bp8tvUYOx46NOIX/g3cceqG5Fpqr7i6d8ZAO1VtLxzwXMDGFqYrElDCZ4fvc0 MFMS1knxgr/+yCMF5zHdjbvvjss6U2nTQGnVFxd2017yh+XPX6XHSPEbxPEYCnT2ZJF3 o1jyqFuM0MxteU4xoBKJAoTo41PzGfHWkF1RrL1TtNxCl2cyAJ5aBhayFcdkq57T9WEI 2yNb24af6cwwZ3oeqcMu3s1TChGRnEIBc1AKywIUe/lrsavXrNAfoNysfEmbEjDn8diG fBvLEsH2iSPJ+u9FHepaLyZRMvUSon6lxxELyJjyvKbWIFPnuexBD2ZLmPnpDfYMfMIO TQTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115566; x=1727720366; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=DB+9TXTkpzmpJhLs8qE2orQTUzZeD2kPnUO93xvC9pc=; b=paGmrksOwS99GNmrLcZH7xUM3qmux5NORLXSHCv5ojxLplLZqzTCSQsdMZpO9ivWWD umptGMfZOKXMkM5pfQZTmpoYS5liKm2WDaWshl27VUWsn6ZVxalSI8CoL7IMSLJG7a24 cWM0W7+nlAs9pkLBTlZNGSek8eDL0EWzw+kd22bxeMDW8RsA5Cj9XUXPUWnLZBvnqED6 EdGpixC5kjsEgsdO1XRNQ3fuwCiuvEbYre75aIV2aa3M7Xt6yEoG0TVEW9t0P5/S6SWT ZcXeP7jsbR/11s+nnKRLcnV9js3mqSLHnpmVi2cEB4GV+3+UPFfNzsIhD8+k0OfQC0Fb B/4w== X-Forwarded-Encrypted: i=1; AJvYcCWppze4yBmi685h+Wp0vdBAs2YMAmgqei4pqwr6V1aqlipkz3+cpwB2YTUNIvHxYq3K9lcLbtEvBVaJeSw=@vger.kernel.org X-Gm-Message-State: AOJu0Yw6RdrHMjXRxLBtxjsX3pu+7XxyuyaSoJPXtqwN2klPRpVKLbjK 0WWddxSjzOXT/FuctONkhmnQ4QktH63P2+1Ez4Xo+8lHYm+upZ+qE8uBxr9bnnOUfAn5o29j3e4 XX/An6ljqayUewzDxzdhG7mOy2w== X-Google-Smtp-Source: AGHT+IEptnJIfoI+HL/ej56BOwTnghewlaOMrPmw+bwPxXE+r6Tu/6fUqGd9RSHzZXz7q+UHJQ4Am7epXYilKK/Kka0= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a05:690c:688a:b0:6dd:bcce:7cd4 with SMTP id 00721157ae682-6dff270dc8cmr1011377b3.2.1727115565857; Mon, 23 Sep 2024 11:19:25 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:57 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=10094; i=samitolvanen@google.com; h=from:subject; bh=F+Slq6plceRzR9rmq0FI3V1NpzM62BS5pOj+D4AGsN4=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN3LrGnDeL+04zlnxt7DqX5fZ9PW3lPOfL48srGW+E LY065lDRykLgxgHg6yYIkvL19Vbd393Sn31uUgCZg4rE8gQBi5OAZjI0xWMDB8X9J0PK+QIazj+ 13+ZM/duKaG599flO0w0qS/9ESAgq8vIsJ3vitaBZO41iX1z9W83fTl0/Gjb1vez7GceNK4/cH3 VWnYA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-33-samitolvanen@google.com> Subject: [PATCH v3 11/20] gendwarfksyms: Limit structure expansion From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Expand each structure type only once per exported symbol. This is necessary to support self-referential structures, which would otherwise result in infinite recursion, but is still sufficient for catching ABI changes. For pointers, limit structure expansion after the first pointer in the symbol type. This should be plenty for detecting ABI differences, but it stops us from pulling in half the kernel for types that contain pointers to large kernel data structures, like task_struct, for example. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/Makefile | 1 + scripts/gendwarfksyms/cache.c | 44 +++++++++++ scripts/gendwarfksyms/dwarf.c | 107 ++++++++++++++++++++++++-- scripts/gendwarfksyms/gendwarfksyms.h | 37 +++++++++ 4 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 scripts/gendwarfksyms/cache.c diff --git a/scripts/gendwarfksyms/Makefile b/scripts/gendwarfksyms/Makefile index c0d4ce50fc27..c06145d84df8 100644 --- a/scripts/gendwarfksyms/Makefile +++ b/scripts/gendwarfksyms/Makefile @@ -2,6 +2,7 @@ hostprogs-always-y +=3D gendwarfksyms =20 gendwarfksyms-objs +=3D gendwarfksyms.o +gendwarfksyms-objs +=3D cache.o gendwarfksyms-objs +=3D die.o gendwarfksyms-objs +=3D dwarf.o gendwarfksyms-objs +=3D symbols.o diff --git a/scripts/gendwarfksyms/cache.c b/scripts/gendwarfksyms/cache.c new file mode 100644 index 000000000000..2f1517133a20 --- /dev/null +++ b/scripts/gendwarfksyms/cache.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + */ + +#include "gendwarfksyms.h" + +struct expanded { + uintptr_t addr; + struct hlist_node hash; +}; + +void __cache_mark_expanded(struct expansion_cache *ec, uintptr_t addr) +{ + struct expanded *es; + + es =3D xmalloc(sizeof(struct expanded)); + es->addr =3D addr; + hash_add(ec->cache, &es->hash, addr_hash(addr)); +} + +bool __cache_was_expanded(struct expansion_cache *ec, uintptr_t addr) +{ + struct expanded *es; + + hash_for_each_possible(ec->cache, es, hash, addr_hash(addr)) { + if (es->addr =3D=3D addr) + return true; + } + + return false; +} + +void cache_clear_expanded(struct expansion_cache *ec) +{ + struct hlist_node *tmp; + struct expanded *es; + + hash_for_each_safe(ec->cache, es, tmp, hash) { + free(es); + } + + hash_init(ec->cache); +} diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index b7f1dc29cb9c..5fb9eadd782c 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -26,6 +26,7 @@ static void process_linebreak(struct die *cache, int n) !dwarf_form##attr(&da, value); \ } =20 +DEFINE_GET_ATTR(flag, bool) DEFINE_GET_ATTR(udata, Dwarf_Word) =20 static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *v= alue) @@ -79,6 +80,13 @@ static bool match_export_symbol(struct state *state, Dwa= rf_Die *die) return !!state->sym; } =20 +static bool is_declaration(Dwarf_Die *die) +{ + bool value; + + return get_flag_attr(die, DW_AT_declaration, &value) && value; +} + /* * Type string processing */ @@ -452,19 +460,28 @@ static void __process_structure_type(struct state *st= ate, struct die *cache, die_callback_t process_func, die_match_callback_t match_func) { + bool is_decl; + process(cache, type); process_fqn(cache, die); process(cache, " {"); process_linebreak(cache, 1); =20 - check(process_die_container(state, cache, die, process_func, - match_func)); + is_decl =3D is_declaration(die); + + if (!is_decl && state->expand.expand) { + cache_mark_expanded(&state->expansion_cache, die->addr); + check(process_die_container(state, cache, die, process_func, + match_func)); + } =20 process_linebreak(cache, -1); process(cache, "}"); =20 - process_byte_size_attr(cache, die); - process_alignment_attr(cache, die); + if (!is_decl && state->expand.expand) { + process_byte_size_attr(cache, die); + process_alignment_attr(cache, die); + } } =20 #define DEFINE_PROCESS_STRUCTURE_TYPE(structure) \ @@ -549,6 +566,42 @@ static void process_cached(struct state *state, struct= die *cache, } } =20 +static void state_init(struct state *state) +{ + state->expand.expand =3D true; + state->expand.ptr_depth =3D 0; + state->expand.ptr_expansion_depth =3D 0; + hash_init(state->expansion_cache.cache); +} + +static void expansion_state_restore(struct expansion_state *state, + struct expansion_state *saved) +{ + state->expand =3D saved->expand; + state->ptr_depth =3D saved->ptr_depth; + state->ptr_expansion_depth =3D saved->ptr_expansion_depth; +} + +static void expansion_state_save(struct expansion_state *state, + struct expansion_state *saved) +{ + expansion_state_restore(saved, state); +} + +static bool is_pointer_type(int tag) +{ + return tag =3D=3D DW_TAG_pointer_type || tag =3D=3D DW_TAG_reference_type; +} + +static bool is_expanded_type(int tag) +{ + return tag =3D=3D DW_TAG_class_type || tag =3D=3D DW_TAG_structure_type || + tag =3D=3D DW_TAG_union_type || tag =3D=3D DW_TAG_enumeration_type; +} + +/* The maximum depth for expanding structures in pointers */ +#define MAX_POINTER_EXPANSION_DEPTH 2 + #define PROCESS_TYPE(type) \ case DW_TAG_##type##_type: \ process_##type##_type(state, cache, die); \ @@ -556,18 +609,52 @@ static void process_cached(struct state *state, struc= t die *cache, =20 static int process_type(struct state *state, struct die *parent, Dwarf_Die= *die) { + enum die_state want_state =3D DIE_COMPLETE; struct die *cache; + struct expansion_state saved; int tag =3D dwarf_tag(die); =20 + expansion_state_save(&state->expand, &saved); + + /* + * Structures and enumeration types are expanded only once per + * exported symbol. This is sufficient for detecting ABI changes + * within the structure. + * + * We fully expand the first pointer reference in the exported + * symbol, but limit the expansion of further pointer references + * to at most MAX_POINTER_EXPANSION_DEPTH levels. + */ + if (is_pointer_type(tag)) + state->expand.ptr_depth++; + + if (state->expand.ptr_depth > 0 && is_expanded_type(tag)) { + if (state->expand.ptr_expansion_depth >=3D + MAX_POINTER_EXPANSION_DEPTH || + cache_was_expanded(&state->expansion_cache, die->addr)) + state->expand.expand =3D false; + + if (state->expand.expand) + state->expand.ptr_expansion_depth++; + } + /* - * If we have the DIE already cached, use it instead of walking + * If we have want_state already cached, use it instead of walking * through DWARF. */ - cache =3D die_map_get(die, DIE_COMPLETE); + if (!state->expand.expand && is_expanded_type(tag)) + want_state =3D DIE_UNEXPANDED; + + cache =3D die_map_get(die, want_state); + + if (cache->state =3D=3D want_state) { + if (want_state =3D=3D DIE_COMPLETE && is_expanded_type(tag)) + cache_mark_expanded(&state->expansion_cache, die->addr); =20 - if (cache->state =3D=3D DIE_COMPLETE) { process_cached(state, cache, die); die_map_add_die(parent, cache); + + expansion_state_restore(&state->expand, &saved); return 0; } =20 @@ -608,9 +695,10 @@ static int process_type(struct state *state, struct di= e *parent, Dwarf_Die *die) =20 /* Update cache state and append to the parent (if any) */ cache->tag =3D tag; - cache->state =3D DIE_COMPLETE; + cache->state =3D want_state; die_map_add_die(parent, cache); =20 + expansion_state_restore(&state->expand, &saved); return 0; } =20 @@ -672,11 +760,14 @@ static int process_exported_symbols(struct state *unu= sed, struct die *cache, if (!match_export_symbol(&state, die)) return 0; =20 + state_init(&state); + if (tag =3D=3D DW_TAG_subprogram) process_subprogram(&state, &state.die); else process_variable(&state, &state.die); =20 + cache_clear_expanded(&state.expansion_cache); return 0; } default: diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index ad50e35e3351..16d4746aaef9 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -104,6 +104,7 @@ struct symbol *symbol_get(const char *name); =20 enum die_state { DIE_INCOMPLETE, + DIE_UNEXPANDED, DIE_COMPLETE, DIE_LAST =3D DIE_COMPLETE }; @@ -134,6 +135,7 @@ static inline const char *die_state_name(enum die_state= state) switch (state) { default: CASE_CONST_TO_STR(DIE_INCOMPLETE) + CASE_CONST_TO_STR(DIE_UNEXPANDED) CASE_CONST_TO_STR(DIE_COMPLETE) } } @@ -154,9 +156,40 @@ void die_map_add_linebreak(struct die *pd, int linebre= ak); void die_map_add_die(struct die *pd, struct die *child); void die_map_free(void); =20 +/* + * cache.c + */ + +#define EXPANSION_CACHE_HASH_BITS 11 + +/* A cache for addresses we've already seen. */ +struct expansion_cache { + HASHTABLE_DECLARE(cache, 1 << EXPANSION_CACHE_HASH_BITS); +}; + +void __cache_mark_expanded(struct expansion_cache *ec, uintptr_t addr); +bool __cache_was_expanded(struct expansion_cache *ec, uintptr_t addr); + +static inline void cache_mark_expanded(struct expansion_cache *ec, void *a= ddr) +{ + __cache_mark_expanded(ec, (uintptr_t)addr); +} + +static inline bool cache_was_expanded(struct expansion_cache *ec, void *ad= dr) +{ + return __cache_was_expanded(ec, (uintptr_t)addr); +} + +void cache_clear_expanded(struct expansion_cache *ec); + /* * dwarf.c */ +struct expansion_state { + bool expand; + unsigned int ptr_depth; + unsigned int ptr_expansion_depth; +}; =20 struct state { struct symbol *sym; @@ -164,6 +197,10 @@ struct state { =20 /* List expansion */ bool first_list_item; + + /* Structure expansion */ + struct expansion_state expand; + struct expansion_cache expansion_cache; }; =20 typedef int (*die_callback_t)(struct state *state, struct die *cache, --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (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 758E41A3A85 for ; Mon, 23 Sep 2024 18:19:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115570; cv=none; b=GxnitI9LWNzH9dwITNDqu+whscMegr8oTDHbo+EYWFgoySPE1Fz9OHdn65Q2TSepAn4XrdutCjVbNT8NhV5VBksHkra+jSbEUM46XzI3v8kSSbei3+m5MujQ96wU3zj++T/uYmE/0TumpgF9pedDZWak1Pv4Vn1HmaO0jC44iu0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115570; c=relaxed/simple; bh=5jrCWgKy6c4XVO9Lg3hj9B9apzoGLkDqi2vgJTVKkFo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=TN2eVn4ekZc0OzPXerKFurRv5GHd5XisKM63wcOr7eXv2WtE0vrS8yz81kSFAwp+gkf4NulHL1fXMMniIDmsH3xPnNztgYsLar2qxp6DzQNIhts0TG/RlXqEIrNHiAIZ+LuEzEyRNYJnlZWGXPmy+6L8iy5csCkUP6oSpwvac5s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=YATp9Xng; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="YATp9Xng" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-2da8c2eeecaso5116455a91.1 for ; Mon, 23 Sep 2024 11:19:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115568; x=1727720368; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=JY1uJle74XQm0yf6l6izNHChhI79bQGWAHE9tPRlGlo=; b=YATp9Xngv3CeHMPnnEctggR44pYDOplQ2/ReScFR9kIuKimn++7qlntDyvLtScRh+f jcm37ItjJvbE0jR9jTFrAwiRgaToRE7PP6EDOVPveikLpn4qfAq/IoFjO54zqbug5irm 9bnwH7n1G+UcJXcgW5C7c9rpiAJRywqvau9i6iTT1gsDKNpcF/eDqgzAd4zKT5ET6Kvw AF2i88KoWW6+KicKBCiee8devn9b00y/Tmb9LmnzqsBMn5RYEzORAH848/l/GPx3gpwt UKrUEBouZxIxrpAWA2NsMg0jdesmrGATy+SPpgRRGKbeN6p/6dXsFwQ5g4i8zsEVKzTw eWIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115568; x=1727720368; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=JY1uJle74XQm0yf6l6izNHChhI79bQGWAHE9tPRlGlo=; b=awCN1gHaEgJEQJXd3vtHKnRZ+KAw0NlYtmVOEXh2DA7sxrxbkzwMySq6fmPxxZJoRn 6SndCSvjVGNHOBa8zJONVR5HZWJvJ2b8kfe5eW0BZDvhIR/YjzMmpogtskiU1L7Rxr0e mybezPuFVeupjhqntmH/YYH9upM4Ntajss16Ncrlgi8ud30Y846Kg+mB04zrtpv00BFL 5kTRsqGy2/t12ob18znRrVYY8VZmFZIpkC6FehYMYpZ/eF9NJE4JghrZOwr2CpbvpiM1 00YgvgGyRlK+BPw5YFuISz3g+vLlCGfC8fkuf+kFvLCPXO3+L+4Wd24vJqm7gA9WP8hL G3Yg== X-Forwarded-Encrypted: i=1; AJvYcCVhISBMsWE7XptATPmP4TwzpVe5zor9+PU7nDru/NyA1CZCcaShSmo7pBZcj3J7JHuK1p62bZPEgeSkgUQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwyNxRDZkruL+zRfwlxFKLWprGmQadv55wCCAV3Ih2ddAKUd1WO frRnTywPo+ZAGTYF2j1d7SOpWy4mdbx7LWup2feF8u7KNP/hLipeSCMOMfEo12rZWGj8LZUMyuJ 8c768nqJ3ERk1b8pLae2cNgedcQ== X-Google-Smtp-Source: AGHT+IHNkVnvCtV9wup56JFPDu+v4oNO+WNkshVpN7zdW5xRmKK1LUQn3oo3TLrHTIcCE4dCODTQF/nukTA4OVTuUJk= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a17:90a:dfc4:b0:2d8:f130:82ca with SMTP id 98e67ed59e1d1-2dd7f37f32amr22037a91.1.1727115567616; Mon, 23 Sep 2024 11:19:27 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:58 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=5089; i=samitolvanen@google.com; h=from:subject; bh=5jrCWgKy6c4XVO9Lg3hj9B9apzoGLkDqi2vgJTVKkFo=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/J8stnqysVlvOzup6msyXMrlHSdXRROi0ZYNssd/ Jxhu+ZYRykLgxgHg6yYIkvL19Vbd393Sn31uUgCZg4rE8gQBi5OAZiIQjPDH2696a37j2mVT55z MH//p/VTdS4eVw40XcEkGnkxjv+enxbD/1KeQ6dars09xcH76NO5ZyFL7N9s8+uuMWp4frYuUlz HixUA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-34-samitolvanen@google.com> Subject: [PATCH v3 12/20] gendwarfksyms: Add die_map debugging From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Debugging the DWARF processing can be somewhat challenging, so add more detailed debugging output for die_map operations. Add the --dump-die-map flag, which adds color coded tags to the output for die_map changes. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/dwarf.c | 15 +++++++++++++++ scripts/gendwarfksyms/gendwarfksyms.c | 7 +++++++ scripts/gendwarfksyms/gendwarfksyms.h | 13 +++++++++++++ 3 files changed, 35 insertions(+) diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 5fb9eadd782c..d2c6e91a7653 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -103,6 +103,8 @@ static void process(struct die *cache, const char *s) if (dump_dies) fputs(s, stderr); =20 + if (cache) + die_debug_r("cache %p string '%s'", cache, s); die_map_add_string(cache, s); } =20 @@ -549,6 +551,8 @@ static void process_cached(struct state *state, struct = die *cache, list_for_each_entry(df, &cache->fragments, list) { switch (df->type) { case FRAGMENT_STRING: + die_debug_b("cache %p STRING '%s'", cache, + df->data.str); process(NULL, df->data.str); break; case FRAGMENT_LINEBREAK: @@ -558,6 +562,8 @@ static void process_cached(struct state *state, struct = die *cache, if (!dwarf_die_addr_die(dwarf_cu_getdwarf(die->cu), (void *)df->data.addr, &child)) error("dwarf_die_addr_die failed"); + die_debug_b("cache %p DIE addr %" PRIxPTR " tag %x", + cache, df->data.addr, dwarf_tag(&child)); check(process_type(state, NULL, &child)); break; default: @@ -648,6 +654,9 @@ static int process_type(struct state *state, struct die= *parent, Dwarf_Die *die) cache =3D die_map_get(die, want_state); =20 if (cache->state =3D=3D want_state) { + die_debug_g("cached addr %p tag %x -- %s", die->addr, tag, + die_state_name(cache->state)); + if (want_state =3D=3D DIE_COMPLETE && is_expanded_type(tag)) cache_mark_expanded(&state->expansion_cache, die->addr); =20 @@ -658,6 +667,9 @@ static int process_type(struct state *state, struct die= *parent, Dwarf_Die *die) return 0; } =20 + die_debug_g("addr %p tag %x -- %s -> %s", die->addr, tag, + die_state_name(cache->state), die_state_name(want_state)); + switch (tag) { /* Type modifiers */ PROCESS_TYPE(atomic) @@ -693,6 +705,9 @@ static int process_type(struct state *state, struct die= *parent, Dwarf_Die *die) error("unexpected type: %x", tag); } =20 + die_debug_r("parent %p cache %p die addr %p tag %x", parent, cache, + die->addr, tag); + /* Update cache state and append to the parent (if any) */ cache->tag =3D tag; cache->state =3D want_state; diff --git a/scripts/gendwarfksyms/gendwarfksyms.c b/scripts/gendwarfksyms/= gendwarfksyms.c index 66806b0936e4..83b7eb8226dd 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.c +++ b/scripts/gendwarfksyms/gendwarfksyms.c @@ -19,6 +19,8 @@ int debug; /* Dump DIE contents */ int dump_dies; +/* Print debugging information about die_map changes */ +int dump_die_map; =20 static void usage(void) { @@ -26,6 +28,7 @@ static void usage(void) "Options:\n" " -d, --debug Print debugging information\n" " --dump-dies Dump DWARF DIE contents\n" + " --dump-die-map Print debugging information about die_map c= hanges\n" " -h, --help Print this message\n" "\n", stderr); @@ -74,6 +77,7 @@ int main(int argc, char **argv) =20 struct option opts[] =3D { { "debug", 0, NULL, 'd' }, { "dump-dies", 0, &dump_dies, 1 }, + { "dump-die-map", 0, &dump_die_map, 1 }, { "help", 0, NULL, 'h' }, { 0, 0, NULL, 0 } }; =20 @@ -93,6 +97,9 @@ int main(int argc, char **argv) } } =20 + if (dump_die_map) + dump_dies =3D 1; + if (optind >=3D argc) { usage(); error("no input files?"); diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index 16d4746aaef9..c913a2421515 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -24,6 +24,7 @@ */ extern int debug; extern int dump_dies; +extern int dump_die_map; =20 /* * Output helpers @@ -46,6 +47,18 @@ extern int dump_dies; exit(1); \ } while (0) =20 +#define __die_debug(color, format, ...) \ + do { \ + if (dump_dies && dump_die_map) \ + fprintf(stderr, \ + "\033[" #color "m<" format ">\033[39m", \ + __VA_ARGS__); \ + } while (0) + +#define die_debug_r(format, ...) __die_debug(91, format, __VA_ARGS__) +#define die_debug_g(format, ...) __die_debug(92, format, __VA_ARGS__) +#define die_debug_b(format, ...) __die_debug(94, format, __VA_ARGS__) + /* * Error handling helpers */ --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (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 7916A1A3AB1 for ; Mon, 23 Sep 2024 18:19:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115572; cv=none; b=A2ccZy8JFWuLFdJOnClNX8swH2X0K4YvSX1QC8kuhvmbfZO7eRSeMv5xeNyHpCvyMGXU5W6rPKj7/PvhYmx0N3tuLbzRGs3H7wekVEeZmQxYbJeSEhC+L80n7s2/b+z4D4hv7r62iopH0LuLG9PFqFSCbEuABDKIBdgTzFMq4rU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115572; c=relaxed/simple; bh=1xKBkZXfOARYS2S1Jov+944NphE2QInUDswo5pK9/90=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=TVmO33T1ieoBzw841XYfA2EBHVBBxxZOhg5TykjrAYv+voC0NSiF3PTNGt7tCrk5MN0nBctXFWPl6MTz5WQ/NqAvvXC9FSscYtOW6TpvQBNFe2akpEO3gepPHchmeA9Pvb5jIeAvXSdt5KGU+fOY6TE1iWqauit2hnv1t8UbtOM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=VdlsTiJw; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="VdlsTiJw" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-6d4f52a4069so81090727b3.3 for ; Mon, 23 Sep 2024 11:19:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115569; x=1727720369; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=f95D7vabrF97I5SuWiNeXKXt2St66qrVnN5xT1ayeds=; b=VdlsTiJwfccCXXmOHG0AJfrdEeqQeIx/+6/Mtxx0XNb/8GswdkiQ/NpON2tQ3UoBLW QskqqK6sA9r3tfcmHrlgTe9yeO/7nTFce3KaO7/gWutP6uuqW77HkZX0iawvKXQES/IC AFL3PHgVQpZhm9irGcSiHx7Sub/CIOVD+Amhm1Qpj1+FsFDvp2G7uRSLdrf+3u0dfbeK t+w4mjXX+aHNvXSQ+5y2Uflo6d87kr6qq/fwwNpUff6uBd77f45dFDQuTUQ84jjZZ7bT FvY+duP4bS/uy9JVRTQzsaqr6I98MDJopHoLaCYAkMAP6zUXUevu0ywshZ0yWGNhWp8k FDgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115569; x=1727720369; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=f95D7vabrF97I5SuWiNeXKXt2St66qrVnN5xT1ayeds=; b=lUi5lBr5A/DxrYrHfZBPf0GTNIAyzB8XuCgRKyJuBLUvkLE2BEA8yROG1P82dMzqyZ TcyhlSO/BHy8u8tzqX3Ai83eXR/LOGzz1G4+nDILIijhVbUTajLe3tWTG77bv2DYsVzh INM2gLNv05IFdGZYLedlNDOKQM8vstd8sdqgFM/ZY0JeLvgWdVBOh0nWIsZ7AFacEoTv exBeCTJTjLow8f8nR74p8xP1LdOdtUzdAqEZjyjaupJaJkK2Zybc+J76nxSKrtg4/3gU kIzhzq8yqU4kUywcZttGJPe1C4rwx4nqavoujWoDD1WLZCbe0Gg9c4rNJk1vAjS4EaGW AiNA== X-Forwarded-Encrypted: i=1; AJvYcCUfK2/K2b0LxfGJj+6qxRrZ6QgJEZ1qTR/A6Dlim+vjTnaDiSwtBJoNB954ZhDGVX36qB6OLGDETtPvUdY=@vger.kernel.org X-Gm-Message-State: AOJu0YzApBcOW18b0KKCDK0LrPzRJ9Sm9jViNcO/X9R9pGZfyU6UeQS8 j3K8L7+TVvV0Lhy/ep5FaFxrw/7hYUTMuHqSAOHEWLYPsvjpAuk2I9h3YX72RzEBqrAPNUvIz/U vjfJatLPIeFNDTaCosMTgWSXm1Q== X-Google-Smtp-Source: AGHT+IE8X/XBPFl4/JAlN1dgkCWdxwJteJjEpwiYaKMbysPwi14YbpQnM3XVwDxBEeM0anMEH0CXnfTmDslc9co2GTc= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a05:690c:726:b0:690:d536:27e1 with SMTP id 00721157ae682-6dff27056c9mr334847b3.2.1727115569427; Mon, 23 Sep 2024 11:19:29 -0700 (PDT) Date: Mon, 23 Sep 2024 18:18:59 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=17008; i=samitolvanen@google.com; h=from:subject; bh=1xKBkZXfOARYS2S1Jov+944NphE2QInUDswo5pK9/90=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/JEXOQQ0vBdz7TZtMlF5gvDw/uF586FM9zRbRE6r /tuM4dRRykLgxgHg6yYIkvL19Vbd393Sn31uUgCZg4rE8gQBi5OAZjIlgWMDK89jt+ULTUtVC9b WeHcOtXUSKH5c+g+rUNhoSG6ofLL5jIy/ErmuS4v/vmY84ZS1UVlgUdCi3UVnG/s3dbg8nZR2DN WLgA= X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-35-samitolvanen@google.com> Subject: [PATCH v3 13/20] gendwarfksyms: Add symtypes output From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for producing genksyms-style symtypes files. Process die_map to find the longest expansions for each type, and use symtypes references in type definitions. The basic file format is similar to genksyms, with two notable exceptions: 1. Type names with spaces (common with Rust) in references are wrapped in single quotes. E.g.: s#'core::result::Result' 2. The actual type definition is the simple parsed DWARF format we output with --dump-dies, not the preprocessed C-style format genksyms produces. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/Makefile | 1 + scripts/gendwarfksyms/die.c | 11 + scripts/gendwarfksyms/dwarf.c | 1 + scripts/gendwarfksyms/gendwarfksyms.c | 36 ++- scripts/gendwarfksyms/gendwarfksyms.h | 19 ++ scripts/gendwarfksyms/symbols.c | 4 +- scripts/gendwarfksyms/types.c | 359 ++++++++++++++++++++++++++ 7 files changed, 428 insertions(+), 3 deletions(-) create mode 100644 scripts/gendwarfksyms/types.c diff --git a/scripts/gendwarfksyms/Makefile b/scripts/gendwarfksyms/Makefile index c06145d84df8..6540282dc746 100644 --- a/scripts/gendwarfksyms/Makefile +++ b/scripts/gendwarfksyms/Makefile @@ -6,5 +6,6 @@ gendwarfksyms-objs +=3D cache.o gendwarfksyms-objs +=3D die.o gendwarfksyms-objs +=3D dwarf.o gendwarfksyms-objs +=3D symbols.o +gendwarfksyms-objs +=3D types.o =20 HOSTLDLIBS_gendwarfksyms :=3D -ldw -lelf diff --git a/scripts/gendwarfksyms/die.c b/scripts/gendwarfksyms/die.c index 2829387fd815..df1ca3a032bb 100644 --- a/scripts/gendwarfksyms/die.c +++ b/scripts/gendwarfksyms/die.c @@ -22,6 +22,7 @@ static inline unsigned int die_hash(uintptr_t addr, enum = die_state state) static void init_die(struct die *cd) { cd->state =3D DIE_INCOMPLETE; + cd->mapped =3D false; cd->fqn =3D NULL; cd->tag =3D -1; cd->addr =3D 0; @@ -83,6 +84,16 @@ static void reset_die(struct die *cd) init_die(cd); } =20 +void die_map_for_each(die_map_callback_t func, void *arg) +{ + struct hlist_node *tmp; + struct die *cd; + + hash_for_each_safe(die_map, cd, tmp, hash) { + func(cd, arg); + } +} + void die_map_free(void) { struct hlist_node *tmp; diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index d2c6e91a7653..2f80c78e356e 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -725,6 +725,7 @@ static void process_symbol(struct state *state, Dwarf_D= ie *die, { debug("%s", state->sym->name); check(process_func(state, NULL, die)); + state->sym->state =3D SYMBOL_MAPPED; if (dump_dies) fputs("\n", stderr); } diff --git a/scripts/gendwarfksyms/gendwarfksyms.c b/scripts/gendwarfksyms/= gendwarfksyms.c index 83b7eb8226dd..c077c4c1d346 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.c +++ b/scripts/gendwarfksyms/gendwarfksyms.c @@ -21,6 +21,11 @@ int debug; int dump_dies; /* Print debugging information about die_map changes */ int dump_die_map; +/* Print out type strings (i.e. type_map) */ +int dump_types; +/* Write a symtypes file */ +int symtypes; +static const char *symtypes_file; =20 static void usage(void) { @@ -29,6 +34,8 @@ static void usage(void) " -d, --debug Print debugging information\n" " --dump-dies Dump DWARF DIE contents\n" " --dump-die-map Print debugging information about die_map c= hanges\n" + " --dump-types Dump type strings\n" + " -T, --symtypes file Write a symtypes file\n" " -h, --help Print this message\n" "\n", stderr); @@ -41,6 +48,7 @@ static int process_module(Dwfl_Module *mod, void **userda= ta, const char *name, Dwarf_Die cudie; Dwarf_CU *cu =3D NULL; Dwarf *dbg; + FILE *symfile =3D arg; int res; =20 debug("%s", name); @@ -60,6 +68,10 @@ static int process_module(Dwfl_Module *mod, void **userd= ata, const char *name, process_cu(&cudie); } while (cu); =20 + /* + * Use die_map to expand type strings and write them to `symfile`. + */ + generate_symtypes(symfile); die_map_free(); =20 return DWARF_CB_OK; @@ -72,22 +84,29 @@ static const Dwfl_Callbacks callbacks =3D { =20 int main(int argc, char **argv) { + FILE *symfile =3D NULL; unsigned int n; int opt; =20 struct option opts[] =3D { { "debug", 0, NULL, 'd' }, { "dump-dies", 0, &dump_dies, 1 }, { "dump-die-map", 0, &dump_die_map, 1 }, + { "dump-types", 0, &dump_types, 1 }, + { "symtypes", 1, NULL, 'T' }, { "help", 0, NULL, 'h' }, { 0, 0, NULL, 0 } }; =20 - while ((opt =3D getopt_long(argc, argv, "dh", opts, NULL)) !=3D EOF) { + while ((opt =3D getopt_long(argc, argv, "dT:h", opts, NULL)) !=3D EOF) { switch (opt) { case 0: break; case 'd': debug =3D 1; break; + case 'T': + symtypes =3D 1; + symtypes_file =3D optarg; + break; case 'h': usage(); return 0; @@ -107,6 +126,16 @@ int main(int argc, char **argv) =20 symbol_read_exports(stdin); =20 + if (symtypes_file) { + symfile =3D fopen(symtypes_file, "w"); + + if (!symfile) { + error("fopen failed for '%s': %s", symtypes_file, + strerror(errno)); + return -1; + } + } + for (n =3D optind; n < argc; n++) { Dwfl *dwfl; int fd; @@ -135,7 +164,7 @@ int main(int argc, char **argv) =20 dwfl_report_end(dwfl, NULL, NULL); =20 - if (dwfl_getmodules(dwfl, &process_module, NULL, 0)) { + if (dwfl_getmodules(dwfl, &process_module, symfile, 0)) { error("dwfl_getmodules failed for '%s'", argv[n]); return -1; } @@ -143,5 +172,8 @@ int main(int argc, char **argv) dwfl_end(dwfl); } =20 + if (symfile) + check(fclose(symfile)); + return 0; } diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index c913a2421515..9fff30699d15 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -25,6 +25,8 @@ extern int debug; extern int dump_dies; extern int dump_die_map; +extern int dump_types; +extern int symtypes; =20 /* * Output helpers @@ -93,6 +95,11 @@ static inline unsigned int addr_hash(uintptr_t addr) return hash_ptr((const void *)addr); } =20 +enum symbol_state { + SYMBOL_UNPROCESSED, + SYMBOL_MAPPED, +}; + struct symbol_addr { uint32_t section; Elf64_Addr address; @@ -103,6 +110,8 @@ struct symbol { struct symbol_addr addr; struct hlist_node addr_hash; struct hlist_node name_hash; + enum symbol_state state; + uintptr_t die_addr; }; =20 typedef void (*symbol_callback_t)(struct symbol *, void *arg); @@ -155,6 +164,7 @@ static inline const char *die_state_name(enum die_state= state) =20 struct die { enum die_state state; + bool mapped; char *fqn; int tag; uintptr_t addr; @@ -162,10 +172,13 @@ struct die { struct hlist_node hash; }; =20 +typedef void (*die_map_callback_t)(struct die *, void *arg); + int __die_map_get(uintptr_t addr, enum die_state state, struct die **res); struct die *die_map_get(Dwarf_Die *die, enum die_state state); void die_map_add_string(struct die *pd, const char *str); void die_map_add_linebreak(struct die *pd, int linebreak); +void die_map_for_each(die_map_callback_t func, void *arg); void die_map_add_die(struct die *pd, struct die *child); void die_map_free(void); =20 @@ -227,4 +240,10 @@ int process_die_container(struct state *state, struct = die *cache, =20 void process_cu(Dwarf_Die *cudie); =20 +/* + * types.c + */ + +void generate_symtypes(FILE *file); + #endif /* __GENDWARFKSYMS_H */ diff --git a/scripts/gendwarfksyms/symbols.c b/scripts/gendwarfksyms/symbol= s.c index d84b46675dd1..a89e4869925a 100644 --- a/scripts/gendwarfksyms/symbols.c +++ b/scripts/gendwarfksyms/symbols.c @@ -92,6 +92,7 @@ void symbol_read_exports(FILE *file) sym =3D xcalloc(1, sizeof(struct symbol)); sym->name =3D name; sym->addr.section =3D SHN_UNDEF; + sym->state =3D SYMBOL_UNPROCESSED; =20 hash_add(symbol_names, &sym->name_hash, hash_str(sym->name)); ++nsym; @@ -107,7 +108,8 @@ static void get_symbol(struct symbol *sym, void *arg) { struct symbol **res =3D arg; =20 - *res =3D sym; + if (sym->state =3D=3D SYMBOL_UNPROCESSED) + *res =3D sym; } =20 struct symbol *symbol_get(const char *name) diff --git a/scripts/gendwarfksyms/types.c b/scripts/gendwarfksyms/types.c new file mode 100644 index 000000000000..c05811299eba --- /dev/null +++ b/scripts/gendwarfksyms/types.c @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + */ + +#include "gendwarfksyms.h" + +static struct expansion_cache expansion_cache; + +/* + * A simple linked list of shared or owned strings to avoid copying strings + * around when not necessary. + */ +struct type_list_entry { + const char *str; + void *owned; + struct list_head list; +}; + +static void type_list_free(struct list_head *list) +{ + struct type_list_entry *entry; + struct type_list_entry *tmp; + + list_for_each_entry_safe(entry, tmp, list, list) { + if (entry->owned) + free(entry->owned); + free(entry); + } + + INIT_LIST_HEAD(list); +} + +static int type_list_append(struct list_head *list, const char *s, void *o= wned) +{ + struct type_list_entry *entry; + + if (!s) + return 0; + + entry =3D xmalloc(sizeof(struct type_list_entry)); + entry->str =3D s; + entry->owned =3D owned; + list_add_tail(&entry->list, list); + + return strlen(entry->str); +} + +static void type_list_write(struct list_head *list, FILE *file) +{ + struct type_list_entry *entry; + + list_for_each_entry(entry, list, list) { + if (entry->str) + checkp(fputs(entry->str, file)); + } +} + +/* + * An expanded type string in symtypes format. + */ +struct type_expansion { + char *name; + size_t len; + struct list_head expanded; + struct hlist_node hash; +}; + +static void type_expansion_init(struct type_expansion *type) +{ + type->name =3D NULL; + type->len =3D 0; + INIT_LIST_HEAD(&type->expanded); +} + +static inline void type_expansion_free(struct type_expansion *type) +{ + free(type->name); + type->name =3D NULL; + type->len =3D 0; + type_list_free(&type->expanded); +} + +static void type_expansion_append(struct type_expansion *type, const char = *s, + void *owned) +{ + type->len +=3D type_list_append(&type->expanded, s, owned); +} + +/* + * type_map -- the longest expansions for each type. + * + * const char *name -> struct type_expansion * + */ +#define TYPE_HASH_BITS 16 +static HASHTABLE_DEFINE(type_map, 1 << TYPE_HASH_BITS); + +static int type_map_get(const char *name, struct type_expansion **res) +{ + struct type_expansion *e; + + hash_for_each_possible(type_map, e, hash, hash_str(name)) { + if (!strcmp(name, e->name)) { + *res =3D e; + return 0; + } + } + + return -1; +} + +static void type_map_add(const char *name, struct type_expansion *type) +{ + struct type_expansion *e; + + if (type_map_get(name, &e)) { + e =3D xmalloc(sizeof(struct type_expansion)); + type_expansion_init(e); + e->name =3D xstrdup(name); + + hash_add(type_map, &e->hash, hash_str(e->name)); + + if (dump_types) + debug("adding %s", e->name); + } else { + /* Use the longest available expansion */ + if (type->len <=3D e->len) + return; + + type_list_free(&e->expanded); + + if (dump_types) + debug("replacing %s", e->name); + } + + /* Take ownership of type->expanded */ + list_replace_init(&type->expanded, &e->expanded); + e->len =3D type->len; + + if (dump_types) { + checkp(fputs(e->name, stderr)); + checkp(fputs(" ", stderr)); + type_list_write(&e->expanded, stderr); + checkp(fputs("\n", stderr)); + } +} + +static void type_map_write(FILE *file) +{ + struct type_expansion *e; + struct hlist_node *tmp; + + if (!file) + return; + + hash_for_each_safe(type_map, e, tmp, hash) { + checkp(fputs(e->name, file)); + checkp(fputs(" ", file)); + type_list_write(&e->expanded, file); + checkp(fputs("\n", file)); + } +} + +static void type_map_free(void) +{ + struct type_expansion *e; + struct hlist_node *tmp; + + hash_for_each_safe(type_map, e, tmp, hash) { + type_expansion_free(e); + free(e); + } + + hash_init(type_map); +} + +/* + * Type reference format: #, where prefix: + * s -> structure + * u -> union + * e -> enum + * t -> typedef + * + * Names with spaces are additionally wrapped in single quotes. + */ +static char get_type_prefix(int tag) +{ + switch (tag) { + case DW_TAG_class_type: + case DW_TAG_structure_type: + return 's'; + case DW_TAG_union_type: + return 'u'; + case DW_TAG_enumeration_type: + return 'e'; + case DW_TAG_typedef_type: + return 't'; + default: + return 0; + } +} + +static char *get_type_name(struct die *cache) +{ + const char *quote; + char prefix; + char *name; + + if (cache->state =3D=3D DIE_INCOMPLETE) { + warn("found incomplete cache entry: %p", cache); + return NULL; + } + if (!cache->fqn || !*cache->fqn) + return NULL; + + prefix =3D get_type_prefix(cache->tag); + if (!prefix) + return NULL; + + /* Wrap names with spaces in single quotes */ + quote =3D strstr(cache->fqn, " ") ? "'" : ""; + + /* #\0 */ + if (asprintf(&name, "%c#%s%s%s", prefix, quote, cache->fqn, quote) < 0) + error("asprintf failed for '%s'", cache->fqn); + + return name; +} + +static void __type_expand(struct die *cache, struct type_expansion *type, + bool recursive); + +static void type_expand_child(struct die *cache, struct type_expansion *ty= pe, + bool recursive) +{ + struct type_expansion child; + char *name; + + name =3D get_type_name(cache); + if (!name) { + __type_expand(cache, type, recursive); + return; + } + + if (recursive && !__cache_was_expanded(&expansion_cache, cache->addr)) { + __cache_mark_expanded(&expansion_cache, cache->addr); + type_expansion_init(&child); + __type_expand(cache, &child, true); + type_map_add(name, &child); + type_expansion_free(&child); + } + + type_expansion_append(type, name, name); +} + +static void __type_expand(struct die *cache, struct type_expansion *type, + bool recursive) +{ + struct die_fragment *df; + struct die *child; + + list_for_each_entry(df, &cache->fragments, list) { + switch (df->type) { + case FRAGMENT_STRING: + type_expansion_append(type, df->data.str, NULL); + break; + case FRAGMENT_DIE: + /* Use a complete die_map expansion if available */ + if (__die_map_get(df->data.addr, DIE_COMPLETE, + &child) && + __die_map_get(df->data.addr, DIE_UNEXPANDED, + &child)) + error("unknown child: %" PRIxPTR, + df->data.addr); + + type_expand_child(child, type, recursive); + break; + case FRAGMENT_LINEBREAK: + /* + * Keep whitespace in the symtypes format, but avoid + * repeated spaces. + */ + if (list_is_last(&df->list, &cache->fragments) || + list_next_entry(df, list)->type !=3D + FRAGMENT_LINEBREAK) + type_expansion_append(type, " ", NULL); + break; + default: + error("empty die_fragment in %p", cache); + } + } +} + +static void type_expand(struct die *cache, struct type_expansion *type, + bool recursive) +{ + type_expansion_init(type); + __type_expand(cache, type, recursive); + cache_clear_expanded(&expansion_cache); +} + +static void expand_type(struct die *cache, void *arg) +{ + struct type_expansion type; + char *name; + + if (cache->mapped) + return; + + cache->mapped =3D true; + + /* + * Skip unexpanded die_map entries if there's a complete + * expansion available for this DIE. + */ + if (cache->state =3D=3D DIE_UNEXPANDED && + !__die_map_get(cache->addr, DIE_COMPLETE, &cache)) { + if (cache->mapped) + return; + + cache->mapped =3D true; + } + + name =3D get_type_name(cache); + if (!name) + return; + + debug("%s", name); + type_expand(cache, &type, true); + type_map_add(name, &type); + + type_expansion_free(&type); + free(name); +} + +void generate_symtypes(FILE *file) +{ + hash_init(expansion_cache.cache); + + /* + * die_map processing: + * + * 1. die_map contains all types referenced in exported symbol + * signatures, but can contain duplicates just like the original + * DWARF, and some references may not be fully expanded depending + * on how far we processed the DIE tree for that specific symbol. + * + * For each die_map entry, find the longest available expansion, + * and add it to type_map. + */ + die_map_for_each(expand_type, NULL); + + /* + * 2. If a symtypes file is requested, write type_map contents to + * the file. + */ + type_map_write(file); + type_map_free(); +} --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (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 100061A3BB9 for ; Mon, 23 Sep 2024 18:19:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115574; cv=none; b=lO6SesurWyaEwb5eGZbArrUy3Qn29QnDaGj4z7zkhEiXG2fj1Llz0iaoizp+B+hh+DAFM2P0YzQbPXwT/+fUFTkZWfjwk/7G860mWcMGlbTLKPrFdJqOdFqmxWfi+274xEOirQlen5u8N8BMDi/Pub3mmaNqJsUEeZWFhpSMgto= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115574; c=relaxed/simple; bh=NyQMJW8xoyRkaDj9KuuEnvX2h4eDKw1AvcUUXqq6aaU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=AsRBcopuD3OvI+CtC+SslvLo9omfM0eb0ai93DBmhFpaDRb7QvJjvU+gDEZOT+/EmySnCpKQh9Nnkj4fl64gpknoJSimZAL0wA84FgVb1rzYDK7KPZ9lQox0FMdHZsO0CsM28p1CfJkJK4VKruVbbeCJLBA9b2d0gujTvA0Pxwg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=3gv0IYaF; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="3gv0IYaF" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-2d8859d6e9dso4292082a91.1 for ; Mon, 23 Sep 2024 11:19:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115571; x=1727720371; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=YQDh+AQxocSUIORA7y8NGTKu8fBAIKbAEgaeqYm4RPQ=; b=3gv0IYaFfXRoSIXMbxHH1fMoxSsKOfZL7pEYQHjykfRsGI3OEpaUSX4rMjeciwP+KJ CUkaRkdm/Twni01hRFCjhgS20Ed2PImnDo3MOl/vhhV92vnUKIAPftg7kIJdf7BekOuo 5W8FvBNFmUboMCcEW506b4L8bo6yVB0MWKAkuRx6HyEIojLgxX7VmPKzY1fo2RgBd8Yp w9ypf3te/bUhxBFTZ4PDGzAvP/C6Oj/9vQL95E978fbMhybxHHb9PJ7MgVtPTrvqh3H9 XJSG+zHRJ82GN++agvV0Cw1afsT1lJJrDsatAHpWW6UQiWZATRXn3vSLOy6gveFLyYlv odXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115571; x=1727720371; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YQDh+AQxocSUIORA7y8NGTKu8fBAIKbAEgaeqYm4RPQ=; b=Y6b4bP91+goiR0BwtcXow27Jg/HXNGtMafMQj09U2UigtDqLXk6CdzBnNoF1pzn1kd tNtkRBta+WG0nzxkCdi+IVMivDLIBC1vve1UQPlfKKYO9kSpq4HF6UnJWS9MVe6SghVe mguZimMIDEiMP4D7R+vUYfwI0L6W1OAnbaC0FPqc725LP8aY8Z05UphbCDEPZzCTLS24 RyZWimtfFh08ecF25EqPlnr2rjWqmgZBxWXEKjtvyKMP5QEMt1ABLrzurK3fv4gzqR13 bm0qPq12uYM11lv3ZqaPGblWHy+w5nR0W4ambdu+tZQ+O9V3hYAJElsnvqBLJQmeaY0e FuYA== X-Forwarded-Encrypted: i=1; AJvYcCVonWgmraBgAEdZIBeh8G/71atvP1B2VgXkNKwEJnS4eZsHlbeuMp12pbNIsbbZP9pJse+9GyFpaHSEZYM=@vger.kernel.org X-Gm-Message-State: AOJu0YyUsKfVA6rB5X1Pu+ompo9qKj0qj9QWL9Xf8kbCyjYpADFF4UQi gJJjUArelXgnsgodJ2/hID8aw7590zQX8WEFLNPcXHve6reglpSbvOVb4zcvm+d9bchv40PJ56L MhZOvaskMYEVggciT7rlCryYvfw== X-Google-Smtp-Source: AGHT+IHDCpMMeDju4PawTIDwF7TntYE+Y3rH7ZsGT9ME5cBiLIfyubQG1RPL/WTp7CVLxceXz5aEd8YUOuFXqZPV3bo= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a17:90b:4a8e:b0:2d8:e4f9:259e with SMTP id 98e67ed59e1d1-2dd7f7527f5mr15155a91.3.1727115571325; Mon, 23 Sep 2024 11:19:31 -0700 (PDT) Date: Mon, 23 Sep 2024 18:19:00 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=12492; i=samitolvanen@google.com; h=from:subject; bh=NyQMJW8xoyRkaDj9KuuEnvX2h4eDKw1AvcUUXqq6aaU=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/Iqf2m7JL/4+fTbnRtf6E0/8L7j2dJjc5f2KVQaz fd1ND97paOUhUGMg0FWTJGl5evqrbu/O6W++lwkATOHlQlkCAMXpwBMZPN3RoYJghy/JvlOvOj0 w3l36lUXL9HrIuskXna/6FNdvfPGh/OqDH/FD/0okb7szcL5uaktcPljhdd/p32sTlcWbd8uVOo 1iY0VAA== X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-36-samitolvanen@google.com> Subject: [PATCH v3 14/20] gendwarfksyms: Add symbol versioning From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Calculate symbol versions from the fully expanded type strings in type_map, and output the versions in a genksyms-compatible format. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/dwarf.c | 25 +++++- scripts/gendwarfksyms/gendwarfksyms.c | 11 ++- scripts/gendwarfksyms/gendwarfksyms.h | 13 ++- scripts/gendwarfksyms/symbols.c | 59 +++++++++++++ scripts/gendwarfksyms/types.c | 122 +++++++++++++++++++++++++- 5 files changed, 222 insertions(+), 8 deletions(-) diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 2f80c78e356e..8d1a7d808413 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -720,12 +720,33 @@ static int process_type(struct state *state, struct d= ie *parent, Dwarf_Die *die) /* * Exported symbol processing */ +static struct die *get_symbol_cache(struct state *state, Dwarf_Die *die) +{ + struct die *cache; + + cache =3D die_map_get(die, DIE_SYMBOL); + + if (cache->state !=3D DIE_INCOMPLETE) + return NULL; /* We already processed a symbol for this DIE */ + + cache->tag =3D dwarf_tag(die); + return cache; +} + static void process_symbol(struct state *state, Dwarf_Die *die, die_callback_t process_func) { + struct die *cache; + + symbol_set_die(state->sym, die); + + cache =3D get_symbol_cache(state, die); + if (!cache) + return; + debug("%s", state->sym->name); - check(process_func(state, NULL, die)); - state->sym->state =3D SYMBOL_MAPPED; + check(process_func(state, cache, die)); + cache->state =3D DIE_SYMBOL; if (dump_dies) fputs("\n", stderr); } diff --git a/scripts/gendwarfksyms/gendwarfksyms.c b/scripts/gendwarfksyms/= gendwarfksyms.c index c077c4c1d346..7fb17bf81e02 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.c +++ b/scripts/gendwarfksyms/gendwarfksyms.c @@ -23,6 +23,8 @@ int dump_dies; int dump_die_map; /* Print out type strings (i.e. type_map) */ int dump_types; +/* Print out expanded type strings used for symbol versions */ +int dump_versions; /* Write a symtypes file */ int symtypes; static const char *symtypes_file; @@ -35,6 +37,7 @@ static void usage(void) " --dump-dies Dump DWARF DIE contents\n" " --dump-die-map Print debugging information about die_map c= hanges\n" " --dump-types Dump type strings\n" + " --dump-versions Dump expanded type strings used for symbol = versions\n" " -T, --symtypes file Write a symtypes file\n" " -h, --help Print this message\n" "\n", @@ -69,9 +72,10 @@ static int process_module(Dwfl_Module *mod, void **userd= ata, const char *name, } while (cu); =20 /* - * Use die_map to expand type strings and write them to `symfile`. + * Use die_map to expand type strings, write them to `symfile`, and + * calculate symbol versions. */ - generate_symtypes(symfile); + generate_symtypes_and_versions(symfile); die_map_free(); =20 return DWARF_CB_OK; @@ -92,6 +96,7 @@ int main(int argc, char **argv) { "dump-dies", 0, &dump_dies, 1 }, { "dump-die-map", 0, &dump_die_map, 1 }, { "dump-types", 0, &dump_types, 1 }, + { "dump-versions", 0, &dump_versions, 1 }, { "symtypes", 1, NULL, 'T' }, { "help", 0, NULL, 'h' }, { 0, 0, NULL, 0 } }; @@ -175,5 +180,7 @@ int main(int argc, char **argv) if (symfile) check(fclose(symfile)); =20 + symbol_print_versions(); + return 0; } diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index 9fff30699d15..db9b4964ed8a 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -26,6 +26,7 @@ extern int debug; extern int dump_dies; extern int dump_die_map; extern int dump_types; +extern int dump_versions; extern int symtypes; =20 /* @@ -98,6 +99,7 @@ static inline unsigned int addr_hash(uintptr_t addr) enum symbol_state { SYMBOL_UNPROCESSED, SYMBOL_MAPPED, + SYMBOL_PROCESSED }; =20 struct symbol_addr { @@ -112,6 +114,7 @@ struct symbol { struct hlist_node name_hash; enum symbol_state state; uintptr_t die_addr; + unsigned long crc; }; =20 typedef void (*symbol_callback_t)(struct symbol *, void *arg); @@ -119,6 +122,10 @@ typedef void (*symbol_callback_t)(struct symbol *, voi= d *arg); void symbol_read_exports(FILE *file); void symbol_read_symtab(int fd); struct symbol *symbol_get(const char *name); +void symbol_set_die(struct symbol *sym, Dwarf_Die *die); +void symbol_set_crc(struct symbol *sym, unsigned long crc); +void symbol_for_each(symbol_callback_t func, void *arg); +void symbol_print_versions(void); =20 /* * die.c @@ -128,7 +135,8 @@ enum die_state { DIE_INCOMPLETE, DIE_UNEXPANDED, DIE_COMPLETE, - DIE_LAST =3D DIE_COMPLETE + DIE_SYMBOL, + DIE_LAST =3D DIE_SYMBOL }; =20 enum die_fragment_type { @@ -159,6 +167,7 @@ static inline const char *die_state_name(enum die_state= state) CASE_CONST_TO_STR(DIE_INCOMPLETE) CASE_CONST_TO_STR(DIE_UNEXPANDED) CASE_CONST_TO_STR(DIE_COMPLETE) + CASE_CONST_TO_STR(DIE_SYMBOL) } } =20 @@ -244,6 +253,6 @@ void process_cu(Dwarf_Die *cudie); * types.c */ =20 -void generate_symtypes(FILE *file); +void generate_symtypes_and_versions(FILE *file); =20 #endif /* __GENDWARFKSYMS_H */ diff --git a/scripts/gendwarfksyms/symbols.c b/scripts/gendwarfksyms/symbol= s.c index a89e4869925a..924f52ee4acd 100644 --- a/scripts/gendwarfksyms/symbols.c +++ b/scripts/gendwarfksyms/symbols.c @@ -66,6 +66,36 @@ static int for_each(const char *name, bool name_only, sy= mbol_callback_t func, return 0; } =20 +static void set_crc(struct symbol *sym, void *data) +{ + unsigned long *crc =3D data; + + if (sym->state =3D=3D SYMBOL_PROCESSED && sym->crc !=3D *crc) + warn("overriding version for symbol %s (crc %lx vs. %lx)", + sym->name, sym->crc, *crc); + + sym->state =3D SYMBOL_PROCESSED; + sym->crc =3D *crc; +} + +void symbol_set_crc(struct symbol *sym, unsigned long crc) +{ + if (checkp(for_each(sym->name, false, set_crc, &crc)) =3D=3D 0) + error("no matching symbols: '%s'", sym->name); +} + +static void set_die(struct symbol *sym, void *data) +{ + sym->die_addr =3D (uintptr_t)((Dwarf_Die *)data)->addr; + sym->state =3D SYMBOL_MAPPED; +} + +void symbol_set_die(struct symbol *sym, Dwarf_Die *die) +{ + if (checkp(for_each(sym->name, false, set_die, die)) =3D=3D 0) + error("no matching symbols: '%s'", sym->name); +} + static bool is_exported(const char *name) { return checkp(for_each(name, true, NULL, NULL)) > 0; @@ -120,6 +150,16 @@ struct symbol *symbol_get(const char *name) return sym; } =20 +void symbol_for_each(symbol_callback_t func, void *arg) +{ + struct hlist_node *tmp; + struct symbol *sym; + + hash_for_each_safe(symbol_names, sym, tmp, name_hash) { + func(sym, arg); + } +} + typedef void (*elf_symbol_callback_t)(const char *name, GElf_Sym *sym, Elf32_Word xndx, void *arg); =20 @@ -229,3 +269,22 @@ void symbol_read_symtab(int fd) { elf_for_each_global(fd, elf_set_symbol_addr, NULL); } + +void symbol_print_versions(void) +{ + struct hlist_node *tmp; + struct symbol *sym; + + hash_for_each_safe(symbol_names, sym, tmp, name_hash) { + if (sym->state !=3D SYMBOL_PROCESSED) + warn("no information for symbol %s", sym->name); + + printf("#SYMVER %s 0x%08lx\n", sym->name, sym->crc); + + free((void *)sym->name); + free(sym); + } + + hash_init(symbol_addrs); + hash_init(symbol_names); +} diff --git a/scripts/gendwarfksyms/types.c b/scripts/gendwarfksyms/types.c index c05811299eba..08886063363c 100644 --- a/scripts/gendwarfksyms/types.c +++ b/scripts/gendwarfksyms/types.c @@ -3,6 +3,7 @@ * Copyright (C) 2024 Google LLC */ =20 +#include #include "gendwarfksyms.h" =20 static struct expansion_cache expansion_cache; @@ -174,6 +175,33 @@ static void type_map_free(void) hash_init(type_map); } =20 +/* + * CRC for a type, with an optional fully expanded type string for + * debugging. + */ +struct version { + struct type_expansion type; + unsigned long crc; +}; + +static void version_init(struct version *version) +{ + version->crc =3D 0xffffffff; + type_expansion_init(&version->type); +} + +static void version_free(struct version *version) +{ + type_expansion_free(&version->type); +} + +static void version_add(struct version *version, const char *s) +{ + version->crc =3D partial_crc32(s, version->crc); + if (dump_versions) + type_expansion_append(&version->type, s, NULL); +} + /* * Type reference format: #, where prefix: * s -> structure @@ -183,6 +211,12 @@ static void type_map_free(void) * * Names with spaces are additionally wrapped in single quotes. */ +static inline bool is_type_prefix(const char *s) +{ + return (s[0] =3D=3D 's' || s[0] =3D=3D 'u' || s[0] =3D=3D 'e' || s[0] =3D= =3D 't') && + s[1] =3D=3D '#'; +} + static char get_type_prefix(int tag) { switch (tag) { @@ -210,6 +244,8 @@ static char *get_type_name(struct die *cache) warn("found incomplete cache entry: %p", cache); return NULL; } + if (cache->state =3D=3D DIE_SYMBOL) + return NULL; if (!cache->fqn || !*cache->fqn) return NULL; =20 @@ -227,6 +263,39 @@ static char *get_type_name(struct die *cache) return name; } =20 +static void __calculate_version(struct version *version, struct list_head = *list) +{ + struct type_list_entry *entry; + struct type_expansion *e; + + /* Calculate a CRC over an expanded type string */ + list_for_each_entry(entry, list, list) { + if (is_type_prefix(entry->str)) { + check(type_map_get(entry->str, &e)); + + /* + * It's sufficient to expand each type reference just + * once to detect changes. + */ + if (cache_was_expanded(&expansion_cache, e)) { + version_add(version, entry->str); + } else { + cache_mark_expanded(&expansion_cache, e); + __calculate_version(version, &e->expanded); + } + } else { + version_add(version, entry->str); + } + } +} + +static void calculate_version(struct version *version, struct list_head *l= ist) +{ + version_init(version); + __calculate_version(version, list); + cache_clear_expanded(&expansion_cache); +} + static void __type_expand(struct die *cache, struct type_expansion *type, bool recursive); =20 @@ -333,7 +402,49 @@ static void expand_type(struct die *cache, void *arg) free(name); } =20 -void generate_symtypes(FILE *file) +static void expand_symbol(struct symbol *sym, void *arg) +{ + struct type_expansion type; + struct version version; + struct die *cache; + + /* + * No need to expand again unless we want a symtypes file entry + * for the symbol. Note that this means `sym` has the same address + * as another symbol that was already processed. + */ + if (!symtypes && sym->state =3D=3D SYMBOL_PROCESSED) + return; + + if (__die_map_get(sym->die_addr, DIE_SYMBOL, &cache)) + return; /* We'll warn about missing CRCs later. */ + + type_expand(cache, &type, false); + + /* If the symbol already has a version, don't calculate it again. */ + if (sym->state !=3D SYMBOL_PROCESSED) { + calculate_version(&version, &type.expanded); + symbol_set_crc(sym, version.crc); + debug("%s =3D %lx", sym->name, version.crc); + + if (dump_versions) { + checkp(fputs(sym->name, stderr)); + checkp(fputs(" ", stderr)); + type_list_write(&version.type.expanded, stderr); + checkp(fputs("\n", stderr)); + } + + version_free(&version); + } + + /* These aren't needed in type_map unless we want a symtypes file. */ + if (symtypes) + type_map_add(sym->name, &type); + + type_expansion_free(&type); +} + +void generate_symtypes_and_versions(FILE *file) { hash_init(expansion_cache.cache); =20 @@ -351,7 +462,14 @@ void generate_symtypes(FILE *file) die_map_for_each(expand_type, NULL); =20 /* - * 2. If a symtypes file is requested, write type_map contents to + * 2. For each exported symbol, expand the die_map type, and use + * type_map expansions to calculate a symbol version from the + * fully expanded type string. + */ + symbol_for_each(expand_symbol, NULL); + + /* + * 3. If a symtypes file is requested, write type_map contents to * the file. */ type_map_write(file); --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 B917B1A42AB for ; Mon, 23 Sep 2024 18:19:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115575; cv=none; b=KPmlGlRLmov4jOpdZSRLmLKPdQLZAQovlClOOZJkECiaLtbvoXwOGUaThpSE0BvxJ38xaqiW82IJZhHpCg9AF0AcAZPXshrWlnKWQGDlkNNKp8RAS1cYIK1GLAkoDCKNdXllN5Ysx+oyb6JDqT+JOPV57bj7G+KQqV/47gBh9RQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115575; c=relaxed/simple; bh=1BY/5ZgPikShEh5G1ID4ZZgXwL4aUjSEY2X709I49f0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=o9YoIG6U1qUBu2DMI5fSBOyPLuhXf83ZM2e/H0ywPqE42pWCsogyUdnXzTPOcmr4NfyhRsv2/izx1XuavGZuoJ4jshtc2cepWuWfojKVd+6vWp8cBskcv4Q/Kx92C/4nZpdm/qkDQBef++okJs/i664EenJr8RibPuE9MYLa/Nk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=GfuF0Zmh; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="GfuF0Zmh" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-20535259f94so48327835ad.1 for ; Mon, 23 Sep 2024 11:19:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115573; x=1727720373; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=cD7gYzqsnIdyKf8BqCoD5wNYjELs+mOU9BHPdKzFna4=; b=GfuF0ZmhV3x7ZHfvlTqHnCv+aASrIDeJK1Lgg9n3H0+Hn15N6Qp1fmeJtDl/LNMcki dN8itsEx6KB3RI0MixDly2Sn+opTaTtJWZ6oMBOgbGV5c535KyBUOF4y+tZLR1QUP308 vUQ8ZUdclS38grq4BlEmi5wLhZrMDHXB2j5bZuK6JP185BZcXmNcfX9B/k9j8niyRJul CbxB1r1IVwjeCXeB5JEYQ0V39WDbzPCVi2DbrAEjjebyPSg3W+w9WwLXapeoqzLa+yJy JgZ6byAZy93sskEyTs579b/KC7b6zex7zob7WT9Jk7YryOK2cFzrRTnwgaMqqkABJlQU j/XA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115573; x=1727720373; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=cD7gYzqsnIdyKf8BqCoD5wNYjELs+mOU9BHPdKzFna4=; b=iGDOTcJMBVcT6aH7Ytl3kNCAGJKHCc5I5eL3veLYbuXWgKN243uChWeJj6+EeDX+KI MME5IH/0tSw12Fh33+tDQr+IZlQ9A9yS5VZV6tCob9+yjTdogQpdT5xGTDZ0xy+2vTan 0BTvyS28kOrTYzuM/xngTBXGASaMcvrziQkPKBasDM4o0DSX6LfBc9wgNKrGD8YxYxuJ f5ReWRXT84yYXssyUKyTXJOSGAUjD45jJU3PaT/Y+NNDiBgIzrNUry9APyXrWIGsV/zu pVqDGoxY6lbkCUtOKqatm6GfgpCi6E4d2reMAFdSRE8lHFJhE0TRl3eXPcoFYyK7l2Rn p5kw== X-Forwarded-Encrypted: i=1; AJvYcCXrX3QEDlPO7zWN/fnIRKosyndtXoDdOhu4Vvr4MnU1YYz/PtM8GOC7itOoMmjR4ltkfC/CG3kN2zswU8s=@vger.kernel.org X-Gm-Message-State: AOJu0YxYYS7zM7wnRbcSqdtYgO+0r5AMvQBJAVIacNjSxVwu/P3qBwbU zH2anDy6vuBtiYGUkP0IPACzRaeAvRyUm/SD7ECKAhwtX2ZBUQLYylwr2Ce9ydtd1gHPrPEdi8n 9iVSrAzkiDHdmUy43VO80Vvde/g== X-Google-Smtp-Source: AGHT+IEgj7CcGlvVrjTix3NIh+c5WRmt3LKNEs/nyn6lwVRQfqj60CMXbCvIHsnyDIAV98f8SI7Ndnui62wGsY+13iE= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a17:903:1cf:b0:205:66a5:5fc7 with SMTP id d9443c01a7336-208d988adffmr293885ad.8.1727115572980; Mon, 23 Sep 2024 11:19:32 -0700 (PDT) Date: Mon, 23 Sep 2024 18:19:01 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=17924; i=samitolvanen@google.com; h=from:subject; bh=1BY/5ZgPikShEh5G1ID4ZZgXwL4aUjSEY2X709I49f0=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/IaSD/eG2n3cK/TxzMTdzetrLp1+sv6B0xW/7ij2 MPdl9y+2FHKwiDGwSArpsjS8nX11t3fnVJffS6SgJnDygQyhIGLUwAmYubF8D/drd7i0oY4Ff17 XPUyN+rvH5n3/JOtqv2kF53S/67lJAcyMsyVEyntW8z69kTKzunPKo55Ptv0c+NbT57cR8tPbSl 3keQBAA== X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-37-samitolvanen@google.com> Subject: [PATCH v3 15/20] gendwarfksyms: Add support for kABI rules From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Distributions that want to maintain a stable kABI need the ability to make ABI compatible changes to kernel without affecting symbol versions, either because of LTS updates or backports. With genksyms, developers would typically hide these changes from version calculation with #ifndef __GENKSYMS__, which would result in the symbol version not changing even though the actual type has changed. When we process precompiled object files, this isn't an option. To support this use case, add a --stable command line flag that gates kABI stability features that are not needed in mainline kernels, but can be useful for distributions, and add support for kABI rules, which can be used to restrict gendwarfksyms output. The rules are specified as a set of null-terminated strings stored in the .discard.gendwarfksyms.kabi_rules section. Each rule consists of four strings as follows: "version\0type\0target\0value" The version string ensures the structure can be changed in a backwards compatible way. The type string indicates the type of the rule, and target and value strings contain rule-specific data. Initially support two simple rules: 1. Declaration-only structures A structure declaration can change into a full definition when additional includes are pulled in to the TU, which changes the versions of any symbol that references the struct. Add support for defining declaration-only structs whose definition is not expanded during versioning. 2. Ignored enum fields It's possible to add new enum fields without changing the ABI, but as the fields are included in symbol versioning, this would change the versions. Add support for ignoring specific fields. Add examples for using the rules under the examples/ directory. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/Makefile | 1 + scripts/gendwarfksyms/dwarf.c | 19 +- scripts/gendwarfksyms/examples/kabi.h | 61 ++++++ scripts/gendwarfksyms/examples/kabi_rules.c | 56 +++++ scripts/gendwarfksyms/gendwarfksyms.c | 11 +- scripts/gendwarfksyms/gendwarfksyms.h | 57 ++++++ scripts/gendwarfksyms/kabi.c | 214 ++++++++++++++++++++ 7 files changed, 415 insertions(+), 4 deletions(-) create mode 100644 scripts/gendwarfksyms/examples/kabi.h create mode 100644 scripts/gendwarfksyms/examples/kabi_rules.c create mode 100644 scripts/gendwarfksyms/kabi.c diff --git a/scripts/gendwarfksyms/Makefile b/scripts/gendwarfksyms/Makefile index 6540282dc746..27258c31e839 100644 --- a/scripts/gendwarfksyms/Makefile +++ b/scripts/gendwarfksyms/Makefile @@ -5,6 +5,7 @@ gendwarfksyms-objs +=3D gendwarfksyms.o gendwarfksyms-objs +=3D cache.o gendwarfksyms-objs +=3D die.o gendwarfksyms-objs +=3D dwarf.o +gendwarfksyms-objs +=3D kabi.o gendwarfksyms-objs +=3D symbols.o gendwarfksyms-objs +=3D types.o =20 diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 8d1a7d808413..1af8b44101f7 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -80,11 +80,12 @@ static bool match_export_symbol(struct state *state, Dw= arf_Die *die) return !!state->sym; } =20 -static bool is_declaration(Dwarf_Die *die) +static bool is_declaration(struct die *cache, Dwarf_Die *die) { bool value; =20 - return get_flag_attr(die, DW_AT_declaration, &value) && value; + return (get_flag_attr(die, DW_AT_declaration, &value) && value) || + kabi_is_struct_declonly(cache->fqn); } =20 /* @@ -469,10 +470,11 @@ static void __process_structure_type(struct state *st= ate, struct die *cache, process(cache, " {"); process_linebreak(cache, 1); =20 - is_decl =3D is_declaration(die); + is_decl =3D is_declaration(cache, die); =20 if (!is_decl && state->expand.expand) { cache_mark_expanded(&state->expansion_cache, die->addr); + state->expand.current_fqn =3D cache->fqn; check(process_die_container(state, cache, die, process_func, match_func)); } @@ -505,6 +507,15 @@ static void process_enumerator_type(struct state *stat= e, struct die *cache, { Dwarf_Word value; =20 + if (stable) { + /* Get the fqn before we process anything */ + update_fqn(cache, die); + + if (kabi_is_enumerator_ignored(state->expand.current_fqn, + cache->fqn)) + return; + } + process_list_comma(state, cache); process(cache, "enumerator"); process_fqn(cache, die); @@ -577,6 +588,7 @@ static void state_init(struct state *state) state->expand.expand =3D true; state->expand.ptr_depth =3D 0; state->expand.ptr_expansion_depth =3D 0; + state->expand.current_fqn =3D NULL; hash_init(state->expansion_cache.cache); } =20 @@ -586,6 +598,7 @@ static void expansion_state_restore(struct expansion_st= ate *state, state->expand =3D saved->expand; state->ptr_depth =3D saved->ptr_depth; state->ptr_expansion_depth =3D saved->ptr_expansion_depth; + state->current_fqn =3D saved->current_fqn; } =20 static void expansion_state_save(struct expansion_state *state, diff --git a/scripts/gendwarfksyms/examples/kabi.h b/scripts/gendwarfksyms/= examples/kabi.h new file mode 100644 index 000000000000..c53e8d4a7d2e --- /dev/null +++ b/scripts/gendwarfksyms/examples/kabi.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 Google LLC + * + * Example macros for maintaining kABI stability. + * + * This file is based on android_kabi.h, which has the following notice: + * + * Heavily influenced by rh_kabi.h which came from the RHEL/CENTOS kernel + * and was: + * Copyright (c) 2014 Don Zickus + * Copyright (c) 2015-2018 Jiri Benc + * Copyright (c) 2015 Sabrina Dubroca, Hannes Frederic Sowa + * Copyright (c) 2016-2018 Prarit Bhargava + * Copyright (c) 2017 Paolo Abeni, Larry Woodman + */ + +#ifndef __KABI_H__ +#define __KABI_H__ + +/* Kernel macros for userspace testing. */ +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif +#ifndef __used +#define __used __attribute__((__used__)) +#endif +#ifndef __section +#define __section(section) __attribute__((__section__(section))) +#endif +#ifndef __PASTE +#define ___PASTE(a, b) a##b +#define __PASTE(a, b) ___PASTE(a, b) +#endif +#ifndef __stringify +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) +#endif + +#define __KABI_RULE(hint, target, value) \ + static const char __PASTE(__gendwarfksyms_rule_, \ + __COUNTER__)[] __used __aligned(1) \ + __section(".discard.gendwarfksyms.kabi_rules") =3D \ + "1\0" #hint "\0" #target "\0" #value + +/* + * KABI_USE_ARRAY(fqn) + * Treat the struct fqn as a declaration, i.e. even if a definition + * is available, don't expand the contents. + */ +#define KABI_STRUCT_DECLONLY(fqn) __KABI_RULE(struct_declonly, fqn, ;) + +/* + * KABI_ENUMERATOR_IGNORE(fqn, field) + * When expanding enum fqn, skip the provided field. This makes it + * possible to hide added enum fields from versioning. + */ +#define KABI_ENUMERATOR_IGNORE(fqn, field) \ + __KABI_RULE(enumerator_ignore, fqn, field) + +#endif /* __KABI_H__ */ diff --git a/scripts/gendwarfksyms/examples/kabi_rules.c b/scripts/gendwarf= ksyms/examples/kabi_rules.c new file mode 100644 index 000000000000..446818e67d80 --- /dev/null +++ b/scripts/gendwarfksyms/examples/kabi_rules.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + * + * Examples for kABI rules with --stable. + */ + +/* + * The comments below each example contain the expected gendwarfksyms + * output which can be verified using LLVM's FileCheck tool: + * + * https://llvm.org/docs/CommandGuide/FileCheck.html + * + * RUN: gcc -g -c examples/kabi_rules.c -o examples/kabi_rules.o + * + * Verify --stable output: + * + * RUN: echo -e "ex0\nex1" | \ + * RUN: ./gendwarfksyms --stable --dump-dies \ + * RUN: examples/kabi_rules.o 2>&1 >/dev/null | \ + * RUN: FileCheck examples/kabi_rules.c --check-prefix=3DSTABLE + */ + +#include "kabi.h" + +struct s { + int a; +}; + +KABI_STRUCT_DECLONLY(s); + +struct s e0; + +/* + * STABLE: variable structure_type s { + * STABLE-NEXT: } + */ + +enum e { + A, + B, + C, + D, +}; + +KABI_ENUMERATOR_IGNORE(e, B); +KABI_ENUMERATOR_IGNORE(e, C); + +enum e e1; + +/* + * STABLE: variable enumeration_type e { + * STABLE-NEXT: enumerator A =3D 0 , + * STABLE-NEXT: enumerator D =3D 3 + * STABLE-NEXT: } byte_size(4) + */ diff --git a/scripts/gendwarfksyms/gendwarfksyms.c b/scripts/gendwarfksyms/= gendwarfksyms.c index 7fb17bf81e02..a36f05faae1f 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.c +++ b/scripts/gendwarfksyms/gendwarfksyms.c @@ -25,6 +25,8 @@ int dump_die_map; int dump_types; /* Print out expanded type strings used for symbol versions */ int dump_versions; +/* Support kABI stability features */ +int stable; /* Write a symtypes file */ int symtypes; static const char *symtypes_file; @@ -38,6 +40,7 @@ static void usage(void) " --dump-die-map Print debugging information about die_map c= hanges\n" " --dump-types Dump type strings\n" " --dump-versions Dump expanded type strings used for symbol = versions\n" + " -s, --stable Support kABI stability features\n" " -T, --symtypes file Write a symtypes file\n" " -h, --help Print this message\n" "\n", @@ -97,17 +100,21 @@ int main(int argc, char **argv) { "dump-die-map", 0, &dump_die_map, 1 }, { "dump-types", 0, &dump_types, 1 }, { "dump-versions", 0, &dump_versions, 1 }, + { "stable", 0, NULL, 's' }, { "symtypes", 1, NULL, 'T' }, { "help", 0, NULL, 'h' }, { 0, 0, NULL, 0 } }; =20 - while ((opt =3D getopt_long(argc, argv, "dT:h", opts, NULL)) !=3D EOF) { + while ((opt =3D getopt_long(argc, argv, "dsT:h", opts, NULL)) !=3D EOF) { switch (opt) { case 0: break; case 'd': debug =3D 1; break; + case 's': + stable =3D 1; + break; case 'T': symtypes =3D 1; symtypes_file =3D optarg; @@ -153,6 +160,7 @@ int main(int argc, char **argv) } =20 symbol_read_symtab(fd); + kabi_read_rules(fd); =20 dwfl =3D dwfl_begin(&callbacks); if (!dwfl) { @@ -175,6 +183,7 @@ int main(int argc, char **argv) } =20 dwfl_end(dwfl); + kabi_free(); } =20 if (symfile) diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index db9b4964ed8a..e8fc0caa9856 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -27,6 +27,7 @@ extern int dump_dies; extern int dump_die_map; extern int dump_types; extern int dump_versions; +extern int stable; extern int symtypes; =20 /* @@ -224,6 +225,7 @@ struct expansion_state { bool expand; unsigned int ptr_depth; unsigned int ptr_expansion_depth; + const char *current_fqn; }; =20 struct state { @@ -255,4 +257,59 @@ void process_cu(Dwarf_Die *cudie); =20 void generate_symtypes_and_versions(FILE *file); =20 +/* + * kabi.c + */ + +#define KABI_RULE_SECTION ".discard.gendwarfksyms.kabi_rules" +#define KABI_RULE_VERSION "1" + +/* + * The rule section consists of four null-terminated strings per + * entry: + * + * 1. version + * Entry format version. Must match KABI_RULE_VERSION. + * + * 2. type + * Type of the kABI rule. Must be one of the tags defined below. + * + * 3. target + * Rule-dependent target, typically the fully qualified name of + * the target DIE. + * + * 4. value + * Rule-dependent value. + */ +#define KABI_RULE_MIN_ENTRY_SIZE \ + (/* version\0 */ 2 + /* type\0 */ 2 + /* target\0" */ 2 + \ + /* value\0 */ 2) +#define KABI_RULE_EMPTY_VALUE ";" + +/* + * Rule: struct_declonly + * - For the struct in the target field, treat it as a declaration + * only even if a definition is available. + */ +#define KABI_RULE_TAG_STRUCT_DECLONLY "struct_declonly" + +/* + * Rule: enumerator_ignore + * - For the enum in the target field, ignore the named enumerator + * in the value field. + */ +#define KABI_RULE_TAG_ENUMERATOR_IGNORE "enumerator_ignore" + +enum kabi_rule_type { + KABI_RULE_TYPE_UNKNOWN, + KABI_RULE_TYPE_STRUCT_DECLONLY, + KABI_RULE_TYPE_ENUMERATOR_IGNORE, +}; + +bool kabi_is_enumerator_ignored(const char *fqn, const char *field); +bool kabi_is_struct_declonly(const char *fqn); + +void kabi_read_rules(int fd); +void kabi_free(void); + #endif /* __GENDWARFKSYMS_H */ diff --git a/scripts/gendwarfksyms/kabi.c b/scripts/gendwarfksyms/kabi.c new file mode 100644 index 000000000000..a5414382782c --- /dev/null +++ b/scripts/gendwarfksyms/kabi.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + */ + +#include "gendwarfksyms.h" + +#define RULE_HASH_BITS 10 + +struct rule { + enum kabi_rule_type type; + const char *target; + const char *value; + struct hlist_node hash; +}; + +/* { type, target, value } -> struct rule */ +static HASHTABLE_DEFINE(rules, 1 << RULE_HASH_BITS); + +static inline unsigned int rule_hash(enum kabi_rule_type type, + const char *target, const char *value) +{ + return hash_32(type) ^ hash_str(target) ^ hash_str(value); +} + +static inline unsigned int __rule_hash(const struct rule *rule) +{ + return rule_hash(rule->type, rule->target, rule->value); +} + +static inline const char *get_rule_field(const char **pos, ssize_t *left) +{ + const char *start =3D *pos; + size_t len; + + if (*left <=3D 1) + error("unexpected end of kABI rules"); + + len =3D strnlen(start, *left); + if (!len) + error("empty kABI rule field"); + + len +=3D 1; + *pos +=3D len; + *left -=3D len; + + return start; +} + +void kabi_read_rules(int fd) +{ + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + Elf_Data *rule_data =3D NULL; + Elf_Scn *scn; + Elf *elf; + size_t shstrndx; + const char *rule_str; + ssize_t left; + int i; + + const struct { + enum kabi_rule_type type; + const char *tag; + } rule_types[] =3D { + { + .type =3D KABI_RULE_TYPE_STRUCT_DECLONLY, + .tag =3D KABI_RULE_TAG_STRUCT_DECLONLY, + }, + { + .type =3D KABI_RULE_TYPE_ENUMERATOR_IGNORE, + .tag =3D KABI_RULE_TAG_ENUMERATOR_IGNORE, + }, + }; + + if (!stable) + return; + + if (elf_version(EV_CURRENT) !=3D EV_CURRENT) + error("elf_version failed: %s", elf_errmsg(-1)); + + elf =3D elf_begin(fd, ELF_C_READ_MMAP, NULL); + if (!elf) + error("elf_begin failed: %s", elf_errmsg(-1)); + + if (elf_getshdrstrndx(elf, &shstrndx) < 0) + error("elf_getshdrstrndx failed: %s", elf_errmsg(-1)); + + scn =3D elf_nextscn(elf, NULL); + + while (scn) { + shdr =3D gelf_getshdr(scn, &shdr_mem); + if (shdr) { + const char *sname =3D + elf_strptr(elf, shstrndx, shdr->sh_name); + + if (sname && !strcmp(sname, KABI_RULE_SECTION)) { + rule_data =3D elf_getdata(scn, NULL); + break; + } + } + + scn =3D elf_nextscn(elf, scn); + } + + if (!rule_data) { + debug("kABI rules not found"); + return; + } + + rule_str =3D rule_data->d_buf; + left =3D shdr->sh_size; + + if (left < KABI_RULE_MIN_ENTRY_SIZE) + error("kABI rule section too small: %zd bytes", left); + + if (rule_str[left - 1] !=3D '\0') + error("kABI rules are not null-terminated"); + + while (left > KABI_RULE_MIN_ENTRY_SIZE) { + enum kabi_rule_type type =3D KABI_RULE_TYPE_UNKNOWN; + const char *field; + struct rule *rule; + + /* version */ + field =3D get_rule_field(&rule_str, &left); + + if (strcmp(field, KABI_RULE_VERSION)) + error("unsupported kABI rule version: '%s'", field); + + /* type */ + field =3D get_rule_field(&rule_str, &left); + + for (i =3D 0; i < ARRAY_SIZE(rule_types); i++) { + if (!strcmp(field, rule_types[i].tag)) { + type =3D rule_types[i].type; + break; + } + } + + if (type =3D=3D KABI_RULE_TYPE_UNKNOWN) + error("unsupported kABI rule type: '%s'", field); + + rule =3D xmalloc(sizeof(struct rule)); + + rule->type =3D type; + rule->target =3D xstrdup(get_rule_field(&rule_str, &left)); + rule->value =3D xstrdup(get_rule_field(&rule_str, &left)); + + hash_add(rules, &rule->hash, __rule_hash(rule)); + + debug("kABI rule: type: '%s', target: '%s', value: '%s'", field, + rule->target, rule->value); + } + + if (left > 0) + warn("unexpected data at the end of the kABI rules section"); + + check(elf_end(elf)); +} + +bool kabi_is_struct_declonly(const char *fqn) +{ + struct rule *rule; + + if (!stable) + return false; + if (!fqn || !*fqn) + return false; + + hash_for_each_possible(rules, rule, hash, + rule_hash(KABI_RULE_TYPE_STRUCT_DECLONLY, fqn, + KABI_RULE_EMPTY_VALUE)) { + if (rule->type =3D=3D KABI_RULE_TYPE_STRUCT_DECLONLY && + !strcmp(fqn, rule->target)) + return true; + } + + return false; +} + +bool kabi_is_enumerator_ignored(const char *fqn, const char *field) +{ + struct rule *rule; + + if (!stable) + return false; + if (!fqn || !*fqn || !field || !*field) + return false; + + hash_for_each_possible(rules, rule, hash, + rule_hash(KABI_RULE_TYPE_ENUMERATOR_IGNORE, fqn, + field)) { + if (rule->type =3D=3D KABI_RULE_TYPE_ENUMERATOR_IGNORE && + !strcmp(fqn, rule->target) && !strcmp(field, rule->value)) + return true; + } + + return false; +} + +void kabi_free(void) +{ + struct hlist_node *tmp; + struct rule *rule; + + hash_for_each_safe(rules, rule, tmp, hash) { + free((void *)rule->target); + free((void *)rule->value); + free(rule); + } + + hash_init(rules); +} --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (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 B375C1A0712 for ; Mon, 23 Sep 2024 18:19:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115578; cv=none; b=sNMIYa+XrccwwBgHLZIvU2uk4YqdpYV8uiivUEf7/P/lvOLeG6TwpIOn/tU+c25EcRtwg7SPzRsta5hDfeWO884IM3K1mF50mcbm35kRvzt3chsAUCML+nwkImf/zQiYoMebtSYQy0d6Z63kO/JKAv1IiQ+uLP9VYuEOwpIVX1w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115578; c=relaxed/simple; bh=MJID5O+FzfZkOVxedfx+eaCetdeDBfP/Hy3Clv0Yji4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=gNh82njorJMLywg2Jd3iZ+ijVU+cOqvSlfwRoH3U3C0xoPJWMwD+PPsv28gj8jzrYkNXRwyK3XxhIBcAv/h99vI2i7RhdgA1/EnPXNLBJVwg3rMUXT/dSvY/OYhkaXLeNQiGjMC3N0sLOk7TnHUDulkKHLn4t25DyPOtqwylRps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=CskNUsUB; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="CskNUsUB" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-6e20b046922so113437b3.1 for ; Mon, 23 Sep 2024 11:19:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115575; x=1727720375; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=2g/K+1OKaZip03MKPf08zcf09HdsvREemzVLMX0O8ec=; b=CskNUsUBtj68a9bpoC0r1Blccw3f1Uwvwh68mquaey/mziWIW3+HzgO71N700Dg/di CFbeIJvQPx3A9+VdsF+3G1QFBNa3ANnbf6GXXUFpzJBxtPPjAtrQooCi8tkFXGG99uef d6Y5kdqZpHYlZHiQ9MaO6tk18xhD6D3KBdH0ypQFYGaWIu/lwW7+ROyqIoKCfETiOzq2 nAld9eC098BniPNr3tnrLb8dMrKKNoyDztCf4XAbP1u1drQ6mDyWG8CIB8Namxe52P5O oFL9MuSYFWFM2ol7y7gYFXrz0/PSarYdggPFfNNu8VU4VFBYCsJkoLO6QmdWZx9ilsCf j7hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115575; x=1727720375; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=2g/K+1OKaZip03MKPf08zcf09HdsvREemzVLMX0O8ec=; b=o7iKzCswvgDVzkTp4zWvqy8VWX/9UvHiIQNCaYM3ybhbUquR0cotYLACjv0nuI0kOG Pkndj/OqszZz171UzMkN6sx/whCagwiECR0WjvMj3vDArfdPCsdJV6bxA6+tXWTzQlul LYdukpcocckLW1xOvw8atvaIwn/IAlB27hieddMARB2wNSEBHGygPnn2f+keChd72GDM zqTVVB4/qbpJYfXHFPKCZ28e1DupKUwrhhjk710PE4tsa7+3nmJkLPJHvRvzzjquIJu+ t3OVgpCUBWSIDrWItNkJwVqrTN1acyhvD2PPc0T4HCvdwsYTmrkv69uQFRhwE1Ntwos4 nmiA== X-Forwarded-Encrypted: i=1; AJvYcCVodqoDfLuhM9YEcApdPlyY2ET7yULGzQOcVQksnphKs/kve5KQHAZIA5KprqfDzHujQlxgVqKHr5/6Hhc=@vger.kernel.org X-Gm-Message-State: AOJu0YyOFiN7FO5fAc6H//gO5+pX1ZWGSqqaRF0lxl/rd6VgOMJN2nx5 k4PhllfvLHviKrAbUUNEhm5O5+8V09hKyFvVq56L2SYCZ74r7wAkBOk7+jDPExkUj0uhSHjzL4Y eIRhWfKu+oINksZ8FMxU90ELUZA== X-Google-Smtp-Source: AGHT+IHh6toLov+le4Wgd5NDx29UZu99lu6fwpaXycA78MWmvX88V1cjai42zrEs8Snlu1MHYM0ssL5ax3dVXY7ToI0= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a81:c94c:0:b0:6db:c6d8:59f with SMTP id 00721157ae682-6dfeea04714mr202467b3.0.1727115574642; Mon, 23 Sep 2024 11:19:34 -0700 (PDT) Date: Mon, 23 Sep 2024 18:19:02 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=23468; i=samitolvanen@google.com; h=from:subject; bh=MJID5O+FzfZkOVxedfx+eaCetdeDBfP/Hy3Clv0Yji4=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/LFbJ8mYT1hYsA0sWc2nk7cT6J2z0w7GyqbUbz48 Lvgz047OkpZGMQ4GGTFFFlavq7euvu7U+qrz0USMHNYmUCGMHBxCsBEqnMZ/sfnh6pL/briov05 Uyh4q3B2p/HS1YUuvU3OujMefK+YqszwP033uRJ7340wC81Azu068ewMjXLCemLnzi4UdHik2rW AEwA= X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-38-samitolvanen@google.com> Subject: [PATCH v3 16/20] gendwarfksyms: Add support for reserved and ignored fields From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Distributions that want to maintain a stable kABI need the ability to make ABI compatible changes to kernel data structures without affecting symbol versions, either because of LTS updates or backports. With genksyms, developers would typically hide these changes from version calculation with #ifndef __GENKSYMS__, which would result in the symbol version not changing even though the actual type has changed. When we process precompiled object files, this isn't an option. Change union processing to recognize field name prefixes that allow the user to ignore the union completely during symbol versioning with a __kabi_ignored prefix in a field name, or to replace the type of a placeholder field using a __kabi_reserved field name prefix. For example, assume we want to add a new field to an existing alignment hole in a data structure, and ignore the new field when calculating symbol versions: struct struct1 { int a; /* a 4-byte alignment hole */ unsigned long b; }; To add `int n` to the alignment hole, we can add a union that includes a __kabi_ignored field that causes gendwarfksyms to ignore the entire union: struct struct1 { int a; union { char __kabi_ignored_0; int n; }; unsigned long b; }; With --stable, both structs produce the same symbol version. Alternatively, when a distribution expects future modification to a data structure, they can explicitly add reserved fields: struct struct2 { long a; long __kabi_reserved_0; /* reserved for future use */ }; To take the field into use, we can again replace it with a union, with one of the fields keeping the __kabi_reserved name prefix to indicate the original type: struct struct2 { long a; union { long __kabi_reserved_0; struct { int b; int v; }; }; Here gendwarfksyms --stable replaces the union with the type of the placeholder field when calculating versions. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/dwarf.c | 202 +++++++++++++++++++++- scripts/gendwarfksyms/examples/kabi.h | 80 +++++++++ scripts/gendwarfksyms/examples/kabi_ex0.c | 86 +++++++++ scripts/gendwarfksyms/examples/kabi_ex1.c | 89 ++++++++++ scripts/gendwarfksyms/examples/kabi_ex2.c | 98 +++++++++++ scripts/gendwarfksyms/gendwarfksyms.h | 29 ++++ 6 files changed, 583 insertions(+), 1 deletion(-) create mode 100644 scripts/gendwarfksyms/examples/kabi_ex0.c create mode 100644 scripts/gendwarfksyms/examples/kabi_ex1.c create mode 100644 scripts/gendwarfksyms/examples/kabi_ex2.c diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 1af8b44101f7..f11cafa69309 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -306,6 +306,9 @@ static void __process_list_type(struct state *state, st= ruct die *cache, { const char *name =3D get_name_attr(die); =20 + if (stable && is_kabi_prefix(name)) + name =3D NULL; + process_list_comma(state, cache); process(cache, type); process_type_attr(state, cache, die); @@ -438,11 +441,193 @@ static void process_variant_part_type(struct state *= state, struct die *cache, process(cache, "}"); } =20 +static int get_kabi_status(Dwarf_Die *die) +{ + const char *name =3D get_name_attr(die); + + if (is_kabi_prefix(name)) { + name +=3D KABI_PREFIX_LEN; + + if (!strncmp(name, KABI_RESERVED_PREFIX, + KABI_RESERVED_PREFIX_LEN)) + return KABI_RESERVED; + if (!strncmp(name, KABI_IGNORED_PREFIX, + KABI_IGNORED_PREFIX_LEN)) + return KABI_IGNORED; + } + + return KABI_NORMAL; +} + +static int check_struct_member_kabi_status(struct state *state, + struct die *__unused, Dwarf_Die *die) +{ + int res; + + if (dwarf_tag(die) !=3D DW_TAG_member_type) + error("expected a member"); + + /* + * If the union member is a struct, expect the __kabi field to + * be the first member of the structure, i.e..: + * + * union { + * type new_member; + * struct { + * type __kabi_field; + * } + * }; + */ + res =3D get_kabi_status(die); + + if (res =3D=3D KABI_RESERVED && + !get_ref_die_attr(die, DW_AT_type, &state->kabi.placeholder)) + error("structure member missing a type?"); + + return res; +} + +static int check_union_member_kabi_status(struct state *state, + struct die *__unused, Dwarf_Die *die) +{ + Dwarf_Die type; + int res; + + if (dwarf_tag(die) !=3D DW_TAG_member_type) + error("expected a member"); + + if (!get_ref_die_attr(die, DW_AT_type, &type)) + error("union member missing a type?"); + + /* + * We expect a union with two members. Check if either of them + * has a __kabi name prefix, i.e.: + * + * union { + * ... + * type memberN; // <- type, N =3D {0,1} + * ... + * }; + * + * The member can also be a structure type, in which case we'll + * check the first structure member. + * + * In any case, stop processing after we've seen two members. + */ + res =3D get_kabi_status(die); + + if (res =3D=3D KABI_RESERVED) + state->kabi.placeholder =3D type; + if (res !=3D KABI_NORMAL) + return res; + + if (dwarf_tag(&type) =3D=3D DW_TAG_structure_type) + res =3D checkp(process_die_container( + state, NULL, &type, check_struct_member_kabi_status, + match_member_type)); + + if (res <=3D KABI_NORMAL && ++state->kabi.members < 2) + return 0; /* Continue */ + + return res; +} + +static int get_union_kabi_status(Dwarf_Die *die, Dwarf_Die *placeholder) +{ + struct state state; + int res; + + if (!stable) + return KABI_NORMAL; + + /* + * To maintain a stable kABI, distributions may choose to reserve + * space in structs for later use by adding placeholder members, + * for example: + * + * struct s { + * u32 a; + * // an 8-byte placeholder for future use + * u64 __kabi_reserved_0; + * }; + * + * When the reserved member is taken into use, the type change + * would normally cause the symbol version to change as well, but + * if the replacement uses the following convention, gendwarfksyms + * continues to use the placeholder type for versioning instead, + * thus maintaining the same symbol version: + * + * struct s { + * u32 a; + * union { + * // placeholder replaced with a new member `b` + * struct t b; + * struct { + * // the placeholder type that is still + * // used for versioning + * u64 __kabi_reserved_0; + * }; + * }; + * }; + * + * I.e., as long as the replaced member is in a union, and the + * placeholder has a __kabi_reserved name prefix, we'll continue + * to use the placeholder type (here u64) for version calculation + * instead of the union type. + * + * It's also possible to ignore new members from versioning if + * they've been added to alignment holes, for example, by + * including them in a union with another member that uses the + * __kabi_ignored name prefix: + * + * struct s { + * u32 a; + * // an alignment hole is used to add `n` + * union { + * u32 n; + * // hide the entire union member from versioning + * u8 __kabi_ignored_0; + * }; + * u64 b; + * }; + * + * Note that the user of this feature is responsible for ensuring + * that the structure actually remains ABI compatible. + */ + state.kabi.members =3D 0; + + res =3D checkp(process_die_container(&state, NULL, die, + check_union_member_kabi_status, + match_member_type)); + + if (placeholder && res =3D=3D KABI_RESERVED) + *placeholder =3D state.kabi.placeholder; + + return res; +} + +static bool is_kabi_ignored(Dwarf_Die *die) +{ + Dwarf_Die type; + + if (!stable) + return false; + + if (!get_ref_die_attr(die, DW_AT_type, &type)) + error("member missing a type?"); + + return dwarf_tag(&type) =3D=3D DW_TAG_union_type && + checkp(get_union_kabi_status(&type, NULL)) =3D=3D KABI_IGNORED; +} + static int ___process_structure_type(struct state *state, struct die *cach= e, Dwarf_Die *die) { switch (dwarf_tag(die)) { case DW_TAG_member: + if (is_kabi_ignored(die)) + return 0; + return check(process_type(state, cache, die)); case DW_TAG_variant_part: return check(process_type(state, cache, die)); case DW_TAG_class_type: @@ -500,7 +685,22 @@ static void __process_structure_type(struct state *sta= te, struct die *cache, =20 DEFINE_PROCESS_STRUCTURE_TYPE(class) DEFINE_PROCESS_STRUCTURE_TYPE(structure) -DEFINE_PROCESS_STRUCTURE_TYPE(union) + +static void process_union_type(struct state *state, struct die *cache, + Dwarf_Die *die) +{ + Dwarf_Die placeholder; + + int res =3D checkp(get_union_kabi_status(die, &placeholder)); + + if (res =3D=3D KABI_RESERVED) + check(process_type(state, cache, &placeholder)); + if (res > KABI_NORMAL) + return; + + __process_structure_type(state, cache, die, "union_type", + ___process_structure_type, match_all); +} =20 static void process_enumerator_type(struct state *state, struct die *cache, Dwarf_Die *die) diff --git a/scripts/gendwarfksyms/examples/kabi.h b/scripts/gendwarfksyms/= examples/kabi.h index c53e8d4a7d2e..ec99c2fb9e96 100644 --- a/scripts/gendwarfksyms/examples/kabi.h +++ b/scripts/gendwarfksyms/examples/kabi.h @@ -43,6 +43,28 @@ __section(".discard.gendwarfksyms.kabi_rules") =3D \ "1\0" #hint "\0" #target "\0" #value =20 +#define __KABI_NORMAL_SIZE_ALIGN(_orig, _new) = \ + union { = \ + _Static_assert( = \ + sizeof(struct { _new; }) <=3D sizeof(struct { _orig; }), \ + __FILE__ ":" __stringify(__LINE__) ": " __stringify( \ + _new) " is larger than " __stringify(_orig)); \ + _Static_assert( = \ + __alignof__(struct { _new; }) <=3D \ + __alignof__(struct { _orig; }), \ + __FILE__ ":" __stringify(__LINE__) ": " __stringify( \ + _orig) " is not aligned the same as " __stringify(_new)); \ + } + +#define __KABI_REPLACE(_orig, _new) \ + union { \ + _new; \ + struct { \ + _orig; \ + }; \ + __KABI_NORMAL_SIZE_ALIGN(_orig, _new); \ + } + /* * KABI_USE_ARRAY(fqn) * Treat the struct fqn as a declaration, i.e. even if a definition @@ -58,4 +80,62 @@ #define KABI_ENUMERATOR_IGNORE(fqn, field) \ __KABI_RULE(enumerator_ignore, fqn, field) =20 +/* + * KABI_RESERVE + * Reserve some "padding" in a structure for use by LTS backports. + * This normally placed at the end of a structure. + * number: the "number" of the padding variable in the structure. Start= with + * 1 and go up. + */ +#define KABI_RESERVE(n) unsigned long __kabi_reserved##n + +/* + * KABI_RESERVE_ARRAY + * Same as _BACKPORT_RESERVE but allocates an array with the specified + * size in bytes. + */ +#define KABI_RESERVE_ARRAY(n, s) \ + unsigned char __aligned(8) __kabi_reserved##n[s] + +/* + * KABI_IGNORE + * Add a new field that's ignored in versioning. + */ +#define KABI_IGNORE(n, _new) \ + union { \ + _new; \ + unsigned char __kabi_ignored##n; \ + } + +/* + * KABI_USE(number, _new) + * Use a previous padding entry that was defined with KABI_RESERVE + * number: the previous "number" of the padding variable + * _new: the variable to use now instead of the padding variable + */ +#define KABI_USE(number, _new) __KABI_REPLACE(KABI_RESERVE(number), _new) + +/* + * KABI_USE2(number, _new1, _new2) + * Use a previous padding entry that was defined with KABI_RESERVE for + * two new variables that fit into 64 bits. This is good for when you d= o not + * want to "burn" a 64bit padding variable for a smaller variable size i= f not + * needed. + */ +#define KABI_USE2(number, _new1, _new2) \ + __KABI_REPLACE( \ + KABI_RESERVE(number), struct { \ + _new1; \ + _new2; \ + }) +/* + * KABI_USE_ARRAY(number, bytes, _new) + * Use a previous padding entry that was defined with KABI_RESERVE_ARRAY + * number: the previous "number" of the padding variable + * bytes: the size in bytes reserved for the array + * _new: the variable to use now instead of the padding variable + */ +#define KABI_USE_ARRAY(number, bytes, _new) \ + __KABI_REPLACE(KABI_RESERVE_ARRAY(number, bytes), _new) + #endif /* __KABI_H__ */ diff --git a/scripts/gendwarfksyms/examples/kabi_ex0.c b/scripts/gendwarfks= yms/examples/kabi_ex0.c new file mode 100644 index 000000000000..934324cba837 --- /dev/null +++ b/scripts/gendwarfksyms/examples/kabi_ex0.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * kabi_ex0.c + * + * Copyright (C) 2024 Google LLC + * + * Reserved and ignored data structure field examples with --stable. + */ + +/* + * The comments below each example contain the expected gendwarfksyms + * output, which can be verified using LLVM's FileCheck tool: + * + * https://llvm.org/docs/CommandGuide/FileCheck.html + * + * $ gcc -g -c examples/kabi_ex0.c examples/kabi_ex0.o + * + * Verify --stable output: + * + * $ echo -e "ex0a\nex0b\nex0c" | \ + * ./gendwarfksyms --stable --dump-dies \ + * examples/kabi_ex0.o 2>&1 >/dev/null | \ + * FileCheck examples/kabi_ex0.c --check-prefix=3DSTABLE + * + * Verify that symbol versions match with --stable: + * + * $ echo -e "ex0a\nex0b\nex0c" | \ + * ./gendwarfksyms --stable examples/kabi_ex0.o | \ + * sort | \ + * FileCheck examples/kabi_ex0.c --check-prefix=3DVERSION + */ + +#include "kabi.h" + +/* + * Example 0: Reserved fields. + */ + +struct { + int a; + KABI_RESERVE(0); + KABI_RESERVE(1); +} ex0a; + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_mem= ber_location(0) , + * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long= ]] byte_size(8) encoding(7) data_member_location(8) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data= _member_location(16) + * STABLE-NEXT: } byte_size(24) + * + * VERSION-DAG: #SYMVER ex0a 0x[[#%.08x,EX0:]] + */ + +struct { + int a; + KABI_RESERVE(0); + KABI_USE2(1, int b, int c); +} ex0b; + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_mem= ber_location(0) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data= _member_location(8) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data= _member_location(16) + * + * STABLE-NEXT: } byte_size(24) + * + * VERSION-DAG: #SYMVER ex0b 0x[[#%.08x,EX0]] + */ + +struct { + int a; + KABI_USE(0, void *p); + KABI_USE2(1, int b, int c); +} ex0c; + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_mem= ber_location(0) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data= _member_location(8) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data= _member_location(16) + * STABLE-NEXT: } byte_size(24) + * + * VERSION-DAG: #SYMVER ex0c 0x[[#%.08x,EX0]] + */ diff --git a/scripts/gendwarfksyms/examples/kabi_ex1.c b/scripts/gendwarfks= yms/examples/kabi_ex1.c new file mode 100644 index 000000000000..7bc34bc7dec8 --- /dev/null +++ b/scripts/gendwarfksyms/examples/kabi_ex1.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * kabi_ex1.c + * + * Copyright (C) 2024 Google LLC + * + * Reserved and ignored data structure field examples with --stable. + */ + +/* + * The comments below each example contain the expected gendwarfksyms + * output, which can be verified using LLVM's FileCheck tool: + * + * https://llvm.org/docs/CommandGuide/FileCheck.html + * + * $ gcc -g -c examples/kabi_ex1.c examples/kabi_ex1.o + * + * Verify --stable output: + * + * $ echo -e "ex1a\nex1b\nex1c" | \ + * ./gendwarfksyms --stable --dump-dies \ + * examples/kabi_ex1.o 2>&1 >/dev/null | \ + * FileCheck examples/kabi_ex1.c --check-prefix=3DSTABLE + * + * Verify that symbol versions match with --stable: + * + * $ echo -e "ex1a\nex1b\nex1c" | \ + * ./gendwarfksyms --stable examples/kabi_ex1.o | \ + * sort | \ + * FileCheck examples/kabi_ex1.c --check-prefix=3DVERSION + */ + +#include "kabi.h" + +/* + * Example 1: A reserved array. + */ + +struct { + unsigned int a; + KABI_RESERVE_ARRAY(0, 64); +} ex1a; + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a= data_member_location(0) , + * STABLE-NEXT: member array_type[64] { + * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) + * STABLE-NEXT: } data_member_location(8) + * STABLE-NEXT: } byte_size(72) + * + * VERSION-DAG: #SYMVER ex1a 0x[[#%.08x,EX1:]] + */ + +struct { + unsigned int a; + KABI_USE_ARRAY( + 0, 64, struct { + void *p; + KABI_RESERVE_ARRAY(1, 56); + }); +} ex1b; + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a= data_member_location(0) , + * STABLE-NEXT: member array_type[64] { + * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) + * STABLE-NEXT: } data_member_location(8) + * STABLE-NEXT: } byte_size(72) + * + * VERSION-DAG: #SYMVER ex1b 0x[[#%.08x,EX1]] + */ + +struct { + unsigned int a; + KABI_USE_ARRAY(0, 64, void *p[8]); +} ex1c; + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a= data_member_location(0) , + * STABLE-NEXT: member array_type[64] { + * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) + * STABLE-NEXT: } data_member_location(8) + * STABLE-NEXT: } byte_size(72) + * + * VERSION-DAG: #SYMVER ex1c 0x[[#%.08x,EX1]] + */ diff --git a/scripts/gendwarfksyms/examples/kabi_ex2.c b/scripts/gendwarfks= yms/examples/kabi_ex2.c new file mode 100644 index 000000000000..947ea5675b4f --- /dev/null +++ b/scripts/gendwarfksyms/examples/kabi_ex2.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * kabi_ex2.c + * + * Copyright (C) 2024 Google LLC + * + * Reserved and ignored data structure field examples with --stable. + */ + +/* + * The comments below each example contain the expected gendwarfksyms + * output, which can be verified using LLVM's FileCheck tool: + * + * https://llvm.org/docs/CommandGuide/FileCheck.html + * + * $ gcc -g -c examples/kabi_ex2.c examples/kabi_ex2.o + * + * Verify --stable output: + * + * $ echo -e "ex2a\nex2b\nex2c" | \ + * ./gendwarfksyms --stable --dump-dies \ + * examples/kabi_ex2.o 2>&1 >/dev/null | \ + * FileCheck examples/kabi_ex2.c --check-prefix=3DSTABLE + * + * Verify that symbol versions match with --stable: + * + * $ echo -e "ex2a\nex2b\nex2c" | \ + * ./gendwarfksyms --stable examples/kabi_ex2.o | \ + * sort | \ + * FileCheck examples/kabi_ex2.c --check-prefix=3DVERSION + */ + +#include "kabi.h" + +/* + * Example 2: An ignored field added to an alignment hole. + */ + +struct { + int a; + unsigned long b; + int c; + unsigned long d; +} ex2a; + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_mem= ber_location(0) , + * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long= ]] byte_size(8) encoding(7) b data_member_location(8) + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_mem= ber_location(16) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d da= ta_member_location(24) + * STABLE-NEXT: } byte_size(32) + * + * VERSION-DAG: #SYMVER ex2a 0x[[#%.08x,EX2:]] + */ + +struct { + int a; + KABI_IGNORE(0, unsigned int n); + unsigned long b; + int c; + unsigned long d; +} ex2b; + +_Static_assert(sizeof(ex2a) =3D=3D sizeof(ex2b), "ex2a size doesn't match = ex2b"); + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_mem= ber_location(0) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b da= ta_member_location(8) + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_mem= ber_location(16) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d da= ta_member_location(24) + * STABLE-NEXT: } byte_size(32) + * + * VERSION-DAG: #SYMVER ex2b 0x[[#%.08x,EX2]] + */ + +struct { + int a; + KABI_IGNORE(0, unsigned int n); + unsigned long b; + int c; + KABI_IGNORE(1, unsigned int m); + unsigned long d; +} ex2c; + +_Static_assert(sizeof(ex2a) =3D=3D sizeof(ex2c), "ex2a size doesn't match = ex2c"); + +/* + * STABLE: variable structure_type { + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_mem= ber_location(0) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b da= ta_member_location(8) + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_mem= ber_location(16) , + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d da= ta_member_location(24) + * STABLE-NEXT: } byte_size(32) + * + * VERSION-DAG: #SYMVER ex2c 0x[[#%.08x,EX2]] + */ diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index e8fc0caa9856..7a927e55f567 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -221,6 +221,20 @@ void cache_clear_expanded(struct expansion_cache *ec); /* * dwarf.c */ + +/* See dwarf.c:get_union_kabi_status */ +#define KABI_PREFIX "__kabi_" +#define KABI_PREFIX_LEN (sizeof(KABI_PREFIX) - 1) +#define KABI_RESERVED_PREFIX "reserved" +#define KABI_RESERVED_PREFIX_LEN (sizeof(KABI_RESERVED_PREFIX) - 1) +#define KABI_IGNORED_PREFIX "ignored" +#define KABI_IGNORED_PREFIX_LEN (sizeof(KABI_IGNORED_PREFIX) - 1) + +static inline bool is_kabi_prefix(const char *name) +{ + return name && !strncmp(name, KABI_PREFIX, KABI_PREFIX_LEN); +} + struct expansion_state { bool expand; unsigned int ptr_depth; @@ -228,6 +242,18 @@ struct expansion_state { const char *current_fqn; }; =20 +enum kabi_status { + /* >0 to stop DIE processing */ + KABI_NORMAL =3D 1, + KABI_RESERVED, + KABI_IGNORED, +}; + +struct kabi_state { + int members; + Dwarf_Die placeholder; +}; + struct state { struct symbol *sym; Dwarf_Die die; @@ -238,6 +264,9 @@ struct state { /* Structure expansion */ struct expansion_state expand; struct expansion_cache expansion_cache; + + /* Reserved or ignored members */ + struct kabi_state kabi; }; =20 typedef int (*die_callback_t)(struct state *state, struct die *cache, --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yb1-f202.google.com (mail-yb1-f202.google.com [209.85.219.202]) (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 5C3321A4B8F for ; Mon, 23 Sep 2024 18:19:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115579; cv=none; b=L5koJui2u4/rbpjfGh8zScextJ4qW/k81GxB0CPqDLW7duxAEwz+I2KcBXGT1wsJDhUICZMEI6/qFCbA2U+7A/2jEPuZkddDq1jx7NARrN050ewi+vyypM5+i8Hw++RVlX/5uSqkEB6qbv6lKoOUTV9Lac6tq+XY4swJaROCSYM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115579; c=relaxed/simple; bh=laL39BCEF1vO4bPX+whfqr94UBUcQ7hjGSB8gg4m9nA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dPOWG+P4k/zLQsZfaSno00Un8lw4lp08SCw1vaBQKeKyz0NLF4l7SmfAlP093eb01GPFqXettWAuvD17xt2yr3g93jWxHS262jCb1bP0oWqDwvny4GzZYeLDgc9VWE+f4nvZPDpFeBSCsQJe4YgV2yPW8xim5A9eh+GJus5Ye1g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Ri6gpi58; arc=none smtp.client-ip=209.85.219.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Ri6gpi58" Received: by mail-yb1-f202.google.com with SMTP id 3f1490d57ef6-e1cfb9d655eso6806352276.0 for ; Mon, 23 Sep 2024 11:19:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115576; x=1727720376; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=kkPce0rZ8yrGArv9CTYYGTdGaCslopSteUVWh/sw0Jc=; b=Ri6gpi58TBoG5X1FIMhiodcXkZHh4eZaVklV08r+vajw+VEE0J0byWR3smK9RrUv7+ hRhiu66PLhBGwl1pVr3yqrXvPZGrmbwIaAte05OMkgx5RqZFo705Tej4LQpassTu8RYg Uyz2nJe99yg69cqr2soENTow00KdotvCTO3kPDenO8uDLw1jM5XFNwUNIBXwxhVpQt+d USrI+4m+OnpbAfFaycUMyYiUFWxk0EggScDpwUtoY0ymqZMYtqBZm6WFnZl30j2vPZI+ XoJ74wsr6hOHv/sdFzURIkZWT4fylsLmUR+cq+HF845LlYTD2cUPqOkEhG5OX0ROSBgS 3kFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115576; x=1727720376; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=kkPce0rZ8yrGArv9CTYYGTdGaCslopSteUVWh/sw0Jc=; b=gHMLX+qRz6bxVlCBBQ9EmWIZnNdWmZeFLuy0D+m78E8TeichU9qUEHdh2ln4zolrGz irJrav5vw2Veo9xPZQtMLEdgA1MATEiFbur7yImn5JSGJ8Bn1QXqkqUFRy48WUGD6m1S 1TVBvcaEYzfJqbhU6ImbNja2ffO2zkEH+ppGbLPXVFM5E+YLUwYvRXuINYTomnaI531I GNEF1/ZV0/QWK/mSaEgkgMmsK9fHe1PzfC1U3HlFOy7Fy3OZHpCAnOwuQ8TZt9Mduf2C onnbIKPMvRUjYwMT4i3ZehE0gXTyLwbqvL2jkonV6kmDWfVzzCJuesVhAxeXG0TBaghP G7eA== X-Forwarded-Encrypted: i=1; AJvYcCXRMKsVwKazDKpiJTsygn3Wc9KEqCNJdJjShWMpN7jcj3QPc6qF/tWH6v13bsYYyOPlwGzSvy6dwK4QnEI=@vger.kernel.org X-Gm-Message-State: AOJu0Ywhfwac1rmUA30fTPBlOGse9hcjUwTGRh6pv5jSgJ/N9iLgdmgM 2h+JNoAl9r2JZx6q9SJUL6wvl60QRX/v5SEDGHWo2osje0gXtZtvTI2nscAXw/liZHbG9AxnN1M PKmubfrzUmOl3qRMKtGPsgWNbKg== X-Google-Smtp-Source: AGHT+IFpJAOnY2xEvQeJy6OEMCEWO2JQSZDOv+6UB6KUd6XvMz5bKLXgxnuuCaeF+f8dJzr1U88mT4tMwf6IJJcQk20= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a05:6902:68d:b0:e20:1596:87b8 with SMTP id 3f1490d57ef6-e2252fd9b4dmr122835276.11.1727115576387; Mon, 23 Sep 2024 11:19:36 -0700 (PDT) Date: Mon, 23 Sep 2024 18:19:03 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=7756; i=samitolvanen@google.com; h=from:subject; bh=laL39BCEF1vO4bPX+whfqr94UBUcQ7hjGSB8gg4m9nA=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/L9rnt4ZUUhk7u+efx1UcVeU6XZL74WmFjocyg/1 tH0aZ3aUcrCIMbBICumyNLydfXW3d+dUl99LpKAmcPKBDKEgYtTACYSasvI8E8m7WJ8zRduq89m Bl5c/w5bPPK87yBWs2f6r7U/Dj9ON2dkeD/JsmPW35cmORuEnU55Tal+Yjv/8l7xrTu2Lvhoen9 RIgcA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-39-samitolvanen@google.com> Subject: [PATCH v3 17/20] gendwarfksyms: Add support for symbol type pointers From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The compiler may choose not to emit type information in DWARF for external symbols. Clang, for example, does this for symbols not defined in the current TU. To provide a way to work around this issue, add support for __gendwarfksyms_ptr_ pointers that force the compiler to emit the necessary type information in DWARF also for the missing symbols. Example usage: #define GENDWARFKSYMS_PTR(sym) \ static typeof(sym) *__gendwarfksyms_ptr_##sym __used \ __section(".discard.gendwarfksyms") =3D &sym; extern int external_symbol(void); GENDWARFKSYMS_PTR(external_symbol); Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- scripts/gendwarfksyms/dwarf.c | 55 +++++++++++++++++++++- scripts/gendwarfksyms/examples/symbolptr.c | 29 ++++++++++++ scripts/gendwarfksyms/gendwarfksyms.h | 7 +++ scripts/gendwarfksyms/symbols.c | 27 +++++++++++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 scripts/gendwarfksyms/examples/symbolptr.c diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index f11cafa69309..c2ce66e4e333 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c @@ -989,6 +989,31 @@ static void process_variable(struct state *state, Dwar= f_Die *die) process_symbol(state, die, __process_variable); } =20 +static void save_symbol_ptr(struct state *state) +{ + Dwarf_Die ptr_type; + Dwarf_Die type; + + if (!get_ref_die_attr(&state->die, DW_AT_type, &ptr_type) || + dwarf_tag(&ptr_type) !=3D DW_TAG_pointer_type) + error("%s must be a pointer type!", + get_symbol_name(&state->die)); + + if (!get_ref_die_attr(&ptr_type, DW_AT_type, &type)) + error("%s pointer missing a type attribute?", + get_symbol_name(&state->die)); + + /* + * Save the symbol pointer DIE in case the actual symbol is + * missing from the DWARF. Clang, for example, intentionally + * omits external symbols from the debugging information. + */ + if (dwarf_tag(&type) =3D=3D DW_TAG_subroutine_type) + symbol_set_ptr(state->sym, &type); + else + symbol_set_ptr(state->sym, &ptr_type); +} + static int process_exported_symbols(struct state *unused, struct die *cach= e, Dwarf_Die *die) { @@ -1012,7 +1037,9 @@ static int process_exported_symbols(struct state *unu= sed, struct die *cache, =20 state_init(&state); =20 - if (tag =3D=3D DW_TAG_subprogram) + if (is_symbol_ptr(get_symbol_name(&state.die))) + save_symbol_ptr(&state); + else if (tag =3D=3D DW_TAG_subprogram) process_subprogram(&state, &state.die); else process_variable(&state, &state.die); @@ -1025,8 +1052,34 @@ static int process_exported_symbols(struct state *un= used, struct die *cache, } } =20 +static void process_symbol_ptr(struct symbol *sym, void *arg) +{ + struct state state; + Dwarf *dwarf =3D arg; + + if (sym->state !=3D SYMBOL_UNPROCESSED || !sym->ptr_die_addr) + return; + + debug("%s", sym->name); + state_init(&state); + state.sym =3D sym; + + if (!dwarf_die_addr_die(dwarf, (void *)sym->ptr_die_addr, &state.die)) + error("dwarf_die_addr_die failed for symbol ptr: '%s'", + sym->name); + + if (dwarf_tag(&state.die) =3D=3D DW_TAG_subroutine_type) + process_subprogram(&state, &state.die); + else + process_variable(&state, &state.die); + + cache_clear_expanded(&state.expansion_cache); +} + void process_cu(Dwarf_Die *cudie) { check(process_die_container(NULL, NULL, cudie, process_exported_symbols, match_all)); + + symbol_for_each(process_symbol_ptr, dwarf_cu_getdwarf(cudie->cu)); } diff --git a/scripts/gendwarfksyms/examples/symbolptr.c b/scripts/gendwarfk= syms/examples/symbolptr.c new file mode 100644 index 000000000000..c808f07d8268 --- /dev/null +++ b/scripts/gendwarfksyms/examples/symbolptr.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Google LLC + * + * Example for symbol pointers. When compiled with Clang, gendwarfkyms + * uses a symbol pointer for `f`. + * + * $ clang -g -c examples/symbolptr.c examples/symbolptr.o + * $ echo -e "f\ng" | ./gendwarfksyms -d examples/symbolptr.o + */ + +/* Kernel macros for userspace testing. */ +#ifndef __used +#define __used __attribute__((__used__)) +#endif +#ifndef __section +#define __section(section) __attribute__((__section__(section))) +#endif + +#define __GENDWARFKSYMS_EXPORT(sym) \ + static typeof(sym) *__gendwarfksyms_ptr_##sym __used \ + __section(".discard.gendwarfksyms") =3D &sym; + +extern void f(int *arg); +void g(int *arg); +void g(int *arg) {} + +__GENDWARFKSYMS_EXPORT(f); +__GENDWARFKSYMS_EXPORT(g); diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/= gendwarfksyms.h index 7a927e55f567..b3bfb25d3313 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -92,6 +92,10 @@ extern int symtypes; * symbols.c */ =20 +/* See symbols.c:is_symbol_ptr */ +#define SYMBOL_PTR_PREFIX "__gendwarfksyms_ptr_" +#define SYMBOL_PTR_PREFIX_LEN (sizeof(SYMBOL_PTR_PREFIX) - 1) + static inline unsigned int addr_hash(uintptr_t addr) { return hash_ptr((const void *)addr); @@ -115,14 +119,17 @@ struct symbol { struct hlist_node name_hash; enum symbol_state state; uintptr_t die_addr; + uintptr_t ptr_die_addr; unsigned long crc; }; =20 typedef void (*symbol_callback_t)(struct symbol *, void *arg); =20 +bool is_symbol_ptr(const char *name); void symbol_read_exports(FILE *file); void symbol_read_symtab(int fd); struct symbol *symbol_get(const char *name); +void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr); void symbol_set_die(struct symbol *sym, Dwarf_Die *die); void symbol_set_crc(struct symbol *sym, unsigned long crc); void symbol_for_each(symbol_callback_t func, void *arg); diff --git a/scripts/gendwarfksyms/symbols.c b/scripts/gendwarfksyms/symbol= s.c index 924f52ee4acd..5e6d3a62bdcf 100644 --- a/scripts/gendwarfksyms/symbols.c +++ b/scripts/gendwarfksyms/symbols.c @@ -39,6 +39,20 @@ static int __for_each_addr(struct symbol *sym, symbol_ca= llback_t func, return processed; } =20 +/* + * For symbols without debugging information (e.g. symbols defined in other + * TUs), we also match __gendwarfksyms_ptr_ symbols, which the + * kernel uses to ensure type information is present in the TU that exports + * the symbol. A __gendwarfksyms_ptr pointer must have the same type as the + * exported symbol, e.g.: + * + * typeof(symname) *__gendwarf_ptr_symname =3D &symname; + */ +bool is_symbol_ptr(const char *name) +{ + return name && !strncmp(name, SYMBOL_PTR_PREFIX, SYMBOL_PTR_PREFIX_LEN); +} + static int for_each(const char *name, bool name_only, symbol_callback_t fu= nc, void *data) { @@ -47,6 +61,8 @@ static int for_each(const char *name, bool name_only, sym= bol_callback_t func, =20 if (!name || !*name) return 0; + if (is_symbol_ptr(name)) + name +=3D SYMBOL_PTR_PREFIX_LEN; =20 hash_for_each_possible_safe(symbol_names, match, tmp, name_hash, hash_str(name)) { @@ -84,6 +100,17 @@ void symbol_set_crc(struct symbol *sym, unsigned long c= rc) error("no matching symbols: '%s'", sym->name); } =20 +static void set_ptr(struct symbol *sym, void *data) +{ + sym->ptr_die_addr =3D (uintptr_t)((Dwarf_Die *)data)->addr; +} + +void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr) +{ + if (checkp(for_each(sym->name, false, set_ptr, ptr)) =3D=3D 0) + error("no matching symbols: '%s'", sym->name); +} + static void set_die(struct symbol *sym, void *data) { sym->die_addr =3D (uintptr_t)((Dwarf_Die *)data)->addr; --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) (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 DB1901A4E7B for ; Mon, 23 Sep 2024 18:19:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115580; cv=none; b=VSLyK00ANtkXNsfkV4bA3cqPxusKmzP2vRB4p5m+FnyBlU/Rb2qntPXDd12RZYhsWLoOdgpyjbBQLtAPuxKgV0pskXfWNrEwQaj79JgLKW1eZSk3Augcf2kHFnlvG/hf6xlzP0kUOa6iFYl5EhBQc6br8rdyPGhZDk5KlislC3o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115580; c=relaxed/simple; bh=+UvoU8FD7maTKGVExD/e4mqqBkqzCVeVz2B4x7Mcj68=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=DfPYNnLzZl/ehENAuOFPdwiXK0r0eOzsT9phKLE8f6+DqrcOof8QG2dZsHiriW/6gszRmvfOr8SrZOkznewxcfjQsOw6roXdNFQ2CE6wkuyZfCQIRFBG0RQAw5SMVuc8ai1+V9U6H2Iem7e5gNLSRwhGtZHYawnw/CAQ3QtXqAs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=JkGjtCWh; arc=none smtp.client-ip=209.85.210.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="JkGjtCWh" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-71985781cbdso4330142b3a.3 for ; Mon, 23 Sep 2024 11:19:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115578; x=1727720378; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=wBp4ZQRSWGSz9WsZC/MJ1xrrw9uz490jpQ8iIOLHT0A=; b=JkGjtCWhd855rziKszRLB7HHDzJU/GUmn/sgvR6q7uL4YDYV9FfkWAbo3uRzHadslf fO/xBL0Fpt0YWA7jUV9yz1926UfYIU2Vd7QMWlVRoQG39zvBse2TC2LMlkUmj/yD2Q+s Rmn7wsdzcqjX9jd+gwLXouM95+OKDlJE95URQfhljiCNbBKhvb0T41RWzE+XaPSukesI I1lLNSvX1PMwTOOY88d3ssl+PIumjwZ+gmvYPlCD0VMIT0R6lL/AncxBAW5lALEQ3a+N wy/dFUKt5k5U5Tlayhem0b60TfuRucFxh7ZQfUsGKFU+4+ov0LyymrYQDtxXAYxgzEeF E6Ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115578; x=1727720378; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=wBp4ZQRSWGSz9WsZC/MJ1xrrw9uz490jpQ8iIOLHT0A=; b=owXpBxJPE0RtpRLwdegEfrS8j/PvMfVRmxlnuBdoPvP9R3G66U3N6HlTpopDbb+1ys 45ZCNQaSUHBk9N2PRABVCQc/JAbPWKjs7mRaxFPRsKN3QRTqI64Ng3EVxWY8xqLEEKHa uV7nYHO9+zi7+B0o4lt2DRwZj9DJ7CmUvqApDkfIWqz07ayT/FcXjIxvH5ixWYOCnTrv 0B79fi355LhPxHU9y45iUkWZRn4LSZ+2uGvUY0nbHJT94dupac5aqbS2DXcz5cvlUyOZ xn0ntb9btBQzwpmDi4fW+elcuHX11u+Xok/MA3DrZqVgUQRQAkTjiO18TnmEkfOAbG+6 Ej4Q== X-Forwarded-Encrypted: i=1; AJvYcCW3awg8Xhw92lBmpMtBAUBgBPoZMty8uSBV+Tvaco1lQ6o4QP2WOZRTFr3ZUJlTXblQwqtQj48T2zDUvE8=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/YLnQQ1D5wUztOP6Ne+DXJFCO9237/dVIPe7WcA4AWqOx4Btt Cfa6mycHOGAGlRd7kAvejBSaDXcKahI0sOactVhNfvVeKNeTrJvLbq4GLj3MEVgJd0Xg5WRzEV3 RRSkLHyZoqJdUFCZpREasDi2JcQ== X-Google-Smtp-Source: AGHT+IEfhnnGFLNqxmlxpS6JZN5ZKd9QA3K4jtdAwTpy/rFImsyDZ7zzpRDe8/9I6s/nxiyGkzCR7eTK9rO2z27zOVg= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a05:6a00:4bb4:b0:717:8dee:d810 with SMTP id d2e1a72fcca58-7199ca6bbccmr18336b3a.5.1727115578261; Mon, 23 Sep 2024 11:19:38 -0700 (PDT) Date: Mon, 23 Sep 2024 18:19:04 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=2005; i=samitolvanen@google.com; h=from:subject; bh=+UvoU8FD7maTKGVExD/e4mqqBkqzCVeVz2B4x7Mcj68=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/L/Wmu/+g6PmN/FR6lzFR3evt4qxfT64czd7z++U PviHLj6eEcpC4MYB4OsmCJLy9fVW3d/d0p99blIAmYOKxPIEAYuTgGYiOtThn/Gwc87+donpSpK T54afXBp1vx9axN6DiRFfDHJtZUR9GNl+O9Q6vCAdcklt4Xy0Q9mM03Z9l9n0u3ExGWfWeZ8uVD //QkrAA== X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-40-samitolvanen@google.com> Subject: [PATCH v3 18/20] export: Add __gendwarfksyms_ptr_ references to exported symbols From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With gendwarfksyms, we need each TU where the EXPORT_SYMBOL() macro is used to also contain DWARF type information for the symbols it exports. However, as a TU can also export external symbols and compilers may choose not to emit debugging information for symbols not defined in the current TU, the missing types will result in missing symbol versions. Stand-alone assembly code also doesn't contain type information for exported symbols, so we need to compile a temporary object file with asm-prototypes.h instead, and similarly need to ensure the DWARF in the temporary object file contains the necessary types. To always emit type information for external exports, add explicit __gendwarfksyms_ptr_ references to them in EXPORT_SYMBOL(). gendwarfksyms will use the type information for __gendwarfksyms_ptr_* if needed. Discard the pointers from the final binary to avoid further bloat. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- include/linux/export.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/export.h b/include/linux/export.h index 0bbd02fd351d..cf71d3202e5b 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -52,9 +52,24 @@ =20 #else =20 +#ifdef CONFIG_GENDWARFKSYMS +/* + * With CONFIG_GENDWARFKSYMS, ensure the compiler emits debugging + * information for all exported symbols, including those defined in + * different TUs, by adding a __gendwarfksyms_ptr_ pointer + * that's discarded during the final link. + */ +#define __GENDWARFKSYMS_EXPORT(sym) \ + static typeof(sym) *__gendwarfksyms_ptr_##sym __used \ + __section(".discard.gendwarfksyms") =3D &sym; +#else +#define __GENDWARFKSYMS_EXPORT(sym) +#endif + #define __EXPORT_SYMBOL(sym, license, ns) \ extern typeof(sym) sym; \ __ADDRESSABLE(sym) \ + __GENDWARFKSYMS_EXPORT(sym) \ asm(__stringify(___EXPORT_SYMBOL(sym, license, ns))) =20 #endif --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yb1-f202.google.com (mail-yb1-f202.google.com [209.85.219.202]) (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 5D2471A0727 for ; Mon, 23 Sep 2024 18:19:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115583; cv=none; b=A4ibcZU0ulpz7Hlc/EG8VugW6bHAkk2REnMQ2p6Jijlt+3Q6GEjwIDYR8nLd472WGKh64bHAEz0BuTR1kcEyljM+yRr20VuPVfaB3pl0X9QzJSJAtGArIviIV6xqfTPx9HWiQFyZcA0FlzwoBHE8z3Fu8SJre5oSS76qYOsmF00= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115583; c=relaxed/simple; bh=OH24tQPuDnVpzlK2A4pw7td01bMw79FJr1MczVyAYNk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=BwIblG22p/YHRSOHvZszvZctym6kj6HG4KtSVa3/91kUFfAfe+uiNsrNfXE+++OGKLQWWtqHMVlXr0KnvfXdTxO7VxTD94lkwCAC68Ohg74qnXEGkgVydNxatL6F2UuTSIZDiU7atD7H7v59IWQn824h4B/hjo0KbCXsBF/1n0Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=1DT54jtG; arc=none smtp.client-ip=209.85.219.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="1DT54jtG" Received: by mail-yb1-f202.google.com with SMTP id 3f1490d57ef6-e165fc5d94fso7385095276.2 for ; Mon, 23 Sep 2024 11:19:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115580; x=1727720380; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=BgepgN3aRhrp+ARvxjN9eiDJ8ZxKyJSzBfNXPMCj9LE=; b=1DT54jtGnr+kES2waefeSMhdddasSguEMyfLRwa8f6E2anVxSPC5tpYcza+a3X5Cyq dg5GN4P3AeALiiG49/rBzu7B+Tl2tgGP7mAHb2iq6ilyEsSXBgUz5tj4dwGpkBiaS702 eb8MfiNc9Xem0T201Qn6+kCcwhP2wRYuh13UIbbJuyohqT7fUCWVifDOn4Zjz0KdvB/r JFFhBVkEI8s1YrP+XlpVyaNwaflJDpFONp0UY4qr2hggm36XUSgDey5ofW/1EOQAzOO8 XFefW/Mlb81LmaENdDi9WRv+DAcXQWbgNW0W2/kT8UNXpWEra5Ife5pXbgZYC476PuEP lXig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115580; x=1727720380; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=BgepgN3aRhrp+ARvxjN9eiDJ8ZxKyJSzBfNXPMCj9LE=; b=HCL2F2N6yPmWNFuScP/uOMRDeshG2T8GIYOihWO0fuQaFpysxYhwOgZs2G7xfNz/es iL+te8NMqcWhpypWqjc0yaZIhDxQPDjHcLnmhDz/9udFeAmMzoeMDdx3mzKbsX8aWTxb y53Ta5GWBK5yc7w1pjPkOglrNBSNlSNmTW5mMEs3Y78AqF9g3oqDgmbR5gfGeyN1kWbm iv/la50cyIDFAp7XFZR7Gz1rD64/Ut8/jU4gGDOgzxNDLb4ljzlswoEnVmdo2NPBt4wg Es4FIKCd/5SDE4GtYWzhLMRK3zXw37B7VygupPdY11iyfJNZdt2Z9CYzAW1Y23jC3R7S NC2Q== X-Forwarded-Encrypted: i=1; AJvYcCVJedX7+go4HvGTLtOsU6B6dGqLlFdevXz6Sy9427T9sWNm10qhZpQ1mDSYIMuS38zIX1ZNLEP0WfxITaY=@vger.kernel.org X-Gm-Message-State: AOJu0Yyd2AD3OjrU38x9Bk8pit8toGU/0hn8dS0qdzAQaAg7LkJOK2HT hkwjps5MHguXPJHWPIrEcHK16eGQz7wonOSfGoQXC2GVPEkLPuKNLIBG/mBIzdC3iOsARQySqcb nZ9vGTykPcnOYnbBkCT/OYW8lTw== X-Google-Smtp-Source: AGHT+IGm8TyRvIoRQAss2gkVdi1286GfP5Qqk6F1uonGTA9V0dZMsunnuESBlFP3IoWyCP3MD6ektydfKaQSmobwhCE= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a25:690e:0:b0:e1d:21ae:3b95 with SMTP id 3f1490d57ef6-e2252fe2127mr32040276.10.1727115579734; Mon, 23 Sep 2024 11:19:39 -0700 (PDT) Date: Mon, 23 Sep 2024 18:19:05 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=5161; i=samitolvanen@google.com; h=from:subject; bh=OH24tQPuDnVpzlK2A4pw7td01bMw79FJr1MczVyAYNk=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfN/JHTGAzkBH499+JOzF4Q/GVkLQ6gQNlt85t453Sp 6H/cV98RykLgxgHg6yYIkvL19Vbd393Sn31uUgCZg4rE8gQBi5OAZjI3XZGhmPRhh96pt7a0fG7 7KDBo02/Wx5ZWjao6OltCGf3YJ1fpMfI8FX6q21dl+311W+zl9351zBjqbvBDtHNW40N2QLd+Kw ceQE= X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-41-samitolvanen@google.com> Subject: [PATCH v3 19/20] kbuild: Add gendwarfksyms as an alternative to genksyms From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When MODVERSIONS is enabled, allow selecting gendwarfksyms as the implementation, but default to genksyms. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- kernel/module/Kconfig | 25 ++++++++++++++++++++++++- scripts/Makefile | 2 +- scripts/Makefile.build | 39 +++++++++++++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index c3a0172a909f..804b0b515d04 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -168,13 +168,36 @@ config MODVERSIONS make them incompatible with the kernel you are running. If unsure, say N. =20 +choice + prompt "Module versioning implementation" + depends on MODVERSIONS + default GENKSYMS + help + Select the tool used to calculate symbol versions for modules. + + If unsure, select GENKSYMS. + +config GENKSYMS + bool "genksyms (from source code)" + help + Calculate symbol versions from pre-processed source code using + genksyms. + + If unsure, say Y. + config GENDWARFKSYMS - bool + bool "gendwarfksyms (from debugging information)" depends on DEBUG_INFO # Requires full debugging information, split DWARF not supported. depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT # Requires ELF object files. depends on !LTO + help + Calculate symbol versions from DWARF debugging information using + gendwarfksyms. Requires DEBUG_INFO to be enabled. + + If unsure, say N. +endchoice =20 config ASM_MODVERSIONS bool diff --git a/scripts/Makefile b/scripts/Makefile index d7fec46d38c0..8533f4498885 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -53,7 +53,7 @@ hostprogs +=3D unifdef targets +=3D module.lds =20 subdir-$(CONFIG_GCC_PLUGINS) +=3D gcc-plugins -subdir-$(CONFIG_MODVERSIONS) +=3D genksyms +subdir-$(CONFIG_GENKSYMS) +=3D genksyms subdir-$(CONFIG_GENDWARFKSYMS) +=3D gendwarfksyms subdir-$(CONFIG_SECURITY_SELINUX) +=3D selinux subdir-$(CONFIG_SECURITY_IPE) +=3D ipe diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 8f423a1faf50..ae13afb71123 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -107,18 +107,28 @@ cmd_cpp_i_c =3D $(CPP) $(c_flags) -o $@ $< $(obj)/%.i: $(obj)/%.c FORCE $(call if_changed_dep,cpp_i_c) =20 +gendwarfksyms :=3D scripts/gendwarfksyms/gendwarfksyms +getexportsymbols =3D $(NM) $(1) | sed -n 's/.* __export_symbol_\(.*\)/$(2)= /p' + genksyms =3D scripts/genksyms/genksyms \ $(if $(1), -T $(2)) \ $(if $(KBUILD_PRESERVE), -p) \ -r $(or $(wildcard $(2:.symtypes=3D.symref)), /dev/null) =20 # These mirror gensymtypes_S and co below, keep them in synch. +ifdef CONFIG_GENDWARFKSYMS +symtypes_dep_c =3D $(obj)/%.o +cmd_gensymtypes_c =3D $(if $(skip_gendwarfksyms),, \ + $(call getexportsymbols,$(2:.symtypes=3D.o),\1) | \ + $(gendwarfksyms) $(2:.symtypes=3D.o) $(if $(1), --symtypes $(2))) +else cmd_gensymtypes_c =3D $(CPP) -D__GENKSYMS__ $(c_flags) $< | $(genksyms) +endif # CONFIG_GENDWARFKSYMS =20 quiet_cmd_cc_symtypes_c =3D SYM $(quiet_modtag) $@ cmd_cc_symtypes_c =3D $(call cmd_gensymtypes_c,true,$@) >/dev/null =20 -$(obj)/%.symtypes : $(obj)/%.c FORCE +$(obj)/%.symtypes : $(obj)/%.c $(symtypes_dep_c) FORCE $(call cmd,cc_symtypes_c) =20 # LLVM assembly @@ -314,19 +324,32 @@ $(obj)/%.ll: $(obj)/%.rs FORCE # This is convoluted. The .S file must first be preprocessed to run guards= and # expand names, then the resulting exports must be constructed into plain # EXPORT_SYMBOL(symbol); to build our dummy C file, and that gets preproce= ssed -# to make the genksyms input. +# to make the genksyms input or compiled into an object for gendwarfksyms. # # These mirror gensymtypes_c and co above, keep them in synch. -cmd_gensymtypes_S =3D = \ - { echo "\#include " ; = \ - echo "\#include " ; = \ - $(NM) $@ | sed -n 's/.* __export_symbol_\(.*\)/EXPORT_SYMBOL(\1);/p' = ; } | \ - $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms) +getasmexports =3D \ + { echo "\#include " ; \ + echo "\#include " ; \ + echo "\#include " ; \ + $(call getexportsymbols,$(2:.symtypes=3D.o),EXPORT_SYMBOL(\1);) ; } + +ifdef CONFIG_GENDWARFKSYMS +cmd_gensymtypes_S =3D \ + $(getasmexports) | \ + $(CC) $(c_flags) -c -o $(2:.symtypes=3D.gendwarfksyms.o) -xc -; \ + $(call getexportsymbols,$(2:.symtypes=3D.o),\1) | \ + $(gendwarfksyms) $(2:.symtypes=3D.gendwarfksyms.o) \ + $(if $(1), --symtypes $(2)) +else +cmd_gensymtypes_S =3D \ + $(getasmexports) | \ + $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms) +endif # CONFIG_GENDWARFKSYMS =20 quiet_cmd_cc_symtypes_S =3D SYM $(quiet_modtag) $@ cmd_cc_symtypes_S =3D $(call cmd_gensymtypes_S,true,$@) >/dev/null =20 -$(obj)/%.symtypes : $(obj)/%.S FORCE +$(obj)/%.symtypes : $(obj)/%.S $(obj)/%.o FORCE $(call cmd,cc_symtypes_S) =20 =20 --=20 2.46.0.792.g87dc391469-goog From nobody Sun Feb 8 14:16:04 2026 Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (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 7B2181A4F2E for ; Mon, 23 Sep 2024 18:19:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115585; cv=none; b=MKKLTZNAQy3pxmxHc6mGfbDvENpgXTRwTT99p35K7NvK8QmAdbma8NCGtNVvYaI/2RlIj/MzUzqHSX5gz7zfESKJqLLjYX4L3xJlEKY43DA/akfEUNg9gHCnCr9L3RjvEsvJQ2r5AGQ3s9sk2dKJU2NG/kZ9dHyriCUmc/09RF0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727115585; c=relaxed/simple; bh=MUvyVDOVnoZUdt93DJbmEjcHlGHywIDAJExoIyBJwTc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=EyLGkwUgeVnAad+WXFPK4b/zFh1fQw+oIDd2zYoqntnSoHVdVKlEfQLyiD+yF/nNJqESHzhm4mBKIEpRqDkoEo1YLwwPHpS1DbXoD9m5HG7DupcV3SYNyoEKDO+Go/HkigxrbNfBt/IBX+WX5GVXVJiUx1lAJSpIXs68jGm1t3g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nPTJd6au; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--samitolvanen.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nPTJd6au" Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-6e1fbe2a9a2so15592897b3.1 for ; Mon, 23 Sep 2024 11:19:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1727115582; x=1727720382; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=LIeNJExclvncrOtPvfgf/zFSBPEGc6h5JAKcbMZPgWU=; b=nPTJd6auPw5uWBT+1NZ2Qr+KeCYyBTCENVaVKqEi4cw4jtR9GbbGsgNgVnfsvWKxi3 uYHOcO/8ry9UgJwHIeNNvzbfASJL4iutgp/+MH/rSxfy7VOqtaGHC5A+52Vc40gvlSZx CHjDDR1uHFqhC7oikBKkwYKy7EzbkKEuGNFd9AGn1Fv/VH652cwowyp6N37Ewk3XhNDK alNvbD7e74f3QNsogumpxrmDF+Gci+djYeVAsTEbcoBHE+iwbhVgatkoB8JkzqMrhURE 2gCYmHgEypyZ90Cv6izAlZdAckRtuzhyQxRgGHBBuXBWYciwtPlNCsngbkG8VV8nZMoL 3iaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727115582; x=1727720382; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=LIeNJExclvncrOtPvfgf/zFSBPEGc6h5JAKcbMZPgWU=; b=jk+ySS8f4dzk8jzi3p1ybv7S8aQFXNmFPu0+RDKhsRwFgqqZx3Y2er+RWgV8Nvhnkc 17JeMYqnKOrsY1K9ZCZSmx/VHkB5H5j3cTjFfm4TDy9qxKKZd4pVf/y6TGefIu6RL3l7 nGd1Nc0IXpJIBkZJ5MrF7YG4yjtzhnUQ14TOro21xNkPckVwV7nKMpJjW0Uj+TRg374f HnoN+xQYfe8xUkQrbBLD6VXE9yoh/ugl8RD8ccP1EfFCGP6BLE4ORD26A2PqgjSyE94d nsosWDCDGsBnc6H2kcytXDmyZG+mRR0fURxjgTHnlI8XomSrASrM6Hvf9RGtsKmd2ouN D3QQ== X-Forwarded-Encrypted: i=1; AJvYcCWOzir05wXaECNca3GNzvzRwoivPeO9VUbpKNFH3n8GMSOCCCyadOGYwI18ZvjjJ76Yj5uyKeaPFllicdQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxS52ACehsSgHX2Lhz16uwFrml/eR3c7qVTR6iCW9c9CtDYtwdu 519XzPtfu5iZVMALNCIClwbvbBMFQK8R8tAvoXrqoSxy961tzRJzNmdRy0C6qb1iYWk3+MJ3nDB irhgWSsRfuL2U6m0yv4uOcN3ZOA== X-Google-Smtp-Source: AGHT+IGn5NLkaYtJf4zx1Oj6VLn9yvEjY3yp8FW/8aCXhpJ0JMKN//NTWxYZpRpKz1KNy1nm96hS6Hsq1+IESPg824U= X-Received: from samitolvanen.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:4f92]) (user=samitolvanen job=sendgmr) by 2002:a81:a704:0:b0:6db:c6eb:bae9 with SMTP id 00721157ae682-6dff270d59bmr1849607b3.2.1727115581692; Mon, 23 Sep 2024 11:19:41 -0700 (PDT) Date: Mon, 23 Sep 2024 18:19:06 +0000 In-Reply-To: <20240923181846.549877-22-samitolvanen@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240923181846.549877-22-samitolvanen@google.com> X-Developer-Key: i=samitolvanen@google.com; a=openpgp; fpr=35CCFB63B283D6D3AEB783944CB5F6848BBC56EE X-Developer-Signature: v=1; a=openpgp-sha256; l=11935; i=samitolvanen@google.com; h=from:subject; bh=MUvyVDOVnoZUdt93DJbmEjcHlGHywIDAJExoIyBJwTc=; b=owGbwMvMwCEWxa662nLh8irG02pJDGkfNwq0Kpa5t5WHuQfeK867smrOH7WfMx615Xc9cWI/0 nJk7U62jlIWBjEOBlkxRZaWr6u37v7ulPrqc5EEzBxWJpAhDFycAjCRfysZGXqF3h5okQ0XnzJd XO2QbLnqPp7e67f0XmxWXJO+MWTdxycM/3QUre208y5l+cxZzrFqk8Xq4MllL5aEetl6GBjGZfR v4wYA X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog Message-ID: <20240923181846.549877-42-samitolvanen@google.com> Subject: [PATCH v3 20/20] Documentation/kbuild: Add DWARF module versioning From: Sami Tolvanen To: Masahiro Yamada , Luis Chamberlain , Miguel Ojeda , Greg Kroah-Hartman Cc: Matthew Maurer , Alex Gaynor , Wedson Almeida Filho , Gary Guo , Petr Pavlu , Neal Gompa , Hector Martin , Janne Grunau , Miroslav Benes , Asahi Linux , linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, rust-for-linux@vger.kernel.org, Sami Tolvanen Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add documentation for gendwarfksyms changes, and the kABI stability features that can be useful for distributions even though they're not used in mainline kernels. Signed-off-by: Sami Tolvanen Acked-by: Neal Gompa --- Documentation/kbuild/gendwarfksyms.rst | 274 +++++++++++++++++++++++++ Documentation/kbuild/index.rst | 1 + 2 files changed, 275 insertions(+) create mode 100644 Documentation/kbuild/gendwarfksyms.rst diff --git a/Documentation/kbuild/gendwarfksyms.rst b/Documentation/kbuild/= gendwarfksyms.rst new file mode 100644 index 000000000000..4b89743d2a88 --- /dev/null +++ b/Documentation/kbuild/gendwarfksyms.rst @@ -0,0 +1,274 @@ +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +DWARF module versioning +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +1. Introduction +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +When CONFIG_MODVERSIONS is enabled, symbol versions for modules +are typically calculated from preprocessed source code using the +**genksyms** tool. However, this is incompatible with languages such +as Rust, where the source code has insufficient information about +the resulting ABI. With CONFIG_GENDWARFKSYMS (and CONFIG_DEBUG_INFO) +selected, **gendwarfksyms** is used instead to calculate symbol versions +from the DWARF debugging information, which contains the necessary +details about the final module ABI. + +1.1. Usage +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +gendwarfksyms accepts a list of object files on the command line, and a +list of symbol names (one per line) in standard input:: + + Usage: gendwarfksyms [options] elf-object-file ... < symbol-list + + Options: + -d, --debug Print debugging information + --dump-dies Dump DWARF DIE contents + --dump-die-map Print debugging information about die_map c= hanges + --dump-types Dump type strings + --dump-versions Dump expanded type strings used for symbol = versions + -s, --stable Support kABI stability features + -T, --symtypes file Write a symtypes file + -h, --help Print this message + + +2. Type information availability +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D + +While symbols are typically exported in the same translation unit (TU) +where they're defined, it's also perfectly fine for a TU to export +external symbols. For example, this is done when calculating symbol +versions for exports in stand-alone assembly code. + +To ensure the compiler emits the necessary DWARF type information in the +TU where symbols are actually exported, gendwarfksyms adds a pointer +to exported symbols in the `EXPORT_SYMBOL()` macro using the following +macro:: + + #define __GENDWARFKSYMS_EXPORT(sym) \ + static typeof(sym) *__gendwarfksyms_ptr_##sym __used \ + __section(".discard.gendwarfksyms") =3D &sym; + + +When a symbol pointer is found in DWARF, gendwarfksyms can use its +type for calculating symbol versions even if the symbol is defined +elsewhere. The name of the symbol pointer is expected to start with +`__gendwarfksyms_ptr_`, followed by the name of the exported symbol. + +3. Symtypes output format +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +Similarly to genksyms, gendwarfksyms supports writing a symtypes file +for each processed object that contain types for exported symbols and +each referenced type that was used in calculating symbol versions. These +files can be useful when trying to determine what exactly caused symbol +versions to change between builds. + +Matching the existing format, the first column of each line contains +either a type reference or a symbol name. Type references have a +one-letter prefix followed by "#" and the name of the type. Four +reference types are supported:: + + e# =3D enum + s# =3D struct + t# =3D typedef + u# =3D union + +Type names with spaces in them are wrapped in single quotes, e.g.:: + + s#'core::result::Result' + +The rest of the line contains a type string. Unlike with genksyms that +produces C-style type strings, gendwarfksyms uses the same simple parsed +DWARF format produced by **--dump-dies**, but with type references +instead of fully expanded strings. + +4. Maintaining a stable kABI +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + +Distribution maintainers often need the ability to make ABI compatible +changes to kernel data structures due to LTS updates or backports. Using +the traditional `#ifndef __GENKSYMS__` to hide these changes from symbol +versioning won't work when processing object files. To support this +use case, gendwarfksyms provides kABI stability features designed to +hide changes that won't affect the ABI when calculating versions. These +features are all gated behind the **--stable** command line flag and are +not used in the mainline kernel. + +Examples for using these features are provided in the +**scripts/gendwarfksyms/examples** directory, including helper macros +for source code annotation. Note that as these features are only used to +transform the inputs for symbol versioning, the user is responsible for +ensuring that their changes actually won't break the ABI. + +4.1. kABI rules +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +kABI rules allow distributions to fine-tune certain parts +of gendwarfksyms output and thus control how symbol +versions are calculated. These rules are defined in the +`.discard.gendwarfksyms.kabi_rules` section of the object file and +consist of simple null-terminated strings with the following structure:: + + version\0type\0target\0value\0 + +This string sequence is repeated as many times as needed to express all +the rules. The fields are as follows: + +- `version`: Ensures backward compatibility for future changes to the + structure. Currently expected to be "1". +- `type`: Indicates the type of rule being applied. +- `target`: Specifies the target of the rule, typically the fully + qualified name of the DWARF Debugging Information Entry (DIE). +- `value`: Provides rule-specific data. + +The following helper macro, for example, can be used to specify rules +in the source code:: + + #define __KABI_RULE(hint, target, value) \ + static const char __PASTE(__gendwarfksyms_rule_, \ + __COUNTER__)[] __used __aligned(1) \ + __section(".discard.gendwarfksyms.kabi_rules") =3D \ + "1\0" #hint "\0" #target "\0" #value + + +Currently, only the rules discussed in this section are supported, but +the format is extensible enough to allow further rules to be added as +need arises. + +4.1.1. Managing structure visibility +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +A structure declaration can change into a full definition when +additional includes are pulled into the translation unit. This changes +the versions of any symbol that references the structure even if the ABI +remains unchanged. As it may not be possible to drop includes without +breaking the build, the `struct_declonly` rule can be used to specify a +data structure as declaration-only, even if the debugging information +contains the full definition. + +The rule fields are expected to be as follows: + +- `type`: "struct_declonly" +- `target`: The fully qualified name of the target data structure + (as shown in **--dump-dies** output). +- `value`: This field is ignored and is expected to have the value ";". + +Using the `__KABI_RULE` macro, this rule can be defined as:: + + #define KABI_STRUCT_DECLONLY(fqn) \ + __KABI_RULE(struct_declonly, fqn, ;) + +Example usage:: + + struct s { + /* definition */ + }; + + KABI_STRUCT_DECLONLY(s); + +4.1.2. Adding enumerators +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +For enums, all enumerators and their values are included in calculating +symbol versions, which becomes a problem if we later need to add more +enumerators without changing symbol versions. The `enumerator_ignore` +rule allows us to hide named enumerators from the input. + +The rule fields are expected to be as follows: + +- `type`: "enumerator_ignore" +- `target`: The fully qualified name of the target enum + (as shown in **--dump-dies** output). +- `value`: The name of the enumerator to ignore. + +Using the `__KABI_RULE` macro, this rule can be defined as:: + + #define KABI_ENUMERATOR_IGNORE(fqn, field) \ + __KABI_RULE(enumerator_ignore, fqn, field) + +Example usage:: + + enum e { + A, B, C, D, + }; + + KABI_ENUMERATOR_IGNORE(e, B); + KABI_ENUMERATOR_IGNORE(e, C); + + +4.3. Adding structure members +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D + +Perhaps the most common ABI compatible changeis adding a member to a +kernel data structure. When changes to a structure are anticipated, +distribution maintainers can pre-emptively reserve space in the +structure and take it into use later without breaking the ABI. If +changes are needed to data structures without reserved space, existing +alignment holes can potentially be used instead. While kABI rules could +be added for these type of changes, using unions is typically a more +natural method. This section describes gendwarfksyms support for using +reserved space in data structures and hiding members that don't change +the ABI when calculating symbol versions. + +4.3.1. Reserving space and replacing members +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +To reserve space in a struct, adding a member of any type with a name +that starts with `__kabi_` will result in the name being left out of +symbol versioning:: + + struct s { + long a; + long __kabi_reserved_0; /* reserved for future use */ + }; + +The space reserved by this member can be later taken into use by +wrapping it into a union, which includes the original type and the +replacement struct member:: + + struct s { + long a; + union { + long __kabi_reserved_0; /* original type */ + struct b b; /* replaced field */ + }; + }; + +As long as the reserved member's name in the union starts with +`__kabi_reserved_`, the original type will be used for symbol +versioning and rest of the union is ignored. The examples include +`KABI_(RESERVE|USE)*` macros that help simplify the process and also +ensure the replacement member's size won't exceed the reserved space. + +4.3.2. Hiding members +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Predicting which structures will require changes during the support +timeframe isn't always possible, in which case one might have to resort +to placing new members into existing alignment holes:: + + struct s { + int a; + /* a 4-byte alignment hole */ + unsigned long b; + }; + + +While this won't change the size of the data structure, one needs to +be able to hide the added members from symbol versioning. Similarly +to reserved fields, this can be accomplished by wrapping the added +member to a union where one of the fields has a name starting with +`__kabi_ignored`:: + + struct s { + int a; + union { + char __kabi_ignored_0; + int n; + }; + unsigned long b; + }; + +With **--stable**, both versions produce the same symbol version. diff --git a/Documentation/kbuild/index.rst b/Documentation/kbuild/index.rst index cee2f99f734b..e82af05cd652 100644 --- a/Documentation/kbuild/index.rst +++ b/Documentation/kbuild/index.rst @@ -21,6 +21,7 @@ Kernel Build System reproducible-builds gcc-plugins llvm + gendwarfksyms =20 .. only:: subproject and html =20 --=20 2.46.0.792.g87dc391469-goog