From patchwork Tue May 24 00:16:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Madhavan T. Venkataraman" X-Patchwork-Id: 12859573 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1C54AC433FE for ; Tue, 24 May 2022 00:18:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Cc:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=a0FH16/+qjxbYeWIF5UR0iFtFN4BhRxb0v5+FJZIvpA=; b=32JflPHQQprkmC buhtXJmSSQ0+zuVzdy5CjuxT2ef+YVoRQX2t8Ln13DrXSUs6N/OTNr8MDvSOQiR/Yfvg6uj8dZoIi G51v+cwAs+JrEQLZ1Hoguw2eI4cXgO1lw7BkiTfUX0SC59R9l3rbrix/gHLsJ+z9hQ9wa8AgFerbq 5D2Ico9gTyqJk7YC2zokWYVt791fO7eK+iPWA5RRjGXMPpJKDvmUCOuDrA4oLWXuCvsF9F6pLOtBM qY6Zww3WToN49aptO0r8KCRm1ISK0DKQuoBs3a0yn1+xz7YxxYpDi14A5xV/PnXR+70Y49XgFnmQY X1e+Wue8MuR6JHTgCj+g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1ntIEf-006Jba-JC; Tue, 24 May 2022 00:17:17 +0000 Received: from linux.microsoft.com ([13.77.154.182]) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1ntIEE-006JM2-GL for linux-arm-kernel@lists.infradead.org; Tue, 24 May 2022 00:16:53 +0000 Received: from x64host.home (unknown [47.189.24.195]) by linux.microsoft.com (Postfix) with ESMTPSA id 7A49E20B87F6; Mon, 23 May 2022 17:16:49 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 7A49E20B87F6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1653351410; bh=PrjM6sNWCbaOpnfA+c2bSGMaKIm9RjxL72wTSFxI6qc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=N5oJapbEd2k+mIf2MT3PqvMssXV2Hg5mEIlndw3toTXfRJIqSFIq8DFKNsEdXLRmA NaQd7x4nC43KjAcSSYr3lhrX4iSOmcQkNxWsaxLDP4octNv5y2mcSSXufmzLw6RNdl RaK+pdtWBUqFBdG54tIPJpI5LN0kSv1iiGTwfFAM= From: madvenka@linux.microsoft.com To: jpoimboe@redhat.com, peterz@infradead.org, chenzhongjin@huawei.com, mark.rutland@arm.com, broonie@kernel.org, nobuta.keiya@fujitsu.com, sjitindarsingh@gmail.com, catalin.marinas@arm.com, will@kernel.org, jamorris@linux.microsoft.com, linux-arm-kernel@lists.infradead.org, live-patching@vger.kernel.org, linux-kernel@vger.kernel.org, madvenka@linux.microsoft.com Subject: [RFC PATCH v2 03/20] objtool: Move decode_instructions() to a separate file Date: Mon, 23 May 2022 19:16:20 -0500 Message-Id: <20220524001637.1707472-4-madvenka@linux.microsoft.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220524001637.1707472-1-madvenka@linux.microsoft.com> References: <20220524001637.1707472-1-madvenka@linux.microsoft.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_171650_637797_7FC58E75 X-CRM114-Status: GOOD ( 20.95 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: "Madhavan T. Venkataraman" check.c implements static stack validation. But decode_instructions() which resides in it can be shared with other types of validation. E.g., dynamic FP validation. Move the function to its own file - decode.c. Signed-off-by: Madhavan T. Venkataraman --- tools/objtool/Build | 2 + tools/objtool/check.c | 96 ------------------------ tools/objtool/decode.c | 106 +++++++++++++++++++++++++++ tools/objtool/include/objtool/insn.h | 1 + 4 files changed, 109 insertions(+), 96 deletions(-) create mode 100644 tools/objtool/decode.c diff --git a/tools/objtool/Build b/tools/objtool/Build index 52ed2f710d2a..199561f86c1e 100644 --- a/tools/objtool/Build +++ b/tools/objtool/Build @@ -5,10 +5,12 @@ objtool-y += weak.o objtool-$(SUBCMD_CHECK) += check.o objtool-$(SUBCMD_CHECK) += cfi.o objtool-$(SUBCMD_CHECK) += insn.o +objtool-$(SUBCMD_CHECK) += decode.o objtool-$(SUBCMD_CHECK) += special.o objtool-$(SUBCMD_ORC) += check.o objtool-$(SUBCMD_ORC) += cfi.o objtool-$(SUBCMD_ORC) += insn.o +objtool-$(SUBCMD_ORC) += decode.o objtool-$(SUBCMD_ORC) += orc_gen.o objtool-$(SUBCMD_ORC) += orc_dump.o diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 78168e0ad2bf..334ddc737bf9 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -163,104 +163,8 @@ static bool dead_end_function(struct objtool_file *file, struct symbol *func) return __dead_end_function(file, func, 0); } -static unsigned long nr_insns; static unsigned long nr_insns_visited; -/* - * Call the arch-specific instruction decoder for all the instructions and add - * them to the global instruction list. - */ -static int decode_instructions(struct objtool_file *file) -{ - struct section *sec; - struct symbol *func; - unsigned long offset; - struct instruction *insn; - int ret; - - for_each_sec(file, sec) { - - if (!(sec->sh.sh_flags & SHF_EXECINSTR)) - continue; - - if (strcmp(sec->name, ".altinstr_replacement") && - strcmp(sec->name, ".altinstr_aux") && - strncmp(sec->name, ".discard.", 9)) - sec->text = true; - - if (!strcmp(sec->name, ".noinstr.text") || - !strcmp(sec->name, ".entry.text")) - sec->noinstr = true; - - for (offset = 0; offset < sec->sh.sh_size; offset += insn->len) { - insn = malloc(sizeof(*insn)); - if (!insn) { - WARN("malloc failed"); - return -1; - } - memset(insn, 0, sizeof(*insn)); - INIT_LIST_HEAD(&insn->alts); - INIT_LIST_HEAD(&insn->stack_ops); - INIT_LIST_HEAD(&insn->call_node); - - insn->sec = sec; - insn->offset = offset; - - ret = arch_decode_instruction(file, sec, offset, - sec->sh.sh_size - offset, - &insn->len, &insn->type, - &insn->immediate, - &insn->stack_ops); - if (ret) - goto err; - - /* - * By default, "ud2" is a dead end unless otherwise - * annotated, because GCC 7 inserts it for certain - * divide-by-zero cases. - */ - if (insn->type == INSN_BUG) - insn->dead_end = true; - - hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); - list_add_tail(&insn->list, &file->insn_list); - nr_insns++; - } - - list_for_each_entry(func, &sec->symbol_list, list) { - if (func->type != STT_FUNC || func->alias != func) - continue; - - if (!find_insn(file, sec, func->offset)) { - WARN("%s(): can't find starting instruction", - func->name); - return -1; - } - - sym_for_each_insn(file, func, insn) { - insn->func = func; - if (insn->type == INSN_ENDBR && list_empty(&insn->call_node)) { - if (insn->offset == insn->func->offset) { - list_add_tail(&insn->call_node, &file->endbr_list); - file->nr_endbr++; - } else { - file->nr_endbr_int++; - } - } - } - } - } - - if (stats) - printf("nr_insns: %lu\n", nr_insns); - - return 0; - -err: - free(insn); - return ret; -} - /* * Read the pv_ops[] .data table to find the static initialized values. */ diff --git a/tools/objtool/decode.c b/tools/objtool/decode.c new file mode 100644 index 000000000000..4ed438ccc07f --- /dev/null +++ b/tools/objtool/decode.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2015-2017 Josh Poimboeuf + */ +#include + +#include +#include +#include + +static unsigned long nr_insns; + +/* + * Call the arch-specific instruction decoder for all the instructions and add + * them to the global instruction list. + */ +int decode_instructions(struct objtool_file *file) +{ + struct section *sec; + struct symbol *func; + unsigned long offset; + struct instruction *insn; + int ret; + + for_each_sec(file, sec) { + + if (!(sec->sh.sh_flags & SHF_EXECINSTR)) + continue; + + if (strcmp(sec->name, ".altinstr_replacement") && + strcmp(sec->name, ".altinstr_aux") && + strncmp(sec->name, ".discard.", 9)) + sec->text = true; + + if (!strcmp(sec->name, ".noinstr.text") || + !strcmp(sec->name, ".entry.text")) + sec->noinstr = true; + + for (offset = 0; offset < sec->sh.sh_size; offset += insn->len) { + insn = malloc(sizeof(*insn)); + if (!insn) { + WARN("malloc failed"); + return -1; + } + memset(insn, 0, sizeof(*insn)); + INIT_LIST_HEAD(&insn->alts); + INIT_LIST_HEAD(&insn->stack_ops); + INIT_LIST_HEAD(&insn->call_node); + + insn->sec = sec; + insn->offset = offset; + + ret = arch_decode_instruction(file, sec, offset, + sec->sh.sh_size - offset, + &insn->len, &insn->type, + &insn->immediate, + &insn->stack_ops); + if (ret) + goto err; + + /* + * By default, "ud2" is a dead end unless otherwise + * annotated, because GCC 7 inserts it for certain + * divide-by-zero cases. + */ + if (insn->type == INSN_BUG) + insn->dead_end = true; + + hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); + list_add_tail(&insn->list, &file->insn_list); + nr_insns++; + } + + list_for_each_entry(func, &sec->symbol_list, list) { + if (func->type != STT_FUNC || func->alias != func) + continue; + + if (!find_insn(file, sec, func->offset)) { + WARN("%s(): can't find starting instruction", + func->name); + return -1; + } + + sym_for_each_insn(file, func, insn) { + insn->func = func; + if (insn->type == INSN_ENDBR && list_empty(&insn->call_node)) { + if (insn->offset == insn->func->offset) { + list_add_tail(&insn->call_node, &file->endbr_list); + file->nr_endbr++; + } else { + file->nr_endbr_int++; + } + } + } + } + } + + if (stats) + printf("nr_insns: %lu\n", nr_insns); + + return 0; + +err: + free(insn); + return ret; +} diff --git a/tools/objtool/include/objtool/insn.h b/tools/objtool/include/objtool/insn.h index 1b9fce586679..5f01fd0ce8ed 100644 --- a/tools/objtool/include/objtool/insn.h +++ b/tools/objtool/include/objtool/insn.h @@ -83,6 +83,7 @@ struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn); bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2); bool same_function(struct instruction *insn1, struct instruction *insn2); bool is_first_func_insn(struct instruction *insn); +int decode_instructions(struct objtool_file *file); #define for_each_insn(file, insn) \ list_for_each_entry(insn, &file->insn_list, list)