All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sathvika Vasireddy <sv@linux.ibm.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: jpoimboe@redhat.com, peterz@infradead.org,
	linux-kernel@vger.kernel.org, aik@ozlabs.ru, mpe@ellerman.id.au,
	rostedt@goodmis.org, naveen.n.rao@linux.vnet.ibm.com,
	sv@linux.ibm.com
Subject: [RFC PATCH 2/3] objtool: Enable and implement 'mcount' subcommand
Date: Fri, 18 Mar 2022 16:21:39 +0530	[thread overview]
Message-ID: <20220318105140.43914-3-sv@linux.ibm.com> (raw)
In-Reply-To: <20220318105140.43914-1-sv@linux.ibm.com>

This patch adds 'mcount' as a subcommand to objtool, and enables
the same for x86. objtool is built if CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
is selected. Additionally, architectures can select HAVE_NOP_MCOUNT
if they choose to nop out mcount call sites. If that config option is
selected, then --mnop is passed as an option to 'objtool mcount'

Signed-off-by: Sathvika Vasireddy <sv@linux.ibm.com>
---
 Makefile                                |   6 ++
 arch/x86/Kconfig                        |   3 +-
 scripts/Makefile.build                  |  12 +++
 tools/objtool/Build                     |   2 +
 tools/objtool/Makefile                  |   4 +-
 tools/objtool/builtin-mcount.c          |  74 +++++++++++++
 tools/objtool/include/objtool/builtin.h |   4 +-
 tools/objtool/include/objtool/objtool.h |   1 +
 tools/objtool/mcount.c                  | 138 ++++++++++++++++++++++++
 tools/objtool/objtool.c                 |   1 +
 tools/objtool/weak.c                    |   5 +
 11 files changed, 247 insertions(+), 3 deletions(-)
 create mode 100644 tools/objtool/builtin-mcount.c
 create mode 100644 tools/objtool/mcount.c

diff --git a/Makefile b/Makefile
index 55a30ca69350..316f7d08b30a 100644
--- a/Makefile
+++ b/Makefile
@@ -846,7 +846,9 @@ ifdef CONFIG_FTRACE_MCOUNT_USE_CC
   endif
 endif
 ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+ ifdef CONFIG_HAVE_NOP_MCOUNT
   CC_FLAGS_USING	+= -DCC_USING_NOP_MCOUNT
+ endif
 endif
 ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
   ifdef CONFIG_HAVE_C_RECORDMCOUNT
@@ -1303,6 +1305,10 @@ ifdef CONFIG_STACK_VALIDATION
 prepare: tools/objtool
 endif
 
+ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+prepare: tools/objtool
+endif
+
 ifdef CONFIG_BPF
 ifdef CONFIG_DEBUG_INFO_BTF
 prepare: tools/bpf/resolve_btfids
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9f5bd41bf660..eecfe588cd9f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -185,7 +185,8 @@ config X86
 	select HAVE_CONTEXT_TRACKING		if X86_64
 	select HAVE_CONTEXT_TRACKING_OFFSTACK	if HAVE_CONTEXT_TRACKING
 	select HAVE_C_RECORDMCOUNT
-	select HAVE_OBJTOOL_MCOUNT		if STACK_VALIDATION
+	select HAVE_OBJTOOL_MCOUNT
+	select HAVE_NOP_MCOUNT			if HAVE_OBJTOOL_MCOUNT
 	select HAVE_BUILDTIME_MCOUNT_SORT
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_CONTIGUOUS
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index a4b89b757287..6a09b4ba14a1 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -242,6 +242,18 @@ cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(o
 
 endif # CONFIG_STACK_VALIDATION
 
+ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+
+objtool := $(objtree)/tools/objtool/objtool
+
+objtool_args := mcount
+objtool_args += $(if $(CONFIG_HAVE_NOP_MCOUNT), --mnop)
+
+cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@)
+cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd)
+
+endif # CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+
 ifdef CONFIG_LTO_CLANG
 
 # Skip objtool for LLVM bitcode
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 161fd451241a..0b9b8bd0ee92 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -2,12 +2,14 @@ objtool-y += arch/$(SRCARCH)/
 
 objtool-y += weak.o
 
