Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp5217170ybi; Tue, 11 Jun 2019 22:00:48 -0700 (PDT) X-Google-Smtp-Source: APXvYqwJMGFSV69mCY7wLHwklaF/vIGZFIAdcmlq2rTi8JMqbC2RYQR3g7ESf5CzO1lq0GTuF8Kh X-Received: by 2002:a63:234c:: with SMTP id u12mr23739577pgm.264.1560315648711; Tue, 11 Jun 2019 22:00:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560315648; cv=none; d=google.com; s=arc-20160816; b=s+5uTlIqFJWrJsj/iawgJNhmtQNtOlMT+2iuV95o0w/szg2HKI5Nm3HGGLs8GPS2x8 TM0JzcRm4qVWCsMh7f+mKGJgb2JEkDL/4EgWKRurGFU5bpJaW08/ehLBTYiInjAAcyEc 4E7zxCbg9B3cSoftUIM+6NwlqqnxUhaSoaPKxbWTcz8vX5ESGDctomdToW8kdDFtVHus ChScTqQe0WiIXgRoclDO0jMcAjchqn8JkIpi+pRC5BPc7tWHmUM6pQ/8Tn17vJ/J//td CWw/i+dAfRE4ukAJtk65Cl7j8lbu6ulrJcwr2zQbDHY3svCnzwunPPxo2lLjjQAWeo8a Tp1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=yuVwdt3CAPP87O6/K9cLhc4IByXZ65Pvi49QQkm7D0I=; b=rc4sOAsOLn3ujSZVT2uS96oNv2WMaOd+FmYekXsHW96p5Cq57fcja+mxAXQRiZGfmz 1xKD8TXg0fPxZPEJxCvxn63VrmpDq2eDYVTjIdKpfzvRr2uBeIPpJFVURgZjCCewijca ifLXvUM5opJEiPN0GoK+2vCOlw5Dv6lmrAOEw10qtyMe1pVLN27Jdn3NUUB6Qov4K+dR ORFvTSi3J6xfnHE7/ONPEbWvc0XNtMIg+ZcliUlOj25pVtKwmf2OGNPQ2XVv4f+WDf4e ok1QXFPri1rCMXDYC8rEiTE60lXJ6zQuJbtDsgk1xaO1qlDLXON4p0H2TlGp3fOV4hwe bAoA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=vmware.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 31si15383091plk.342.2019.06.11.22.00.32; Tue, 11 Jun 2019 22:00:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=vmware.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2436892AbfFKWW1 (ORCPT + 99 others); Tue, 11 Jun 2019 18:22:27 -0400 Received: from ex13-edg-ou-001.vmware.com ([208.91.0.189]:3298 "EHLO EX13-EDG-OU-001.vmware.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2436835AbfFKWWU (ORCPT ); Tue, 11 Jun 2019 18:22:20 -0400 Received: from sc9-mailhost3.vmware.com (10.113.161.73) by EX13-EDG-OU-001.vmware.com (10.113.208.155) with Microsoft SMTP Server id 15.0.1156.6; Tue, 11 Jun 2019 15:22:11 -0700 Received: from rlwimi.localdomain (unknown [10.129.220.121]) by sc9-mailhost3.vmware.com (Postfix) with ESMTP id 3038141BB1; Tue, 11 Jun 2019 15:22:18 -0700 (PDT) From: Matt Helsley To: LKML CC: Ingo Molnar , Josh Poimboeuf , Peter Zijlstra , Steven Rostedt , Matt Helsley Subject: [PATCH v2 10/13] objtool: Make recordmcount into an objtool subcmd Date: Tue, 11 Jun 2019 15:21:52 -0700 Message-ID: X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII Received-SPF: None (EX13-EDG-OU-001.vmware.com: mhelsley@vmware.com does not designate permitted sender hosts) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rather than a standalone executable merge recordmcount as a sub command of objtool. This is a small step towards cleaning up recordmcount and eventually saving ELF code with objtool. For the initial step all that's required is a bit of Makefile changes and invoking the former main() function from recordmcount.c because the subcommand code uses similar function arguments as main when dispatching. objtool ignores some object files that tracing does not, specifically those with OBJECT_FILES_NON_STANDARD Makefile variables. For this reason we keep the recordmcount_dep separate from the objtool_dep. When using objtool mcount we can also, like the other objtool invocations, just depend on the binary rather than the source the binary is built from. Subsequent patches will gradually convert recordmcount to use more and more of libelf/objtool's ELF accessor code. This will both clean up recordmcount to be more easily readable and remove recordmcount's crude accessor wrapping code. Signed-off-by: Matt Helsley --- Makefile | 6 +-- scripts/Makefile.build | 24 ++++++------ tools/objtool/Build | 3 +- tools/objtool/Makefile | 12 +----- tools/objtool/builtin-mcount.c | 72 ++++++++++++++++++++++++++++++++++ tools/objtool/builtin-mcount.h | 23 +++++++++++ tools/objtool/builtin.h | 1 + tools/objtool/objtool.c | 1 + tools/objtool/recordmcount.c | 29 +++++--------- 9 files changed, 123 insertions(+), 48 deletions(-) create mode 100644 tools/objtool/builtin-mcount.c create mode 100644 tools/objtool/builtin-mcount.h diff --git a/Makefile b/Makefile index b81e17261250..b2b20057deab 100644 --- a/Makefile +++ b/Makefile @@ -813,11 +813,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_FTRACE) $(CC_FLAGS_USING) KBUILD_AFLAGS += $(CC_FLAGS_USING) ifdef CONFIG_DYNAMIC_FTRACE ifdef CONFIG_HAVE_C_RECORDMCOUNT - BUILD_C_RECORDMCOUNT := y - export BUILD_C_RECORDMCOUNT + USE_OBJTOOL_MCOUNT := y + export USE_OBJTOOL_MCOUNT endif endif -endif +endif # CONFIG_FUNCTION_TRACER # We trigger additional mismatches with less inlining ifdef CONFIG_DEBUG_SECTION_MISMATCH diff --git a/scripts/Makefile.build b/scripts/Makefile.build index f32cfe63bb0e..98034b21bf48 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -175,22 +175,21 @@ endif ifdef CONFIG_FTRACE_MCOUNT_RECORD ifndef CC_USING_RECORD_MCOUNT -# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl -ifdef BUILD_C_RECORDMCOUNT +# compiler will not generate __mcount_loc use objtool mcount record or recordmcount.pl +ifdef USE_OBJTOOL_MCOUNT ifeq ("$(origin RECORDMCOUNT_WARN)", "command line") RECORDMCOUNT_FLAGS = -w endif # Due to recursion, we must skip empty.o. # The empty.o file is created in the make process in order to determine # the target endianness and word size. It is made before all other C -# files, including recordmcount. +# files, including objtool. sub_cmd_record_mcount = \ if [ $(@) != "scripts/mod/empty.o" ]; then \ - $(objtree)/tools/objtool/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \ + $(objtree)/tools/objtool/objtool mcount record $(RECORDMCOUNT_FLAGS) "$(@)"; \ fi; -recordmcount_source := $(srctree)/tools/objtool/recordmcount.c \ - $(srctree)/tools/objtool/recordmcount.h +recordmcount_dep := $(objtree)/tools/objtool/objtool else sub_cmd_record_mcount = perl $(srctree)/tools/objtool/recordmcount.pl "$(ARCH)" \ "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ @@ -198,8 +197,8 @@ sub_cmd_record_mcount = perl $(srctree)/tools/objtool/recordmcount.pl "$(ARCH)" "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \ "$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \ "$(if $(part-of-module),1,0)" "$(@)"; -recordmcount_source := $(srctree)/tools/objtool/recordmcount.pl -endif # BUILD_C_RECORDMCOUNT +recordmcount_dep := $(srctree)/tools/objtool/recordmcount.pl +endif # USE_OBJTOOL_MCOUNT cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \ $(sub_cmd_record_mcount)) endif # CC_USING_RECORD_MCOUNT @@ -241,9 +240,10 @@ endif # SKIP_STACK_VALIDATION endif # CONFIG_STACK_VALIDATION # Rebuild all objects when objtool changes, or is enabled/disabled. -objtool_dep = $(objtool_obj) \ +objtool_dep += $(objtool_obj) \ $(wildcard include/config/orc/unwinder.h \ - include/config/stack/validation.h) + include/config/stack/validation.h \ + include/config/ftrace/mcount/record.h) ifdef CONFIG_TRIM_UNUSED_KSYMS cmd_gen_ksymdeps = \ @@ -275,13 +275,13 @@ cmd_undef_syms = echo endif # Built-in and composite module parts -$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE +$(obj)/%.o: $(src)/%.c $(recordmcount_dep) $(objtool_dep) FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) # Single-part modules are special since we need to mark them in $(MODVERDIR) -$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE +$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_dep) $(objtool_dep) FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) @{ echo $(@:.o=.ko); echo $@; \ diff --git a/tools/objtool/Build b/tools/objtool/Build index 78c4a8a2f9e7..85e125e14c0d 100644 --- a/tools/objtool/Build +++ b/tools/objtool/Build @@ -1,6 +1,7 @@ objtool-y += arch/$(SRCARCH)/ objtool-y += builtin-check.o objtool-y += builtin-orc.o +objtool-y += builtin-mcount.o recordmcount.o objtool-y += check.o objtool-y += orc_gen.o objtool-y += orc_dump.o @@ -20,5 +21,3 @@ $(OUTPUT)libstring.o: ../lib/string.c FORCE $(OUTPUT)str_error_r.o: ../lib/str_error_r.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) - -recordmcount-y += recordmcount.o diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index bd9d0b6534cf..30f7e98ee8ef 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -29,12 +29,6 @@ OBJTOOL_IN := $(OBJTOOL)-in.o LIBELF_FLAGS := $(shell pkg-config libelf --cflags 2>/dev/null) LIBELF_LIBS := $(shell pkg-config libelf --libs 2>/dev/null || echo -lelf) -RECORDMCOUNT := $(OUTPUT)recordmcount -RECORDMCOUNT_IN := $(RECORDMCOUNT)-in.o -ifeq ($(BUILD_C_RECORDMCOUNT),y) -all: $(RECORDMCOUNT) -endif - all: $(OBJTOOL) INCLUDES := -I$(srctree)/tools/include \ @@ -55,21 +49,17 @@ include $(srctree)/tools/build/Makefile.include $(OBJTOOL_IN): fixdep FORCE @$(MAKE) $(build)=objtool -$(RECORDMCOUNT_IN): fixdep FORCE - @$(MAKE) $(build)=recordmcount $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) @$(CONFIG_SHELL) ./sync-check.sh $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ -$(RECORDMCOUNT): $(RECORDMCOUNT_IN) - $(QUIET_LINK)$(CC) $(RECORDMCOUNT_IN) $(KBUILD_HOSTLDFLAGS) -o $@ $(LIBSUBCMD): fixdep FORCE $(Q)$(MAKE) -C $(SUBCMD_SRCDIR) OUTPUT=$(LIBSUBCMD_OUTPUT) clean: - $(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL) $(RECORDMCOUNT) + $(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL) $(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete $(Q)$(RM) $(OUTPUT)arch/x86/lib/inat-tables.c $(OUTPUT)fixdep diff --git a/tools/objtool/builtin-mcount.c b/tools/objtool/builtin-mcount.c new file mode 100644 index 000000000000..0ed014b82b9d --- /dev/null +++ b/tools/objtool/builtin-mcount.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Matt Helsley + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * objtool mcount: + * + * This command analyzes a .o file and constructs a table of the locations of + * calls to 'mcount' useful to ftrace. We can optionally append this table to + * the object file ("objtool mcount record foo.o") or output it separately + * ("objtool mcount show"). The latter can be used to compare the expected + * callers of mcount to those actually found. + */ + +#include +#include +#include "builtin.h" + +#ifndef cmd_mcount +#include "builtin-mcount.h" + +static const char * const mcount_usage[] = { + "objtool mcount record [] file.o [file2.o ...]", + NULL, +}; + +bool warn_on_notrace_sect; + +const static struct option mcount_options[] = { + OPT_BOOLEAN('w', "warn-on-notrace-section", &warn_on_notrace_sect, + "Emit a warning when a section omitting mcount " + "(possibly due to \"notrace\" marking) is encountered"), + OPT_END(), +}; + +int cmd_mcount(int argc, const char **argv) +{ + argc--; argv++; + if (argc <= 0) + usage_with_options(mcount_usage, mcount_options); + + if (!strncmp(argv[0], "rec", 3)) { + if (argc != 2) + usage_with_options(mcount_usage, mcount_options); + + argc = parse_options(argc, argv, + mcount_options, mcount_usage, 0); + if (argc < 1) + usage_with_options(mcount_usage, mcount_options); + + return record_mcount(argc, argv); + } + + usage_with_options(mcount_usage, mcount_options); + + return 0; +} +#endif /* !def cmd_mcount */ diff --git a/tools/objtool/builtin-mcount.h b/tools/objtool/builtin-mcount.h new file mode 100644 index 000000000000..b7b508781127 --- /dev/null +++ b/tools/objtool/builtin-mcount.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Matt Helsley + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#ifndef BUILTIN_SUBCMD_MCOUNT +#define BUILTIN_SUBCMD_MCOUNT 1 + +extern int record_mcount(int argc, const char **argv); + +#endif /* BUILTIN_SUBCMD_MCOUNT */ diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h index a32736f8d2a4..125207c6a2fa 100644 --- a/tools/objtool/builtin.h +++ b/tools/objtool/builtin.h @@ -12,5 +12,6 @@ extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess; 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/objtool.c b/tools/objtool/objtool.c index 0b3528f05053..a2c45e70d74f 100644 --- a/tools/objtool/objtool.c +++ b/tools/objtool/objtool.c @@ -35,6 +35,7 @@ static const char objtool_usage_string[] = static struct cmd_struct objtool_cmds[] = { {"check", cmd_check, "Perform stack metadata validation on an object file" }, {"orc", cmd_orc, "Generate in-place ORC unwind tables for an object file" }, + {"mcount", cmd_mcount, "Construct a table of locations of calls to mcount. Useful for ftrace."}, }; bool help; diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c index 9f4af109277e..2de31e2913d1 100644 --- a/tools/objtool/recordmcount.c +++ b/tools/objtool/recordmcount.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -32,6 +31,8 @@ #include #include +#include "builtin-mcount.h" + #ifndef EM_AARCH64 #define EM_AARCH64 183 #define R_AARCH64_NONE 0 @@ -470,7 +471,7 @@ static int do_file(char const *const fname) goto out; case ELFDATA2LSB: if (*(unsigned char const *)&endian != 1) { - /* main() is big endian, file.o is little endian. */ + /* objtool is big endian, file.o is little endian. */ w = w4rev; w2 = w2rev; w8 = w8rev; @@ -483,7 +484,7 @@ static int do_file(char const *const fname) break; case ELFDATA2MSB: if (*(unsigned char const *)&endian != 0) { - /* main() is little endian, file.o is big endian. */ + /* objtool is little endian, file.o is big endian. */ w = w4rev; w2 = w2rev; w8 = w8rev; @@ -596,33 +597,21 @@ static int do_file(char const *const fname) return rc; } -int main(int argc, char *argv[]) +int record_mcount(int argc, const char **argv) { const char ftrace[] = "/ftrace.o"; int ftrace_size = sizeof(ftrace) - 1; int n_error = 0; /* gcc-4.3.0 false positive complaint */ - int c; int i; - while ((c = getopt(argc, argv, "w")) >= 0) { - switch (c) { - case 'w': - warn_on_notrace_sect = 1; - break; - default: - fprintf(stderr, "usage: recordmcount [-w] file.o...\n"); - return 0; - } - } - - if ((argc - optind) < 1) { - fprintf(stderr, "usage: recordmcount [-w] file.o...\n"); + if (argc < 1) { + fprintf(stderr, "usage: objtool mcount record [-w] file.o...\n"); return 0; } /* Process each file in turn, allowing deep failure. */ - for (i = optind; i < argc; i++) { - char *file = argv[i]; + for (i = 0; i < argc; i++) { + const char *file = argv[i]; int len; /* -- 2.20.1