From nobody Wed Feb 5 14:53:55 2025 Received: from pegase2.c-s.fr (pegase2.c-s.fr [93.17.235.10]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D3EE11DDC01 for ; Wed, 15 Jan 2025 22:50:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=93.17.235.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736981440; cv=none; b=IXU12z/M0Sa0g0goHDZzSaQPmjst+tNp32FRIHH5uqMlJXBOlowophtXpBqJW0wJTqVMEiVzw48JxI48ccCu5AzEs8GVnOth5xpZSWyxYbd2SKA2ftFPgX5DAMAI3w2N1vMHHHLoJ9oOjJ9t/uj7ZZw8QeJGhkWjPrAw100mJpw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736981440; c=relaxed/simple; bh=5NdIHm7DD4bTebG2kf3cj71x6eBUoq5xTfa2EU+XO1s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CMFEsTFQ5Ko6uVVLfJKGM/YOdWp/aZdzhB8dPCcAcV2OHbkpWByHcLOm6Uw4/LnMEChn6K9apIE9Ul7V0It9ELB5wfNO9+kvN+IpwZOd3OQuZvxVg+tss90E3fB9kajf86DU+/HgGZdLGAS9WkyBg67sGIwhdXoi0cF0+p3Wju8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=csgroup.eu; spf=pass smtp.mailfrom=csgroup.eu; arc=none smtp.client-ip=93.17.235.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=csgroup.eu Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=csgroup.eu Received: from localhost (mailhub3.si.c-s.fr [172.26.127.67]) by localhost (Postfix) with ESMTP id 4YYLcd2pn8z9sSY; Wed, 15 Jan 2025 23:43:13 +0100 (CET) X-Virus-Scanned: amavisd-new at c-s.fr Received: from pegase2.c-s.fr ([172.26.127.65]) by localhost (pegase2.c-s.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id xdYktiID7W5v; Wed, 15 Jan 2025 23:43:13 +0100 (CET) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase2.c-s.fr (Postfix) with ESMTP id 4YYLcd1v6Vz9sSX; Wed, 15 Jan 2025 23:43:13 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 2F7B08B77A; Wed, 15 Jan 2025 23:43:13 +0100 (CET) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id Kex8_2sVL1dd; Wed, 15 Jan 2025 23:43:13 +0100 (CET) Received: from PO20335.idsi0.si.c-s.fr (unknown [192.168.202.221]) by messagerie.si.c-s.fr (Postfix) with ESMTP id BAC938B774; Wed, 15 Jan 2025 23:43:10 +0100 (CET) From: Christophe Leroy To: Josh Poimboeuf , Peter Zijlstra , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Julien Thierry , Miroslav Benes , Raphael Gault , Michael Ellerman , Nicholas Piggin , Naveen N Rao , Madhavan Srinivasan Cc: Christophe Leroy , linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, llvm@lists.linux.dev Subject: [PATCH v5 09/15] objtool: Find end of switch table directly Date: Wed, 15 Jan 2025 23:42:49 +0100 Message-ID: <3e31a9910c471ad9c17b76a96cc910e7a8aa2a10.1736955567.git.christophe.leroy@csgroup.eu> X-Mailer: git-send-email 2.47.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1736980964; l=3780; i=christophe.leroy@csgroup.eu; s=20211009; h=from:subject:message-id; bh=5NdIHm7DD4bTebG2kf3cj71x6eBUoq5xTfa2EU+XO1s=; b=BcAyjkvv2GQlZ+Fyl9KJ+tQwNqAdeIWlAHl9O6Ty4zCgkXVj/S8xZQe1aKUxm5oF0FDMbJc7W JOP1Tx9G/avATVxQ3jZE7d6jRzv5jFdeUmD+Jmkmbse21bYHCv8HrCo X-Developer-Key: i=christophe.leroy@csgroup.eu; a=ed25519; pk=HIzTzUj91asvincQGOFx6+ZF5AoUuP9GdOtQChs7Mm0= Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" At the time being, the end of a switch table can only be known once the start of the following switch table has ben located. This is a problem when switch tables are nested because until the first switch table is properly added, the second one cannot be located as a the backward walk will abut on the dynamic switch of the previous one. So perform a first forward walk in the code in order to locate all possible relocations to switch tables and build a local table with those relocations. Later on once one switch table is found, go through this local table to know where next switch table starts. Signed-off-by: Christophe Leroy --- tools/objtool/check.c | 63 ++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 72b977f81dd6..0ad2bdd92232 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -2058,14 +2058,30 @@ static void find_jump_table(struct objtool_file *fi= le, struct symbol *func, } } =20 +static struct reloc *find_next_table(struct instruction *insn, + struct reloc **table, unsigned int size) +{ + unsigned long offset =3D reloc_offset(insn_jump_table(insn)); + int i; + struct reloc *reloc =3D NULL; + + for (i =3D 0; i < size; i++) { + if (reloc_offset(table[i]) > offset && + (!reloc || reloc_offset(table[i]) < reloc_offset(reloc))) + reloc =3D table[i]; + } + return reloc; +} + /* * First pass: Mark the head of each jump table so that in the next pass, * we know when a given jump table ends and the next one starts. */ static int mark_add_func_jump_tables(struct objtool_file *file, - struct symbol *func) + struct symbol *func, + struct reloc **table, unsigned int size) { - struct instruction *insn, *last =3D NULL, *insn_t1 =3D NULL, *insn_t2; + struct instruction *insn, *last =3D NULL; int ret =3D 0; =20 func_for_each_insn(file, func, insn) { @@ -2094,23 +2110,11 @@ static int mark_add_func_jump_tables(struct objtool= _file *file, if (!insn_jump_table(insn)) continue; =20 - if (!insn_t1) { - insn_t1 =3D insn; - continue; - } - - insn_t2 =3D insn; - - ret =3D add_jump_table(file, insn_t1, insn_jump_table(insn_t2)); + ret =3D add_jump_table(file, insn, find_next_table(insn, table, size)); if (ret) return ret; - - insn_t1 =3D insn_t2; } =20 - if (insn_t1) - ret =3D add_jump_table(file, insn_t1, NULL); - return ret; } =20 @@ -2123,15 +2127,42 @@ static int add_jump_table_alts(struct objtool_file = *file) { struct symbol *func; int ret; + struct instruction *insn; + unsigned int size =3D 0, i =3D 0; + struct reloc **table =3D NULL; =20 if (!file->rodata) return 0; =20 + for_each_insn(file, insn) { + struct instruction *dest_insn; + struct reloc *reloc; + unsigned long table_size; + + func =3D insn_func(insn) ? insn_func(insn)->pfunc : NULL; + reloc =3D arch_find_switch_table(file, insn, &table_size, NULL); + /* + * Each table entry has a rela associated with it. The rela + * should reference text in the same function as the original + * instruction. + */ + if (!reloc) + continue; + dest_insn =3D find_insn(file, reloc->sym->sec, reloc_addend(reloc)); + if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != =3D func) + continue; + if (i =3D=3D size) { + size +=3D 1024; + table =3D realloc(table, size * sizeof(*table)); + } + table[i++] =3D reloc; + } + for_each_sym(file, func) { if (func->type !=3D STT_FUNC) continue; =20 - ret =3D mark_add_func_jump_tables(file, func); + ret =3D mark_add_func_jump_tables(file, func, table, i); if (ret) return ret; } --=20 2.47.0