+objtool-$(SUBCMD_MCOUNT) += mcount.o
 objtool-$(SUBCMD_CHECK) += check.o
 objtool-$(SUBCMD_CHECK) += special.o
 objtool-$(SUBCMD_ORC) += check.o
 objtool-$(SUBCMD_ORC) += orc_gen.o
 objtool-$(SUBCMD_ORC) += orc_dump.o
 
+objtool-y += builtin-mcount.o
 objtool-y += builtin-check.o
 objtool-y += builtin-orc.o
 objtool-y += elf.o
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 92ce4fce7bc7..8404cf696954 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -41,13 +41,15 @@ AWK = awk
 
 SUBCMD_CHECK := n
 SUBCMD_ORC := n
+SUBCMD_MCOUNT := n
 
 ifeq ($(SRCARCH),x86)
 	SUBCMD_CHECK := y
 	SUBCMD_ORC := y
+	SUBCMD_MCOUNT := y
 endif
 
-export SUBCMD_CHECK SUBCMD_ORC
+export SUBCMD_CHECK SUBCMD_ORC SUBCMD_MCOUNT
 export srctree OUTPUT CFLAGS SRCARCH AWK
 include $(srctree)/tools/build/Makefile.include
 
diff --git a/tools/objtool/builtin-mcount.c b/tools/objtool/builtin-mcount.c
new file mode 100644
index 000000000000..f203d118cffa
--- /dev/null
+++ b/tools/objtool/builtin-mcount.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <subcmd/parse-options.h>
+#include <string.h>
+#include <stdlib.h>
+#include <objtool/builtin.h>
+#include <objtool/objtool.h>
+
+bool mnop;
+
+static const char * const mcount_usage[] = {
+	"objtool mcount [<options>] file.o",
+	NULL,
+};
+
+static const char * const env_usage[] = {
+	"OBJTOOL_ARGS=\"<options>\"",
+	NULL,
+};
+
+const struct option mcount_options[] = {
+	OPT_BOOLEAN('N', "mnop", &mnop, "nop mcount call sites"),
+	OPT_END(),
+};
+
+int cmd_parse_options_mcount(int argc, const char **argv, const char * const usage[])
+{
+	const char *envv[16] = { };
+	char *env;
+	int envc;
+
+	env = getenv("OBJTOOL_ARGS");
+	if (env) {
+		envv[0] = "OBJTOOL_ARGS";
+		for (envc = 1; envc < ARRAY_SIZE(envv); ) {
+			envv[envc++] = env;
+			env = strchr(env, ' ');
+			if (!env)
+				break;
+			*env = '\0';
+			env++;
+		}
+
+		parse_options(envc, envv, mcount_options, env_usage, 0);
+	}
+
+	argc = parse_options(argc, argv, mcount_options, usage, 0);
+	if (argc != 1)
+		usage_with_options(usage, mcount_options);
+	return argc;
+}
+
+int cmd_mcount(int argc, const char **argv)
+{
+	const char *objname;
+	struct objtool_file *file;
+	int ret;
+
+	argc = cmd_parse_options_mcount(argc, argv, mcount_usage);
+	objname = argv[0];
+
+	file = objtool_open_read(objname);
+	if (!file)
+		return 1;
+
+	ret = objtool_mcount(file);
+	if (ret)
+		return ret;
+
+	if (file->elf->changed)
+		return elf_write(file->elf);
+
+	return 0;
+}
diff --git a/tools/objtool/include/objtool/builtin.h b/tools/objtool/include/objtool/builtin.h
index 89ba869ed08f..d7ed6ff65729 100644
--- a/tools/objtool/include/objtool/builtin.h
+++ b/tools/objtool/include/objtool/builtin.h
@@ -9,11 +9,13 @@
 
 extern const struct option check_options[];
 extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats,
-            validate_dup, vmlinux, mcount, noinstr, backup, sls;
+	    validate_dup, vmlinux, mcount, noinstr, backup, sls, mnop;
 
 extern int cmd_parse_options(int argc, const char **argv, const char * const usage[]);
+extern int cmd_parse_options_mcount(int argc, const char **argv, const char * const usage[]);
 
 extern int cmd_check(int argc, const char **argv);
 extern int cmd_orc(int argc, const char **argv);
+extern int cmd_mcount(int argc, const char **argv);
 
 #endif /* _BUILTIN_H */
diff --git a/tools/objtool/include/objtool/objtool.h b/tools/objtool/include/objtool/objtool.h
index f99fbc6078d5..edcf28d4407c 100644
--- a/tools/objtool/include/objtool/objtool.h
+++ b/tools/objtool/include/objtool/objtool.h
@@ -41,5 +41,6 @@ void objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func);
 int check(struct objtool_file *file);
 int orc_dump(const char *objname);
 int orc_create(struct objtool_file *file);
+int objtool_mcount(struct objtool_file *file);
 
 #endif /* _OBJTOOL_H */
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
new file mode 100644
index 000000000000..fc3d215671bf
--- /dev/null
+++ b/tools/objtool/mcount.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#include <arch/elf.h>
+#include <objtool/builtin.h>
+#include <objtool/cfi.h>
+#include <objtool/arch.h>
+#include <objtool/check.h>
+#include <objtool/utils.h>
+#include <objtool/special.h>
+#include <objtool/warn.h>
+
+#include <linux/objtool.h>
+#include <linux/hashtable.h>
+#include <linux/kernel.h>
+#include <linux/static_call_types.h>
+
+static int classify_symbols(struct objtool_file *file)
+{
+	struct section *sec;
+	struct symbol *func;
+
+	for_each_sec(file, sec) {
+		list_for_each_entry(func, &sec->symbol_list, list) {
+			if (func->bind != STB_GLOBAL)
+				continue;
+			if ((!strcmp(func->name, "__fentry__")) || (!strcmp(func->name, "_mcount")))
+				func->fentry = true;
+		}
+	}
+
+	return 0;
+}
+
+static void annotate_call_site(struct objtool_file *file,
+							   struct instruction *insn, bool sibling)
+{
+	struct reloc *reloc = insn_reloc(file, insn);
+	struct symbol *sym = insn->call_dest;
+
+	if (!sym)
+		sym = reloc->sym;
+
+	if (sym->fentry) {
+		if (sibling)
+			WARN_FUNC("Tail call to _mcount !?!?", insn->sec, insn->offset);
+		if (mnop) {
+			if (reloc) {
+				reloc->type = R_NONE;
+				elf_write_reloc(file->elf, reloc);
+			}
+			elf_write_insn(file->elf, insn->sec,
+				       insn->offset, insn->len,
+				       arch_nop_insn(insn->len));
+
+			insn->type = INSN_NOP;
+		}
+
+		list_add_tail(&insn->call_node, &file->mcount_loc_list);
+		return;
+	}
+}
+
+static void add_call_dest(struct objtool_file *file, struct instruction *insn,
+						  struct symbol *dest, bool sibling)
+{
+	insn->call_dest = dest;
+	if (!dest)
+		return;
+
+	remove_insn_ops(insn);
+
+	annotate_call_site(file, insn, sibling);
+}
+static int add_call_destinations(struct objtool_file *file)
+{
+	struct instruction *insn;
+	unsigned long dest_off;
+	struct symbol *dest;
+	struct reloc *reloc;
+
+	for_each_insn(file, insn) {
+		if (insn->type != INSN_CALL)
+			continue;
+
+		reloc = insn_reloc(file, insn);
+		if (!reloc) {
+			dest_off = arch_jump_destination(insn);
+			dest = find_call_destination(insn->sec, dest_off);
+
+			add_call_dest(file, insn, dest, false);
+
+
+		} else {
+			add_call_dest(file, insn, reloc->sym, false);
+		}
+	}
+
+	return 0;
+}
+
+static int decode_sections(struct objtool_file *file)
+{
+	int ret;
+
+	ret = decode_instructions(file);
+	if (ret)
+		return ret;
+
+	ret = classify_symbols(file);
+	if (ret)
+		return ret;
+
+	ret = add_call_destinations(file);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+
+int objtool_mcount(struct objtool_file *file)
+{
+	int ret, warnings = 0;
+
+	ret = decode_sections(file);
+	if (ret < 0)
+		return 0;
+
+	ret = create_mcount_loc_sections(file);
+	if (ret < 0)
+		return 0;
+	warnings += ret;
+	return 0;
+}
diff --git a/tools/objtool/objtool.c b/tools/objtool/objtool.c
index bdf699f6552b..e19851813d5b 100644
--- a/tools/objtool/objtool.c
+++ b/tools/objtool/objtool.c
@@ -37,6 +37,7 @@ static const char objtool_usage_string[] =
 
 static struct cmd_struct objtool_cmds[] = {
 	{"check",	cmd_check,	"Perform stack metadata validation on an object file" },
+	{"mcount",      cmd_mcount,    "Generate __mcount_loc section" },
 	{"orc",		cmd_orc,	"Generate in-place ORC unwind tables for an object file" },
 };
 
diff --git a/tools/objtool/weak.c b/tools/objtool/weak.c
index 8314e824db4a..19b2dfcacf2e 100644
--- a/tools/objtool/weak.c
+++ b/tools/objtool/weak.c
@@ -29,3 +29,8 @@ int __weak orc_create(struct objtool_file *file)
 {
 	UNSUPPORTED("orc");
 }
+
+int __weak objtool_mcount(struct objtool_file *file)
+{
+	UNSUPPORTED("mcount subcommand");
+}
-- 
2.31.1


WARNING: multiple messages have this Message-ID (diff)
From: Sathvika Vasireddy <sv@linux.ibm.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: peterz@infradead.org, linux-kernel@vger.kernel.org,
	rostedt@goodmis.org, aik@ozlabs.ru, sv@linux.ibm.com,
	jpoimboe@redhat.com, naveen.n.rao@linux.vnet.ibm.com
Subject: [RFC PATCH 2/3] objtool: Enable and implement 'mcount' subcommand
Date: Fri, 18 Mar 2022 16:21:39 +0530	[thread overview]
Message-ID: <20220318105140.43914-3-sv@linux.ibm.com> (raw)
In-Reply-To: <20220318105140.43914-1-sv@linux.ibm.com>

This patch adds 'mcount' as a subcommand to objtool, and enables
the same for x86. objtool is built if CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
is selected. Additionally, architectures can select HAVE_NOP_MCOUNT
if they choose to nop out mcount call sites. If that config option is
selected, then --mnop is passed as an option to 'objtool mcount'

Signed-off-by: Sathvika Vasireddy <sv@linux.ibm.com>
---
 Makefile                                |   6 ++
 arch/x86/Kconfig                        |   3 +-
 scripts/Makefile.build                  |  12 +++
 tools/objtool/Build                     |   2 +
 tools/objtool/Makefile                  |   4 +-
 tools/objtool/builtin-mcount.c          |  74 +++++++++++++
 tools/objtool/include/objtool/builtin.h |   4 +-
 tools/objtool/include/objtool/objtool.h |   1 +
 tools/objtool/mcount.c                  | 138 ++++++++++++++++++++++++
 tools/objtool/objtool.c                 |   1 +
 tools/objtool/weak.c                    |   5 +
 11 files changed, 247 insertions(+), 3 deletions(-)
 create mode 100644 tools/objtool/builtin-mcount.c
 create mode 100644 tools/objtool/mcount.c

diff --git a/Makefile b/Makefile
index 55a30ca69350..316f7d08b30a 100644
--- a/Makefile
+++ b/Makefile
@@ -846,7 +846,9 @@ ifdef CONFIG_FTRACE_MCOUNT_USE_CC
   endif
 endif
 ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+ ifdef CONFIG_HAVE_NOP_MCOUNT
   CC_FLAGS_USING	+= -DCC_USING_NOP_MCOUNT
+ endif
 endif
 ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
   ifdef CONFIG_HAVE_C_RECORDMCOUNT
@@ -1303,6 +1305,10 @@ ifdef CONFIG_STACK_VALIDATION
 prepare: tools/objtool
 endif
 
+ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+prepare: tools/objtool
+endif
+
 ifdef CONFIG_BPF
 ifdef CONFIG_DEBUG_INFO_BTF
 prepare: tools/bpf/resolve_btfids
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9f5bd41bf660..eecfe588cd9f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -185,7 +185,8 @@ config X86
 	select HAVE_CONTEXT_TRACKING		if X86_64
 	select HAVE_CONTEXT_TRACKING_OFFSTACK	if HAVE_CONTEXT_TRACKING
 	select HAVE_C_RECORDMCOUNT
-	select HAVE_OBJTOOL_MCOUNT		if STACK_VALIDATION
+	select HAVE_OBJTOOL_MCOUNT
+	select HAVE_NOP_MCOUNT			if HAVE_OBJTOOL_MCOUNT
 	select HAVE_BUILDTIME_MCOUNT_SORT
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_CONTIGUOUS
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index a4b89b757287..6a09b4ba14a1 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -242,6 +242,18 @@ cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(o
 
 endif # CONFIG_STACK_VALIDATION
 
+ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+
+objtool := $(objtree)/tools/objtool/objtool
+
+objtool_args := mcount
+objtool_args += $(if $(CONFIG_HAVE_NOP_MCOUNT), --mnop)
+
+cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@)
+cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd)
+
+endif # CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+
 ifdef CONFIG_LTO_CLANG
 
 # Skip objtool for LLVM bitcode
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 161fd451241a..0b9b8bd0ee92 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -2,12 +2,14 @@ objtool-y += arch/$(SRCARCH)/
 
 objtool-y += weak.o
 
+objtool-$(SUBCMD_MCOUNT) += mcount.o
 objtool-$(SUBCMD_CHECK) += check.o
 objtool-$(SUBCMD_CHECK) += special.o
 objtool-$(SUBCMD_ORC) += check.o
 objtool-$(SUBCMD_ORC) += orc_gen.o
 objtool-$(SUBCMD_ORC) += orc_dump.o
 
+objtool-y += builtin-mcount.o
 objtool-y += builtin-check.o
 objtool-y += builtin-orc.o
 objtool-y += elf.o
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 92ce4fce7bc7..8404cf696954 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -41,13 +41,15 @@ AWK = awk
 
 SUBCMD_CHECK := n
 SUBCMD_ORC := n
+SUBCMD_MCOUNT := n
 
 ifeq ($(SRCARCH),x86)
 	SUBCMD_CHECK := y
 	SUBCMD_ORC := y
+	SUBCMD_MCOUNT := y
 endif
 
-export SUBCMD_CHECK SUBCMD_ORC
+export SUBCMD_CHECK SUBCMD_ORC SUBCMD_MCOUNT
 export srctree OUTPUT CFLAGS SRCARCH AWK
 include $(srctree)/tools/build/Makefile.include
 
diff --git a/tools/objtool/builtin-mcount.c b/tools/objtool/builtin-mcount.c
new file mode 100644
index 000000000000..f203d118cffa
--- /dev/null
+++ b/tools/objtool/builtin-mcount.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <subcmd/parse-options.h>
+#include <string.h>
+#include <stdlib.h>
+#include <objtool/builtin.h>
+#include <objtool/objtool.h>
+
+bool mnop;
+
+static const char * const mcount_usage[] = {
+	"objtool mcount [<options>] file.o",
+	NULL,
+};
+
+static const char * const env_usage[] = {
+	"OBJTOOL_ARGS=\"<options>\"",
+	NULL,
+};
+
+const struct option mcount_options[] = {
+	OPT_BOOLEAN('N', "mnop", &mnop, "nop mcount call sites"),
+	OPT_END(),
+};
+
+int cmd_parse_options_mcount(int argc, const char **argv, const char * const usage[])
+{
+	const char *envv[16] = { };
+	char *env;
+	int envc;
+
+	env = getenv("OBJTOOL_ARGS");
+	if (env) {
+		envv[0] = "OBJTOOL_ARGS";
+		for (envc = 1; envc < ARRAY_SIZE(envv); ) {
+			envv[envc++] = env;
+			env = strchr(env, ' ');
+			if (!env)
+				break;
+			*env = '\0';
+			env++;
+		}
+
+		parse_options(envc, envv, mcount_options, env_usage, 0);
+	}
+
+	argc = parse_options(argc, argv, mcount_options, usage, 0);
+	if (argc != 1)
+		usage_with_options(usage, mcount_options);
+	return argc;
+}
+
+int cmd_mcount(int argc, const char **argv)
+{
+	const char *objname;
+	struct objtool_file *file;
+	int ret;
+
+	argc = cmd_parse_options_mcount(argc, argv, mcount_usage);
+	objname = argv[0];
+
+	file = objtool_open_read(objname);
+	if (!file)
+		return 1;
+
+	ret = objtool_mcount(file);
+	if (ret)
+		return ret;
+
+	if (file->elf->changed)
+		return elf_write(file->elf);
+
+	return 0;
+}
diff --git a/tools/objtool/include/objtool/builtin.h b/tools/objtool/include/objtool/builtin.h
index 89ba869ed08f..d7ed6ff65729 100644
--- a/tools/objtool/include/objtool/builtin.h
+++ b/tools/objtool/include/objtool/builtin.h
@@ -9,11 +9,13 @@
 
 extern const struct option check_options[];
 extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats,
-            validate_dup, vmlinux, mcount, noinstr, backup, sls;
+	    validate_dup, vmlinux, mcount, noinstr, backup, sls, mnop;
 
 extern int cmd_parse_options(int argc, const char **argv, const char * const usage[]);
+extern int cmd_parse_options_mcount(int argc, const char **argv, const char * const usage[]);
 
 extern int cmd_check(int argc, const char **argv);
 extern int cmd_orc(int argc, const char **argv);
+extern int cmd_mcount(int argc, const char **argv);
 
 #endif /* _BUILTIN_H */
diff --git a/tools/objtool/include/objtool/objtool.h b/tools/objtool/include/objtool/objtool.h
index f99fbc6078d5..edcf28d4407c 100644
--- a/tools/objtool/include/objtool/objtool.h
+++ b/tools/objtool/include/objtool/objtool.h
@@ -41,5 +41,6 @@ void objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func);
 int check(struct objtool_file *file);
 int orc_dump(const char *objname);
 int orc_create(struct objtool_file *file);
+int objtool_mcount(struct objtool_file *file);
 
 #endif /* _OBJTOOL_H */
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
new file mode 100644
index 000000000000..fc3d215671bf
--- /dev/null
+++ b/tools/objtool/mcount.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#include <arch/elf.h>
+#include <objtool/builtin.h>
+#include <objtool/cfi.h>
+#include <objtool/arch.h>
+#include <objtool/check.h>
+#include <objtool/utils.h>
+#include <objtool/special.h>
+#include <objtool/warn.h>
+
+#include <linux/objtool.h>
+#include <linux/hashtable.h>
+#include <linux/kernel.h>
+#include <linux/static_call_types.h>
+
+static int classify_symbols(struct objtool_file *file)
+{
+	struct section *sec;
+	struct symbol *func;
+
+	for_each_sec(file, sec) {
+		list_for_each_entry(func, &sec->symbol_list, list) {
+			if (func->bind != STB_GLOBAL)
+				continue;
+			if ((!strcmp(func->name, "__fentry__")) || (!strcmp(func->name, "_mcount")))
+				func->fentry = true;
+		}
+	}
+
+	return 0;
+}
+
+static void annotate_call_site(struct objtool_file *file,
+							   struct instruction *insn, bool sibling)
+{
+	struct reloc *reloc = insn_reloc(file, insn);
+	struct symbol *sym = insn->call_dest;
+
+	if (!sym)
+		sym = reloc->sym;
+
+	if (sym->fentry) {
+		if (sibling)
+			WARN_FUNC("Tail call to _mcount !?!?", insn->sec, insn->offset);
+		if (mnop) {
+			if (reloc) {
+				reloc->type = R_NONE;
+				elf_write_reloc(file->elf, reloc);
+			}
+			elf_write_insn(file->elf, insn->sec,
+				       insn->offset, insn->len,
+				       arch_nop_insn(insn->len));
+
+			insn->type = INSN_NOP;
+		}
+
+		list_add_tail(&insn->call_node, &file->mcount_loc_list);
+		return;
+	}
+}
+
+static void add_call_dest(struct objtool_file *file, struct instruction *insn,
+						  struct symbol *dest, bool sibling)
+{
+	insn->call_dest = dest;
+	if (!dest)
+		return;
+
+	remove_insn_ops(insn);
+
+	annotate_call_site(file, insn, sibling);
+}
+static int add_call_destinations(struct objtool_file *file)
+{
+	struct instruction *insn;
+	unsigned long dest_off;
+	struct symbol *dest;
+	struct reloc *reloc;
+
+	for_each_insn(file, insn) {
+		if (insn->type != INSN_CALL)
+			continue;
+
+		reloc = insn_reloc(file, insn);
+		if (!reloc) {
+			dest_off = arch_jump_destination(insn);
+			dest = find_call_destination(insn->sec, dest_off);
+
+			add_call_dest(file, insn, dest, false);
+
+
+		} else {
+			add_call_dest(file, insn, reloc->sym, false);
+		}
+	}
+
+	return 0;
+}
+
+static int decode_sections(struct objtool_file *file)
+{
+	int ret;
+
+	ret = decode_instructions(file);
+	if (ret)
+		return ret;
+
+	ret = classify_symbols(file);
+	if (ret)
+		return ret;
+
+	ret = add_call_destinations(file);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+
+int objtool_mcount(struct objtool_file *file)
+{
+	int ret, warnings = 0;
+
+	ret = decode_sections(file);
+	if (ret < 0)
+		return 0;
+
+	ret = create_mcount_loc_sections(file);
+	if (ret < 0)
+		return 0;
+	warnings += ret;
+	return 0;
+}
diff --git a/tools/objtool/objtool.c b/tools/objtool/objtool.c
index bdf699f6552b..e19851813d5b 100644
--- a/tools/objtool/objtool.c
+++ b/tools/objtool/objtool.c
@@ -37,6 +37,7 @@ static const char objtool_usage_string[] =
 
 static struct cmd_struct objtool_cmds[] = {
 	{"check",	cmd_check,	"Perform stack metadata validation on an object file" },
+	{"mcount",      cmd_mcount,    "Generate __mcount_loc section" },
 	{"orc",		cmd_orc,	"Generate in-place ORC unwind tables for an object file" },
 };
 
diff --git a/tools/objtool/weak.c b/tools/objtool/weak.c
index 8314e824db4a..19b2dfcacf2e 100644
--- a/tools/objtool/weak.c
+++ b/tools/objtool/weak.c
@@ -29,3 +29,8 @@ int __weak orc_create(struct objtool_file *file)
 {
 	UNSUPPORTED("orc");
 }
+
+int __weak objtool_mcount(struct objtool_file *file)
+{
+	UNSUPPORTED("mcount subcommand");
+}
-- 
2.31.1


  parent reply	other threads:[~2022-03-18 10:54 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-18 10:51 [RFC PATCH 0/3] objtool: Add mcount sub-command Sathvika Vasireddy
2022-03-18 10:51 ` Sathvika Vasireddy
2022-03-18 10:51 ` [RFC PATCH 1/3] objtool: Move common code to utils.c Sathvika Vasireddy
2022-03-18 10:51   ` Sathvika Vasireddy
2022-03-23 18:02   ` Miroslav Benes
2022-03-23 18:02     ` Miroslav Benes
2022-03-18 10:51 ` Sathvika Vasireddy [this message]
2022-03-18 10:51   ` [RFC PATCH 2/3] objtool: Enable and implement 'mcount' subcommand Sathvika Vasireddy
2022-03-21  7:06   ` Christophe Leroy
2022-03-21  8:19     ` Naveen N. Rao
2022-03-21  8:19       ` Naveen N. Rao
2022-03-21  8:26       ` Christophe Leroy
2022-03-21  8:26         ` Christophe Leroy
2022-03-21  9:48         ` Naveen N. Rao
2022-03-21  9:48           ` Naveen N. Rao
2022-03-18 10:51 ` [RFC PATCH 3/3] objtool/mcount: Add powerpc specific functions Sathvika Vasireddy
2022-03-18 10:51   ` Sathvika Vasireddy
2022-03-18 12:26   ` Peter Zijlstra
2022-03-18 12:26     ` Peter Zijlstra
2022-03-18 13:59     ` Christophe Leroy
2022-03-18 13:59       ` Christophe Leroy
2022-03-21  2:27       ` Michael Ellerman
2022-03-21  6:47         ` Christophe Leroy
2022-03-21  7:46         ` Christophe Leroy
2022-03-21  7:56         ` Christophe Leroy
2022-03-21  8:30           ` Christophe Leroy
2022-03-21  8:59             ` Christophe Leroy
2022-03-26  7:58           ` Christophe Leroy
2022-03-26  7:58             ` Christophe Leroy
2022-03-21  6:25     ` Naveen N. Rao
2022-03-21  6:25       ` Naveen N. Rao
2022-03-27  9:09     ` Christophe Leroy
2022-03-27  9:09       ` Christophe Leroy
2022-03-28 19:59       ` Josh Poimboeuf
2022-03-28 19:59         ` Josh Poimboeuf
2022-03-28 20:14         ` Peter Zijlstra
2022-03-28 20:14           ` Peter Zijlstra
2022-03-28 20:15           ` Peter Zijlstra
2022-03-28 20:15             ` Peter Zijlstra
2022-03-28 20:21           ` Josh Poimboeuf
2022-03-28 20:21             ` Josh Poimboeuf
2022-03-29 12:01         ` Michael Ellerman
2022-03-29 12:01           ` Michael Ellerman
2022-03-29 17:32           ` Christophe Leroy
2022-03-30  4:26             ` Josh Poimboeuf
2022-03-30  4:26               ` Josh Poimboeuf
2022-03-30 18:40             ` Naveen N. Rao
2022-03-30 18:40               ` Naveen N. Rao
2022-05-12 14:52         ` Christophe Leroy
2022-05-12 14:52           ` Christophe Leroy
2022-05-12 15:12           ` Josh Poimboeuf
2022-05-12 15:12             ` Josh Poimboeuf
2022-05-21  9:38             ` Christophe Leroy
2022-05-21  9:38               ` Christophe Leroy
2022-05-21 10:57               ` Peter Zijlstra
2022-05-21 10:57                 ` Peter Zijlstra
2022-05-23  5:39                 ` Naveen N. Rao
2022-05-23  5:39                   ` Naveen N. Rao
2022-03-19  1:35 ` [RFC PATCH 0/3] objtool: Add mcount sub-command Josh Poimboeuf
2022-03-19  1:35   ` Josh Poimboeuf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220318105140.43914-3-sv@linux.ibm.com \
    --to=sv@linux.ibm.com \
    --cc=aik@ozlabs.ru \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=mpe@ellerman.id.au \
    --cc=naveen.n.rao@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.