linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand
@ 2020-06-18 20:37 Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 01/51] objtool: Factor out reasons to build objtool Matt Helsley
                   ` (51 more replies)
  0 siblings, 52 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

recordmcount has its own ELF wrapper code and could utilize
objtool's ELF code to more-portably handle architecture variations.
This series makes recordmcount a subcommand of objtool. It very
gradually converts recordmcount to become a subcommand of objtool and
then reuses parts of objtool's ELF code.

recordmcount maps the file in and collects simple information it needs to
append a section to the object file. The only part of the original file it
modifies is the address of new section tables -- interestingly enough this
resembles RCU in that we don't really trim the old tables so
much as unlink them via a critical offset and then rely on
future tooling, in this case, to drop the unused bits.

Much of the recordmcount ELF code is only reading and walking the data
structures to collect the mcount locations it records in a separate
area of memory. This means it's safe to mix access to the mapped
file with access to the objtool-style linked data
structures as we gradually convert it to using only the linked data
structures. Once the old ELF code is no longer in use we can drop it
and use objtool to take over the task of writing the results without
using the RCU-like trick any more.

After that we greatly simplify the mcount subcommand by adding a
few flags to the ELF reading code in objtool. Overall the series
removes about 600 lines of recordmcount while adding little to
objtool's ELF code.

Testing so far:

I've been using scripts to test cross compilation and execution of
objtool, and mcount on objects built for x86, ppc64le, arm64, s390, and
sparc.


Applies on top of:
	objtool/core

	Peter Zijlstra's "x86/entry: noinstr fixes" [2]

	Sami Tolvanen's patch enabling support for more than 64k
	sections in recordmcount, already going upstream. [3]

Changes since v4[1]:
v5:
	Updated the HAVE_C_RECORDMCOUNT Kconfig description.

	Removed unused extern is_cmd_mcount_available() spotted by Julien Thierry.

	Issue with symbol info handling reported and fixed by Kamalesh Babulal.

	Removed the giant per-supported-arch series of ifdef blocks in
	the objtool Makefile and replaced with new CONFIG_ variables
	as suggested by Julien Thierry.

	Moved the first pass through the sections into objtool's ELF
	code as suggested by Peter Zijlstra.

	Removed a redundant section lookup.

	Removed old comments that no longer apply since conversion to objtool.

v4:
	Split out recordmcount cleanups and upstreamed. [5]

	Split out, iterated on objtool multi-arch support, and upstreamed. [6]

	Split out expanded relocation support, renamed types, and functions
	to reflect expanded relocation support, and upstreamed. [4]

	This set is based on the patches sent upstream and posted above.

	Adapted to renames by Ingo and Peter: s/elf_open/elf_open_read/

	Added weak symbols for mcount subcommand
		This nicely eliminated the need for the mcount.h header.

	Added tools/objtool/Makefile per-arch SUBCMD_ blocks for each
		arch recordmcount / mcount supports.

	Moved ftrace/mcount/record.h from objtool_dep to recordmcount_dep
		This keeps the dependencies better organized.

	Fixed Makefile issue reported for PowerPC and a couple other archs
		by kbuild test robot. The always-$(BUILD_C_RECORDMCOUNT)
		line wasn't sufficiently replaced. Added to prepare-objtool
		target in top level Makefile.

	Split up dependencies to be independent of CONFIG_STACK_VALIDATION
		and CONFIG_UNWINDER_ORC since these are x86-specific.
		Now any arch which uses the C version of recordmcount
		will build objtool if dynamic tracing is enabled.

	Added a second rename at the end to be consistent with other
		objtool subcommands.

v3:
        Rebased on mainline. s/elf_open/elf_read/ in recordmcount.c

v2:
        Fix whitespace before line continuation

        Add ftrace/mcount/record.h to objtool_dep

        Rename the Makefile variable BUILD_C_RECORDMCOUNT to
            better reflect its purpose

        Similar: rename recordmcount_source => recordmcount_dep
            When using objtool we can just depend on the
            binary rather than the source the binary is
            built from. This should address Josh's feedback and
            make the Makefile code a bit clearer

        Add a comment to make reading the Makefile a little
            easier

        Rebased to latest mainline -rc

[1] https://lore.kernel.org/lkml/cover.1591125127.git.mhelsley@vmware.com/
[2] https://lore.kernel.org/lkml/20200618144407.520952071@infradead.org
[3] https://lore.kernel.org/lkml/20200424193046.160744-1-samitolvanen@google.com
[4] https://lore.kernel.org/lkml/cover.1590785960.git.mhelsley@vmware.com/
[5] https://lore.kernel.org/lkml/20190802134712.2d8cc63f@gandalf.local.home/
[6] https://lore.kernel.org/lkml/cover.1586468801.git.mhelsley@vmware.com/


Matt Helsley (51):
  objtool: Factor out reasons to build objtool
  objtool: Prepare to merge recordmcount
  objtool: Make recordmcount into mcount subcmd
  objtool: recordmcount: Start using objtool's elf wrapper
  objtool: recordmcount: Search for __mcount_loc before walking the
    sections
  objtool: recordmcount: Convert do_func() relhdrs
  objtool: mcount: Move nhdr into find_symtab()
  objtool: mcount: Remove unused fname parameter
  objtool: mcount: Use libelf for section header names
  objtool: mcount: Walk objtool Elf structs in find_secsym_ndx
  objtool: mcount: Use symbol structs to find mcount relocations
  objtool: mcount: Walk relocation lists
  objtool: mcount: Return symbol from mcountsym
  objtool: mcount: Move get_mcountsym
  objtool: mcount: Replace MIPS offset types
  objtool: mcount: Move is_fake_mcount()
  objtool: mcount: Stop using ehdr in find_section_sym_index
  objtool: mcount: Move find_section_sym_index()
  objtool: mcount: Restrict using ehdr in append_func()
  objtool: mcount: Use objtool ELF to write
  objtool: mcount: Move nop_mcount()
  objtool: mcount: Move has_rel_mcount() and tot_relsize()
  objtool: mcount: Move relocation entry size detection
  objtool: mcount: Only keep ELF file size
  objtool: mcount: Use ELF header from objtool
  objtool: mcount: Remove unused file mapping
  objtool: mcount: Reduce usage of _size wrapper
  objtool: mcount: Move mcount_adjust out of wrapper
  objtool: mcount: Pre-allocate new ELF sections
  objtool: mcount: Generic location and relocation table types
  objtool: mcount: Use objtool relocation section
  objtool: mcount: Move sift_rel_mcount out of wrapper file
  objtool: mcount: Remove wrapper for ELF relocation type
  objtool: mcount: Remove wrapper double-include trick
  objtool: mcount: Remove endian wrappers
  objtool: mcount: Rename to mcount.c
  objtool: mcount: Simplify mcount name matching
  objtool: mcount: mcount symbol name simplification
  objtool: mcount: Verify x86 instruction with memcmp()
  objtool: mcount: const-ify ARM instruction patterns
  objtool: mcount: Convert nop writes to elf_write_insn()
  objtool: mcount: Move mcount symbol name testing
  objtool: check: Use class to recognize kcov calls
  objtool: mcount: Keep lists locations and relocations
  objtool: mcount: Move mcount section test to objtool ELF
  objtool: mcount: Flag mcount relocation sections
  objtool: mcount: Merge section mcount flags
  objtool: mcount: Eliminate first pass
  objtool: mcount: Remove relocation size check
  objtool: mcount: Remove useless lookup
  objtool: mcount: Remove stale description

 Documentation/dontdiff                     |   2 +-
 Documentation/trace/ftrace-design.rst      |   4 +-
 Documentation/trace/ftrace.rst             |   6 +-
 Makefile                                   |  39 +-
 arch/Kconfig                               |  23 +
 arch/arm64/include/asm/ftrace.h            |   2 +-
 arch/x86/Kconfig.debug                     |   1 +
 arch/x86/include/asm/ftrace.h              |   2 +-
 kernel/trace/Kconfig                       |   9 +-
 lib/Kconfig.debug                          |   1 +
 scripts/.gitignore                         |   1 -
 scripts/Makefile                           |   1 -
 scripts/Makefile.build                     |  22 +-
 scripts/recordmcount.c                     | 663 --------------------
 scripts/recordmcount.h                     | 692 ---------------------
 scripts/sorttable.h                        |   2 +-
 tools/objtool/.gitignore                   |   1 +
 tools/objtool/Build                        |   2 +
 tools/objtool/Makefile                     |  14 +-
 tools/objtool/builtin-mcount.c             |  50 ++
 tools/objtool/builtin.h                    |   1 +
 tools/objtool/check.c                      |   3 +-
 tools/objtool/elf.c                        |  60 +-
 tools/objtool/elf.h                        |  12 +-
 tools/objtool/mcount.c                     | 596 ++++++++++++++++++
 tools/objtool/objtool.c                    |   1 +
 tools/objtool/objtool.h                    |   1 +
 {scripts => tools/objtool}/recordmcount.pl |   0
 tools/objtool/weak.c                       |   5 +
 29 files changed, 806 insertions(+), 1410 deletions(-)
 delete mode 100644 scripts/recordmcount.c
 delete mode 100644 scripts/recordmcount.h
 create mode 100644 tools/objtool/builtin-mcount.c
 create mode 100644 tools/objtool/mcount.c
 rename {scripts => tools/objtool}/recordmcount.pl (100%)


base-commit: 14bda4e5293ed9722f1dc39b543024e37707d6c6
prerequisite-patch-id: b9f6483185e4e80fccbb6ec7276bf61ce0329472
prerequisite-patch-id: 6d3fec64974cdce64fec35141ff71f0532cb8c82
prerequisite-patch-id: b71e084f3d2adeb4d05e4327183b75b388a20e6d
prerequisite-patch-id: 261f5d8102f4ecee86df2eb93be6a29495702717
prerequisite-patch-id: 64fa3e2f92e5dfd1b64289b4118288b6d2a25a67
prerequisite-patch-id: e5671d612490912b263505907657f3197c4a0833
prerequisite-patch-id: cba407d3dc82ad54095a9b5149b0c851c4e30b19
prerequisite-patch-id: bcf669a844506eec601cba1797f954e59cc7a2ad
-- 
2.20.1


^ permalink raw reply	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 01/51] objtool: Factor out reasons to build objtool
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-24 15:37   ` Miroslav Benes
  2020-06-18 20:37 ` [RFC][PATCH v5 02/51] objtool: Prepare to merge recordmcount Matt Helsley
                   ` (50 subsequent siblings)
  51 siblings, 1 reply; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Currently the reasons to build and run objtool are:
	Stack validation (objtool subcmds: orc + check)
	Orc data generation (objtool subcmds: orc)
	Code analysis (objtool subcmds: check)

Since the reasons are varied and the stack validation step is
skipped with a warning if libelf is missing, the logic of
Kconfig and the Makefiles is somewhat messy and will only get
messier the more subcommands objtool supports. In preparation
for adding new subcommands, break up the current configurations
such as CONFIG_STACK_VALIDATION, CONFIG_UNWINDER_ORC, etc.
so that we translate them into the objtool subcommands that we
need to build into objtool and whether the objtool pass is
optional (SKIP_STACK_VALIDATION=1).

This allows us to greatly simplify the objtool Makefile so
that the arch-dependence of the subcommands can be encoded in
the usual place, arch/Kconfig, rather than a bunch of
per-supported-arch ifdef blocks in tools/objtool/Makefile.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 Makefile               | 15 ++++++++-------
 arch/Kconfig           | 23 +++++++++++++++++++++++
 arch/x86/Kconfig.debug |  1 +
 lib/Kconfig.debug      |  1 +
 tools/objtool/Makefile |  5 +++--
 5 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/Makefile b/Makefile
index ae5d8220f431..cf731709ebe7 100644
--- a/Makefile
+++ b/Makefile
@@ -1051,18 +1051,19 @@ mod_sign_cmd = true
 endif
 export mod_sign_cmd
 
+ifdef CONFIG_OBJTOOL_SUBCMDS
 HOST_LIBELF_LIBS = $(shell pkg-config libelf --libs 2>/dev/null || echo -lelf)
-
-ifdef CONFIG_STACK_VALIDATION
-  has_libelf := $(call try-run,\
+has_libelf := $(call try-run,\
 		echo "int main() {}" | $(HOSTCC) -xc -o /dev/null $(HOST_LIBELF_LIBS) -,1,0)
-  ifeq ($(has_libelf),1)
-    objtool_target := tools/objtool FORCE
-  else
+ifeq ($(has_libelf),1)
+  objtool_target := tools/objtool FORCE
+else
+  ifdef CONFIG_STACK_VALIDATION
     SKIP_STACK_VALIDATION := 1
     export SKIP_STACK_VALIDATION
   endif
-endif
+endif # has_libelf
+endif # CONFIG_OBJTOOL_SUBCMDS
 
 PHONY += prepare0
 
diff --git a/arch/Kconfig b/arch/Kconfig
index 8cc35dc556c7..4919412031eb 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -767,6 +767,29 @@ config HAVE_STACK_VALIDATION
 	  Architecture supports the 'objtool check' host tool command, which
 	  performs compile-time stack metadata validation.
 
+config OBJTOOL_SUBCMD_CHECK
+	bool
+	select OBJTOOL_SUBCMDS
+	help
+	  Run the 'objtool check' host tool command, which
+	  performs compile-time stack metadata validation.
+
+config OBJTOOL_SUBCMD_ORC
+	bool
+	select OBJTOOL_SUBCMDS
+	help
+	  Run the 'objtool orc' host tool command, which collects information
+	  enabling reliable runtime kernel stack traces.
+
+config OBJTOOL_SUBCMDS
+	bool
+	default n
+	help
+	  Other configurations require running objtool host tool commands.
+	  For example, stack validation is available on the architecture
+	  (HAVE_STACK_VALIDATION=y) and has been enabled (STACK_VALIDATION=y)
+	  which selects OBJTOOL_SUBCMD_CHECK and OBJTOOL_SUBCMDS
+
 config HAVE_RELIABLE_STACKTRACE
 	bool
 	help
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 0dd319e6e5b4..4f2d596505c1 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -241,6 +241,7 @@ config UNWINDER_ORC
 	bool "ORC unwinder"
 	depends on X86_64
 	select STACK_VALIDATION
+	select OBJTOOL_SUBCMD_ORC
 	help
 	  This option enables the ORC (Oops Rewind Capability) unwinder for
 	  unwinding kernel stack traces.  It uses a custom data format which is
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index d74ac0fd6b2d..e38e6cb22aa5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -386,6 +386,7 @@ config FRAME_POINTER
 config STACK_VALIDATION
 	bool "Compile-time stack metadata validation"
 	depends on HAVE_STACK_VALIDATION
+	select OBJTOOL_SUBCMD_CHECK
 	default n
 	help
 	  Add compile-time checks to validate stack metadata, including frame
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 7770edcda3a0..aa0c6d3d2d46 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 include ../scripts/Makefile.include
 include ../scripts/Makefile.arch
+include $(OUTPUT)/../../include/config/auto.conf
 
 # always use the host compiler
 ifneq ($(LLVM),)
@@ -47,8 +48,8 @@ CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
 
 AWK = awk
 
-SUBCMD_CHECK := n
-SUBCMD_ORC := n
+SUBCMD_CHECK := $(CONFIG_OBJTOOL_SUBCMD_CHECK)
+SUBCMD_ORC := $(CONFIG_OBJTOOL_SUBCMD_ORC)
 
 ifeq ($(SRCARCH),x86)
 	SUBCMD_CHECK := y
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 02/51] objtool: Prepare to merge recordmcount
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 01/51] objtool: Factor out reasons to build objtool Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 03/51] objtool: Make recordmcount into mcount subcmd Matt Helsley
                   ` (49 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Move recordmcount into the objtool directory. We keep this step separate
so changes which turn recordmcount into a subcommand of objtool don't
get obscured.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 Documentation/trace/ftrace-design.rst      |  4 ++--
 Documentation/trace/ftrace.rst             |  2 +-
 Makefile                                   | 11 +++++++----
 scripts/.gitignore                         |  1 -
 scripts/Makefile                           |  1 -
 scripts/Makefile.build                     | 11 ++++++-----
 tools/objtool/.gitignore                   |  1 +
 tools/objtool/Build                        |  2 ++
 tools/objtool/Makefile                     | 13 ++++++++++++-
 {scripts => tools/objtool}/recordmcount.c  |  0
 {scripts => tools/objtool}/recordmcount.h  |  0
 {scripts => tools/objtool}/recordmcount.pl |  0
 12 files changed, 31 insertions(+), 15 deletions(-)
 rename {scripts => tools/objtool}/recordmcount.c (100%)
 rename {scripts => tools/objtool}/recordmcount.h (100%)
 rename {scripts => tools/objtool}/recordmcount.pl (100%)

diff --git a/Documentation/trace/ftrace-design.rst b/Documentation/trace/ftrace-design.rst
index 6893399157f0..f793a76ff65a 100644
--- a/Documentation/trace/ftrace-design.rst
+++ b/Documentation/trace/ftrace-design.rst
@@ -253,7 +253,7 @@ You need very few things to get the syscalls tracing in an arch.
 HAVE_FTRACE_MCOUNT_RECORD
 -------------------------
 
-See scripts/recordmcount.pl for more info.  Just fill in the arch-specific
+See tools/objtool/recordmcount.pl for more info.  Just fill in the arch-specific
 details for how to locate the addresses of mcount call sites via objdump.
 This option doesn't make much sense without also implementing dynamic ftrace.
 
@@ -371,7 +371,7 @@ linux/ftrace.h for the functions::
 	ftrace_make_call()
 
 The rec->ip value is the address of the mcount call site that was collected
-by the scripts/recordmcount.pl during build time.
+by the tools/objtool/recordmcount.pl during build time.
 
 The last function is used to do runtime patching of the active tracer.  This
 will be modifying the assembly code at the location of the ftrace_call symbol
diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index 430a16283103..24ec4ec2d98d 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -2685,7 +2685,7 @@ starts of pointing to a simple return. (Enabling FTRACE will
 include the -pg switch in the compiling of the kernel.)
 
 At compile time every C file object is run through the
-recordmcount program (located in the scripts directory). This
+recordmcount program (located in the tools/objtool directory). This
 program will parse the ELF headers in the C object to find all
 the locations in the .text section that call mcount. Starting
 with gcc version 4.6, the -mfentry has been added for x86, which
diff --git a/Makefile b/Makefile
index cf731709ebe7..e20c30f82c58 100644
--- a/Makefile
+++ b/Makefile
@@ -862,6 +862,7 @@ ifdef CONFIG_DYNAMIC_FTRACE
 	ifdef CONFIG_HAVE_C_RECORDMCOUNT
 		BUILD_C_RECORDMCOUNT := y
 		export BUILD_C_RECORDMCOUNT
+		objtool_target := tools/objtool FORCE
 	endif
 endif
 endif
@@ -1191,13 +1192,15 @@ uapi-asm-generic:
 
 PHONY += prepare-objtool
 prepare-objtool: $(objtool_target)
-ifeq ($(SKIP_STACK_VALIDATION),1)
-ifdef CONFIG_UNWINDER_ORC
+ifneq ($(has_libelf),1)
+  ifdef CONFIG_UNWINDER_ORC
 	@echo "error: Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel" >&2
 	@false
-else
+  else
+    ifeq ($(SKIP_STACK_VALIDATION),1)
 	@echo "warning: Cannot use CONFIG_STACK_VALIDATION=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel" >&2
-endif
+    endif
+  endif
 endif
 
 # Generate some files
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 0d1c8e217cd7..dafda6d2c306 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -2,7 +2,6 @@
 bin2c
 kallsyms
 unifdef
-recordmcount
 sorttable
 asn1_compiler
 extract-cert
diff --git a/scripts/Makefile b/scripts/Makefile
index 95ecf970c74c..d8d81de4f1cb 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -5,7 +5,6 @@
 
 always-$(CONFIG_BUILD_BIN2C)			+= bin2c
 always-$(CONFIG_KALLSYMS)			+= kallsyms
-always-$(BUILD_C_RECORDMCOUNT)			+= recordmcount
 always-$(CONFIG_BUILDTIME_TABLE_SORT)		+= sorttable
 always-$(CONFIG_ASN1)				+= asn1_compiler
 always-$(CONFIG_MODULE_SIG_FORMAT)		+= sign-file
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 2e8810b7e5ed..f3f58d71951c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -188,18 +188,19 @@ endif
 # files, including recordmcount.
 sub_cmd_record_mcount =					\
 	if [ $(@) != "scripts/mod/empty.o" ]; then	\
-		$(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)";	\
+		$(objtree)/tools/objtool/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)";	\
 	fi;
-recordmcount_source := $(srctree)/scripts/recordmcount.c \
-		    $(srctree)/scripts/recordmcount.h
+
+recordmcount_source := $(srctree)/tools/objtool/recordmcount.c \
+		    $(srctree)/tools/objtool/recordmcount.h
 else
-sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+sub_cmd_record_mcount = perl $(srctree)/tools/objtool/recordmcount.pl "$(ARCH)" \
 	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
 	"$(if $(CONFIG_64BIT),64,32)" \
 	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \
 	"$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \
 	"$(if $(part-of-module),1,0)" "$(@)";
-recordmcount_source := $(srctree)/scripts/recordmcount.pl
+recordmcount_source := $(srctree)/tools/objtool/recordmcount.pl
 endif # BUILD_C_RECORDMCOUNT
 cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),	\
 	$(sub_cmd_record_mcount))
diff --git a/tools/objtool/.gitignore b/tools/objtool/.gitignore
index 45cefda24c7b..ea441abcd1d3 100644
--- a/tools/objtool/.gitignore
+++ b/tools/objtool/.gitignore
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 arch/x86/lib/inat-tables.c
 objtool
+recordmcount
 fixdep
diff --git a/tools/objtool/Build b/tools/objtool/Build
index b7222d5cc7bc..4d399aff76de 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -35,3 +35,5 @@ $(OUTPUT)str_error_r.o: ../lib/str_error_r.c FORCE
 $(OUTPUT)librbtree.o: ../lib/rbtree.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 aa0c6d3d2d46..d7aef1f8718e 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -32,6 +32,12 @@ 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 \
@@ -64,15 +70,20 @@ $(OBJTOOL_IN): fixdep FORCE
 	@$(CONFIG_SHELL) ./sync-check.sh
 	@$(MAKE) $(build)=objtool
 
+$(RECORDMCOUNT_IN): fixdep FORCE
+	@$(MAKE) $(build)=recordmcount
+
 $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN)
 	$(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)
+	$(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL) $(RECORDMCOUNT)
 	$(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
 	$(Q)$(RM) $(OUTPUT)arch/x86/inat-tables.c $(OUTPUT)fixdep
 
diff --git a/scripts/recordmcount.c b/tools/objtool/recordmcount.c
similarity index 100%
rename from scripts/recordmcount.c
rename to tools/objtool/recordmcount.c
diff --git a/scripts/recordmcount.h b/tools/objtool/recordmcount.h
similarity index 100%
rename from scripts/recordmcount.h
rename to tools/objtool/recordmcount.h
diff --git a/scripts/recordmcount.pl b/tools/objtool/recordmcount.pl
similarity index 100%
rename from scripts/recordmcount.pl
rename to tools/objtool/recordmcount.pl
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 03/51] objtool: Make recordmcount into mcount subcmd
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 01/51] objtool: Factor out reasons to build objtool Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 02/51] objtool: Prepare to merge recordmcount Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-25 10:39   ` Miroslav Benes
  2020-06-18 20:37 ` [RFC][PATCH v5 04/51] objtool: recordmcount: Start using objtool's elf wrapper Matt Helsley
                   ` (48 subsequent siblings)
  51 siblings, 1 reply; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than a standalone executable merge recordmcount as a sub command
of objtool. This is a small step towards cleaning up recordmcount and
eventually sharing  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 <mhelsley@vmware.com>
---
 Documentation/dontdiff          |  2 +-
 Documentation/trace/ftrace.rst  |  6 ++--
 Makefile                        | 15 ++++------
 arch/arm64/include/asm/ftrace.h |  2 +-
 arch/x86/include/asm/ftrace.h   |  2 +-
 kernel/trace/Kconfig            |  9 +++++-
 scripts/Makefile.build          | 19 +++++++------
 scripts/sorttable.h             |  2 +-
 tools/objtool/Build             |  4 +--
 tools/objtool/Makefile          | 20 ++-----------
 tools/objtool/builtin-mcount.c  | 50 +++++++++++++++++++++++++++++++++
 tools/objtool/builtin.h         |  1 +
 tools/objtool/objtool.c         |  1 +
 tools/objtool/objtool.h         |  1 +
 tools/objtool/recordmcount.c    | 36 +++++++-----------------
 tools/objtool/weak.c            |  5 ++++
 16 files changed, 104 insertions(+), 71 deletions(-)
 create mode 100644 tools/objtool/builtin-mcount.c

diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index ef9519c32c55..82cc4e3bb713 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -211,7 +211,7 @@ r420_reg_safe.h
 r600_reg_safe.h
 randomize_layout_hash.h
 randomize_layout_seed.h
-recordmcount
+objtool
 relocs
 rlim_names.h
 rn50_reg_safe.h
diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index 24ec4ec2d98d..eefb966e5832 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -2684,8 +2684,8 @@ every kernel function, produced by the -pg switch in gcc),
 starts of pointing to a simple return. (Enabling FTRACE will
 include the -pg switch in the compiling of the kernel.)
 
-At compile time every C file object is run through the
-recordmcount program (located in the tools/objtool directory). This
+At compile time every C file object is run through objtool's
+mcount subcommand (located in the tools/objtool directory). This
 program will parse the ELF headers in the C object to find all
 the locations in the .text section that call mcount. Starting
 with gcc version 4.6, the -mfentry has been added for x86, which
@@ -2699,7 +2699,7 @@ can be traced.
 
 A section called "__mcount_loc" is created that holds
 references to all the mcount/fentry call sites in the .text section.
-The recordmcount program re-links this section back into the
+Running "objtool mcount" re-links this section back into the
 original object. The final linking stage of the kernel will add all these
 references into a single table.
 
diff --git a/Makefile b/Makefile
index e20c30f82c58..3842d7258b43 100644
--- a/Makefile
+++ b/Makefile
@@ -841,6 +841,7 @@ ifdef CONFIG_FTRACE_MCOUNT_RECORD
   ifeq ($(call cc-option-yn,-mrecord-mcount),y)
     CC_FLAGS_FTRACE	+= -mrecord-mcount
     export CC_USING_RECORD_MCOUNT := 1
+    undefine CONFIG_OBJTOOL_SUBCMD_MCOUNT
   endif
   ifdef CONFIG_HAVE_NOP_MCOUNT
     ifeq ($(call cc-option-yn, -mnop-mcount),y)
@@ -848,7 +849,7 @@ ifdef CONFIG_FTRACE_MCOUNT_RECORD
       CC_FLAGS_USING	+= -DCC_USING_NOP_MCOUNT
     endif
   endif
-endif
+endif # CONFIG_FTRACE_MCOUNT_RECORD
 ifdef CONFIG_HAVE_FENTRY
   ifeq ($(call cc-option-yn, -mfentry),y)
     CC_FLAGS_FTRACE	+= -mfentry
@@ -858,14 +859,7 @@ endif
 export CC_FLAGS_FTRACE
 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
-		objtool_target := tools/objtool FORCE
-	endif
-endif
-endif
+endif # CONFIG_FUNCTION_TRACER
 
 # We trigger additional mismatches with less inlining
 ifdef CONFIG_DEBUG_SECTION_MISMATCH
@@ -1196,6 +1190,9 @@ ifneq ($(has_libelf),1)
   ifdef CONFIG_UNWINDER_ORC
 	@echo "error: Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel" >&2
 	@false
+  else ifdef CONFIG_OBJTOOL_SUBCMD_MCOUNT
+	@echo "error: Cannot generate tracing metadata for CONFIG_DYNAMIC_FTRACE, please install libelf-dev, libelf-devel or elfutils-libelf-devel" >&2
+	@false
   else
     ifeq ($(SKIP_STACK_VALIDATION),1)
 	@echo "warning: Cannot use CONFIG_STACK_VALIDATION=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel" >&2
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 91fa4baa1a93..5fd71bf592d5 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -62,7 +62,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 		return addr + AARCH64_INSN_SIZE;
 	/*
 	 * addr is the address of the mcount call instruction.
-	 * recordmcount does the necessary offset calculation.
+	 * "objtool mcount" does the necessary offset calculation.
 	 */
 	return addr;
 }
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index 84b9449be080..c849f3818369 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -23,7 +23,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
 	/*
 	 * addr is the address of the mcount call instruction.
-	 * recordmcount does the necessary offset calculation.
+	 * "objtool mcount" does the necessary offset calculation.
 	 */
 	return addr;
 }
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index a4020c0b4508..a56abf4bd331 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -54,7 +54,13 @@ config HAVE_NOP_MCOUNT
 config HAVE_C_RECORDMCOUNT
 	bool
 	help
-	  C version of recordmcount available?
+	  Arch supports objtool mcount subcommand
+
+config OBJTOOL_SUBCMD_MCOUNT
+	bool
+	select OBJTOOL_SUBCMDS
+	help
+	  Record mcount call locations using objtool
 
 config TRACER_MAX_TRACE
 	bool
@@ -176,6 +182,7 @@ config DYNAMIC_FTRACE
 	bool "enable/disable function tracing dynamically"
 	depends on FUNCTION_TRACER
 	depends on HAVE_DYNAMIC_FTRACE
+	select OBJTOOL_SUBCMD_MCOUNT if HAVE_C_RECORDMCOUNT
 	default y
 	help
 	  This option will modify all the calls to function tracing
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index f3f58d71951c..7c8b4fced29c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -177,22 +177,23 @@ 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
+# The compiler does not support generation of the __mcount_loc section.
+# Generate it manually with "objtool mcount record" or recordmcount.pl
+ifdef CONFIG_OBJTOOL_SUBCMD_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	\
+			 $(wildcard include/config/ftrace/mcount/record.h)
 else
 sub_cmd_record_mcount = perl $(srctree)/tools/objtool/recordmcount.pl "$(ARCH)" \
 	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
@@ -200,8 +201,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 # CONFIG_OBJTOOL_SUBCMD_MCOUNT
 cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),	\
 	$(sub_cmd_record_mcount))
 endif # CC_USING_RECORD_MCOUNT
@@ -277,7 +278,7 @@ 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)
 
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a2baa2fefb13..986aa3414cf6 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -11,7 +11,7 @@
  * Some of code was taken out of arch/x86/kernel/unwind_orc.c, written by:
  * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
  *
- * Some of this code was taken out of recordmcount.h written by:
+ * Some of this code was taken out of objtool mcount written by:
  *
  * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
  * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 4d399aff76de..f4f0515d4f91 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -7,9 +7,11 @@ objtool-$(SUBCMD_CHECK) += special.o
 objtool-$(SUBCMD_ORC) += check.o
 objtool-$(SUBCMD_ORC) += orc_gen.o
 objtool-$(SUBCMD_ORC) += orc_dump.o
+objtool-$(SUBCMD_MCOUNT) += recordmcount.o
 
 objtool-y += builtin-check.o
 objtool-y += builtin-orc.o
+objtool-y += builtin-mcount.o
 objtool-y += elf.o
 objtool-y += objtool.o
 
@@ -35,5 +37,3 @@ $(OUTPUT)str_error_r.o: ../lib/str_error_r.c FORCE
 $(OUTPUT)librbtree.o: ../lib/rbtree.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 d7aef1f8718e..e113e0333197 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -32,12 +32,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 \
@@ -56,13 +50,9 @@ AWK = awk
 
 SUBCMD_CHECK := $(CONFIG_OBJTOOL_SUBCMD_CHECK)
 SUBCMD_ORC := $(CONFIG_OBJTOOL_SUBCMD_ORC)
+SUBCMD_MCOUNT := $(CONFIG_OBJTOOL_SUBCMD_MCOUNT)
 
-ifeq ($(SRCARCH),x86)
-	SUBCMD_CHECK := y
-	SUBCMD_ORC := 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
 
@@ -70,20 +60,16 @@ $(OBJTOOL_IN): fixdep FORCE
 	@$(CONFIG_SHELL) ./sync-check.sh
 	@$(MAKE) $(build)=objtool
 
-$(RECORDMCOUNT_IN): fixdep FORCE
-	@$(MAKE) $(build)=recordmcount
 
 $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN)
 	$(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/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..4ffc105ab7bb
--- /dev/null
+++ b/tools/objtool/builtin-mcount.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * 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 <string.h>
+#include <subcmd/parse-options.h>
+#include "builtin.h"
+#include "objtool.h"
+
+static const char * const mcount_usage[] = {
+	"objtool mcount record [<options>] 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], "record", 6)) {
+		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;
+}
diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h
index 85c979caa367..d8a8aa9e16c0 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, stats,
 
 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 58fdda510653..b2d6b9fec7dd 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/objtool.h b/tools/objtool/objtool.h
index 528028a66816..c6563aa9d921 100644
--- a/tools/objtool/objtool.h
+++ b/tools/objtool/objtool.h
@@ -21,6 +21,7 @@ struct objtool_file {
 
 int check(const char *objname, bool orc);
 int orc_dump(const char *objname);
+int record_mcount(int argc, const char **argv);
 int create_orc(struct objtool_file *file);
 int create_orc_sections(struct objtool_file *file);
 
diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 7225107a9aaf..601e83840085 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * recordmcount.c: construct a table of the locations of calls to 'mcount'
- * so that ftrace can find them quickly.
+ * Construct a table of the locations of calls to 'mcount' so that ftrace
+ * can find them quickly.
  * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>.  All rights reserved.
  *
  * Restructured to fit Linux format, as well as other updates:
@@ -24,7 +24,6 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
-#include <getopt.h>
 #include <elf.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -32,6 +31,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "objtool.h"
+
 #ifndef EM_AARCH64
 #define EM_AARCH64	183
 #define R_AARCH64_NONE		0
@@ -47,7 +48,7 @@ static int mmap_failed; /* Boolean flag. */
 static char gpfx;	/* prefix for global symbol name (sometimes '_') */
 static struct stat sb;	/* Remember .st_size, etc. */
 static const char *altmcount;	/* alternate mcount symbol name */
-static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
+extern int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
 static void *file_map;	/* pointer of the mapped file */
 static void *file_end;	/* pointer to the end of the mapped file */
 static int file_updated; /* flag to state file was changed */
@@ -488,7 +489,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;
@@ -501,7 +502,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;
@@ -615,33 +616,16 @@ 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");
-		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;
 
 		/*
diff --git a/tools/objtool/weak.c b/tools/objtool/weak.c
index 942ea5e8ac36..0c9161bb1612 100644
--- a/tools/objtool/weak.c
+++ b/tools/objtool/weak.c
@@ -29,6 +29,11 @@ int __weak orc_dump(const char *_objname)
 	UNSUPPORTED("orc");
 }
 
+int __weak record_mcount(int argc, const char **argv)
+{
+	UNSUPPORTED("mcount");
+}
+
 int __weak create_orc(struct objtool_file *file)
 {
 	UNSUPPORTED("orc");
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 04/51] objtool: recordmcount: Start using objtool's elf wrapper
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (2 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 03/51] objtool: Make recordmcount into mcount subcmd Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 05/51] objtool: recordmcount: Search for __mcount_loc before walking the sections Matt Helsley
                   ` (47 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Use struct elf to grab the file descriptor. We will later
move these calls into other functions as we expand the
lifetime of the struct elf so that it can be passed to
objtool elf.[ch] functions.

This creates the libelf/objtool data structures and gives
us two separate ways to walk the ELF file -- the libelf/objtool
way and the old recordmcount wrapper way which avoids these
extra data structures by using indices, offsets, and pointers
into the mmapped ELF file.

Subsequent patches will convert from the old recordmcount
accessors to the libelf/objtool accessors.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 601e83840085..b2c606eb269b 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -33,6 +33,8 @@
 
 #include "objtool.h"
 
+#include "elf.h"
+
 #ifndef EM_AARCH64
 #define EM_AARCH64	183
 #define R_AARCH64_NONE		0
@@ -57,6 +59,8 @@ static void *file_ptr;	/* current file pointer location */
 static void *file_append; /* added to the end of the file */
 static size_t file_append_size; /* how much is added to end of file */
 
+static struct elf *lf;
+
 /* Per-file resource cleanup when multiple files. */
 static void file_append_cleanup(void)
 {
@@ -73,6 +77,9 @@ static void mmap_cleanup(void)
 	else
 		free(file_map);
 	file_map = NULL;
+	if (lf)
+		elf_close(lf);
+	lf = NULL;
 }
 
 /* ulseek, uwrite, ...:  Check return value for errors. */
@@ -170,11 +177,12 @@ static void *mmap_file(char const *fname)
 	file_updated = 0;
 	sb.st_size = 0;
 
-	fd_map = open(fname, O_RDONLY);
-	if (fd_map < 0) {
+	lf = elf_open_read(fname, O_RDONLY);
+	if (!lf) {
 		perror(fname);
 		return NULL;
 	}
+	fd_map = lf->fd;
 	if (fstat(fd_map, &sb) < 0) {
 		perror(fname);
 		goto out;
@@ -194,14 +202,14 @@ static void *mmap_file(char const *fname)
 		}
 		if (read(fd_map, file_map, sb.st_size) != sb.st_size) {
 			perror(fname);
-			free(file_map);
-			file_map = NULL;
+			mmap_cleanup();
 			goto out;
 		}
 	} else
 		mmap_failed = 0;
 out:
-	close(fd_map);
+	elf_close(lf);
+	lf = NULL;
 	fd_map = -1;
 
 	file_end = file_map + sb.st_size;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 05/51] objtool: recordmcount: Search for __mcount_loc before walking the sections
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (3 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 04/51] objtool: recordmcount: Start using objtool's elf wrapper Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 06/51] objtool: recordmcount: Convert do_func() relhdrs Matt Helsley
                   ` (46 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

recordmcount iterates over the sections in the order they're
listed in the ELF file and checks whether the section name
indicates it's of interest. Objtool's elf code works differently
 -- it scans the elf file and builds up data structures
representing the headers, sections, etc. and then supplies
functions to search these structures. Both walk the elf file
in order, however objtool uses more memory to enable faster
searches it needs for other tools such as the reliable backtrace
support offered by the ORC unwinder.

Rather than walk the section table a second time in the recordmcount
code, we use objtool's elf code to search for the section
recordmcount is interested in. This also simplifies flow and means
we can easily check for already-processed object files before we
do any of the more complex things recordmcount does.

This also allows us to remove the already_has_rel_mcount string
pointer trick.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c |  4 ----
 tools/objtool/recordmcount.h | 17 +++--------------
 2 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index b2c606eb269b..f585bf7f45f5 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -208,8 +208,6 @@ static void *mmap_file(char const *fname)
 	} else
 		mmap_failed = 0;
 out:
-	elf_close(lf);
-	lf = NULL;
 	fd_map = -1;
 
 	file_end = file_map + sb.st_size;
@@ -424,8 +422,6 @@ static int is_mcounted_section_name(char const *const txtname)
 		strcmp(".cpuidle.text", txtname) == 0;
 }
 
-static char const *already_has_rel_mcount = "success"; /* our work here is done! */
-
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index f9b19524da11..a96ffcef515a 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -554,11 +554,6 @@ static char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */
 	Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
 	char const *const txtname = &shstrtab[w(txthdr->sh_name)];
 
-	if (strcmp("__mcount_loc", txtname) == 0) {
-		fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
-			fname);
-		return already_has_rel_mcount;
-	}
 	if (w(txthdr->sh_type) != SHT_PROGBITS ||
 	    !(_w(txthdr->sh_flags) & SHF_EXECINSTR))
 		return NULL;
@@ -587,10 +582,6 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
 
 	for (; nhdr; --nhdr, ++shdrp) {
 		txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname);
-		if (txtname == already_has_rel_mcount) {
-			totrelsz = 0;
-			break;
-		}
 		if (txtname && is_mcounted_section_name(txtname))
 			totrelsz += _w(shdrp->sh_size);
 	}
@@ -628,6 +619,9 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 
 	int result = 0;
 
+	if (find_section_by_name(lf, "__mcount_loc") != NULL)
+		return 0;
+
 	totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
 	if (totrelsz == 0)
 		return 0;
@@ -649,11 +643,6 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 	for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
 		char const *const txtname = has_rel_mcount(relhdr, shdr0,
 			shstrtab, fname);
-		if (txtname == already_has_rel_mcount) {
-			result = 0;
-			file_updated = 0;
-			goto out; /* Nothing to be done; don't append! */
-		}
 		if (txtname && is_mcounted_section_name(txtname)) {
 			unsigned int recsym;
 			uint_t recval = 0;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 06/51] objtool: recordmcount: Convert do_func() relhdrs
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (4 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 05/51] objtool: recordmcount: Search for __mcount_loc before walking the sections Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 07/51] objtool: mcount: Move nhdr into find_symtab() Matt Helsley
                   ` (45 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Use objtool's ELF data structures to visit the relocation
sections in the top-level ELF file walking function, do_func().
This means we can pass pointers to the relocation header structures
into nested functions and avoid the indexing patterns for them.

These conversions don't use libelf/objtool to modify the ELF
file -- it only changes the way we walk the ELF sections and do
lookups to find the relocations.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 61 +++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 29 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index a96ffcef515a..b46e855d32bf 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -364,7 +364,7 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0,
 	return mcountsym;
 }
 
-static void get_sym_str_and_relp(Elf_Shdr const *const relhdr,
+static void get_sym_str_and_relp(GElf_Shdr const *const relhdr,
 				 Elf_Ehdr const *const ehdr,
 				 Elf_Sym const **sym0,
 				 char const **str0,
@@ -372,10 +372,10 @@ static void get_sym_str_and_relp(Elf_Shdr const *const relhdr,
 {
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
 		+ (void *)ehdr);
-	unsigned const symsec_sh_link = w(relhdr->sh_link);
+	unsigned const symsec_sh_link = relhdr->sh_link;
 	Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
 	Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
-	Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
+	Elf_Rel const *const rel0 = (Elf_Rel const *)(relhdr->sh_offset
 		+ (void *)ehdr);
 
 	*sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
@@ -395,9 +395,9 @@ static void get_sym_str_and_relp(Elf_Shdr const *const relhdr,
 static uint_t *sift_rel_mcount(uint_t *mlocp,
 			       unsigned const offbase,
 			       Elf_Rel **const mrelpp,
-			       Elf_Shdr const *const relhdr,
+			       GElf_Shdr const *const relhdr,
 			       Elf_Ehdr const *const ehdr,
-			       unsigned const recsym,
+			       unsigned const recsym_index,
 			       uint_t const recval,
 			       unsigned const reltype)
 {
@@ -406,8 +406,8 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 	Elf_Sym const *sym0;
 	char const *str0;
 	Elf_Rel const *relp;
-	unsigned rel_entsize = _w(relhdr->sh_entsize);
-	unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
+	unsigned int rel_entsize = relhdr->sh_entsize;
+	unsigned const nrel = relhdr->sh_size / rel_entsize;
 	unsigned mcountsym = 0;
 	unsigned t;
 
@@ -423,7 +423,7 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 				_w(_w(relp->r_offset) - recval + mcount_adjust);
 			mrelp->r_offset = _w(offbase
 				+ ((void *)mlocp - (void *)mloc0));
-			Elf_r_info(mrelp, recsym, reltype);
+			Elf_r_info(mrelp, recsym_index, reltype);
 			if (rel_entsize == sizeof(Elf_Rela)) {
 				((Elf_Rela *)mrelp)->r_addend = addend;
 				*mlocp++ = 0;
@@ -443,7 +443,7 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
  * that are not going to be traced. The mcount calls here will be converted
  * into nops.
  */
-static int nop_mcount(Elf_Shdr const *const relhdr,
+static int nop_mcount(GElf_Shdr const *const relhdr,
 		      Elf_Ehdr const *const ehdr,
 		      const char *const txtname)
 {
@@ -452,9 +452,9 @@ static int nop_mcount(Elf_Shdr const *const relhdr,
 	Elf_Sym const *sym0;
 	char const *str0;
 	Elf_Rel const *relp;
-	Elf_Shdr const *const shdr = &shdr0[w(relhdr->sh_info)];
-	unsigned rel_entsize = _w(relhdr->sh_entsize);
-	unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
+	Elf_Shdr const *const shdr = &shdr0[relhdr->sh_info];
+	unsigned int rel_entsize = relhdr->sh_entsize;
+	unsigned const nrel = relhdr->sh_size / rel_entsize;
 	unsigned mcountsym = 0;
 	unsigned t;
 	int once = 0;
@@ -545,13 +545,13 @@ static int find_secsym_ndx(unsigned const txtndx,
 }
 
 /* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
-static char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */
+static char const * __has_rel_mcount(GElf_Shdr const *const relhdr, /* reltype */
 				     Elf_Shdr const *const shdr0,
 				     char const *const shstrtab,
 				     char const *const fname)
 {
 	/* .sh_info depends on .sh_type == SHT_REL[,A] */
-	Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
+	Elf_Shdr const *const txthdr = &shdr0[relhdr->sh_info];
 	char const *const txtname = &shstrtab[w(txthdr->sh_name)];
 
 	if (w(txthdr->sh_type) != SHT_PROGBITS ||
@@ -560,30 +560,29 @@ static char const * __has_rel_mcount(Elf_Shdr const *const relhdr, /* reltype */
 	return txtname;
 }
 
-static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
+static char const *has_rel_mcount(GElf_Shdr const *const relhdr,
 				  Elf_Shdr const *const shdr0,
 				  char const *const shstrtab,
 				  char const *const fname)
 {
-	if (w(relhdr->sh_type) != SHT_REL && w(relhdr->sh_type) != SHT_RELA)
+	if (relhdr->sh_type != SHT_REL && relhdr->sh_type != SHT_RELA)
 		return NULL;
 	return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
 }
 
 
 static unsigned tot_relsize(Elf_Shdr const *const shdr0,
-			    unsigned nhdr,
 			    const char *const shstrtab,
 			    const char *const fname)
 {
+	struct section *sec;
 	unsigned totrelsz = 0;
-	Elf_Shdr const *shdrp = shdr0;
 	char const *txtname;
 
-	for (; nhdr; --nhdr, ++shdrp) {
-		txtname = has_rel_mcount(shdrp, shdr0, shstrtab, fname);
+	list_for_each_entry(sec, &lf->sections, list) {
+		txtname = has_rel_mcount(&sec->sh, shdr0, shstrtab, fname);
 		if (txtname && is_mcounted_section_name(txtname))
-			totrelsz += _w(shdrp->sh_size);
+			totrelsz += sec->sh.sh_size;
 	}
 	return totrelsz;
 }
@@ -599,8 +598,7 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 	char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
 		+ (void *)ehdr);
 
-	Elf_Shdr const *relhdr;
-	unsigned k;
+	GElf_Shdr const *relhdr;
 
 	Elf32_Word *symtab;
 	Elf32_Word *symtab_shndx;
@@ -617,12 +615,14 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 	unsigned rel_entsize = 0;
 	unsigned symsec_sh_link = 0;
 
+	struct section *sec;
+
 	int result = 0;
 
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
 
-	totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
+	totrelsz = tot_relsize(shdr0, shstrtab, fname);
 	if (totrelsz == 0)
 		return 0;
 	mrel0 = umalloc(totrelsz);
@@ -640,15 +640,18 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 
 	find_symtab(ehdr, shdr0, nhdr, &symtab, &symtab_shndx);
 
-	for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
-		char const *const txtname = has_rel_mcount(relhdr, shdr0,
+	list_for_each_entry(sec, &lf->sections, list) {
+		char const *txtname;
+
+		relhdr = &sec->sh;
+		txtname = has_rel_mcount(relhdr, shdr0,
 			shstrtab, fname);
 		if (txtname && is_mcounted_section_name(txtname)) {
 			unsigned int recsym;
 			uint_t recval = 0;
 
-			symsec_sh_link = w(relhdr->sh_link);
-			result = find_secsym_ndx(w(relhdr->sh_info), txtname,
+			symsec_sh_link = relhdr->sh_link;
+			result = find_secsym_ndx(relhdr->sh_info, txtname,
 						&recval, &recsym,
 						&shdr0[symsec_sh_link],
 						symtab, symtab_shndx,
@@ -656,7 +659,7 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 			if (result)
 				goto out;
 
-			rel_entsize = _w(relhdr->sh_entsize);
+			rel_entsize = relhdr->sh_entsize;
 			mlocp = sift_rel_mcount(mlocp,
 				(void *)mlocp - (void *)mloc0, &mrelp,
 				relhdr, ehdr, recsym, recval, reltype);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 07/51] objtool: mcount: Move nhdr into find_symtab()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (5 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 06/51] objtool: recordmcount: Convert do_func() relhdrs Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 08/51] objtool: mcount: Remove unused fname parameter Matt Helsley
                   ` (44 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Since it's no longer needed in the rest of do_func() we can move
it to where it's needed rather than pass it as a parameter.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index b46e855d32bf..4bd61c9d1fd5 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -229,9 +229,10 @@ static int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
 }
 
 static void find_symtab(Elf_Ehdr *const ehdr, Elf_Shdr const *shdr0,
-			unsigned const nhdr, Elf32_Word **symtab,
+			Elf32_Word **symtab,
 			Elf32_Word **symtab_shndx)
 {
+	unsigned const nhdr = get_shnum(ehdr, shdr0);
 	Elf_Shdr const *relhdr;
 	unsigned k;
 
@@ -593,7 +594,6 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 {
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
 		+ (void *)ehdr);
-	unsigned const nhdr = get_shnum(ehdr, shdr0);
 	Elf_Shdr *const shstr = &shdr0[get_shstrndx(ehdr, shdr0)];
 	char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
 		+ (void *)ehdr);
@@ -638,7 +638,7 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 		return -1;
 	}
 
-	find_symtab(ehdr, shdr0, nhdr, &symtab, &symtab_shndx);
+	find_symtab(ehdr, shdr0, &symtab, &symtab_shndx);
 
 	list_for_each_entry(sec, &lf->sections, list) {
 		char const *txtname;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 08/51] objtool: mcount: Remove unused fname parameter
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (6 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 07/51] objtool: mcount: Move nhdr into find_symtab() Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 09/51] objtool: mcount: Use libelf for section header names Matt Helsley
                   ` (43 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

The name of the object file being processed is unused in
the wrapper's leaf functions so we no longer need to pass
it as a parameter.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c |  4 ++--
 tools/objtool/recordmcount.h | 19 ++++++++-----------
 2 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index f585bf7f45f5..9941683b3f60 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -586,7 +586,7 @@ static int do_file(char const *const fname)
 			reltype = R_MIPS_32;
 			is_fake_mcount32 = MIPS32_is_fake_mcount;
 		}
-		if (do32(ehdr, fname, reltype) < 0)
+		if (do32(ehdr, reltype) < 0)
 			goto out;
 		break;
 	case ELFCLASS64: {
@@ -607,7 +607,7 @@ static int do_file(char const *const fname)
 			Elf64_r_info = MIPS64_r_info;
 			is_fake_mcount64 = MIPS64_is_fake_mcount;
 		}
-		if (do64(ghdr, fname, reltype) < 0)
+		if (do64(ghdr, reltype) < 0)
 			goto out;
 		break;
 	}
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 4bd61c9d1fd5..53abfd49a537 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -548,8 +548,7 @@ static int find_secsym_ndx(unsigned const txtndx,
 /* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
 static char const * __has_rel_mcount(GElf_Shdr const *const relhdr, /* reltype */
 				     Elf_Shdr const *const shdr0,
-				     char const *const shstrtab,
-				     char const *const fname)
+				     char const *const shstrtab)
 {
 	/* .sh_info depends on .sh_type == SHT_REL[,A] */
 	Elf_Shdr const *const txthdr = &shdr0[relhdr->sh_info];
@@ -563,25 +562,23 @@ static char const * __has_rel_mcount(GElf_Shdr const *const relhdr, /* reltype *
 
 static char const *has_rel_mcount(GElf_Shdr const *const relhdr,
 				  Elf_Shdr const *const shdr0,
-				  char const *const shstrtab,
-				  char const *const fname)
+				  char const *const shstrtab)
 {
 	if (relhdr->sh_type != SHT_REL && relhdr->sh_type != SHT_RELA)
 		return NULL;
-	return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
+	return __has_rel_mcount(relhdr, shdr0, shstrtab);
 }
 
 
 static unsigned tot_relsize(Elf_Shdr const *const shdr0,
-			    const char *const shstrtab,
-			    const char *const fname)
+			    const char *const shstrtab)
 {
 	struct section *sec;
 	unsigned totrelsz = 0;
 	char const *txtname;
 
 	list_for_each_entry(sec, &lf->sections, list) {
-		txtname = has_rel_mcount(&sec->sh, shdr0, shstrtab, fname);
+		txtname = has_rel_mcount(&sec->sh, shdr0, shstrtab);
 		if (txtname && is_mcounted_section_name(txtname))
 			totrelsz += sec->sh.sh_size;
 	}
@@ -589,7 +586,7 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0,
 }
 
 /* Overall supervision for Elf32 ET_REL file. */
-static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
+static int do_func(Elf_Ehdr *const ehdr,
 		   unsigned const reltype)
 {
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
@@ -622,7 +619,7 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
 
-	totrelsz = tot_relsize(shdr0, shstrtab, fname);
+	totrelsz = tot_relsize(shdr0, shstrtab);
 	if (totrelsz == 0)
 		return 0;
 	mrel0 = umalloc(totrelsz);
@@ -645,7 +642,7 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname,
 
 		relhdr = &sec->sh;
 		txtname = has_rel_mcount(relhdr, shdr0,
-			shstrtab, fname);
+			shstrtab);
 		if (txtname && is_mcounted_section_name(txtname)) {
 			unsigned int recsym;
 			uint_t recval = 0;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 09/51] objtool: mcount: Use libelf for section header names
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (7 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 08/51] objtool: mcount: Remove unused fname parameter Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 10/51] objtool: mcount: Walk objtool Elf structs in find_secsym_ndx Matt Helsley
                   ` (42 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than passing in the string table contents as a parameter,
pass in the section index of the string table and rely on libelf
string table accessor functions to look up section names.

Note that modifying the string table with libelf will come later
so append_func() is unchanged.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c          |  3 +-
 tools/objtool/elf.h          |  1 +
 tools/objtool/recordmcount.c |  2 +-
 tools/objtool/recordmcount.h | 89 ++++++++++++++----------------------
 4 files changed, 37 insertions(+), 58 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 6812cf74be9a..17e39b3a1719 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -185,8 +185,7 @@ struct section *find_section_by_name(const struct elf *elf, const char *name)
 	return NULL;
 }
 
-static struct section *find_section_by_index(struct elf *elf,
-					     unsigned int idx)
+struct section *find_section_by_index(const struct elf *elf, unsigned int idx)
 {
 	struct section *sec;
 
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 6cc80a075166..60eb44661658 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -131,6 +131,7 @@ int elf_write(struct elf *elf);
 void elf_close(struct elf *elf);
 
 struct section *find_section_by_name(const struct elf *elf, const char *name);
+struct section *find_section_by_index(const struct elf *elf, unsigned int idx);
 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 9941683b3f60..f20582ac99e2 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -177,7 +177,7 @@ static void *mmap_file(char const *fname)
 	file_updated = 0;
 	sb.st_size = 0;
 
-	lf = elf_open_read(fname, O_RDONLY);
+	lf = elf_open_read(fname, O_RDWR);
 	if (!lf) {
 		perror(fname);
 		return NULL;
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 53abfd49a537..30f8913aa841 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -25,7 +25,6 @@
 #undef sift_rel_mcount
 #undef nop_mcount
 #undef find_secsym_ndx
-#undef __has_rel_mcount
 #undef has_rel_mcount
 #undef tot_relsize
 #undef get_mcountsym
@@ -60,7 +59,6 @@
 # define sift_rel_mcount	sift64_rel_mcount
 # define nop_mcount		nop_mcount_64
 # define find_secsym_ndx	find64_secsym_ndx
-# define __has_rel_mcount	__has64_rel_mcount
 # define has_rel_mcount		has64_rel_mcount
 # define tot_relsize		tot64_relsize
 # define find_symtab		find_symtab64
@@ -98,7 +96,6 @@
 # define sift_rel_mcount	sift32_rel_mcount
 # define nop_mcount		nop_mcount_32
 # define find_secsym_ndx	find32_secsym_ndx
-# define __has_rel_mcount	__has32_rel_mcount
 # define has_rel_mcount		has32_rel_mcount
 # define tot_relsize		tot32_relsize
 # define find_symtab		find_symtab32
@@ -276,6 +273,7 @@ static int append_func(Elf_Ehdr *const ehdr,
 
 	shstr->sh_size = _w(t);
 	shstr->sh_offset = _w(sb.st_size);
+
 	t += sb.st_size;
 	t += (_align & -t);  /* word-byte align */
 	new_e_shoff = t;
@@ -340,7 +338,7 @@ static int append_func(Elf_Ehdr *const ehdr,
 		return -1;
 	if (uwrite(ehdr, sizeof(*ehdr)) < 0)
 		return -1;
-	return 0;
+	return elf_write(lf);
 }
 
 static unsigned get_mcountsym(Elf_Sym const *const sym0,
@@ -365,7 +363,7 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0,
 	return mcountsym;
 }
 
-static void get_sym_str_and_relp(GElf_Shdr const *const relhdr,
+static void get_sym_str_and_relp(const struct section * const rels,
 				 Elf_Ehdr const *const ehdr,
 				 Elf_Sym const **sym0,
 				 char const **str0,
@@ -373,10 +371,10 @@ static void get_sym_str_and_relp(GElf_Shdr const *const relhdr,
 {
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
 		+ (void *)ehdr);
-	unsigned const symsec_sh_link = relhdr->sh_link;
+	unsigned const symsec_sh_link = rels->sh.sh_link;
 	Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
 	Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
-	Elf_Rel const *const rel0 = (Elf_Rel const *)(relhdr->sh_offset
+	Elf_Rel const *const rel0 = (Elf_Rel const *)(rels->sh.sh_offset
 		+ (void *)ehdr);
 
 	*sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
@@ -396,7 +394,7 @@ static void get_sym_str_and_relp(GElf_Shdr const *const relhdr,
 static uint_t *sift_rel_mcount(uint_t *mlocp,
 			       unsigned const offbase,
 			       Elf_Rel **const mrelpp,
-			       GElf_Shdr const *const relhdr,
+			       const struct section * const rels,
 			       Elf_Ehdr const *const ehdr,
 			       unsigned const recsym_index,
 			       uint_t const recval,
@@ -407,12 +405,12 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 	Elf_Sym const *sym0;
 	char const *str0;
 	Elf_Rel const *relp;
-	unsigned int rel_entsize = relhdr->sh_entsize;
-	unsigned const nrel = relhdr->sh_size / rel_entsize;
+	unsigned int rel_entsize = rels->sh.sh_entsize;
+	unsigned const nrel = rels->sh.sh_size / rel_entsize;
 	unsigned mcountsym = 0;
 	unsigned t;
 
-	get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp);
+	get_sym_str_and_relp(rels, ehdr, &sym0, &str0, &relp);
 
 	for (t = nrel; t; --t) {
 		if (!mcountsym)
@@ -444,7 +442,7 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
  * that are not going to be traced. The mcount calls here will be converted
  * into nops.
  */
-static int nop_mcount(GElf_Shdr const *const relhdr,
+static int nop_mcount(const struct section * const rels,
 		      Elf_Ehdr const *const ehdr,
 		      const char *const txtname)
 {
@@ -453,14 +451,14 @@ static int nop_mcount(GElf_Shdr const *const relhdr,
 	Elf_Sym const *sym0;
 	char const *str0;
 	Elf_Rel const *relp;
-	Elf_Shdr const *const shdr = &shdr0[relhdr->sh_info];
-	unsigned int rel_entsize = relhdr->sh_entsize;
-	unsigned const nrel = relhdr->sh_size / rel_entsize;
+	Elf_Shdr const *const shdr = &shdr0[rels->sh.sh_info];
+	unsigned rel_entsize = rels->sh.sh_entsize;
+	unsigned const nrel = rels->sh.sh_size / rel_entsize;
 	unsigned mcountsym = 0;
 	unsigned t;
 	int once = 0;
 
-	get_sym_str_and_relp(relhdr, ehdr, &sym0, &str0, &relp);
+	get_sym_str_and_relp(rels, ehdr, &sym0, &str0, &relp);
 
 	for (t = nrel; t; --t) {
 		int ret = -1;
@@ -545,40 +543,27 @@ static int find_secsym_ndx(unsigned const txtndx,
 	return -1;
 }
 
-/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
-static char const * __has_rel_mcount(GElf_Shdr const *const relhdr, /* reltype */
-				     Elf_Shdr const *const shdr0,
-				     char const *const shstrtab)
+static char const *has_rel_mcount(const struct section * const rels)
 {
-	/* .sh_info depends on .sh_type == SHT_REL[,A] */
-	Elf_Shdr const *const txthdr = &shdr0[relhdr->sh_info];
-	char const *const txtname = &shstrtab[w(txthdr->sh_name)];
-
-	if (w(txthdr->sh_type) != SHT_PROGBITS ||
-	    !(_w(txthdr->sh_flags) & SHF_EXECINSTR))
+	const struct section *txts;
+	if (rels->sh.sh_type != SHT_REL && rels->sh.sh_type != SHT_RELA)
 		return NULL;
-	return txtname;
-}
-
-static char const *has_rel_mcount(GElf_Shdr const *const relhdr,
-				  Elf_Shdr const *const shdr0,
-				  char const *const shstrtab)
-{
-	if (relhdr->sh_type != SHT_REL && relhdr->sh_type != SHT_RELA)
+	txts = find_section_by_index(lf, rels->sh.sh_info);
+	if ((txts->sh.sh_type != SHT_PROGBITS) ||
+	    !(txts->sh.sh_flags & SHF_EXECINSTR))
 		return NULL;
-	return __has_rel_mcount(relhdr, shdr0, shstrtab);
+	return txts->name;
 }
 
 
-static unsigned tot_relsize(Elf_Shdr const *const shdr0,
-			    const char *const shstrtab)
+static unsigned tot_relsize(void)
 {
-	struct section *sec;
+	const struct section *sec;
 	unsigned totrelsz = 0;
 	char const *txtname;
 
 	list_for_each_entry(sec, &lf->sections, list) {
-		txtname = has_rel_mcount(&sec->sh, shdr0, shstrtab);
+		txtname = has_rel_mcount(sec);
 		if (txtname && is_mcounted_section_name(txtname))
 			totrelsz += sec->sh.sh_size;
 	}
@@ -591,11 +576,6 @@ static int do_func(Elf_Ehdr *const ehdr,
 {
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
 		+ (void *)ehdr);
-	Elf_Shdr *const shstr = &shdr0[get_shstrndx(ehdr, shdr0)];
-	char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
-		+ (void *)ehdr);
-
-	GElf_Shdr const *relhdr;
 
 	Elf32_Word *symtab;
 	Elf32_Word *symtab_shndx;
@@ -612,14 +592,14 @@ static int do_func(Elf_Ehdr *const ehdr,
 	unsigned rel_entsize = 0;
 	unsigned symsec_sh_link = 0;
 
-	struct section *sec;
+	const struct section *sec;
 
 	int result = 0;
 
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
 
-	totrelsz = tot_relsize(shdr0, shstrtab);
+	totrelsz = tot_relsize();
 	if (totrelsz == 0)
 		return 0;
 	mrel0 = umalloc(totrelsz);
@@ -640,15 +620,13 @@ static int do_func(Elf_Ehdr *const ehdr,
 	list_for_each_entry(sec, &lf->sections, list) {
 		char const *txtname;
 
-		relhdr = &sec->sh;
-		txtname = has_rel_mcount(relhdr, shdr0,
-			shstrtab);
+		txtname = has_rel_mcount(sec);
 		if (txtname && is_mcounted_section_name(txtname)) {
 			unsigned int recsym;
 			uint_t recval = 0;
 
-			symsec_sh_link = relhdr->sh_link;
-			result = find_secsym_ndx(relhdr->sh_info, txtname,
+			symsec_sh_link = sec->sh.sh_link;
+			result = find_secsym_ndx(sec->sh.sh_info, txtname,
 						&recval, &recsym,
 						&shdr0[symsec_sh_link],
 						symtab, symtab_shndx,
@@ -656,23 +634,24 @@ static int do_func(Elf_Ehdr *const ehdr,
 			if (result)
 				goto out;
 
-			rel_entsize = relhdr->sh_entsize;
+			rel_entsize = sec->sh.sh_entsize;
 			mlocp = sift_rel_mcount(mlocp,
 				(void *)mlocp - (void *)mloc0, &mrelp,
-				relhdr, ehdr, recsym, recval, reltype);
+				sec, ehdr, recsym, recval, reltype);
 		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
 			/*
 			 * This section is ignored by ftrace, but still
 			 * has mcount calls. Convert them to nops now.
 			 */
-			if (nop_mcount(relhdr, ehdr, txtname) < 0) {
+			if (nop_mcount(sec, ehdr, txtname) < 0) {
 				result = -1;
 				goto out;
 			}
 		}
 	}
 	if (!result && mloc0 != mlocp)
-		result = append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
+		result = append_func(ehdr, &shdr0[get_shstrndx(ehdr, shdr0)],
+				     mloc0, mlocp, mrel0, mrelp,
 				     rel_entsize, symsec_sh_link);
 out:
 	free(mrel0);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 10/51] objtool: mcount: Walk objtool Elf structs in find_secsym_ndx
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (8 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 09/51] objtool: mcount: Use libelf for section header names Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 11/51] objtool: mcount: Use symbol structs to find mcount relocations Matt Helsley
                   ` (41 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than using indices into raw ELF32/64 tables mapped for the
wrapper, use the objtool functions to find the suitable symbol
in the given text section. This also removes all callers to
find_symtab() and get_symindex() so we can remove them as well.

Also take advantage of this commit to rename the function to
something that reads more easily.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c |  2 +
 tools/objtool/recordmcount.h | 94 ++++++++----------------------------
 2 files changed, 22 insertions(+), 74 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index f20582ac99e2..843027a46e1b 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -422,6 +422,8 @@ static int is_mcounted_section_name(char const *const txtname)
 		strcmp(".cpuidle.text", txtname) == 0;
 }
 
+static const unsigned int missing_sym = (unsigned int)-1;
+
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 30f8913aa841..b10f7fcd33c3 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -24,15 +24,13 @@
 #undef mcount_adjust
 #undef sift_rel_mcount
 #undef nop_mcount
-#undef find_secsym_ndx
+#undef find_section_sym_index
 #undef has_rel_mcount
 #undef tot_relsize
 #undef get_mcountsym
-#undef find_symtab
 #undef get_shnum
 #undef set_shnum
 #undef get_shstrndx
-#undef get_symindex
 #undef get_sym_str_and_relp
 #undef do_func
 #undef Elf_Addr
@@ -58,14 +56,12 @@
 # define append_func		append64
 # define sift_rel_mcount	sift64_rel_mcount
 # define nop_mcount		nop_mcount_64
-# define find_secsym_ndx	find64_secsym_ndx
+# define find_section_sym_index	find64_section_sym_index
 # define has_rel_mcount		has64_rel_mcount
 # define tot_relsize		tot64_relsize
-# define find_symtab		find_symtab64
 # define get_shnum		get_shnum64
 # define set_shnum		set_shnum64
 # define get_shstrndx		get_shstrndx64
-# define get_symindex		get_symindex64
 # define get_sym_str_and_relp	get_sym_str_and_relp_64
 # define do_func		do64
 # define get_mcountsym		get_mcountsym_64
@@ -95,14 +91,12 @@
 # define append_func		append32
 # define sift_rel_mcount	sift32_rel_mcount
 # define nop_mcount		nop_mcount_32
-# define find_secsym_ndx	find32_secsym_ndx
+# define find_section_sym_index	find32_section_sym_index
 # define has_rel_mcount		has32_rel_mcount
 # define tot_relsize		tot32_relsize
-# define find_symtab		find_symtab32
 # define get_shnum		get_shnum32
 # define set_shnum		set_shnum32
 # define get_shstrndx		get_shstrndx32
-# define get_symindex		get_symindex32
 # define get_sym_str_and_relp	get_sym_str_and_relp_32
 # define do_func		do32
 # define get_mcountsym		get_mcountsym_32
@@ -185,21 +179,6 @@ static int MIPS_is_fake_mcount(Elf_Rel const *rp)
 	return is_fake;
 }
 
-static unsigned int get_symindex(Elf_Sym const *sym, Elf32_Word const *symtab,
-				 Elf32_Word const *symtab_shndx)
-{
-	unsigned long offset;
-	int index;
-
-	if (sym->st_shndx != SHN_XINDEX)
-		return w2(sym->st_shndx);
-
-	offset = (unsigned long)sym - (unsigned long)symtab;
-	index = offset / sizeof(*sym);
-
-	return w(symtab_shndx[index]);
-}
-
 static unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
 {
 	if (shdr0 && !ehdr->e_shnum)
@@ -225,28 +204,6 @@ static int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
 	return w(shdr0->sh_link);
 }
 
-static void find_symtab(Elf_Ehdr *const ehdr, Elf_Shdr const *shdr0,
-			Elf32_Word **symtab,
-			Elf32_Word **symtab_shndx)
-{
-	unsigned const nhdr = get_shnum(ehdr, shdr0);
-	Elf_Shdr const *relhdr;
-	unsigned k;
-
-	*symtab = NULL;
-	*symtab_shndx = NULL;
-
-	for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
-		if (relhdr->sh_type == SHT_SYMTAB)
-			*symtab = (void *)ehdr + relhdr->sh_offset;
-		else if (relhdr->sh_type == SHT_SYMTAB_SHNDX)
-			*symtab_shndx = (void *)ehdr + relhdr->sh_offset;
-
-		if (*symtab && *symtab_shndx)
-			break;
-	}
-}
-
 /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
 static int append_func(Elf_Ehdr *const ehdr,
 			Elf_Shdr *const shstr,
@@ -507,40 +464,37 @@ static int nop_mcount(const struct section * const rels,
  *    Num:    Value  Size Type    Bind   Vis      Ndx Name
  *      2: 00000000     0 SECTION LOCAL  DEFAULT    1
  */
-static int find_secsym_ndx(unsigned const txtndx,
+static int find_section_sym_index(unsigned const txtndx,
 				char const *const txtname,
 				uint_t *const recvalp,
 				unsigned int *sym_index,
-				Elf_Shdr const *const symhdr,
-				Elf32_Word const *symtab,
-				Elf32_Word const *symtab_shndx,
 				Elf_Ehdr const *const ehdr)
 {
-	Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
-		+ (void *)ehdr);
-	unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
-	Elf_Sym const *symp;
-	unsigned t;
+	struct symbol *sym;
+	struct section *txts = find_section_by_index(lf, txtndx);
 
-	for (symp = sym0, t = nsym; t; --t, ++symp) {
-		unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
+	if (!txts) {
+		fprintf(stderr, "Cannot find section %u: %s.\n",
+			txtndx, txtname);
+		return missing_sym;
+	}
 
-		if (txtndx == get_symindex(symp, symtab, symtab_shndx)
-			/* avoid STB_WEAK */
-		    && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
+	list_for_each_entry(sym, &txts->symbol_list, list) {
+		/* avoid symbols with weak binding */
+		if ((sym->bind == STB_LOCAL) || (sym->bind == STB_GLOBAL)) {
 			/* function symbols on ARM have quirks, avoid them */
 			if (w2(ehdr->e_machine) == EM_ARM
-			    && ELF_ST_TYPE(symp->st_info) == STT_FUNC)
+			    && sym->type == STT_FUNC)
 				continue;
 
-			*recvalp = _w(symp->st_value);
-			*sym_index = symp - sym0;
+			*recvalp = sym->sym.st_value;
+			*sym_index = sym->idx;
 			return 0;
 		}
 	}
 	fprintf(stderr, "Cannot find symbol for section %u: %s.\n",
 		txtndx, txtname);
-	return -1;
+	return missing_sym;
 }
 
 static char const *has_rel_mcount(const struct section * const rels)
@@ -577,9 +531,6 @@ static int do_func(Elf_Ehdr *const ehdr,
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
 		+ (void *)ehdr);
 
-	Elf32_Word *symtab;
-	Elf32_Word *symtab_shndx;
-
 	/* Upper bound on space: assume all relevant relocs are for mcount. */
 	unsigned       totrelsz;
 
@@ -615,8 +566,6 @@ static int do_func(Elf_Ehdr *const ehdr,
 		return -1;
 	}
 
-	find_symtab(ehdr, shdr0, &symtab, &symtab_shndx);
-
 	list_for_each_entry(sec, &lf->sections, list) {
 		char const *txtname;
 
@@ -626,11 +575,8 @@ static int do_func(Elf_Ehdr *const ehdr,
 			uint_t recval = 0;
 
 			symsec_sh_link = sec->sh.sh_link;
-			result = find_secsym_ndx(sec->sh.sh_info, txtname,
-						&recval, &recsym,
-						&shdr0[symsec_sh_link],
-						symtab, symtab_shndx,
-						ehdr);
+			result = find_section_sym_index(sec->sh.sh_info,
+						txtname, &recval, &recsym, ehdr);
 			if (result)
 				goto out;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 11/51] objtool: mcount: Use symbol structs to find mcount relocations
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (9 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 10/51] objtool: mcount: Walk objtool Elf structs in find_secsym_ndx Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 12/51] objtool: mcount: Walk relocation lists Matt Helsley
                   ` (40 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than open coding symbol name lookups in get_sym_and_*()
we rename the structure and use objtool's lookup function to
get the symbol name for a relocation. We also change the name
of the function to better reflect its purpose.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c          |  2 +-
 tools/objtool/elf.h          |  1 +
 tools/objtool/recordmcount.h | 54 ++++++++++--------------------------
 3 files changed, 17 insertions(+), 40 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 17e39b3a1719..8dcdea8020a5 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -196,7 +196,7 @@ struct section *find_section_by_index(const struct elf *elf, unsigned int idx)
 	return NULL;
 }
 
-static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
+struct symbol *find_symbol_by_index(const struct elf *elf, unsigned int idx)
 {
 	struct symbol *sym;
 
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 60eb44661658..09fa0d085341 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -135,6 +135,7 @@ struct section *find_section_by_index(const struct elf *elf, unsigned int idx);
 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
+struct symbol *find_symbol_by_index(const struct elf *elf, unsigned int idx);
 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index b10f7fcd33c3..3dae878f11a8 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -31,7 +31,7 @@
 #undef get_shnum
 #undef set_shnum
 #undef get_shstrndx
-#undef get_sym_str_and_relp
+#undef get_relp
 #undef do_func
 #undef Elf_Addr
 #undef Elf_Ehdr
@@ -62,7 +62,7 @@
 # define get_shnum		get_shnum64
 # define set_shnum		set_shnum64
 # define get_shstrndx		get_shstrndx64
-# define get_sym_str_and_relp	get_sym_str_and_relp_64
+# define get_relp		get_relp_64
 # define do_func		do64
 # define get_mcountsym		get_mcountsym_64
 # define is_fake_mcount		is_fake_mcount64
@@ -97,7 +97,7 @@
 # define get_shnum		get_shnum32
 # define set_shnum		set_shnum32
 # define get_shstrndx		get_shstrndx32
-# define get_sym_str_and_relp	get_sym_str_and_relp_32
+# define get_relp		get_relp_32
 # define do_func		do32
 # define get_mcountsym		get_mcountsym_32
 # define is_fake_mcount		is_fake_mcount32
@@ -298,15 +298,10 @@ static int append_func(Elf_Ehdr *const ehdr,
 	return elf_write(lf);
 }
 
-static unsigned get_mcountsym(Elf_Sym const *const sym0,
-			      Elf_Rel const *relp,
-			      char const *const str0)
+static unsigned get_mcountsym(Elf_Rel const *relp)
 {
-	unsigned mcountsym = 0;
-
-	Elf_Sym const *const symp =
-		&sym0[Elf_r_sym(relp)];
-	char const *symname = &str0[w(symp->st_name)];
+	struct symbol *sym = find_symbol_by_index(lf, Elf_r_sym(relp));
+	char const *symname = sym->name;
 	char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
 	char const *fentry = "__fentry__";
 
@@ -315,31 +310,16 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0,
 	if (strcmp(mcount, symname) == 0 ||
 	    (altmcount && strcmp(altmcount, symname) == 0) ||
 	    (strcmp(fentry, symname) == 0))
-		mcountsym = Elf_r_sym(relp);
-
-	return mcountsym;
+		return Elf_r_sym(relp);
+	return 0;
 }
 
-static void get_sym_str_and_relp(const struct section * const rels,
-				 Elf_Ehdr const *const ehdr,
-				 Elf_Sym const **sym0,
-				 char const **str0,
-				 Elf_Rel const **relp)
+static void get_relp(const struct section * const rels,
+			Elf_Ehdr const *const ehdr,
+			Elf_Rel const **relp)
 {
-	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
-		+ (void *)ehdr);
-	unsigned const symsec_sh_link = rels->sh.sh_link;
-	Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
-	Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
 	Elf_Rel const *const rel0 = (Elf_Rel const *)(rels->sh.sh_offset
 		+ (void *)ehdr);
-
-	*sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
-				  + (void *)ehdr);
-
-	*str0 = (char const *)(_w(strsec->sh_offset)
-			       + (void *)ehdr);
-
 	*relp = rel0;
 }
 
@@ -359,19 +339,17 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 {
 	uint_t *const mloc0 = mlocp;
 	Elf_Rel *mrelp = *mrelpp;
-	Elf_Sym const *sym0;
-	char const *str0;
 	Elf_Rel const *relp;
 	unsigned int rel_entsize = rels->sh.sh_entsize;
 	unsigned const nrel = rels->sh.sh_size / rel_entsize;
 	unsigned mcountsym = 0;
 	unsigned t;
 
-	get_sym_str_and_relp(rels, ehdr, &sym0, &str0, &relp);
+	get_relp(rels, ehdr, &relp);
 
 	for (t = nrel; t; --t) {
 		if (!mcountsym)
-			mcountsym = get_mcountsym(sym0, relp, str0);
+			mcountsym = get_mcountsym(relp);
 
 		if (mcountsym && mcountsym == Elf_r_sym(relp) &&
 				!is_fake_mcount(relp)) {
@@ -405,8 +383,6 @@ static int nop_mcount(const struct section * const rels,
 {
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
 		+ (void *)ehdr);
-	Elf_Sym const *sym0;
-	char const *str0;
 	Elf_Rel const *relp;
 	Elf_Shdr const *const shdr = &shdr0[rels->sh.sh_info];
 	unsigned rel_entsize = rels->sh.sh_entsize;
@@ -415,13 +391,13 @@ static int nop_mcount(const struct section * const rels,
 	unsigned t;
 	int once = 0;
 
-	get_sym_str_and_relp(rels, ehdr, &sym0, &str0, &relp);
+	get_relp(rels, ehdr, &relp);
 
 	for (t = nrel; t; --t) {
 		int ret = -1;
 
 		if (!mcountsym)
-			mcountsym = get_mcountsym(sym0, relp, str0);
+			mcountsym = get_mcountsym(relp);
 
 		if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
 			if (make_nop)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 12/51] objtool: mcount: Walk relocation lists
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (10 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 11/51] objtool: mcount: Use symbol structs to find mcount relocations Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:37 ` [RFC][PATCH v5 13/51] objtool: mcount: Return symbol from mcountsym Matt Helsley
                   ` (39 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than walk the section tables using the old recordmcount mapping
of the ELF file, walk the section list provided by objtool's ELF code.
This removes the last use of of the Elf_r_sym wrapper so we remove
that too.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c |  10 +---
 tools/objtool/recordmcount.h | 103 +++++++++--------------------------
 2 files changed, 28 insertions(+), 85 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 843027a46e1b..dafa6dd10d04 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -429,9 +429,9 @@ static const unsigned int missing_sym = (unsigned int)-1;
 #define RECORD_MCOUNT_64
 #include "recordmcount.h"
 
-static int arm_is_fake_mcount(Elf32_Rel const *rp)
+static int arm_is_fake_mcount(struct reloc const *rp)
 {
-	switch (ELF32_R_TYPE(w(rp->r_info))) {
+	switch (rp->type) {
 	case R_ARM_THM_CALL:
 	case R_ARM_CALL:
 	case R_ARM_PC24:
@@ -462,11 +462,6 @@ union mips_r_info {
 	} r_mips;
 };
 
-static uint64_t MIPS64_r_sym(Elf64_Rel const *rp)
-{
-	return w(((union mips_r_info){ .r_info = rp->r_info }).r_mips.r_sym);
-}
-
 static void MIPS64_r_info(Elf64_Rel *const rp, unsigned sym, unsigned type)
 {
 	rp->r_info = ((union mips_r_info){
@@ -605,7 +600,6 @@ static int do_file(char const *const fname)
 		}
 		if (w2(ghdr->e_machine) == EM_MIPS) {
 			reltype = R_MIPS_64;
-			Elf64_r_sym = MIPS64_r_sym;
 			Elf64_r_info = MIPS64_r_info;
 			is_fake_mcount64 = MIPS64_is_fake_mcount;
 		}
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 3dae878f11a8..df8384f8e9e7 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -31,21 +31,14 @@
 #undef get_shnum
 #undef set_shnum
 #undef get_shstrndx
-#undef get_relp
 #undef do_func
 #undef Elf_Addr
 #undef Elf_Ehdr
 #undef Elf_Shdr
 #undef Elf_Rel
 #undef Elf_Rela
-#undef Elf_Sym
-#undef ELF_R_SYM
-#undef Elf_r_sym
 #undef ELF_R_INFO
 #undef Elf_r_info
-#undef ELF_ST_BIND
-#undef ELF_ST_TYPE
-#undef fn_ELF_R_SYM
 #undef fn_ELF_R_INFO
 #undef uint_t
 #undef _w
@@ -62,7 +55,6 @@
 # define get_shnum		get_shnum64
 # define set_shnum		set_shnum64
 # define get_shstrndx		get_shstrndx64
-# define get_relp		get_relp_64
 # define do_func		do64
 # define get_mcountsym		get_mcountsym_64
 # define is_fake_mcount		is_fake_mcount64
@@ -74,14 +66,8 @@
 # define Elf_Shdr		Elf64_Shdr
 # define Elf_Rel		Elf64_Rel
 # define Elf_Rela		Elf64_Rela
-# define Elf_Sym		Elf64_Sym
-# define ELF_R_SYM		ELF64_R_SYM
-# define Elf_r_sym		Elf64_r_sym
 # define ELF_R_INFO		ELF64_R_INFO
 # define Elf_r_info		Elf64_r_info
-# define ELF_ST_BIND		ELF64_ST_BIND
-# define ELF_ST_TYPE		ELF64_ST_TYPE
-# define fn_ELF_R_SYM		fn_ELF64_R_SYM
 # define fn_ELF_R_INFO		fn_ELF64_R_INFO
 # define uint_t			uint64_t
 # define _w			w8
@@ -97,7 +83,6 @@
 # define get_shnum		get_shnum32
 # define set_shnum		set_shnum32
 # define get_shstrndx		get_shstrndx32
-# define get_relp		get_relp_32
 # define do_func		do32
 # define get_mcountsym		get_mcountsym_32
 # define is_fake_mcount		is_fake_mcount32
@@ -109,14 +94,8 @@
 # define Elf_Shdr		Elf32_Shdr
 # define Elf_Rel		Elf32_Rel
 # define Elf_Rela		Elf32_Rela
-# define Elf_Sym		Elf32_Sym
-# define ELF_R_SYM		ELF32_R_SYM
-# define Elf_r_sym		Elf32_r_sym
 # define ELF_R_INFO		ELF32_R_INFO
 # define Elf_r_info		Elf32_r_info
-# define ELF_ST_BIND		ELF32_ST_BIND
-# define ELF_ST_TYPE		ELF32_ST_TYPE
-# define fn_ELF_R_SYM		fn_ELF32_R_SYM
 # define fn_ELF_R_INFO		fn_ELF32_R_INFO
 # define uint_t			uint32_t
 # define _w			w
@@ -125,17 +104,11 @@
 #endif
 
 /* Functions and pointers that do_file() may override for specific e_machine. */
-static int fn_is_fake_mcount(Elf_Rel const *rp)
+static int fn_is_fake_mcount(struct reloc const *reloc)
 {
 	return 0;
 }
-static int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount;
-
-static uint_t fn_ELF_R_SYM(Elf_Rel const *rp)
-{
-	return ELF_R_SYM(_w(rp->r_info));
-}
-static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
+static int (*is_fake_mcount)(struct reloc const *reloc) = fn_is_fake_mcount;
 
 static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 {
@@ -166,10 +139,10 @@ static int mcount_adjust = 0;
  */
 #define MIPS_FAKEMCOUNT_OFFSET	4
 
-static int MIPS_is_fake_mcount(Elf_Rel const *rp)
+static int MIPS_is_fake_mcount(struct reloc const *reloc)
 {
 	static Elf_Addr old_r_offset = ~(Elf_Addr)0;
-	Elf_Addr current_r_offset = _w(rp->r_offset);
+	Elf_Addr current_r_offset = reloc->offset;
 	int is_fake;
 
 	is_fake = (old_r_offset != ~(Elf_Addr)0) &&
@@ -298,9 +271,9 @@ static int append_func(Elf_Ehdr *const ehdr,
 	return elf_write(lf);
 }
 
-static unsigned get_mcountsym(Elf_Rel const *relp)
+static unsigned get_mcountsym(struct reloc *reloc)
 {
-	struct symbol *sym = find_symbol_by_index(lf, Elf_r_sym(relp));
+	struct symbol *sym = reloc->sym;
 	char const *symname = sym->name;
 	char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
 	char const *fentry = "__fentry__";
@@ -310,19 +283,10 @@ static unsigned get_mcountsym(Elf_Rel const *relp)
 	if (strcmp(mcount, symname) == 0 ||
 	    (altmcount && strcmp(altmcount, symname) == 0) ||
 	    (strcmp(fentry, symname) == 0))
-		return Elf_r_sym(relp);
+		return GELF_R_INFO(reloc->sym->idx, reloc->type);
 	return 0;
 }
 
-static void get_relp(const struct section * const rels,
-			Elf_Ehdr const *const ehdr,
-			Elf_Rel const **relp)
-{
-	Elf_Rel const *const rel0 = (Elf_Rel const *)(rels->sh.sh_offset
-		+ (void *)ehdr);
-	*relp = rel0;
-}
-
 /*
  * Look at the relocations in order to find the calls to mcount.
  * Accumulate the section offsets that are found, and their relocation info,
@@ -332,29 +296,23 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 			       unsigned const offbase,
 			       Elf_Rel **const mrelpp,
 			       const struct section * const rels,
-			       Elf_Ehdr const *const ehdr,
 			       unsigned const recsym_index,
 			       uint_t const recval,
 			       unsigned const reltype)
 {
 	uint_t *const mloc0 = mlocp;
 	Elf_Rel *mrelp = *mrelpp;
-	Elf_Rel const *relp;
 	unsigned int rel_entsize = rels->sh.sh_entsize;
-	unsigned const nrel = rels->sh.sh_size / rel_entsize;
 	unsigned mcountsym = 0;
-	unsigned t;
-
-	get_relp(rels, ehdr, &relp);
+	struct reloc *reloc;
 
-	for (t = nrel; t; --t) {
+	list_for_each_entry(reloc, &rels->reloc_list, list) {
 		if (!mcountsym)
-			mcountsym = get_mcountsym(relp);
+			mcountsym = get_mcountsym(reloc);
 
-		if (mcountsym && mcountsym == Elf_r_sym(relp) &&
-				!is_fake_mcount(relp)) {
+		if (mcountsym == GELF_R_INFO(reloc->sym->idx, reloc->type) && !is_fake_mcount(reloc)) {
 			uint_t const addend =
-				_w(_w(relp->r_offset) - recval + mcount_adjust);
+				_w(reloc->offset - recval + mcount_adjust);
 			mrelp->r_offset = _w(offbase
 				+ ((void *)mlocp - (void *)mloc0));
 			Elf_r_info(mrelp, recsym_index, reltype);
@@ -366,7 +324,6 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 
 			mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
 		}
-		relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
 	}
 	*mrelpp = mrelp;
 	return mlocp;
@@ -377,31 +334,29 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
  * that are not going to be traced. The mcount calls here will be converted
  * into nops.
  */
-static int nop_mcount(const struct section * const rels,
+static int nop_mcount(struct section * const rels,
 		      Elf_Ehdr const *const ehdr,
 		      const char *const txtname)
 {
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
 		+ (void *)ehdr);
-	Elf_Rel const *relp;
+	struct reloc *reloc;
 	Elf_Shdr const *const shdr = &shdr0[rels->sh.sh_info];
-	unsigned rel_entsize = rels->sh.sh_entsize;
-	unsigned const nrel = rels->sh.sh_size / rel_entsize;
 	unsigned mcountsym = 0;
-	unsigned t;
 	int once = 0;
 
-	get_relp(rels, ehdr, &relp);
-
-	for (t = nrel; t; --t) {
+	list_for_each_entry(reloc, &rels->reloc_list, list) {
 		int ret = -1;
 
 		if (!mcountsym)
-			mcountsym = get_mcountsym(relp);
+			mcountsym = get_mcountsym(reloc);
 
-		if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
-			if (make_nop)
-				ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset));
+		if (mcountsym == GELF_R_INFO(reloc->sym->idx, reloc->type) && !is_fake_mcount(reloc)) {
+			if (make_nop) {
+				ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + reloc->offset);
+				if (ret < 0)
+					return -1;
+			}
 			if (warn_on_notrace_sect && !once) {
 				printf("Section %s has mcount callers being ignored\n",
 				       txtname);
@@ -417,15 +372,9 @@ static int nop_mcount(const struct section * const rels,
 		 * as a nop (don't do anything with it).
 		 */
 		if (!ret) {
-			Elf_Rel rel;
-			rel = *(Elf_Rel *)relp;
-			Elf_r_info(&rel, Elf_r_sym(relp), rel_type_nop);
-			if (ulseek((void *)relp - (void *)ehdr, SEEK_SET) < 0)
-				return -1;
-			if (uwrite(&rel, sizeof(rel)) < 0)
-				return -1;
+			reloc->type = rel_type_nop;
+			rels->changed = true;
 		}
-		relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
 	}
 	return 0;
 }
@@ -519,7 +468,7 @@ static int do_func(Elf_Ehdr *const ehdr,
 	unsigned rel_entsize = 0;
 	unsigned symsec_sh_link = 0;
 
-	const struct section *sec;
+	struct section *sec;
 
 	int result = 0;
 
@@ -559,7 +508,7 @@ static int do_func(Elf_Ehdr *const ehdr,
 			rel_entsize = sec->sh.sh_entsize;
 			mlocp = sift_rel_mcount(mlocp,
 				(void *)mlocp - (void *)mloc0, &mrelp,
-				sec, ehdr, recsym, recval, reltype);
+				sec, recsym, recval, reltype);
 		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
 			/*
 			 * This section is ignored by ftrace, but still
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 13/51] objtool: mcount: Return symbol from mcountsym
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (11 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 12/51] objtool: mcount: Walk relocation lists Matt Helsley
@ 2020-06-18 20:37 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 14/51] objtool: mcount: Move get_mcountsym Matt Helsley
                   ` (38 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Before we can move this function out of the wrapper and into
wordsize-independent code we need to return the relocation
symbol information in a size-independent fashion. Previously
we compared the raw info bits but that requires passing around
an unsigned long. Instead we just use a pointer to the objtool
struct symbol which callers can use as-needed.

Reported-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Signed-off-by: Matt Helsley <mhelsley@vmware.com>
Co-developed-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Co-developed-by: Peter Zijlstra <peterz@infradead.org>

--

Thanks to Kamalesh Babulal for reporting this problem and suggesting
a fix. Thanks to Peter Zijlstra for recommending an enhancement to
the fix.
---
 tools/objtool/recordmcount.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index df8384f8e9e7..6ac120aa45af 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -271,7 +271,7 @@ static int append_func(Elf_Ehdr *const ehdr,
 	return elf_write(lf);
 }
 
-static unsigned get_mcountsym(struct reloc *reloc)
+static struct symbol *get_mcountsym(struct reloc *reloc)
 {
 	struct symbol *sym = reloc->sym;
 	char const *symname = sym->name;
@@ -283,8 +283,8 @@ static unsigned get_mcountsym(struct reloc *reloc)
 	if (strcmp(mcount, symname) == 0 ||
 	    (altmcount && strcmp(altmcount, symname) == 0) ||
 	    (strcmp(fentry, symname) == 0))
-		return GELF_R_INFO(reloc->sym->idx, reloc->type);
-	return 0;
+		return sym;
+	return NULL;
 }
 
 /*
@@ -303,14 +303,14 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 	uint_t *const mloc0 = mlocp;
 	Elf_Rel *mrelp = *mrelpp;
 	unsigned int rel_entsize = rels->sh.sh_entsize;
-	unsigned mcountsym = 0;
+	struct symbol *mcountsym = NULL;
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &rels->reloc_list, list) {
 		if (!mcountsym)
 			mcountsym = get_mcountsym(reloc);
 
-		if (mcountsym == GELF_R_INFO(reloc->sym->idx, reloc->type) && !is_fake_mcount(reloc)) {
+		if (mcountsym == reloc->sym && !is_fake_mcount(reloc)) {
 			uint_t const addend =
 				_w(reloc->offset - recval + mcount_adjust);
 			mrelp->r_offset = _w(offbase
@@ -342,7 +342,7 @@ static int nop_mcount(struct section * const rels,
 		+ (void *)ehdr);
 	struct reloc *reloc;
 	Elf_Shdr const *const shdr = &shdr0[rels->sh.sh_info];
-	unsigned mcountsym = 0;
+	struct symbol *mcountsym = NULL;
 	int once = 0;
 
 	list_for_each_entry(reloc, &rels->reloc_list, list) {
@@ -351,7 +351,7 @@ static int nop_mcount(struct section * const rels,
 		if (!mcountsym)
 			mcountsym = get_mcountsym(reloc);
 
-		if (mcountsym == GELF_R_INFO(reloc->sym->idx, reloc->type) && !is_fake_mcount(reloc)) {
+		if (mcountsym == reloc->sym && !is_fake_mcount(reloc)) {
 			if (make_nop) {
 				ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + reloc->offset);
 				if (ret < 0)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 14/51] objtool: mcount: Move get_mcountsym
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (12 preceding siblings ...)
  2020-06-18 20:37 ` [RFC][PATCH v5 13/51] objtool: mcount: Return symbol from mcountsym Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 15/51] objtool: mcount: Replace MIPS offset types Matt Helsley
                   ` (37 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Now that it's been stripped of using the old recordmcount ELF
wrapper get_mcountsym() is ready to be promoted out of the
double-included wrapper header.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 16 ++++++++++++++++
 tools/objtool/recordmcount.h | 19 -------------------
 2 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index dafa6dd10d04..d5f7c06afd57 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -422,6 +422,22 @@ static int is_mcounted_section_name(char const *const txtname)
 		strcmp(".cpuidle.text", txtname) == 0;
 }
 
+static struct symbol *get_mcountsym(struct reloc *reloc)
+{
+	struct symbol *sym = reloc->sym;
+	char const *symname = sym->name;
+	char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
+	char const *fentry = "__fentry__";
+
+	if (symname[0] == '.')
+		++symname;  /* ppc64 hack */
+	if (strcmp(mcount, symname) == 0 ||
+	    (altmcount && strcmp(altmcount, symname) == 0) ||
+	    (strcmp(fentry, symname) == 0))
+		return sym;
+	return NULL;
+}
+
 static const unsigned int missing_sym = (unsigned int)-1;
 
 /* 32 bit and 64 bit are very similar */
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 6ac120aa45af..210899819261 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -27,7 +27,6 @@
 #undef find_section_sym_index
 #undef has_rel_mcount
 #undef tot_relsize
-#undef get_mcountsym
 #undef get_shnum
 #undef set_shnum
 #undef get_shstrndx
@@ -56,7 +55,6 @@
 # define set_shnum		set_shnum64
 # define get_shstrndx		get_shstrndx64
 # define do_func		do64
-# define get_mcountsym		get_mcountsym_64
 # define is_fake_mcount		is_fake_mcount64
 # define fn_is_fake_mcount	fn_is_fake_mcount64
 # define MIPS_is_fake_mcount	MIPS64_is_fake_mcount
@@ -84,7 +82,6 @@
 # define set_shnum		set_shnum32
 # define get_shstrndx		get_shstrndx32
 # define do_func		do32
-# define get_mcountsym		get_mcountsym_32
 # define is_fake_mcount		is_fake_mcount32
 # define fn_is_fake_mcount	fn_is_fake_mcount32
 # define MIPS_is_fake_mcount	MIPS32_is_fake_mcount
@@ -271,22 +268,6 @@ static int append_func(Elf_Ehdr *const ehdr,
 	return elf_write(lf);
 }
 
-static struct symbol *get_mcountsym(struct reloc *reloc)
-{
-	struct symbol *sym = reloc->sym;
-	char const *symname = sym->name;
-	char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
-	char const *fentry = "__fentry__";
-
-	if (symname[0] == '.')
-		++symname;  /* ppc64 hack */
-	if (strcmp(mcount, symname) == 0 ||
-	    (altmcount && strcmp(altmcount, symname) == 0) ||
-	    (strcmp(fentry, symname) == 0))
-		return sym;
-	return NULL;
-}
-
 /*
  * Look at the relocations in order to find the calls to mcount.
  * Accumulate the section offsets that are found, and their relocation info,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 15/51] objtool: mcount: Replace MIPS offset types
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (13 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 14/51] objtool: mcount: Move get_mcountsym Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 16/51] objtool: mcount: Move is_fake_mcount() Matt Helsley
                   ` (36 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Replace MIPS is_fake_mcount code using Elf_Addr with
unsigned long for the offsets. This is consistent with the way
that objtool more generally treats offsets and removes the
last use of the Elf_Addr wrapper.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 210899819261..dde2ec054e51 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -31,7 +31,6 @@
 #undef set_shnum
 #undef get_shstrndx
 #undef do_func
-#undef Elf_Addr
 #undef Elf_Ehdr
 #undef Elf_Shdr
 #undef Elf_Rel
@@ -59,7 +58,6 @@
 # define fn_is_fake_mcount	fn_is_fake_mcount64
 # define MIPS_is_fake_mcount	MIPS64_is_fake_mcount
 # define mcount_adjust		mcount_adjust_64
-# define Elf_Addr		Elf64_Addr
 # define Elf_Ehdr		Elf64_Ehdr
 # define Elf_Shdr		Elf64_Shdr
 # define Elf_Rel		Elf64_Rel
@@ -86,7 +84,6 @@
 # define fn_is_fake_mcount	fn_is_fake_mcount32
 # define MIPS_is_fake_mcount	MIPS32_is_fake_mcount
 # define mcount_adjust		mcount_adjust_32
-# define Elf_Addr		Elf32_Addr
 # define Elf_Ehdr		Elf32_Ehdr
 # define Elf_Shdr		Elf32_Shdr
 # define Elf_Rel		Elf32_Rel
@@ -138,11 +135,11 @@ static int mcount_adjust = 0;
 
 static int MIPS_is_fake_mcount(struct reloc const *reloc)
 {
-	static Elf_Addr old_r_offset = ~(Elf_Addr)0;
-	Elf_Addr current_r_offset = reloc->offset;
+	static unsigned long old_r_offset = ~0UL;
+	unsigned long current_r_offset = reloc->offset;
 	int is_fake;
 
-	is_fake = (old_r_offset != ~(Elf_Addr)0) &&
+	is_fake = (old_r_offset != ~0UL) &&
 		(current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET);
 	old_r_offset = current_r_offset;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 16/51] objtool: mcount: Move is_fake_mcount()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (14 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 15/51] objtool: mcount: Replace MIPS offset types Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 17/51] objtool: mcount: Stop using ehdr in find_section_sym_index Matt Helsley
                   ` (35 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Promote the now-bit-independent is_fake_mcount() out of the old
recordmcount ELF wrapper.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 48 +++++++++++++++++++++++++++++++---
 tools/objtool/recordmcount.h | 50 ------------------------------------
 2 files changed, 45 insertions(+), 53 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index d5f7c06afd57..24b019b82795 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -438,6 +438,48 @@ static struct symbol *get_mcountsym(struct reloc *reloc)
 	return NULL;
 }
 
+/*
+ * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
+ * _mcount symbol is needed for dynamic function tracer, with it, to disable
+ * tracing(ftrace_make_nop), the instruction in the position is replaced with
+ * the "b label" instruction, to enable tracing(ftrace_make_call), replace the
+ * instruction back. So, here, we set the 2nd one as fake and filter it.
+ *
+ * c:	3c030000	lui	v1,0x0		<-->	b	label
+ *		c: R_MIPS_HI16	_mcount
+ *		c: R_MIPS_NONE	*ABS*
+ *		c: R_MIPS_NONE	*ABS*
+ * 10:	64630000	daddiu	v1,v1,0
+ *		10: R_MIPS_LO16	_mcount
+ *		10: R_MIPS_NONE	*ABS*
+ *		10: R_MIPS_NONE	*ABS*
+ * 14:	03e0082d	move	at,ra
+ * 18:	0060f809	jalr	v1
+ * label:
+ */
+#define MIPS_FAKEMCOUNT_OFFSET	4
+
+static int MIPS_is_fake_mcount(struct reloc const *reloc)
+{
+	static unsigned long old_r_offset = ~0UL;
+	unsigned long current_r_offset = reloc->offset;
+	int is_fake;
+
+	is_fake = (old_r_offset != ~0UL) &&
+		(current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET);
+	old_r_offset = current_r_offset;
+
+	return is_fake;
+}
+
+/* Functions and pointers that do_file() may override for specific e_machine. */
+static int fn_is_fake_mcount(struct reloc const *reloc)
+{
+	return 0;
+}
+
+static int (*is_fake_mcount)(struct reloc const *reloc) = fn_is_fake_mcount;
+
 static const unsigned int missing_sym = (unsigned int)-1;
 
 /* 32 bit and 64 bit are very similar */
@@ -557,7 +599,7 @@ static int do_file(char const *const fname)
 		altmcount = "__gnu_mcount_nc";
 		make_nop = make_nop_arm;
 		rel_type_nop = R_ARM_NONE;
-		is_fake_mcount32 = arm_is_fake_mcount;
+		is_fake_mcount = arm_is_fake_mcount;
 		gpfx = 0;
 		break;
 	case EM_AARCH64:
@@ -597,7 +639,7 @@ static int do_file(char const *const fname)
 		}
 		if (w2(ehdr->e_machine) == EM_MIPS) {
 			reltype = R_MIPS_32;
-			is_fake_mcount32 = MIPS32_is_fake_mcount;
+			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		if (do32(ehdr, reltype) < 0)
 			goto out;
@@ -617,7 +659,7 @@ static int do_file(char const *const fname)
 		if (w2(ghdr->e_machine) == EM_MIPS) {
 			reltype = R_MIPS_64;
 			Elf64_r_info = MIPS64_r_info;
-			is_fake_mcount64 = MIPS64_is_fake_mcount;
+			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		if (do64(ghdr, reltype) < 0)
 			goto out;
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index dde2ec054e51..941f96e4f74b 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -18,9 +18,6 @@
  * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  */
 #undef append_func
-#undef is_fake_mcount
-#undef fn_is_fake_mcount
-#undef MIPS_is_fake_mcount
 #undef mcount_adjust
 #undef sift_rel_mcount
 #undef nop_mcount
@@ -54,9 +51,6 @@
 # define set_shnum		set_shnum64
 # define get_shstrndx		get_shstrndx64
 # define do_func		do64
-# define is_fake_mcount		is_fake_mcount64
-# define fn_is_fake_mcount	fn_is_fake_mcount64
-# define MIPS_is_fake_mcount	MIPS64_is_fake_mcount
 # define mcount_adjust		mcount_adjust_64
 # define Elf_Ehdr		Elf64_Ehdr
 # define Elf_Shdr		Elf64_Shdr
@@ -80,9 +74,6 @@
 # define set_shnum		set_shnum32
 # define get_shstrndx		get_shstrndx32
 # define do_func		do32
-# define is_fake_mcount		is_fake_mcount32
-# define fn_is_fake_mcount	fn_is_fake_mcount32
-# define MIPS_is_fake_mcount	MIPS32_is_fake_mcount
 # define mcount_adjust		mcount_adjust_32
 # define Elf_Ehdr		Elf32_Ehdr
 # define Elf_Shdr		Elf32_Shdr
@@ -97,13 +88,6 @@
 # define _size			4
 #endif
 
-/* Functions and pointers that do_file() may override for specific e_machine. */
-static int fn_is_fake_mcount(struct reloc const *reloc)
-{
-	return 0;
-}
-static int (*is_fake_mcount)(struct reloc const *reloc) = fn_is_fake_mcount;
-
 static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 {
 	rp->r_info = _w(ELF_R_INFO(sym, type));
@@ -112,40 +96,6 @@ static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_E
 
 static int mcount_adjust = 0;
 
-/*
- * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
- * _mcount symbol is needed for dynamic function tracer, with it, to disable
- * tracing(ftrace_make_nop), the instruction in the position is replaced with
- * the "b label" instruction, to enable tracing(ftrace_make_call), replace the
- * instruction back. So, here, we set the 2nd one as fake and filter it.
- *
- * c:	3c030000	lui	v1,0x0		<-->	b	label
- *		c: R_MIPS_HI16	_mcount
- *		c: R_MIPS_NONE	*ABS*
- *		c: R_MIPS_NONE	*ABS*
- * 10:	64630000	daddiu	v1,v1,0
- *		10: R_MIPS_LO16	_mcount
- *		10: R_MIPS_NONE	*ABS*
- *		10: R_MIPS_NONE	*ABS*
- * 14:	03e0082d	move	at,ra
- * 18:	0060f809	jalr	v1
- * label:
- */
-#define MIPS_FAKEMCOUNT_OFFSET	4
-
-static int MIPS_is_fake_mcount(struct reloc const *reloc)
-{
-	static unsigned long old_r_offset = ~0UL;
-	unsigned long current_r_offset = reloc->offset;
-	int is_fake;
-
-	is_fake = (old_r_offset != ~0UL) &&
-		(current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET);
-	old_r_offset = current_r_offset;
-
-	return is_fake;
-}
-
 static unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
 {
 	if (shdr0 && !ehdr->e_shnum)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 17/51] objtool: mcount: Stop using ehdr in find_section_sym_index
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (15 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 16/51] objtool: mcount: Move is_fake_mcount() Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 18/51] objtool: mcount: Move find_section_sym_index() Matt Helsley
                   ` (34 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

We can use the objtool GElf_Ehdr structure to access ehdr here.
This makes the function completely independent of the old
recordmcount ELF wrapper. The next step will be to promote it
to the C file.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 941f96e4f74b..cf420f9f64b0 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -225,7 +225,7 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 			       Elf_Rel **const mrelpp,
 			       const struct section * const rels,
 			       unsigned const recsym_index,
-			       uint_t const recval,
+			       unsigned long const recval,
 			       unsigned const reltype)
 {
 	uint_t *const mloc0 = mlocp;
@@ -319,9 +319,8 @@ static int nop_mcount(struct section * const rels,
  */
 static int find_section_sym_index(unsigned const txtndx,
 				char const *const txtname,
-				uint_t *const recvalp,
-				unsigned int *sym_index,
-				Elf_Ehdr const *const ehdr)
+				unsigned long *const recvalp,
+				unsigned int *sym_index)
 {
 	struct symbol *sym;
 	struct section *txts = find_section_by_index(lf, txtndx);
@@ -336,7 +335,7 @@ static int find_section_sym_index(unsigned const txtndx,
 		/* avoid symbols with weak binding */
 		if ((sym->bind == STB_LOCAL) || (sym->bind == STB_GLOBAL)) {
 			/* function symbols on ARM have quirks, avoid them */
-			if (w2(ehdr->e_machine) == EM_ARM
+			if (lf->ehdr.e_machine == EM_ARM
 			    && sym->type == STT_FUNC)
 				continue;
 
@@ -424,12 +423,12 @@ static int do_func(Elf_Ehdr *const ehdr,
 
 		txtname = has_rel_mcount(sec);
 		if (txtname && is_mcounted_section_name(txtname)) {
+			unsigned long recval = 0;
 			unsigned int recsym;
-			uint_t recval = 0;
 
 			symsec_sh_link = sec->sh.sh_link;
 			result = find_section_sym_index(sec->sh.sh_info,
-						txtname, &recval, &recsym, ehdr);
+						txtname, &recval, &recsym);
 			if (result)
 				goto out;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 18/51] objtool: mcount: Move find_section_sym_index()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (16 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 17/51] objtool: mcount: Stop using ehdr in find_section_sym_index Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 19/51] objtool: mcount: Restrict using ehdr in append_func() Matt Helsley
                   ` (33 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

This function is no longer dependent upon the old recordmcount
ELF wrapper code -- it doesn't use the wrapper's Elf_* types nor
does it call wrapped functions. Move it into the C file.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 42 ++++++++++++++++++++++++++++++++
 tools/objtool/recordmcount.h | 47 +-----------------------------------
 2 files changed, 43 insertions(+), 46 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 24b019b82795..2225479157e5 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -482,6 +482,48 @@ static int (*is_fake_mcount)(struct reloc const *reloc) = fn_is_fake_mcount;
 
 static const unsigned int missing_sym = (unsigned int)-1;
 
+/*
+ * Find a symbol in the given section, to be used as the base for relocating
+ * the table of offsets of calls to mcount.  A local or global symbol suffices,
+ * but avoid a Weak symbol because it may be overridden; the change in value
+ * would invalidate the relocations of the offsets of the calls to mcount.
+ * Often the found symbol will be the unnamed local symbol generated by
+ * GNU 'as' for the start of each section.  For example:
+ *    Num:    Value  Size Type    Bind   Vis      Ndx Name
+ *      2: 00000000     0 SECTION LOCAL  DEFAULT    1
+ */
+static int find_section_sym_index(unsigned const txtndx,
+				char const *const txtname,
+				unsigned long *const recvalp,
+				unsigned int *sym_index)
+{
+	struct symbol *sym;
+	struct section *txts = find_section_by_index(lf, txtndx);
+
+	if (!txts) {
+		fprintf(stderr, "Cannot find section %u: %s.\n",
+			txtndx, txtname);
+		return missing_sym;
+	}
+
+	list_for_each_entry(sym, &txts->symbol_list, list) {
+		/* avoid symbols with weak binding */
+		if ((sym->bind == STB_LOCAL) || (sym->bind == STB_GLOBAL)) {
+			/* function symbols on ARM have quirks, avoid them */
+			if (lf->ehdr.e_machine == EM_ARM
+			    && sym->type == STT_FUNC)
+				continue;
+
+			*recvalp = sym->sym.st_value;
+			*sym_index = sym->idx;
+			return 0;
+		}
+	}
+	fprintf(stderr, "Cannot find symbol for section %u: %s.\n",
+		txtndx, txtname);
+	return missing_sym;
+}
+
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index cf420f9f64b0..eed592954f37 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -21,7 +21,6 @@
 #undef mcount_adjust
 #undef sift_rel_mcount
 #undef nop_mcount
-#undef find_section_sym_index
 #undef has_rel_mcount
 #undef tot_relsize
 #undef get_shnum
@@ -44,7 +43,6 @@
 # define append_func		append64
 # define sift_rel_mcount	sift64_rel_mcount
 # define nop_mcount		nop_mcount_64
-# define find_section_sym_index	find64_section_sym_index
 # define has_rel_mcount		has64_rel_mcount
 # define tot_relsize		tot64_relsize
 # define get_shnum		get_shnum64
@@ -67,7 +65,6 @@
 # define append_func		append32
 # define sift_rel_mcount	sift32_rel_mcount
 # define nop_mcount		nop_mcount_32
-# define find_section_sym_index	find32_section_sym_index
 # define has_rel_mcount		has32_rel_mcount
 # define tot_relsize		tot32_relsize
 # define get_shnum		get_shnum32
@@ -307,48 +304,6 @@ static int nop_mcount(struct section * const rels,
 	return 0;
 }
 
-/*
- * Find a symbol in the given section, to be used as the base for relocating
- * the table of offsets of calls to mcount.  A local or global symbol suffices,
- * but avoid a Weak symbol because it may be overridden; the change in value
- * would invalidate the relocations of the offsets of the calls to mcount.
- * Often the found symbol will be the unnamed local symbol generated by
- * GNU 'as' for the start of each section.  For example:
- *    Num:    Value  Size Type    Bind   Vis      Ndx Name
- *      2: 00000000     0 SECTION LOCAL  DEFAULT    1
- */
-static int find_section_sym_index(unsigned const txtndx,
-				char const *const txtname,
-				unsigned long *const recvalp,
-				unsigned int *sym_index)
-{
-	struct symbol *sym;
-	struct section *txts = find_section_by_index(lf, txtndx);
-
-	if (!txts) {
-		fprintf(stderr, "Cannot find section %u: %s.\n",
-			txtndx, txtname);
-		return missing_sym;
-	}
-
-	list_for_each_entry(sym, &txts->symbol_list, list) {
-		/* avoid symbols with weak binding */
-		if ((sym->bind == STB_LOCAL) || (sym->bind == STB_GLOBAL)) {
-			/* function symbols on ARM have quirks, avoid them */
-			if (lf->ehdr.e_machine == EM_ARM
-			    && sym->type == STT_FUNC)
-				continue;
-
-			*recvalp = sym->sym.st_value;
-			*sym_index = sym->idx;
-			return 0;
-		}
-	}
-	fprintf(stderr, "Cannot find symbol for section %u: %s.\n",
-		txtndx, txtname);
-	return missing_sym;
-}
-
 static char const *has_rel_mcount(const struct section * const rels)
 {
 	const struct section *txts;
@@ -435,7 +390,7 @@ static int do_func(Elf_Ehdr *const ehdr,
 			rel_entsize = sec->sh.sh_entsize;
 			mlocp = sift_rel_mcount(mlocp,
 				(void *)mlocp - (void *)mloc0, &mrelp,
-				sec, recsym, recval, reltype);
+				sec, recsym, (uint_t)recval, reltype);
 		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
 			/*
 			 * This section is ignored by ftrace, but still
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 19/51] objtool: mcount: Restrict using ehdr in append_func()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (17 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 18/51] objtool: mcount: Move find_section_sym_index() Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 20/51] objtool: mcount: Use objtool ELF to write Matt Helsley
                   ` (32 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Use the ehdr parameter to append_func() to write the ELF file's
header but use the objtool ELF header data as the basis for
making changes. The makes it clearer when we can switch from
using the old recordmcount wrapper to write the ELF file
because ehdr will only be passed on to uwrite() calls and those
will get replaced later.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index eed592954f37..19bff5a7c8ce 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -93,7 +93,7 @@ static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_E
 
 static int mcount_adjust = 0;
 
-static unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
+static unsigned int get_shnum(GElf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
 {
 	if (shdr0 && !ehdr->e_shnum)
 		return w(shdr0->sh_size);
@@ -133,11 +133,11 @@ static int append_func(Elf_Ehdr *const ehdr,
 	char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
 		? ".rela__mcount_loc"
 		:  ".rel__mcount_loc";
-	uint_t const old_shoff = _w(ehdr->e_shoff);
+	uint_t const old_shoff = lf->ehdr.e_shoff;
 	uint_t const old_shstr_sh_size   = _w(shstr->sh_size);
 	uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
 	Elf_Shdr *const shdr0 = (Elf_Shdr *)(old_shoff + (void *)ehdr);
-	unsigned int const old_shnum = get_shnum(ehdr, shdr0);
+	unsigned int const old_shnum = get_shnum(&lf->ehdr, shdr0);
 	unsigned int const new_shnum = 2 + old_shnum; /* {.rel,}__mcount_loc */
 	uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
 	uint_t new_e_shoff;
@@ -149,8 +149,6 @@ static int append_func(Elf_Ehdr *const ehdr,
 	t += (_align & -t);  /* word-byte align */
 	new_e_shoff = t;
 
-	set_shnum(ehdr, shdr0, new_shnum);
-
 	/* body for new shstrtab */
 	if (ulseek(sb.st_size, SEEK_SET) < 0)
 		return -1;
@@ -205,6 +203,7 @@ static int append_func(Elf_Ehdr *const ehdr,
 		return -1;
 
 	ehdr->e_shoff = _w(new_e_shoff);
+	set_shnum(ehdr, shdr0, new_shnum);
 	if (ulseek(0, SEEK_SET) < 0)
 		return -1;
 	if (uwrite(ehdr, sizeof(*ehdr)) < 0)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 20/51] objtool: mcount: Use objtool ELF to write
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (18 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 19/51] objtool: mcount: Restrict using ehdr in append_func() Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 21/51] objtool: mcount: Move nop_mcount() Matt Helsley
                   ` (31 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than modify the pseudo-mapping of the ELF file directly,
which is the recordmcount way of operating, use the objtool
section list and generic ELF functions to modify the ELF file.

This eliminates a bunch of code -- the ulseek() and uwrite()
functions -- because it's used to patch the ELF data. Instead
we rely on objtool's ELF code to handle updating the ELF file.
This means a bunch of the odd bits in append_func() also go
away since they did things like update the ELF header, add
to the section table, and append the new section names to the
string table -- all handled by objtool's ELF code.

Since we no longer use the get/set_shnum() functions to
determine the next section to allocate and set how many new
sections there are we can also eliminate those two functions.

One unusual part, with respect to objtool is the way we handle
writing nops. Objtool is not designed to modify the an ELF
text section directly (or at least I could not find and example
to base this work on). So we break layering to access the
"data" of the text section via the section's "data buffer".
This is still cleaner -- we can now pass in the section struct
and offset as separate parameters.

Note that this patch does not move the associated parts out
of the wrapper file. We postpone that cleanup for later so that
it's easier to see the changes to the functions rather than
obscuring them with the move.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 161 ++++-----------------------------
 tools/objtool/recordmcount.h | 167 ++++++++---------------------------
 2 files changed, 53 insertions(+), 275 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 2225479157e5..c015091a8a8c 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -52,24 +52,9 @@ static struct stat sb;	/* Remember .st_size, etc. */
 static const char *altmcount;	/* alternate mcount symbol name */
 extern int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
 static void *file_map;	/* pointer of the mapped file */
-static void *file_end;	/* pointer to the end of the mapped file */
-static int file_updated; /* flag to state file was changed */
-static void *file_ptr;	/* current file pointer location */
-
-static void *file_append; /* added to the end of the file */
-static size_t file_append_size; /* how much is added to end of file */
 
 static struct elf *lf;
 
-/* Per-file resource cleanup when multiple files. */
-static void file_append_cleanup(void)
-{
-	free(file_append);
-	file_append = NULL;
-	file_append_size = 0;
-	file_updated = 0;
-}
-
 static void mmap_cleanup(void)
 {
 	if (!mmap_failed)
@@ -82,72 +67,11 @@ static void mmap_cleanup(void)
 	lf = NULL;
 }
 
-/* ulseek, uwrite, ...:  Check return value for errors. */
-
-static off_t ulseek(off_t const offset, int const whence)
-{
-	switch (whence) {
-	case SEEK_SET:
-		file_ptr = file_map + offset;
-		break;
-	case SEEK_CUR:
-		file_ptr += offset;
-		break;
-	case SEEK_END:
-		file_ptr = file_map + (sb.st_size - offset);
-		break;
-	}
-	if (file_ptr < file_map) {
-		fprintf(stderr, "lseek: seek before file\n");
-		return -1;
-	}
-	return file_ptr - file_map;
-}
-
-static ssize_t uwrite(void const *const buf, size_t const count)
-{
-	size_t cnt = count;
-	off_t idx = 0;
-
-	file_updated = 1;
-
-	if (file_ptr + count >= file_end) {
-		off_t aoffset = (file_ptr + count) - file_end;
-
-		if (aoffset > file_append_size) {
-			file_append = realloc(file_append, aoffset);
-			file_append_size = aoffset;
-		}
-		if (!file_append) {
-			perror("write");
-			file_append_cleanup();
-			mmap_cleanup();
-			return -1;
-		}
-		if (file_ptr < file_end) {
-			cnt = file_end - file_ptr;
-		} else {
-			cnt = 0;
-			idx = aoffset - count;
-		}
-	}
-
-	if (cnt)
-		memcpy(file_ptr, buf, cnt);
-
-	if (cnt < count)
-		memcpy(file_append + idx, buf + cnt, count - cnt);
-
-	file_ptr += count;
-	return count;
-}
-
 static void * umalloc(size_t size)
 {
 	void *const addr = malloc(size);
 	if (addr == 0) {
 		fprintf(stderr, "malloc failed: %zu bytes\n", size);
-		file_append_cleanup();
 		mmap_cleanup();
 		return NULL;
 	}
@@ -173,8 +97,6 @@ static void *mmap_file(char const *fname)
 	fd_map = -1;
 	mmap_failed = 1;
 	file_map = NULL;
-	file_ptr = NULL;
-	file_updated = 0;
 	sb.st_size = 0;
 
 	lf = elf_open_read(fname, O_RDWR);
@@ -210,8 +132,6 @@ static void *mmap_file(char const *fname)
 out:
 	fd_map = -1;
 
-	file_end = file_map + sb.st_size;
-
 	return file_map;
 }
 
@@ -222,12 +142,16 @@ static unsigned char *ideal_nop;
 
 static char rel_type_nop;
 
-static int (*make_nop)(void *map, size_t const offset);
+static int (*make_nop)(struct section *, size_t const offset);
 
-static int make_nop_x86(void *map, size_t const offset)
+static int make_nop_x86(struct section *txts, size_t const offset)
 {
 	uint32_t *ptr;
 	unsigned char *op;
+	void *map = txts->data->d_buf;
+
+	if (offset < 1)
+		return -1;
 
 	/* Confirm we have 0xe8 0x0 0x0 0x0 0x0 */
 	ptr = map + offset;
@@ -239,10 +163,7 @@ static int make_nop_x86(void *map, size_t const offset)
 		return -1;
 
 	/* convert to nop */
-	if (ulseek(offset - 1, SEEK_SET) < 0)
-		return -1;
-	if (uwrite(ideal_nop, 5) < 0)
-		return -1;
+	memcpy(op, ideal_nop, 5);
 	return 0;
 }
 
@@ -266,12 +187,13 @@ static unsigned char push_bl_mcount_thumb_le[6] = { 0x00, 0xb5, 0xff, 0xf7, 0xfe
 static unsigned char push_bl_mcount_thumb_be[6] = { 0xb5, 0x00, 0xf7, 0xff, 0xff, 0xfe }; /* push {lr}, bl */
 static unsigned char *push_bl_mcount_thumb;
 
-static int make_nop_arm(void *map, size_t const offset)
+static int make_nop_arm(struct section *txts, size_t const offset)
 {
 	char *ptr;
 	int cnt = 1;
 	int nop_size;
 	size_t off = offset;
+	void *map = txts->data->d_buf;
 
 	ptr = map + offset;
 	if (memcmp(ptr, bl_mcount_arm, 4) == 0) {
@@ -290,21 +212,19 @@ static int make_nop_arm(void *map, size_t const offset)
 		return -1;
 
 	/* Convert to nop */
-	if (ulseek(off, SEEK_SET) < 0)
-		return -1;
-
 	do {
-		if (uwrite(ideal_nop, nop_size) < 0)
-			return -1;
+		memcpy(map + off, ideal_nop, nop_size);
+		off += nop_size;
 	} while (--cnt > 0);
 
 	return 0;
 }
 
 static unsigned char ideal_nop4_arm64[4] = {0x1f, 0x20, 0x03, 0xd5};
-static int make_nop_arm64(void *map, size_t const offset)
+static int make_nop_arm64(struct section *txts, size_t const offset)
 {
 	uint32_t *ptr;
+	void *map = txts->data->d_buf;
 
 	ptr = map + offset;
 	/* bl <_mcount> is 0x94000000 before relocation */
@@ -312,52 +232,7 @@ static int make_nop_arm64(void *map, size_t const offset)
 		return -1;
 
 	/* Convert to nop */
-	if (ulseek(offset, SEEK_SET) < 0)
-		return -1;
-	if (uwrite(ideal_nop, 4) < 0)
-		return -1;
-	return 0;
-}
-
-static int write_file(const char *fname)
-{
-	char tmp_file[strlen(fname) + 4];
-	size_t n;
-
-	if (!file_updated)
-		return 0;
-
-	sprintf(tmp_file, "%s.rc", fname);
-
-	/*
-	 * After reading the entire file into memory, delete it
-	 * and write it back, to prevent weird side effects of modifying
-	 * an object file in place.
-	 */
-	fd_map = open(tmp_file, O_WRONLY | O_TRUNC | O_CREAT, sb.st_mode);
-	if (fd_map < 0) {
-		perror(fname);
-		return -1;
-	}
-	n = write(fd_map, file_map, sb.st_size);
-	if (n != sb.st_size) {
-		perror("write");
-		close(fd_map);
-		return -1;
-	}
-	if (file_append_size) {
-		n = write(fd_map, file_append, file_append_size);
-		if (n != file_append_size) {
-			perror("write");
-			close(fd_map);
-			return -1;
-		}
-	}
-	close(fd_map);
-	if (rename(tmp_file, fname) < 0) {
-		perror(fname);
-		return -1;
-	}
+	memcpy(map + offset, ideal_nop, 4);
 	return 0;
 }
 
@@ -683,8 +558,7 @@ static int do_file(char const *const fname)
 			reltype = R_MIPS_32;
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
-		if (do32(ehdr, reltype) < 0)
-			goto out;
+		rc = do32(reltype);
 		break;
 	case ELFCLASS64: {
 		Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
@@ -703,15 +577,12 @@ static int do_file(char const *const fname)
 			Elf64_r_info = MIPS64_r_info;
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
-		if (do64(ghdr, reltype) < 0)
-			goto out;
+		rc = do64(reltype);
 		break;
 	}
 	}  /* end switch */
 
-	rc = write_file(fname);
 out:
-	file_append_cleanup();
 	mmap_cleanup();
 	return rc;
 }
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 19bff5a7c8ce..1f14c64ed484 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -23,11 +23,7 @@
 #undef nop_mcount
 #undef has_rel_mcount
 #undef tot_relsize
-#undef get_shnum
-#undef set_shnum
-#undef get_shstrndx
 #undef do_func
-#undef Elf_Ehdr
 #undef Elf_Shdr
 #undef Elf_Rel
 #undef Elf_Rela
@@ -36,7 +32,6 @@
 #undef fn_ELF_R_INFO
 #undef uint_t
 #undef _w
-#undef _align
 #undef _size
 
 #ifdef RECORD_MCOUNT_64
@@ -45,13 +40,8 @@
 # define nop_mcount		nop_mcount_64
 # define has_rel_mcount		has64_rel_mcount
 # define tot_relsize		tot64_relsize
-# define get_shnum		get_shnum64
-# define set_shnum		set_shnum64
-# define get_shstrndx		get_shstrndx64
 # define do_func		do64
 # define mcount_adjust		mcount_adjust_64
-# define Elf_Ehdr		Elf64_Ehdr
-# define Elf_Shdr		Elf64_Shdr
 # define Elf_Rel		Elf64_Rel
 # define Elf_Rela		Elf64_Rela
 # define ELF_R_INFO		ELF64_R_INFO
@@ -59,7 +49,6 @@
 # define fn_ELF_R_INFO		fn_ELF64_R_INFO
 # define uint_t			uint64_t
 # define _w			w8
-# define _align			7u
 # define _size			8
 #else
 # define append_func		append32
@@ -67,13 +56,8 @@
 # define nop_mcount		nop_mcount_32
 # define has_rel_mcount		has32_rel_mcount
 # define tot_relsize		tot32_relsize
-# define get_shnum		get_shnum32
-# define set_shnum		set_shnum32
-# define get_shstrndx		get_shstrndx32
 # define do_func		do32
 # define mcount_adjust		mcount_adjust_32
-# define Elf_Ehdr		Elf32_Ehdr
-# define Elf_Shdr		Elf32_Shdr
 # define Elf_Rel		Elf32_Rel
 # define Elf_Rela		Elf32_Rela
 # define ELF_R_INFO		ELF32_R_INFO
@@ -81,7 +65,6 @@
 # define fn_ELF_R_INFO		fn_ELF32_R_INFO
 # define uint_t			uint32_t
 # define _w			w
-# define _align			3u
 # define _size			4
 #endif
 
@@ -93,35 +76,8 @@ static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_E
 
 static int mcount_adjust = 0;
 
-static unsigned int get_shnum(GElf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
-{
-	if (shdr0 && !ehdr->e_shnum)
-		return w(shdr0->sh_size);
-
-	return w2(ehdr->e_shnum);
-}
-
-static void set_shnum(Elf_Ehdr *ehdr, Elf_Shdr *shdr0, unsigned int new_shnum)
-{
-	if (new_shnum >= SHN_LORESERVE) {
-		ehdr->e_shnum = 0;
-		shdr0->sh_size = w(new_shnum);
-	} else
-		ehdr->e_shnum = w2(new_shnum);
-}
-
-static int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0)
-{
-	if (ehdr->e_shstrndx != SHN_XINDEX)
-		return w2(ehdr->e_shstrndx);
-
-	return w(shdr0->sh_link);
-}
-
-/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
-static int append_func(Elf_Ehdr *const ehdr,
-			Elf_Shdr *const shstr,
-			uint_t const *const mloc0,
+/* Append the new  __mcount_loc and its relocations. */
+static int append_func(uint_t const *const mloc0,
 			uint_t const *const mlocp,
 			Elf_Rel const *const mrel0,
 			Elf_Rel const *const mrelp,
@@ -129,85 +85,44 @@ static int append_func(Elf_Ehdr *const ehdr,
 			unsigned int const symsec_sh_link)
 {
 	/* Begin constructing output file */
-	Elf_Shdr mcsec;
+	struct section *mcount_loc_sec, *reloc_sec;
 	char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
 		? ".rela__mcount_loc"
 		:  ".rel__mcount_loc";
-	uint_t const old_shoff = lf->ehdr.e_shoff;
-	uint_t const old_shstr_sh_size   = _w(shstr->sh_size);
-	uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
-	Elf_Shdr *const shdr0 = (Elf_Shdr *)(old_shoff + (void *)ehdr);
-	unsigned int const old_shnum = get_shnum(&lf->ehdr, shdr0);
-	unsigned int const new_shnum = 2 + old_shnum; /* {.rel,}__mcount_loc */
-	uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
-	uint_t new_e_shoff;
-
-	shstr->sh_size = _w(t);
-	shstr->sh_offset = _w(sb.st_size);
-
-	t += sb.st_size;
-	t += (_align & -t);  /* word-byte align */
-	new_e_shoff = t;
-
-	/* body for new shstrtab */
-	if (ulseek(sb.st_size, SEEK_SET) < 0)
-		return -1;
-	if (uwrite(old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size) < 0)
-		return -1;
-	if (uwrite(mc_name, 1 + strlen(mc_name)) < 0)
-		return -1;
 
-	/* old(modified) Elf_Shdr table, word-byte aligned */
-	if (ulseek(t, SEEK_SET) < 0)
-		return -1;
-	t += sizeof(Elf_Shdr) * old_shnum;
-	if (uwrite(old_shoff + (void *)ehdr,
-	       sizeof(Elf_Shdr) * old_shnum) < 0)
+	/* add section: __mcount_loc */
+	mcount_loc_sec = elf_create_section(lf,
+		mc_name + (sizeof(Elf_Rela) == rel_entsize) + strlen(".rel"),
+		_size, mlocp - mloc0);
+	if (!mcount_loc_sec)
 		return -1;
-
-	/* new sections __mcount_loc and .rel__mcount_loc */
-	t += 2*sizeof(mcsec);
-	mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel")
-		+ old_shstr_sh_size);
-	mcsec.sh_type = w(SHT_PROGBITS);
-	mcsec.sh_flags = _w(SHF_ALLOC);
-	mcsec.sh_addr = 0;
-	mcsec.sh_offset = _w(t);
-	mcsec.sh_size = _w((void *)mlocp - (void *)mloc0);
-	mcsec.sh_link = 0;
-	mcsec.sh_info = 0;
-	mcsec.sh_addralign = _w(_size);
-	mcsec.sh_entsize = _w(_size);
-	if (uwrite(&mcsec, sizeof(mcsec)) < 0)
+	// created mcount_loc_sec->sh.sh_size = (void *)mlocp - (void *)mloc0;
+	mcount_loc_sec->sh.sh_link = 0;
+	mcount_loc_sec->sh.sh_info = 0;
+	mcount_loc_sec->sh.sh_addralign = _size;
+	// created mcount_loc_sec->sh.sh_entsize = _size;
+
+	// assert mcount_loc_sec->data->d_size == (void *)mlocp - (void *)mloc0
+	memcpy(mcount_loc_sec->data->d_buf, mloc0,
+	       mcount_loc_sec->data->d_size);
+	elf_flagdata(mcount_loc_sec->data, ELF_C_SET, ELF_F_DIRTY);
+
+	/* add section .rel[a]__mcount_loc */
+	reloc_sec = elf_create_section(lf, mc_name, rel_entsize,
+					      mrelp - mrel0);
+	if (!reloc_sec)
 		return -1;
+	reloc_sec->sh.sh_type = (sizeof(Elf_Rela) == rel_entsize) ?
+						SHT_RELA : SHT_REL;
+	reloc_sec->sh.sh_flags = 0; /* clear SHF_ALLOC */
+	reloc_sec->sh.sh_link = find_section_by_name(lf, ".symtab")->idx;
+	reloc_sec->sh.sh_info = mcount_loc_sec->idx;
+	reloc_sec->sh.sh_addralign = _size;
 
-	mcsec.sh_name = w(old_shstr_sh_size);
-	mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
-		? w(SHT_RELA)
-		: w(SHT_REL);
-	mcsec.sh_flags = 0;
-	mcsec.sh_addr = 0;
-	mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t);
-	mcsec.sh_size   = _w((void *)mrelp - (void *)mrel0);
-	mcsec.sh_link = w(symsec_sh_link);
-	mcsec.sh_info = w(old_shnum);
-	mcsec.sh_addralign = _w(_size);
-	mcsec.sh_entsize = _w(rel_entsize);
-
-	if (uwrite(&mcsec, sizeof(mcsec)) < 0)
-		return -1;
+	// assert reloc_sec->data->d_size == (void *)mrelp - (void *)mrel0
+	memcpy(reloc_sec->data->d_buf, mrel0, reloc_sec->data->d_size);
+	elf_flagdata(reloc_sec->data, ELF_C_SET, ELF_F_DIRTY);
 
-	if (uwrite(mloc0, (void *)mlocp - (void *)mloc0) < 0)
-		return -1;
-	if (uwrite(mrel0, (void *)mrelp - (void *)mrel0) < 0)
-		return -1;
-
-	ehdr->e_shoff = _w(new_e_shoff);
-	set_shnum(ehdr, shdr0, new_shnum);
-	if (ulseek(0, SEEK_SET) < 0)
-		return -1;
-	if (uwrite(ehdr, sizeof(*ehdr)) < 0)
-		return -1;
 	return elf_write(lf);
 }
 
@@ -259,13 +174,10 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
  * into nops.
  */
 static int nop_mcount(struct section * const rels,
-		      Elf_Ehdr const *const ehdr,
 		      const char *const txtname)
 {
-	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
-		+ (void *)ehdr);
 	struct reloc *reloc;
-	Elf_Shdr const *const shdr = &shdr0[rels->sh.sh_info];
+	struct section *txts = find_section_by_index(lf, rels->sh.sh_info);
 	struct symbol *mcountsym = NULL;
 	int once = 0;
 
@@ -277,7 +189,7 @@ static int nop_mcount(struct section * const rels,
 
 		if (mcountsym == reloc->sym && !is_fake_mcount(reloc)) {
 			if (make_nop) {
-				ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + reloc->offset);
+				ret = make_nop(txts, reloc->offset);
 				if (ret < 0)
 					return -1;
 			}
@@ -331,12 +243,8 @@ static unsigned tot_relsize(void)
 }
 
 /* Overall supervision for Elf32 ET_REL file. */
-static int do_func(Elf_Ehdr *const ehdr,
-		   unsigned const reltype)
+static int do_func(unsigned const reltype)
 {
-	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
-		+ (void *)ehdr);
-
 	/* Upper bound on space: assume all relevant relocs are for mcount. */
 	unsigned       totrelsz;
 
@@ -395,15 +303,14 @@ static int do_func(Elf_Ehdr *const ehdr,
 			 * This section is ignored by ftrace, but still
 			 * has mcount calls. Convert them to nops now.
 			 */
-			if (nop_mcount(sec, ehdr, txtname) < 0) {
+			if (nop_mcount(sec, txtname) < 0) {
 				result = -1;
 				goto out;
 			}
 		}
 	}
 	if (!result && mloc0 != mlocp)
-		result = append_func(ehdr, &shdr0[get_shstrndx(ehdr, shdr0)],
-				     mloc0, mlocp, mrel0, mrelp,
+		result = append_func(mloc0, mlocp, mrel0, mrelp,
 				     rel_entsize, symsec_sh_link);
 out:
 	free(mrel0);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 21/51] objtool: mcount: Move nop_mcount()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (19 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 20/51] objtool: mcount: Use objtool ELF to write Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 22/51] objtool: mcount: Move has_rel_mcount() and tot_relsize() Matt Helsley
                   ` (30 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

The nop_mcount() function overwrites mcount calls that should be
ignored with no-ops. This operation varies by architecture and
wordsize so we retain the function pointers used to implement
the fundamental operation while nop_mcount() itself is responsible
for walking the relocations, determining if they should be turned
into no-ops, then calling the arch-specific code. Since none of
these use the recordmcount ELF wrappers anymore we can move it out
of the wrapper.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 47 +++++++++++++++++++++++++++++++++
 tools/objtool/recordmcount.h | 50 ------------------------------------
 2 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index c015091a8a8c..fae0b15d0632 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -399,6 +399,53 @@ static int find_section_sym_index(unsigned const txtndx,
 	return missing_sym;
 }
 
+/*
+ * Read the relocation table again, but this time its called on sections
+ * that are not going to be traced. The mcount calls here will be converted
+ * into nops.
+ */
+static int nop_mcount(struct section * const rels,
+		      const char *const txtname)
+{
+	struct reloc *reloc;
+	struct section *txts = find_section_by_index(lf, rels->sh.sh_info);
+	struct symbol *mcountsym = NULL;
+	int once = 0;
+
+	list_for_each_entry(reloc, &rels->reloc_list, list) {
+		int ret = -1;
+
+		if (!mcountsym)
+			mcountsym = get_mcountsym(reloc);
+
+		if (mcountsym == reloc->sym && !is_fake_mcount(reloc)) {
+			if (make_nop) {
+				ret = make_nop(txts, reloc->offset);
+				if (ret < 0)
+					return -1;
+			}
+			if (warn_on_notrace_sect && !once) {
+				printf("Section %s has mcount callers being ignored\n",
+				       txtname);
+				once = 1;
+				/* just warn? */
+				if (!make_nop)
+					return 0;
+			}
+		}
+
+		/*
+		 * If we successfully removed the mcount, mark the relocation
+		 * as a nop (don't do anything with it).
+		 */
+		if (!ret) {
+			reloc->type = rel_type_nop;
+			rels->changed = true;
+		}
+	}
+	return 0;
+}
+
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 1f14c64ed484..25028c61da2b 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -20,7 +20,6 @@
 #undef append_func
 #undef mcount_adjust
 #undef sift_rel_mcount
-#undef nop_mcount
 #undef has_rel_mcount
 #undef tot_relsize
 #undef do_func
@@ -37,7 +36,6 @@
 #ifdef RECORD_MCOUNT_64
 # define append_func		append64
 # define sift_rel_mcount	sift64_rel_mcount
-# define nop_mcount		nop_mcount_64
 # define has_rel_mcount		has64_rel_mcount
 # define tot_relsize		tot64_relsize
 # define do_func		do64
@@ -53,7 +51,6 @@
 #else
 # define append_func		append32
 # define sift_rel_mcount	sift32_rel_mcount
-# define nop_mcount		nop_mcount_32
 # define has_rel_mcount		has32_rel_mcount
 # define tot_relsize		tot32_relsize
 # define do_func		do32
@@ -168,53 +165,6 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 	return mlocp;
 }
 
-/*
- * Read the relocation table again, but this time its called on sections
- * that are not going to be traced. The mcount calls here will be converted
- * into nops.
- */
-static int nop_mcount(struct section * const rels,
-		      const char *const txtname)
-{
-	struct reloc *reloc;
-	struct section *txts = find_section_by_index(lf, rels->sh.sh_info);
-	struct symbol *mcountsym = NULL;
-	int once = 0;
-
-	list_for_each_entry(reloc, &rels->reloc_list, list) {
-		int ret = -1;
-
-		if (!mcountsym)
-			mcountsym = get_mcountsym(reloc);
-
-		if (mcountsym == reloc->sym && !is_fake_mcount(reloc)) {
-			if (make_nop) {
-				ret = make_nop(txts, reloc->offset);
-				if (ret < 0)
-					return -1;
-			}
-			if (warn_on_notrace_sect && !once) {
-				printf("Section %s has mcount callers being ignored\n",
-				       txtname);
-				once = 1;
-				/* just warn? */
-				if (!make_nop)
-					return 0;
-			}
-		}
-
-		/*
-		 * If we successfully removed the mcount, mark the relocation
-		 * as a nop (don't do anything with it).
-		 */
-		if (!ret) {
-			reloc->type = rel_type_nop;
-			rels->changed = true;
-		}
-	}
-	return 0;
-}
-
 static char const *has_rel_mcount(const struct section * const rels)
 {
 	const struct section *txts;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 22/51] objtool: mcount: Move has_rel_mcount() and tot_relsize()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (20 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 21/51] objtool: mcount: Move nop_mcount() Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 23/51] objtool: mcount: Move relocation entry size detection Matt Helsley
                   ` (29 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

The has_rel_mcount() and tot_relsize() helpers are no longer
dependent on the ELF wrapper so we can move them.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 26 ++++++++++++++++++++++++++
 tools/objtool/recordmcount.h | 33 ---------------------------------
 2 files changed, 26 insertions(+), 33 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index fae0b15d0632..918e47217379 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -446,6 +446,32 @@ static int nop_mcount(struct section * const rels,
 	return 0;
 }
 
+static char const *has_rel_mcount(const struct section * const rels)
+{
+	const struct section *txts;
+	if (rels->sh.sh_type != SHT_REL && rels->sh.sh_type != SHT_RELA)
+		return NULL;
+	txts = find_section_by_index(lf, rels->sh.sh_info);
+	if ((txts->sh.sh_type != SHT_PROGBITS) ||
+	    !(txts->sh.sh_flags & SHF_EXECINSTR))
+		return NULL;
+	return txts->name;
+}
+
+static unsigned tot_relsize(void)
+{
+	const struct section *sec;
+	unsigned totrelsz = 0;
+	char const *txtname;
+
+	list_for_each_entry(sec, &lf->sections, list) {
+		txtname = has_rel_mcount(sec);
+		if (txtname && is_mcounted_section_name(txtname))
+			totrelsz += sec->sh.sh_size;
+	}
+	return totrelsz;
+}
+
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 25028c61da2b..2733f7fde51d 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -20,8 +20,6 @@
 #undef append_func
 #undef mcount_adjust
 #undef sift_rel_mcount
-#undef has_rel_mcount
-#undef tot_relsize
 #undef do_func
 #undef Elf_Shdr
 #undef Elf_Rel
@@ -36,8 +34,6 @@
 #ifdef RECORD_MCOUNT_64
 # define append_func		append64
 # define sift_rel_mcount	sift64_rel_mcount
-# define has_rel_mcount		has64_rel_mcount
-# define tot_relsize		tot64_relsize
 # define do_func		do64
 # define mcount_adjust		mcount_adjust_64
 # define Elf_Rel		Elf64_Rel
@@ -51,8 +47,6 @@
 #else
 # define append_func		append32
 # define sift_rel_mcount	sift32_rel_mcount
-# define has_rel_mcount		has32_rel_mcount
-# define tot_relsize		tot32_relsize
 # define do_func		do32
 # define mcount_adjust		mcount_adjust_32
 # define Elf_Rel		Elf32_Rel
@@ -165,33 +159,6 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
 	return mlocp;
 }
 
-static char const *has_rel_mcount(const struct section * const rels)
-{
-	const struct section *txts;
-	if (rels->sh.sh_type != SHT_REL && rels->sh.sh_type != SHT_RELA)
-		return NULL;
-	txts = find_section_by_index(lf, rels->sh.sh_info);
-	if ((txts->sh.sh_type != SHT_PROGBITS) ||
-	    !(txts->sh.sh_flags & SHF_EXECINSTR))
-		return NULL;
-	return txts->name;
-}
-
-
-static unsigned tot_relsize(void)
-{
-	const struct section *sec;
-	unsigned totrelsz = 0;
-	char const *txtname;
-
-	list_for_each_entry(sec, &lf->sections, list) {
-		txtname = has_rel_mcount(sec);
-		if (txtname && is_mcounted_section_name(txtname))
-			totrelsz += sec->sh.sh_size;
-	}
-	return totrelsz;
-}
-
 /* Overall supervision for Elf32 ET_REL file. */
 static int do_func(unsigned const reltype)
 {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 23/51] objtool: mcount: Move relocation entry size detection
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (21 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 22/51] objtool: mcount: Move has_rel_mcount() and tot_relsize() Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 24/51] objtool: mcount: Only keep ELF file size Matt Helsley
                   ` (28 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Move where we detect the size of relocation entries we wish to
use into the first loop over the sections. This will allow us
to allocate the mcount location and relocation sections before
the next loop that collects them.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 8 +++++---
 tools/objtool/recordmcount.h | 5 ++---
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 918e47217379..29f299e5bb52 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -458,7 +458,7 @@ static char const *has_rel_mcount(const struct section * const rels)
 	return txts->name;
 }
 
-static unsigned tot_relsize(void)
+static unsigned tot_relsize(unsigned int *rel_entsize)
 {
 	const struct section *sec;
 	unsigned totrelsz = 0;
@@ -466,8 +466,10 @@ static unsigned tot_relsize(void)
 
 	list_for_each_entry(sec, &lf->sections, list) {
 		txtname = has_rel_mcount(sec);
-		if (txtname && is_mcounted_section_name(txtname))
-			totrelsz += sec->sh.sh_size;
+		if (!(txtname && is_mcounted_section_name(txtname)))
+			continue;
+		totrelsz += sec->sh.sh_size;
+		*rel_entsize = sec->sh.sh_entsize;
 	}
 	return totrelsz;
 }
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 2733f7fde51d..5ca488f3471c 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -171,7 +171,7 @@ static int do_func(unsigned const reltype)
 	uint_t *      mloc0;
 	uint_t *      mlocp;
 
-	unsigned rel_entsize = 0;
+	unsigned int rel_entsize = 0;
 	unsigned symsec_sh_link = 0;
 
 	struct section *sec;
@@ -181,7 +181,7 @@ static int do_func(unsigned const reltype)
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
 
-	totrelsz = tot_relsize();
+	totrelsz = tot_relsize(&rel_entsize);
 	if (totrelsz == 0)
 		return 0;
 	mrel0 = umalloc(totrelsz);
@@ -211,7 +211,6 @@ static int do_func(unsigned const reltype)
 			if (result)
 				goto out;
 
-			rel_entsize = sec->sh.sh_entsize;
 			mlocp = sift_rel_mcount(mlocp,
 				(void *)mlocp - (void *)mloc0, &mrelp,
 				sec, recsym, (uint_t)recval, reltype);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 24/51] objtool: mcount: Only keep ELF file size
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (22 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 23/51] objtool: mcount: Move relocation entry size detection Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 25/51] objtool: mcount: Use ELF header from objtool Matt Helsley
                   ` (27 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Since we're no longer writing to the ELF file mapping and we're
not appending to it we don't need to keep more information from the
stat structure. At the same time we can give the smaller global
variable a better name.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 29f299e5bb52..aa35173de3d9 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -48,17 +48,17 @@
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static char gpfx;	/* prefix for global symbol name (sometimes '_') */
-static struct stat sb;	/* Remember .st_size, etc. */
 static const char *altmcount;	/* alternate mcount symbol name */
 extern int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
 static void *file_map;	/* pointer of the mapped file */
+static size_t file_map_size; /* original ELF file size */
 
 static struct elf *lf;
 
 static void mmap_cleanup(void)
 {
 	if (!mmap_failed)
-		munmap(file_map, sb.st_size);
+		munmap(file_map, file_map_size);
 	else
 		free(file_map);
 	file_map = NULL;
@@ -93,11 +93,13 @@ static void * umalloc(size_t size)
  */
 static void *mmap_file(char const *fname)
 {
+	struct stat sb;
+
 	/* Avoid problems if early cleanup() */
 	fd_map = -1;
 	mmap_failed = 1;
 	file_map = NULL;
-	sb.st_size = 0;
+	file_map_size = 0;
 
 	lf = elf_open_read(fname, O_RDWR);
 	if (!lf) {
@@ -129,6 +131,7 @@ static void *mmap_file(char const *fname)
 		}
 	} else
 		mmap_failed = 0;
+	file_map_size = sb.st_size;
 out:
 	fd_map = -1;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 25/51] objtool: mcount: Use ELF header from objtool
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (23 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 24/51] objtool: mcount: Only keep ELF file size Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 26/51] objtool: mcount: Remove unused file mapping Matt Helsley
                   ` (26 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

The ELF header is the very first structure in an ELF file.
Rather than cast it from the file mapping we use the ELF
header extracted via objtool's ELF code.

This is the last usage of the open-coded mapping of the ELF
file which we will remove in a later step.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 37 +++++++++++++++++-------------------
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index aa35173de3d9..f8699e52e7e5 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -525,21 +525,19 @@ static void MIPS64_r_info(Elf64_Rel *const rp, unsigned sym, unsigned type)
 static int do_file(char const *const fname)
 {
 	unsigned int reltype = 0;
-	Elf32_Ehdr *ehdr;
 	int rc = -1;
 
-	ehdr = mmap_file(fname);
-	if (!ehdr)
+	if (!mmap_file(fname))
 		goto out;
 
 	w = w4nat;
 	w2 = w2nat;
 	w8 = w8nat;
-	switch (ehdr->e_ident[EI_DATA]) {
+	switch (lf->ehdr.e_ident[EI_DATA]) {
 		static unsigned int const endian = 1;
 	default:
 		fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
-			ehdr->e_ident[EI_DATA], fname);
+			lf->ehdr.e_ident[EI_DATA], fname);
 		goto out;
 	case ELFDATA2LSB:
 		if (*(unsigned char const *)&endian != 1) {
@@ -568,18 +566,18 @@ static int do_file(char const *const fname)
 		push_bl_mcount_thumb = push_bl_mcount_thumb_be;
 		break;
 	}  /* end switch */
-	if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 ||
-	    w2(ehdr->e_type) != ET_REL ||
-	    ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
+	if (memcmp(ELFMAG, lf->ehdr.e_ident, SELFMAG) != 0 ||
+	    lf->ehdr.e_type != ET_REL ||
+	    lf->ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
 		fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
 		goto out;
 	}
 
 	gpfx = '_';
-	switch (w2(ehdr->e_machine)) {
+	switch (lf->ehdr.e_machine) {
 	default:
 		fprintf(stderr, "unrecognized e_machine %u %s\n",
-			w2(ehdr->e_machine), fname);
+			lf->ehdr.e_machine, fname);
 		goto out;
 	case EM_386:
 		reltype = R_386_32;
@@ -620,37 +618,36 @@ static int do_file(char const *const fname)
 		break;
 	}  /* end switch */
 
-	switch (ehdr->e_ident[EI_CLASS]) {
+	switch (lf->ehdr.e_ident[EI_CLASS]) {
 	default:
 		fprintf(stderr, "unrecognized ELF class %d %s\n",
-			ehdr->e_ident[EI_CLASS], fname);
+			lf->ehdr.e_ident[EI_CLASS], fname);
 		goto out;
 	case ELFCLASS32:
-		if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr)
-		||  w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {
+		if (lf->ehdr.e_ehsize != sizeof(Elf32_Ehdr)
+		||  lf->ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
 			fprintf(stderr,
 				"unrecognized ET_REL file: %s\n", fname);
 			goto out;
 		}
-		if (w2(ehdr->e_machine) == EM_MIPS) {
+		if (lf->ehdr.e_machine == EM_MIPS) {
 			reltype = R_MIPS_32;
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		rc = do32(reltype);
 		break;
 	case ELFCLASS64: {
-		Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
-		if (w2(ghdr->e_ehsize) != sizeof(Elf64_Ehdr)
-		||  w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {
+		if (lf->ehdr.e_ehsize != sizeof(Elf64_Ehdr)
+		||  lf->ehdr.e_shentsize != sizeof(Elf64_Shdr)) {
 			fprintf(stderr,
 				"unrecognized ET_REL file: %s\n", fname);
 			goto out;
 		}
-		if (w2(ghdr->e_machine) == EM_S390) {
+		if (lf->ehdr.e_machine == EM_S390) {
 			reltype = R_390_64;
 			mcount_adjust_64 = -14;
 		}
-		if (w2(ghdr->e_machine) == EM_MIPS) {
+		if (lf->ehdr.e_machine == EM_MIPS) {
 			reltype = R_MIPS_64;
 			Elf64_r_info = MIPS64_r_info;
 			is_fake_mcount = MIPS_is_fake_mcount;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 26/51] objtool: mcount: Remove unused file mapping
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (24 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 25/51] objtool: mcount: Use ELF header from objtool Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 27/51] objtool: mcount: Reduce usage of _size wrapper Matt Helsley
                   ` (25 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

The ELF data is now accessed completely through objtool's
ELF code. We can remove the mapping of the original ELF
file and propagate elf_open_read(), elf_close(), and malloc()
up in place of mmap_file(), mmap_cleanup(), and umalloc()
respectively. This also eliminates the last use of the
umalloc() wrapper, reduces the number of global
variables, and limits the use of globals to:

	The struct elf for the file we're working on. This
	saves passing it to nearly every function as a parameter.

	Variables set depending on the ELF file endian, wordsize,
	and arch so that the appropriate relocation structures,
	offset sizes, architecture quirks, and nop encodings will
	be used.

	One command-line option

Note that we're still using the recordmcount wrapper to change
variable sizes and structure definitions we use to build the
mcount relocation data and call instruction offsets.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 99 +++---------------------------------
 tools/objtool/recordmcount.h |  4 +-
 2 files changed, 9 insertions(+), 94 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index f8699e52e7e5..a263062c9c64 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -41,104 +41,14 @@
 #define R_AARCH64_ABS64	257
 #endif
 
-#define R_ARM_PC24		1
 #define R_ARM_THM_CALL		10
-#define R_ARM_CALL		28
 
-static int fd_map;	/* File descriptor for file being modified. */
-static int mmap_failed; /* Boolean flag. */
 static char gpfx;	/* prefix for global symbol name (sometimes '_') */
 static const char *altmcount;	/* alternate mcount symbol name */
 extern int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
-static void *file_map;	/* pointer of the mapped file */
-static size_t file_map_size; /* original ELF file size */
 
 static struct elf *lf;
 
-static void mmap_cleanup(void)
-{
-	if (!mmap_failed)
-		munmap(file_map, file_map_size);
-	else
-		free(file_map);
-	file_map = NULL;
-	if (lf)
-		elf_close(lf);
-	lf = NULL;
-}
-
-static void * umalloc(size_t size)
-{
-	void *const addr = malloc(size);
-	if (addr == 0) {
-		fprintf(stderr, "malloc failed: %zu bytes\n", size);
-		mmap_cleanup();
-		return NULL;
-	}
-	return addr;
-}
-
-/*
- * Get the whole file as a programming convenience in order to avoid
- * malloc+lseek+read+free of many pieces.  If successful, then mmap
- * avoids copying unused pieces; else just read the whole file.
- * Open for both read and write; new info will be appended to the file.
- * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
- * do not propagate to the file until an explicit overwrite at the last.
- * This preserves most aspects of consistency (all except .st_size)
- * for simultaneous readers of the file while we are appending to it.
- * However, multiple writers still are bad.  We choose not to use
- * locking because it is expensive and the use case of kernel build
- * makes multiple writers unlikely.
- */
-static void *mmap_file(char const *fname)
-{
-	struct stat sb;
-
-	/* Avoid problems if early cleanup() */
-	fd_map = -1;
-	mmap_failed = 1;
-	file_map = NULL;
-	file_map_size = 0;
-
-	lf = elf_open_read(fname, O_RDWR);
-	if (!lf) {
-		perror(fname);
-		return NULL;
-	}
-	fd_map = lf->fd;
-	if (fstat(fd_map, &sb) < 0) {
-		perror(fname);
-		goto out;
-	}
-	if (!S_ISREG(sb.st_mode)) {
-		fprintf(stderr, "not a regular file: %s\n", fname);
-		goto out;
-	}
-	file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
-			fd_map, 0);
-	if (file_map == MAP_FAILED) {
-		mmap_failed = 1;
-		file_map = umalloc(sb.st_size);
-		if (!file_map) {
-			perror(fname);
-			goto out;
-		}
-		if (read(fd_map, file_map, sb.st_size) != sb.st_size) {
-			perror(fname);
-			mmap_cleanup();
-			goto out;
-		}
-	} else
-		mmap_failed = 0;
-	file_map_size = sb.st_size;
-out:
-	fd_map = -1;
-
-	return file_map;
-}
-
-
 static unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
 static unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
 static unsigned char *ideal_nop;
@@ -527,8 +437,11 @@ static int do_file(char const *const fname)
 	unsigned int reltype = 0;
 	int rc = -1;
 
-	if (!mmap_file(fname))
+	lf = elf_open_read(fname, O_RDWR);
+	if (!lf) {
+		perror(fname);
 		goto out;
+	}
 
 	w = w4nat;
 	w2 = w2nat;
@@ -658,7 +571,9 @@ static int do_file(char const *const fname)
 	}  /* end switch */
 
 out:
-	mmap_cleanup();
+	if (lf)
+		elf_close(lf);
+	lf = NULL;
 	return rc;
 }
 
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 5ca488f3471c..fcc4f1a74d60 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -184,13 +184,13 @@ static int do_func(unsigned const reltype)
 	totrelsz = tot_relsize(&rel_entsize);
 	if (totrelsz == 0)
 		return 0;
-	mrel0 = umalloc(totrelsz);
+	mrel0 = malloc(totrelsz);
 	mrelp = mrel0;
 	if (!mrel0)
 		return -1;
 
 	/* 2*sizeof(address) <= sizeof(Elf_Rel) */
-	mloc0 = umalloc(totrelsz>>1);
+	mloc0 = malloc(totrelsz>>1);
 	mlocp = mloc0;
 	if (!mloc0) {
 		free(mrel0);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 27/51] objtool: mcount: Reduce usage of _size wrapper
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (25 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 26/51] objtool: mcount: Remove unused file mapping Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 28/51] objtool: mcount: Move mcount_adjust out of wrapper Matt Helsley
                   ` (24 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Use a new loc_size parameter to append_func() rather than
use the wrapper's _size macro directly.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index fcc4f1a74d60..a74a80b3356e 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -72,6 +72,7 @@ static int append_func(uint_t const *const mloc0,
 			uint_t const *const mlocp,
 			Elf_Rel const *const mrel0,
 			Elf_Rel const *const mrelp,
+			unsigned int const loc_size,
 			unsigned int const rel_entsize,
 			unsigned int const symsec_sh_link)
 {
@@ -84,14 +85,14 @@ static int append_func(uint_t const *const mloc0,
 	/* add section: __mcount_loc */
 	mcount_loc_sec = elf_create_section(lf,
 		mc_name + (sizeof(Elf_Rela) == rel_entsize) + strlen(".rel"),
-		_size, mlocp - mloc0);
+		loc_size, mlocp - mloc0);
 	if (!mcount_loc_sec)
 		return -1;
 	// created mcount_loc_sec->sh.sh_size = (void *)mlocp - (void *)mloc0;
 	mcount_loc_sec->sh.sh_link = 0;
 	mcount_loc_sec->sh.sh_info = 0;
-	mcount_loc_sec->sh.sh_addralign = _size;
-	// created mcount_loc_sec->sh.sh_entsize = _size;
+	mcount_loc_sec->sh.sh_addralign = loc_size;
+	// created mcount_loc_sec->sh.sh_entsize = loc_size;
 
 	// assert mcount_loc_sec->data->d_size == (void *)mlocp - (void *)mloc0
 	memcpy(mcount_loc_sec->data->d_buf, mloc0,
@@ -108,7 +109,7 @@ static int append_func(uint_t const *const mloc0,
 	reloc_sec->sh.sh_flags = 0; /* clear SHF_ALLOC */
 	reloc_sec->sh.sh_link = find_section_by_name(lf, ".symtab")->idx;
 	reloc_sec->sh.sh_info = mcount_loc_sec->idx;
-	reloc_sec->sh.sh_addralign = _size;
+	reloc_sec->sh.sh_addralign = loc_size;
 
 	// assert reloc_sec->data->d_size == (void *)mrelp - (void *)mrel0
 	memcpy(reloc_sec->data->d_buf, mrel0, reloc_sec->data->d_size);
@@ -227,7 +228,7 @@ static int do_func(unsigned const reltype)
 	}
 	if (!result && mloc0 != mlocp)
 		result = append_func(mloc0, mlocp, mrel0, mrelp,
-				     rel_entsize, symsec_sh_link);
+				     _size, rel_entsize, symsec_sh_link);
 out:
 	free(mrel0);
 	free(mloc0);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 28/51] objtool: mcount: Move mcount_adjust out of wrapper
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (26 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 27/51] objtool: mcount: Reduce usage of _size wrapper Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 29/51] objtool: mcount: Pre-allocate new ELF sections Matt Helsley
                   ` (23 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

The mcount_adjust variable defines how many bytes to move back
from the relocation address in order to be able to get to the
start of the function call instruction(s) needed to turn it
into a no-op. The values are very small and signed so we don't
need to worry about changing the size of the variable's type
inside the wrapper -- we can just use a regular int.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 11 ++++++++---
 tools/objtool/recordmcount.h |  5 -----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index a263062c9c64..bb53927612fb 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -387,6 +387,11 @@ static unsigned tot_relsize(unsigned int *rel_entsize)
 	return totrelsz;
 }
 
+/* zero or a small negative offset added to get the start of the call
+ * instruction
+ */
+static int mcount_adjust = 0;
+
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
@@ -497,7 +502,7 @@ static int do_file(char const *const fname)
 		rel_type_nop = R_386_NONE;
 		make_nop = make_nop_x86;
 		ideal_nop = ideal_nop5_x86_32;
-		mcount_adjust_32 = -1;
+		mcount_adjust = -1;
 		gpfx = 0;
 		break;
 	case EM_ARM:
@@ -526,7 +531,7 @@ static int do_file(char const *const fname)
 		ideal_nop = ideal_nop5_x86_64;
 		reltype = R_X86_64_64;
 		rel_type_nop = R_X86_64_NONE;
-		mcount_adjust_64 = -1;
+		mcount_adjust = -1;
 		gpfx = 0;
 		break;
 	}  /* end switch */
@@ -558,7 +563,7 @@ static int do_file(char const *const fname)
 		}
 		if (lf->ehdr.e_machine == EM_S390) {
 			reltype = R_390_64;
-			mcount_adjust_64 = -14;
+			mcount_adjust = -14;
 		}
 		if (lf->ehdr.e_machine == EM_MIPS) {
 			reltype = R_MIPS_64;
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index a74a80b3356e..e2c8b9d4725d 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -18,7 +18,6 @@
  * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  */
 #undef append_func
-#undef mcount_adjust
 #undef sift_rel_mcount
 #undef do_func
 #undef Elf_Shdr
@@ -35,7 +34,6 @@
 # define append_func		append64
 # define sift_rel_mcount	sift64_rel_mcount
 # define do_func		do64
-# define mcount_adjust		mcount_adjust_64
 # define Elf_Rel		Elf64_Rel
 # define Elf_Rela		Elf64_Rela
 # define ELF_R_INFO		ELF64_R_INFO
@@ -48,7 +46,6 @@
 # define append_func		append32
 # define sift_rel_mcount	sift32_rel_mcount
 # define do_func		do32
-# define mcount_adjust		mcount_adjust_32
 # define Elf_Rel		Elf32_Rel
 # define Elf_Rela		Elf32_Rela
 # define ELF_R_INFO		ELF32_R_INFO
@@ -65,8 +62,6 @@ static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 }
 static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
 
-static int mcount_adjust = 0;
-
 /* Append the new  __mcount_loc and its relocations. */
 static int append_func(uint_t const *const mloc0,
 			uint_t const *const mlocp,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 29/51] objtool: mcount: Pre-allocate new ELF sections
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (27 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 28/51] objtool: mcount: Move mcount_adjust out of wrapper Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 30/51] objtool: mcount: Generic location and relocation table types Matt Helsley
                   ` (22 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than allocating the ELF sections after collecting the
mcount locations and building the relocation entries, create
the empty sections beforehand. This has the benefit of
removing the memcpy() and just using the resulting libelf
buffers directly.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 122 +++++++++++++++--------------------
 1 file changed, 53 insertions(+), 69 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index e2c8b9d4725d..ce88f0c2f79b 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -17,7 +17,6 @@
  * This conversion to macros was done by:
  * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  */
-#undef append_func
 #undef sift_rel_mcount
 #undef do_func
 #undef Elf_Shdr
@@ -31,7 +30,6 @@
 #undef _size
 
 #ifdef RECORD_MCOUNT_64
-# define append_func		append64
 # define sift_rel_mcount	sift64_rel_mcount
 # define do_func		do64
 # define Elf_Rel		Elf64_Rel
@@ -43,7 +41,6 @@
 # define _w			w8
 # define _size			8
 #else
-# define append_func		append32
 # define sift_rel_mcount	sift32_rel_mcount
 # define do_func		do32
 # define Elf_Rel		Elf32_Rel
@@ -62,57 +59,6 @@ static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 }
 static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
 
-/* Append the new  __mcount_loc and its relocations. */
-static int append_func(uint_t const *const mloc0,
-			uint_t const *const mlocp,
-			Elf_Rel const *const mrel0,
-			Elf_Rel const *const mrelp,
-			unsigned int const loc_size,
-			unsigned int const rel_entsize,
-			unsigned int const symsec_sh_link)
-{
-	/* Begin constructing output file */
-	struct section *mcount_loc_sec, *reloc_sec;
-	char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
-		? ".rela__mcount_loc"
-		:  ".rel__mcount_loc";
-
-	/* add section: __mcount_loc */
-	mcount_loc_sec = elf_create_section(lf,
-		mc_name + (sizeof(Elf_Rela) == rel_entsize) + strlen(".rel"),
-		loc_size, mlocp - mloc0);
-	if (!mcount_loc_sec)
-		return -1;
-	// created mcount_loc_sec->sh.sh_size = (void *)mlocp - (void *)mloc0;
-	mcount_loc_sec->sh.sh_link = 0;
-	mcount_loc_sec->sh.sh_info = 0;
-	mcount_loc_sec->sh.sh_addralign = loc_size;
-	// created mcount_loc_sec->sh.sh_entsize = loc_size;
-
-	// assert mcount_loc_sec->data->d_size == (void *)mlocp - (void *)mloc0
-	memcpy(mcount_loc_sec->data->d_buf, mloc0,
-	       mcount_loc_sec->data->d_size);
-	elf_flagdata(mcount_loc_sec->data, ELF_C_SET, ELF_F_DIRTY);
-
-	/* add section .rel[a]__mcount_loc */
-	reloc_sec = elf_create_section(lf, mc_name, rel_entsize,
-					      mrelp - mrel0);
-	if (!reloc_sec)
-		return -1;
-	reloc_sec->sh.sh_type = (sizeof(Elf_Rela) == rel_entsize) ?
-						SHT_RELA : SHT_REL;
-	reloc_sec->sh.sh_flags = 0; /* clear SHF_ALLOC */
-	reloc_sec->sh.sh_link = find_section_by_name(lf, ".symtab")->idx;
-	reloc_sec->sh.sh_info = mcount_loc_sec->idx;
-	reloc_sec->sh.sh_addralign = loc_size;
-
-	// assert reloc_sec->data->d_size == (void *)mrelp - (void *)mrel0
-	memcpy(reloc_sec->data->d_buf, mrel0, reloc_sec->data->d_size);
-	elf_flagdata(reloc_sec->data, ELF_C_SET, ELF_F_DIRTY);
-
-	return elf_write(lf);
-}
-
 /*
  * Look at the relocations in order to find the calls to mcount.
  * Accumulate the section offsets that are found, and their relocation info,
@@ -167,12 +113,12 @@ static int do_func(unsigned const reltype)
 	uint_t *      mloc0;
 	uint_t *      mlocp;
 
-	unsigned int rel_entsize = 0;
-	unsigned symsec_sh_link = 0;
-
-	struct section *sec;
+	struct section *sec, *mlocs, *mrels;
+	char const *mc_name;
 
-	int result = 0;
+	unsigned int rel_entsize = 0;
+	int result = -1;
+	bool is_rela;
 
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
@@ -180,6 +126,7 @@ static int do_func(unsigned const reltype)
 	totrelsz = tot_relsize(&rel_entsize);
 	if (totrelsz == 0)
 		return 0;
+
 	mrel0 = malloc(totrelsz);
 	mrelp = mrel0;
 	if (!mrel0)
@@ -193,6 +140,31 @@ static int do_func(unsigned const reltype)
 		return -1;
 	}
 
+	is_rela = (sizeof(Elf_Rela) == rel_entsize);
+	mc_name = is_rela
+			? ".rela__mcount_loc"
+			:  ".rel__mcount_loc";
+
+	/* add section: __mcount_loc */
+	mlocs = elf_create_section(lf, mc_name + (is_rela ? 1 : 0) + strlen(".rel"), _size, 0);
+	if (!mlocs)
+		goto out;
+	mlocs->sh.sh_link = 0;
+	mlocs->sh.sh_info = 0;
+	mlocs->sh.sh_addralign = _size;
+
+	/* add section .rel[a]__mcount_loc */
+	mrels = elf_create_section(lf, mc_name, rel_entsize, 0);
+	if (!mrels)
+		goto out;
+	mrels->sh.sh_type = is_rela
+				? SHT_RELA
+				: SHT_REL;
+	mrels->sh.sh_flags = 0; /* clear SHF_ALLOC */
+	mrels->sh.sh_link = find_section_by_name(lf, ".symtab")->idx;
+	mrels->sh.sh_info = mlocs->idx;
+	mrels->sh.sh_addralign = _size;
+
 	list_for_each_entry(sec, &lf->sections, list) {
 		char const *txtname;
 
@@ -201,10 +173,8 @@ static int do_func(unsigned const reltype)
 			unsigned long recval = 0;
 			unsigned int recsym;
 
-			symsec_sh_link = sec->sh.sh_link;
-			result = find_section_sym_index(sec->sh.sh_info,
-						txtname, &recval, &recsym);
-			if (result)
+			if (find_section_sym_index(sec->sh.sh_info,
+						txtname, &recval, &recsym))
 				goto out;
 
 			mlocp = sift_rel_mcount(mlocp,
@@ -215,15 +185,29 @@ static int do_func(unsigned const reltype)
 			 * This section is ignored by ftrace, but still
 			 * has mcount calls. Convert them to nops now.
 			 */
-			if (nop_mcount(sec, txtname) < 0) {
-				result = -1;
+			if (nop_mcount(sec, txtname) < 0)
 				goto out;
-			}
 		}
 	}
-	if (!result && mloc0 != mlocp)
-		result = append_func(mloc0, mlocp, mrel0, mrelp,
-				     _size, rel_entsize, symsec_sh_link);
+
+	if (mloc0 != mlocp) {
+		/* Update the section sizes */
+		mlocs->sh.sh_size = (void *)mlocp - (void *)mloc0;
+		mlocs->len = mlocs->sh.sh_size;
+		mlocs->data->d_size = mlocs->len;
+		mlocs->data->d_buf = mloc0;
+		elf_flagdata(mlocs->data, ELF_C_SET, ELF_F_DIRTY);
+
+		mrels->sh.sh_size = (void *)mrelp - (void *)mrel0;
+		mrels->len = mrels->sh.sh_size;
+		mrels->data->d_size = mrels->len;
+		mrels->data->d_buf = mrel0;
+		elf_flagdata(mrels->data, ELF_C_SET, ELF_F_DIRTY);
+
+		/* overwrite the ELF file */
+		result = elf_write(lf);
+	} else
+		result = 0;
 out:
 	free(mrel0);
 	free(mloc0);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 30/51] objtool: mcount: Generic location and relocation table types
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (28 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 29/51] objtool: mcount: Pre-allocate new ELF sections Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 31/51] objtool: mcount: Use objtool relocation section Matt Helsley
                   ` (21 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than building the exact ELF section data we need and
avoiding libelf's conversion step, use more GElf types
and then libelf's elfxx_xlatetof() functions to convert
the mcount locations (GElf_Addr) and associated relocations.

This converts sift_rel_mcount() so that it doesn't use the
recordmcount wrapper. The next patch will move it out of the
wrapper.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c |  44 +++----------
 tools/objtool/recordmcount.h | 122 ++++++++++++++---------------------
 2 files changed, 60 insertions(+), 106 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index bb53927612fb..34976f3294ac 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -210,7 +210,7 @@ static int is_mcounted_section_name(char const *const txtname)
 		strcmp(".cpuidle.text", txtname) == 0;
 }
 
-static struct symbol *get_mcountsym(struct reloc *reloc)
+static struct symbol *get_mcount_sym(struct reloc *reloc)
 {
 	struct symbol *sym = reloc->sym;
 	char const *symname = sym->name;
@@ -322,16 +322,16 @@ static int nop_mcount(struct section * const rels,
 {
 	struct reloc *reloc;
 	struct section *txts = find_section_by_index(lf, rels->sh.sh_info);
-	struct symbol *mcountsym = NULL;
+	struct symbol *mcount_sym = NULL;
 	int once = 0;
 
 	list_for_each_entry(reloc, &rels->reloc_list, list) {
 		int ret = -1;
 
-		if (!mcountsym)
-			mcountsym = get_mcountsym(reloc);
+		if (!mcount_sym)
+			mcount_sym = get_mcount_sym(reloc);
 
-		if (mcountsym == reloc->sym && !is_fake_mcount(reloc)) {
+		if (mcount_sym == reloc->sym && !is_fake_mcount(reloc)) {
 			if (make_nop) {
 				ret = make_nop(txts, reloc->offset);
 				if (ret < 0)
@@ -392,6 +392,9 @@ static unsigned tot_relsize(unsigned int *rel_entsize)
  */
 static int mcount_adjust = 0;
 
+/* Size of an entry in __mcount_loc; 4 or 8 */
+static size_t loc_size;
+
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
@@ -409,34 +412,6 @@ static int arm_is_fake_mcount(struct reloc const *rp)
 	return 1;
 }
 
-/* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
- * http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
- * We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40]
- * to imply the order of the members; the spec does not say so.
- *	typedef unsigned char Elf64_Byte;
- * fails on MIPS64 because their <elf.h> already has it!
- */
-
-typedef uint8_t myElf64_Byte;		/* Type for a 8-bit quantity.  */
-
-union mips_r_info {
-	Elf64_Xword r_info;
-	struct {
-		Elf64_Word r_sym;		/* Symbol index.  */
-		myElf64_Byte r_ssym;		/* Special symbol.  */
-		myElf64_Byte r_type3;		/* Third relocation.  */
-		myElf64_Byte r_type2;		/* Second relocation.  */
-		myElf64_Byte r_type;		/* First relocation.  */
-	} r_mips;
-};
-
-static void MIPS64_r_info(Elf64_Rel *const rp, unsigned sym, unsigned type)
-{
-	rp->r_info = ((union mips_r_info){
-		.r_mips = { .r_sym = w(sym), .r_type = type }
-	}).r_info;
-}
-
 static int do_file(char const *const fname)
 {
 	unsigned int reltype = 0;
@@ -552,6 +527,7 @@ static int do_file(char const *const fname)
 			reltype = R_MIPS_32;
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
+		loc_size = 4;
 		rc = do32(reltype);
 		break;
 	case ELFCLASS64: {
@@ -567,9 +543,9 @@ static int do_file(char const *const fname)
 		}
 		if (lf->ehdr.e_machine == EM_MIPS) {
 			reltype = R_MIPS_64;
-			Elf64_r_info = MIPS64_r_info;
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
+		loc_size = 8;
 		rc = do64(reltype);
 		break;
 	}
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index ce88f0c2f79b..1d11dfc40d09 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -19,86 +19,63 @@
  */
 #undef sift_rel_mcount
 #undef do_func
-#undef Elf_Shdr
-#undef Elf_Rel
 #undef Elf_Rela
-#undef ELF_R_INFO
-#undef Elf_r_info
-#undef fn_ELF_R_INFO
-#undef uint_t
-#undef _w
-#undef _size
 
 #ifdef RECORD_MCOUNT_64
 # define sift_rel_mcount	sift64_rel_mcount
 # define do_func		do64
-# define Elf_Rel		Elf64_Rel
 # define Elf_Rela		Elf64_Rela
-# define ELF_R_INFO		ELF64_R_INFO
-# define Elf_r_info		Elf64_r_info
-# define fn_ELF_R_INFO		fn_ELF64_R_INFO
-# define uint_t			uint64_t
-# define _w			w8
-# define _size			8
 #else
 # define sift_rel_mcount	sift32_rel_mcount
 # define do_func		do32
-# define Elf_Rel		Elf32_Rel
 # define Elf_Rela		Elf32_Rela
-# define ELF_R_INFO		ELF32_R_INFO
-# define Elf_r_info		Elf32_r_info
-# define fn_ELF_R_INFO		fn_ELF32_R_INFO
-# define uint_t			uint32_t
-# define _w			w
-# define _size			4
 #endif
 
-static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
-{
-	rp->r_info = _w(ELF_R_INFO(sym, type));
-}
-static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
-
 /*
  * Look at the relocations in order to find the calls to mcount.
  * Accumulate the section offsets that are found, and their relocation info,
  * onto the end of the existing arrays.
  */
-static uint_t *sift_rel_mcount(uint_t *mlocp,
-			       unsigned const offbase,
-			       Elf_Rel **const mrelpp,
+static void sift_rel_mcount(GElf_Addr **mlocpp,
+			       GElf_Sxword *r_offsetp,
+			       void **const mrelpp,
 			       const struct section * const rels,
 			       unsigned const recsym_index,
 			       unsigned long const recval,
-			       unsigned const reltype)
+			       unsigned const reltype,
+			       bool is_rela)
 {
-	uint_t *const mloc0 = mlocp;
-	Elf_Rel *mrelp = *mrelpp;
-	unsigned int rel_entsize = rels->sh.sh_entsize;
-	struct symbol *mcountsym = NULL;
+	GElf_Rel *mrelp = *mrelpp;
+	GElf_Rela *mrelap = *mrelpp;
+	struct symbol *mcount_sym = NULL;
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &rels->reloc_list, list) {
-		if (!mcountsym)
-			mcountsym = get_mcountsym(reloc);
-
-		if (mcountsym == reloc->sym && !is_fake_mcount(reloc)) {
-			uint_t const addend =
-				_w(reloc->offset - recval + mcount_adjust);
-			mrelp->r_offset = _w(offbase
-				+ ((void *)mlocp - (void *)mloc0));
-			Elf_r_info(mrelp, recsym_index, reltype);
-			if (rel_entsize == sizeof(Elf_Rela)) {
-				((Elf_Rela *)mrelp)->r_addend = addend;
-				*mlocp++ = 0;
-			} else
-				*mlocp++ = addend;
-
-			mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
+		unsigned long addend;
+
+		if (!mcount_sym)
+			mcount_sym = get_mcount_sym(reloc);
+
+		if (mcount_sym != reloc->sym || is_fake_mcount(reloc))
+			continue;
+
+		addend = reloc->offset - recval + mcount_adjust;
+		if (is_rela) {
+			mrelap->r_offset = *r_offsetp;
+			mrelap->r_info = GELF_R_INFO(recsym_index, reltype);
+			mrelap->r_addend = addend;
+			mrelap++;
+			**mlocpp = 0;
+		} else {
+			mrelp->r_offset = *r_offsetp;
+			mrelp->r_info = GELF_R_INFO(recsym_index, reltype);
+			mrelp++;
+			**mlocpp = addend;
 		}
+		(*mlocpp)++;
+		*r_offsetp += loc_size;
 	}
-	*mrelpp = mrelp;
-	return mlocp;
+	*mrelpp = is_rela ? (void *)mrelap : (void *)mrelp;
 }
 
 /* Overall supervision for Elf32 ET_REL file. */
@@ -107,14 +84,15 @@ static int do_func(unsigned const reltype)
 	/* Upper bound on space: assume all relevant relocs are for mcount. */
 	unsigned       totrelsz;
 
-	Elf_Rel *      mrel0;
-	Elf_Rel *      mrelp;
+	void *mrel0;
+	void *mrelp;
 
-	uint_t *      mloc0;
-	uint_t *      mlocp;
+	GElf_Addr *mloc0;
+	GElf_Addr *mlocp;
+	GElf_Sxword r_offset = 0;
 
 	struct section *sec, *mlocs, *mrels;
-	char const *mc_name;
+	const char *mc_name;
 
 	unsigned int rel_entsize = 0;
 	int result = -1;
@@ -146,24 +124,27 @@ static int do_func(unsigned const reltype)
 			:  ".rel__mcount_loc";
 
 	/* add section: __mcount_loc */
-	mlocs = elf_create_section(lf, mc_name + (is_rela ? 1 : 0) + strlen(".rel"), _size, 0);
+	mlocs = elf_create_section(lf, mc_name + (is_rela ? 1 : 0) + strlen(".rel"), sizeof(*mloc0), 0);
 	if (!mlocs)
 		goto out;
 	mlocs->sh.sh_link = 0;
 	mlocs->sh.sh_info = 0;
-	mlocs->sh.sh_addralign = _size;
+	mlocs->sh.sh_addralign = 8;
+	mlocs->data->d_buf = mloc0;
+	mlocs->data->d_type = ELF_T_ADDR; /* elf_xlatetof() conversion */
 
 	/* add section .rel[a]__mcount_loc */
 	mrels = elf_create_section(lf, mc_name, rel_entsize, 0);
 	if (!mrels)
 		goto out;
-	mrels->sh.sh_type = is_rela
-				? SHT_RELA
-				: SHT_REL;
+	/* Like elf_create_rela_section() without the name bits */
+	mrels->sh.sh_type = is_rela ? SHT_RELA : SHT_REL;
 	mrels->sh.sh_flags = 0; /* clear SHF_ALLOC */
 	mrels->sh.sh_link = find_section_by_name(lf, ".symtab")->idx;
 	mrels->sh.sh_info = mlocs->idx;
-	mrels->sh.sh_addralign = _size;
+	mrels->sh.sh_addralign = 8;
+	mrels->data->d_buf = mrel0;
+	mrels->data->d_type = is_rela ? ELF_T_RELA : ELF_T_REL; /* elf_xlatetof() conversion */
 
 	list_for_each_entry(sec, &lf->sections, list) {
 		char const *txtname;
@@ -177,9 +158,8 @@ static int do_func(unsigned const reltype)
 						txtname, &recval, &recsym))
 				goto out;
 
-			mlocp = sift_rel_mcount(mlocp,
-				(void *)mlocp - (void *)mloc0, &mrelp,
-				sec, recsym, (uint_t)recval, reltype);
+			sift_rel_mcount(&mlocp, &r_offset, &mrelp, sec,
+				recsym, recval, reltype, is_rela);
 		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
 			/*
 			 * This section is ignored by ftrace, but still
@@ -191,17 +171,15 @@ static int do_func(unsigned const reltype)
 	}
 
 	if (mloc0 != mlocp) {
-		/* Update the section sizes */
+		/* Update the section size and Elf_Data size */
 		mlocs->sh.sh_size = (void *)mlocp - (void *)mloc0;
 		mlocs->len = mlocs->sh.sh_size;
 		mlocs->data->d_size = mlocs->len;
-		mlocs->data->d_buf = mloc0;
 		elf_flagdata(mlocs->data, ELF_C_SET, ELF_F_DIRTY);
 
-		mrels->sh.sh_size = (void *)mrelp - (void *)mrel0;
+		mrels->sh.sh_size = mrelp - mrel0;
 		mrels->len = mrels->sh.sh_size;
 		mrels->data->d_size = mrels->len;
-		mrels->data->d_buf = mrel0;
 		elf_flagdata(mrels->data, ELF_C_SET, ELF_F_DIRTY);
 
 		/* overwrite the ELF file */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 31/51] objtool: mcount: Use objtool relocation section
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (29 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 30/51] objtool: mcount: Generic location and relocation table types Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 32/51] objtool: mcount: Move sift_rel_mcount out of wrapper file Matt Helsley
                   ` (20 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Now that we add an initially-empty relocation section and share
the libelf data buffer from the beginning, we can safely use
objtools elf_create_reloc_section() function to simplify the
code further -- use the anticipated base section name, avoid
the need to set sh_info, etc. The only remaining difference
between this and the old recordmcount code is we didn't set
SHF_INFO_LINK so we clear the sh_flags as before.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.h | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 1d11dfc40d09..fc6346a7eaf5 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -92,7 +92,7 @@ static int do_func(unsigned const reltype)
 	GElf_Sxword r_offset = 0;
 
 	struct section *sec, *mlocs, *mrels;
-	const char *mc_name;
+	const char * const mc_name =  "__mcount_loc";
 
 	unsigned int rel_entsize = 0;
 	int result = -1;
@@ -119,12 +119,9 @@ static int do_func(unsigned const reltype)
 	}
 
 	is_rela = (sizeof(Elf_Rela) == rel_entsize);
-	mc_name = is_rela
-			? ".rela__mcount_loc"
-			:  ".rel__mcount_loc";
 
 	/* add section: __mcount_loc */
-	mlocs = elf_create_section(lf, mc_name + (is_rela ? 1 : 0) + strlen(".rel"), sizeof(*mloc0), 0);
+	mlocs = elf_create_section(lf, mc_name, sizeof(*mloc0), 0);
 	if (!mlocs)
 		goto out;
 	mlocs->sh.sh_link = 0;
@@ -134,17 +131,12 @@ static int do_func(unsigned const reltype)
 	mlocs->data->d_type = ELF_T_ADDR; /* elf_xlatetof() conversion */
 
 	/* add section .rel[a]__mcount_loc */
-	mrels = elf_create_section(lf, mc_name, rel_entsize, 0);
+	mrels = elf_create_reloc_section(lf, mlocs,
+					 is_rela ? SHT_RELA : SHT_REL);
 	if (!mrels)
 		goto out;
-	/* Like elf_create_rela_section() without the name bits */
-	mrels->sh.sh_type = is_rela ? SHT_RELA : SHT_REL;
-	mrels->sh.sh_flags = 0; /* clear SHF_ALLOC */
-	mrels->sh.sh_link = find_section_by_name(lf, ".symtab")->idx;
-	mrels->sh.sh_info = mlocs->idx;
-	mrels->sh.sh_addralign = 8;
+	mrels->sh.sh_flags = 0; /* clear SHF_INFO_LINK */
 	mrels->data->d_buf = mrel0;
-	mrels->data->d_type = is_rela ? ELF_T_RELA : ELF_T_REL; /* elf_xlatetof() conversion */
 
 	list_for_each_entry(sec, &lf->sections, list) {
 		char const *txtname;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 32/51] objtool: mcount: Move sift_rel_mcount out of wrapper file
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (30 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 31/51] objtool: mcount: Use objtool relocation section Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 33/51] objtool: mcount: Remove wrapper for ELF relocation type Matt Helsley
                   ` (19 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Now that this function no longer uses any of the old recordmcount
wrapper code we can move it out of the wrapper too.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 47 +++++++++++++++++++++++++++++++++
 tools/objtool/recordmcount.h | 50 ------------------------------------
 2 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 34976f3294ac..b9f15fc1f40e 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -395,6 +395,53 @@ static int mcount_adjust = 0;
 /* Size of an entry in __mcount_loc; 4 or 8 */
 static size_t loc_size;
 
+/*
+ * Look at the relocations in order to find the calls to mcount.
+ * Accumulate the section offsets that are found, and their relocation info,
+ * onto the end of the existing arrays.
+ */
+static void sift_rel_mcount(GElf_Addr **mlocpp,
+			       GElf_Sxword *r_offsetp,
+			       void **const mrelpp,
+			       const struct section * const rels,
+			       unsigned const recsym_index,
+			       unsigned long const recval,
+			       unsigned const reltype,
+			       bool is_rela)
+{
+	GElf_Rel *mrelp = *mrelpp;
+	GElf_Rela *mrelap = *mrelpp;
+	struct symbol *mcount_sym = NULL;
+	struct reloc *reloc;
+
+	list_for_each_entry(reloc, &rels->reloc_list, list) {
+		unsigned long addend;
+
+		if (!mcount_sym)
+			mcount_sym = get_mcount_sym(reloc);
+
+		if (mcount_sym != reloc->sym || is_fake_mcount(reloc))
+			continue;
+
+		addend = reloc->offset - recval + mcount_adjust;
+		if (is_rela) {
+			mrelap->r_offset = *r_offsetp;
+			mrelap->r_info = GELF_R_INFO(recsym_index, reltype);
+			mrelap->r_addend = addend;
+			mrelap++;
+			**mlocpp = 0;
+		} else {
+			mrelp->r_offset = *r_offsetp;
+			mrelp->r_info = GELF_R_INFO(recsym_index, reltype);
+			mrelp++;
+			**mlocpp = addend;
+		}
+		(*mlocpp)++;
+		*r_offsetp += loc_size;
+	}
+	*mrelpp = is_rela ? (void *)mrelap : (void *)mrelp;
+}
+
 /* 32 bit and 64 bit are very similar */
 #include "recordmcount.h"
 #define RECORD_MCOUNT_64
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index fc6346a7eaf5..2dd303d51b78 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -17,67 +17,17 @@
  * This conversion to macros was done by:
  * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  */
-#undef sift_rel_mcount
 #undef do_func
 #undef Elf_Rela
 
 #ifdef RECORD_MCOUNT_64
-# define sift_rel_mcount	sift64_rel_mcount
 # define do_func		do64
 # define Elf_Rela		Elf64_Rela
 #else
-# define sift_rel_mcount	sift32_rel_mcount
 # define do_func		do32
 # define Elf_Rela		Elf32_Rela
 #endif
 
-/*
- * Look at the relocations in order to find the calls to mcount.
- * Accumulate the section offsets that are found, and their relocation info,
- * onto the end of the existing arrays.
- */
-static void sift_rel_mcount(GElf_Addr **mlocpp,
-			       GElf_Sxword *r_offsetp,
-			       void **const mrelpp,
-			       const struct section * const rels,
-			       unsigned const recsym_index,
-			       unsigned long const recval,
-			       unsigned const reltype,
-			       bool is_rela)
-{
-	GElf_Rel *mrelp = *mrelpp;
-	GElf_Rela *mrelap = *mrelpp;
-	struct symbol *mcount_sym = NULL;
-	struct reloc *reloc;
-
-	list_for_each_entry(reloc, &rels->reloc_list, list) {
-		unsigned long addend;
-
-		if (!mcount_sym)
-			mcount_sym = get_mcount_sym(reloc);
-
-		if (mcount_sym != reloc->sym || is_fake_mcount(reloc))
-			continue;
-
-		addend = reloc->offset - recval + mcount_adjust;
-		if (is_rela) {
-			mrelap->r_offset = *r_offsetp;
-			mrelap->r_info = GELF_R_INFO(recsym_index, reltype);
-			mrelap->r_addend = addend;
-			mrelap++;
-			**mlocpp = 0;
-		} else {
-			mrelp->r_offset = *r_offsetp;
-			mrelp->r_info = GELF_R_INFO(recsym_index, reltype);
-			mrelp++;
-			**mlocpp = addend;
-		}
-		(*mlocpp)++;
-		*r_offsetp += loc_size;
-	}
-	*mrelpp = is_rela ? (void *)mrelap : (void *)mrelp;
-}
-
 /* Overall supervision for Elf32 ET_REL file. */
 static int do_func(unsigned const reltype)
 {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 33/51] objtool: mcount: Remove wrapper for ELF relocation type
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (31 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 32/51] objtool: mcount: Move sift_rel_mcount out of wrapper file Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 34/51] objtool: mcount: Remove wrapper double-include trick Matt Helsley
                   ` (18 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Remove the last uses of the Elf_Rela wrapper by passing the
size of the relocations we're dealing with as a parameter.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 4 ++--
 tools/objtool/recordmcount.h | 7 ++-----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index b9f15fc1f40e..6db035252b6c 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -575,7 +575,7 @@ static int do_file(char const *const fname)
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		loc_size = 4;
-		rc = do32(reltype);
+		rc = do32(reltype, sizeof(Elf32_Rela));
 		break;
 	case ELFCLASS64: {
 		if (lf->ehdr.e_ehsize != sizeof(Elf64_Ehdr)
@@ -593,7 +593,7 @@ static int do_file(char const *const fname)
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		loc_size = 8;
-		rc = do64(reltype);
+		rc = do64(reltype, sizeof(Elf64_Rela));
 		break;
 	}
 	}  /* end switch */
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
index 2dd303d51b78..07fc93917736 100644
--- a/tools/objtool/recordmcount.h
+++ b/tools/objtool/recordmcount.h
@@ -18,18 +18,15 @@
  * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  */
 #undef do_func
-#undef Elf_Rela
 
 #ifdef RECORD_MCOUNT_64
 # define do_func		do64
-# define Elf_Rela		Elf64_Rela
 #else
 # define do_func		do32
-# define Elf_Rela		Elf32_Rela
 #endif
 
 /* Overall supervision for Elf32 ET_REL file. */
-static int do_func(unsigned const reltype)
+static int do_func(unsigned const reltype, size_t rela_size)
 {
 	/* Upper bound on space: assume all relevant relocs are for mcount. */
 	unsigned       totrelsz;
@@ -68,7 +65,7 @@ static int do_func(unsigned const reltype)
 		return -1;
 	}
 
-	is_rela = (sizeof(Elf_Rela) == rel_entsize);
+	is_rela = (rela_size == rel_entsize);
 
 	/* add section: __mcount_loc */
 	mlocs = elf_create_section(lf, mc_name, sizeof(*mloc0), 0);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 34/51] objtool: mcount: Remove wrapper double-include trick
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (32 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 33/51] objtool: mcount: Remove wrapper for ELF relocation type Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 35/51] objtool: mcount: Remove endian wrappers Matt Helsley
                   ` (17 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

We no longer need to double-include the recordmcount.h wrapper
All of the types and functions that rely on them have been converted
to using objtool's ELF code. This moves the remaining function to
recordmcount.c and changes the function name to something slightly
more descriptive while dropping the wrapped naming.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 113 ++++++++++++++++++++++++++++--
 tools/objtool/recordmcount.h | 132 -----------------------------------
 2 files changed, 107 insertions(+), 138 deletions(-)
 delete mode 100644 tools/objtool/recordmcount.h

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 6db035252b6c..7f4d18e83e24 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -442,10 +442,111 @@ static void sift_rel_mcount(GElf_Addr **mlocpp,
 	*mrelpp = is_rela ? (void *)mrelap : (void *)mrelp;
 }
 
-/* 32 bit and 64 bit are very similar */
-#include "recordmcount.h"
-#define RECORD_MCOUNT_64
-#include "recordmcount.h"
+/* Overall supervision for Elf32 ET_REL file. */
+static int do_mcount(unsigned const reltype, size_t rela_size)
+{
+	/* Upper bound on space: assume all relevant relocs are for mcount. */
+	unsigned       totrelsz;
+
+	void *mrel0;
+	void *mrelp;
+
+	GElf_Addr *mloc0;
+	GElf_Addr *mlocp;
+	GElf_Sxword r_offset = 0;
+
+	struct section *sec, *mlocs, *mrels;
+	const char * const mc_name =  "__mcount_loc";
+
+	unsigned int rel_entsize = 0;
+	int result = -1;
+	bool is_rela;
+
+	if (find_section_by_name(lf, "__mcount_loc") != NULL)
+		return 0;
+
+	totrelsz = tot_relsize(&rel_entsize);
+	if (totrelsz == 0)
+		return 0;
+
+	mrel0 = malloc(totrelsz);
+	mrelp = mrel0;
+	if (!mrel0)
+		return -1;
+
+	/* 2*sizeof(address) <= sizeof(Elf_Rel) */
+	mloc0 = malloc(totrelsz>>1);
+	mlocp = mloc0;
+	if (!mloc0) {
+		free(mrel0);
+		return -1;
+	}
+
+	is_rela = (rela_size == rel_entsize);
+
+	/* add section: __mcount_loc */
+	mlocs = elf_create_section(lf, mc_name, sizeof(*mloc0), 0);
+	if (!mlocs)
+		goto out;
+	mlocs->sh.sh_link = 0;
+	mlocs->sh.sh_info = 0;
+	mlocs->sh.sh_addralign = 8;
+	mlocs->data->d_buf = mloc0;
+	mlocs->data->d_type = ELF_T_ADDR; /* elf_xlatetof() conversion */
+
+	/* add section .rel[a]__mcount_loc */
+	mrels = elf_create_reloc_section(lf, mlocs,
+					 is_rela ? SHT_RELA : SHT_REL);
+	if (!mrels)
+		goto out;
+	mrels->sh.sh_flags = 0; /* clear SHF_INFO_LINK */
+	mrels->data->d_buf = mrel0;
+
+	list_for_each_entry(sec, &lf->sections, list) {
+		char const *txtname;
+
+		txtname = has_rel_mcount(sec);
+		if (txtname && is_mcounted_section_name(txtname)) {
+			unsigned long recval = 0;
+			unsigned int recsym;
+
+			if (find_section_sym_index(sec->sh.sh_info,
+						txtname, &recval, &recsym))
+				goto out;
+
+			sift_rel_mcount(&mlocp, &r_offset, &mrelp, sec,
+				recsym, recval, reltype, is_rela);
+		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
+			/*
+			 * This section is ignored by ftrace, but still
+			 * has mcount calls. Convert them to nops now.
+			 */
+			if (nop_mcount(sec, txtname) < 0)
+				goto out;
+		}
+	}
+
+	if (mloc0 != mlocp) {
+		/* Update the section size and Elf_Data size */
+		mlocs->sh.sh_size = (void *)mlocp - (void *)mloc0;
+		mlocs->len = mlocs->sh.sh_size;
+		mlocs->data->d_size = mlocs->len;
+		elf_flagdata(mlocs->data, ELF_C_SET, ELF_F_DIRTY);
+
+		mrels->sh.sh_size = mrelp - mrel0;
+		mrels->len = mrels->sh.sh_size;
+		mrels->data->d_size = mrels->len;
+		elf_flagdata(mrels->data, ELF_C_SET, ELF_F_DIRTY);
+
+		/* overwrite the ELF file */
+		result = elf_write(lf);
+	} else
+		result = 0;
+out:
+	free(mrel0);
+	free(mloc0);
+	return result;
+}
 
 static int arm_is_fake_mcount(struct reloc const *rp)
 {
@@ -575,7 +676,7 @@ static int do_file(char const *const fname)
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		loc_size = 4;
-		rc = do32(reltype, sizeof(Elf32_Rela));
+		rc = do_mcount(reltype, sizeof(Elf32_Rela));
 		break;
 	case ELFCLASS64: {
 		if (lf->ehdr.e_ehsize != sizeof(Elf64_Ehdr)
@@ -593,7 +694,7 @@ static int do_file(char const *const fname)
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		loc_size = 8;
-		rc = do64(reltype, sizeof(Elf64_Rela));
+		rc = do_mcount(reltype, sizeof(Elf64_Rela));
 		break;
 	}
 	}  /* end switch */
diff --git a/tools/objtool/recordmcount.h b/tools/objtool/recordmcount.h
deleted file mode 100644
index 07fc93917736..000000000000
--- a/tools/objtool/recordmcount.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * recordmcount.h
- *
- * This code was taken out of recordmcount.c written by
- * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>.  All rights reserved.
- *
- * The original code had the same algorithms for both 32bit
- * and 64bit ELF files, but the code was duplicated to support
- * the difference in structures that were used. This
- * file creates a macro of everything that is different between
- * the 64 and 32 bit code, such that by including this header
- * twice we can create both sets of functions by including this
- * header once with RECORD_MCOUNT_64 undefined, and again with
- * it defined.
- *
- * This conversion to macros was done by:
- * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
- */
-#undef do_func
-
-#ifdef RECORD_MCOUNT_64
-# define do_func		do64
-#else
-# define do_func		do32
-#endif
-
-/* Overall supervision for Elf32 ET_REL file. */
-static int do_func(unsigned const reltype, size_t rela_size)
-{
-	/* Upper bound on space: assume all relevant relocs are for mcount. */
-	unsigned       totrelsz;
-
-	void *mrel0;
-	void *mrelp;
-
-	GElf_Addr *mloc0;
-	GElf_Addr *mlocp;
-	GElf_Sxword r_offset = 0;
-
-	struct section *sec, *mlocs, *mrels;
-	const char * const mc_name =  "__mcount_loc";
-
-	unsigned int rel_entsize = 0;
-	int result = -1;
-	bool is_rela;
-
-	if (find_section_by_name(lf, "__mcount_loc") != NULL)
-		return 0;
-
-	totrelsz = tot_relsize(&rel_entsize);
-	if (totrelsz == 0)
-		return 0;
-
-	mrel0 = malloc(totrelsz);
-	mrelp = mrel0;
-	if (!mrel0)
-		return -1;
-
-	/* 2*sizeof(address) <= sizeof(Elf_Rel) */
-	mloc0 = malloc(totrelsz>>1);
-	mlocp = mloc0;
-	if (!mloc0) {
-		free(mrel0);
-		return -1;
-	}
-
-	is_rela = (rela_size == rel_entsize);
-
-	/* add section: __mcount_loc */
-	mlocs = elf_create_section(lf, mc_name, sizeof(*mloc0), 0);
-	if (!mlocs)
-		goto out;
-	mlocs->sh.sh_link = 0;
-	mlocs->sh.sh_info = 0;
-	mlocs->sh.sh_addralign = 8;
-	mlocs->data->d_buf = mloc0;
-	mlocs->data->d_type = ELF_T_ADDR; /* elf_xlatetof() conversion */
-
-	/* add section .rel[a]__mcount_loc */
-	mrels = elf_create_reloc_section(lf, mlocs,
-					 is_rela ? SHT_RELA : SHT_REL);
-	if (!mrels)
-		goto out;
-	mrels->sh.sh_flags = 0; /* clear SHF_INFO_LINK */
-	mrels->data->d_buf = mrel0;
-
-	list_for_each_entry(sec, &lf->sections, list) {
-		char const *txtname;
-
-		txtname = has_rel_mcount(sec);
-		if (txtname && is_mcounted_section_name(txtname)) {
-			unsigned long recval = 0;
-			unsigned int recsym;
-
-			if (find_section_sym_index(sec->sh.sh_info,
-						txtname, &recval, &recsym))
-				goto out;
-
-			sift_rel_mcount(&mlocp, &r_offset, &mrelp, sec,
-				recsym, recval, reltype, is_rela);
-		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
-			/*
-			 * This section is ignored by ftrace, but still
-			 * has mcount calls. Convert them to nops now.
-			 */
-			if (nop_mcount(sec, txtname) < 0)
-				goto out;
-		}
-	}
-
-	if (mloc0 != mlocp) {
-		/* Update the section size and Elf_Data size */
-		mlocs->sh.sh_size = (void *)mlocp - (void *)mloc0;
-		mlocs->len = mlocs->sh.sh_size;
-		mlocs->data->d_size = mlocs->len;
-		elf_flagdata(mlocs->data, ELF_C_SET, ELF_F_DIRTY);
-
-		mrels->sh.sh_size = mrelp - mrel0;
-		mrels->len = mrels->sh.sh_size;
-		mrels->data->d_size = mrels->len;
-		elf_flagdata(mrels->data, ELF_C_SET, ELF_F_DIRTY);
-
-		/* overwrite the ELF file */
-		result = elf_write(lf);
-	} else
-		result = 0;
-out:
-	free(mrel0);
-	free(mloc0);
-	return result;
-}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 35/51] objtool: mcount: Remove endian wrappers
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (33 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 34/51] objtool: mcount: Remove wrapper double-include trick Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 36/51] objtool: mcount: Rename to mcount.c Matt Helsley
                   ` (16 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Now that they're no longer used we can remove these endian
wrappers.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/recordmcount.c | 63 ------------------------------------
 1 file changed, 63 deletions(-)

diff --git a/tools/objtool/recordmcount.c b/tools/objtool/recordmcount.c
index 7f4d18e83e24..ff52697613b1 100644
--- a/tools/objtool/recordmcount.c
+++ b/tools/objtool/recordmcount.c
@@ -149,53 +149,6 @@ static int make_nop_arm64(struct section *txts, size_t const offset)
 	return 0;
 }
 
-/* w8rev, w8nat, ...: Handle endianness. */
-
-static uint64_t w8rev(uint64_t const x)
-{
-	return   ((0xff & (x >> (0 * 8))) << (7 * 8))
-	       | ((0xff & (x >> (1 * 8))) << (6 * 8))
-	       | ((0xff & (x >> (2 * 8))) << (5 * 8))
-	       | ((0xff & (x >> (3 * 8))) << (4 * 8))
-	       | ((0xff & (x >> (4 * 8))) << (3 * 8))
-	       | ((0xff & (x >> (5 * 8))) << (2 * 8))
-	       | ((0xff & (x >> (6 * 8))) << (1 * 8))
-	       | ((0xff & (x >> (7 * 8))) << (0 * 8));
-}
-
-static uint32_t w4rev(uint32_t const x)
-{
-	return   ((0xff & (x >> (0 * 8))) << (3 * 8))
-	       | ((0xff & (x >> (1 * 8))) << (2 * 8))
-	       | ((0xff & (x >> (2 * 8))) << (1 * 8))
-	       | ((0xff & (x >> (3 * 8))) << (0 * 8));
-}
-
-static uint32_t w2rev(uint16_t const x)
-{
-	return   ((0xff & (x >> (0 * 8))) << (1 * 8))
-	       | ((0xff & (x >> (1 * 8))) << (0 * 8));
-}
-
-static uint64_t w8nat(uint64_t const x)
-{
-	return x;
-}
-
-static uint32_t w4nat(uint32_t const x)
-{
-	return x;
-}
-
-static uint32_t w2nat(uint16_t const x)
-{
-	return x;
-}
-
-static uint64_t (*w8)(uint64_t);
-static uint32_t (*w)(uint32_t);
-static uint32_t (*w2)(uint16_t);
-
 /* Names of the sections that could contain calls to mcount. */
 static int is_mcounted_section_name(char const *const txtname)
 {
@@ -571,22 +524,12 @@ static int do_file(char const *const fname)
 		goto out;
 	}
 
-	w = w4nat;
-	w2 = w2nat;
-	w8 = w8nat;
 	switch (lf->ehdr.e_ident[EI_DATA]) {
-		static unsigned int const endian = 1;
 	default:
 		fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
 			lf->ehdr.e_ident[EI_DATA], fname);
 		goto out;
 	case ELFDATA2LSB:
-		if (*(unsigned char const *)&endian != 1) {
-			/* objtool is big endian, file.o is little endian. */
-			w = w4rev;
-			w2 = w2rev;
-			w8 = w8rev;
-		}
 		ideal_nop4_arm = ideal_nop4_arm_le;
 		bl_mcount_arm = bl_mcount_arm_le;
 		push_arm = push_arm_le;
@@ -594,12 +537,6 @@ static int do_file(char const *const fname)
 		push_bl_mcount_thumb = push_bl_mcount_thumb_le;
 		break;
 	case ELFDATA2MSB:
-		if (*(unsigned char const *)&endian != 0) {
-			/*  objtool is little endian, file.o is big endian. */
-			w = w4rev;
-			w2 = w2rev;
-			w8 = w8rev;
-		}
 		ideal_nop4_arm = ideal_nop4_arm_be;
 		bl_mcount_arm = bl_mcount_arm_be;
 		push_arm = push_arm_be;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 36/51] objtool: mcount: Rename to mcount.c
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (34 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 35/51] objtool: mcount: Remove endian wrappers Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 37/51] objtool: mcount: Simplify mcount name matching Matt Helsley
                   ` (15 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Now that we've converted recordmcount to a subcommand of objtool
rename the .c file in order to follow the convention of the other
objtool subcmds.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/Build                        | 2 +-
 tools/objtool/{recordmcount.c => mcount.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename tools/objtool/{recordmcount.c => mcount.c} (100%)

diff --git a/tools/objtool/Build b/tools/objtool/Build
index f4f0515d4f91..7815a094c991 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -7,7 +7,7 @@ objtool-$(SUBCMD_CHECK) += special.o
 objtool-$(SUBCMD_ORC) += check.o
 objtool-$(SUBCMD_ORC) += orc_gen.o
 objtool-$(SUBCMD_ORC) += orc_dump.o
-objtool-$(SUBCMD_MCOUNT) += recordmcount.o
+objtool-$(SUBCMD_MCOUNT) += mcount.o
 
 objtool-y += builtin-check.o
 objtool-y += builtin-orc.o
diff --git a/tools/objtool/recordmcount.c b/tools/objtool/mcount.c
similarity index 100%
rename from tools/objtool/recordmcount.c
rename to tools/objtool/mcount.c
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 37/51] objtool: mcount: Simplify mcount name matching
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (35 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 36/51] objtool: mcount: Rename to mcount.c Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 38/51] objtool: mcount: mcount symbol name simplification Matt Helsley
                   ` (14 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Setting altmcount only when processing ARM ELF files is
not necessary -- we can make the code easier to read
by always checking for the string.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index ff52697613b1..7e621769c488 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -44,7 +44,6 @@
 #define R_ARM_THM_CALL		10
 
 static char gpfx;	/* prefix for global symbol name (sometimes '_') */
-static const char *altmcount;	/* alternate mcount symbol name */
 extern int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
 
 static struct elf *lf;
@@ -173,7 +172,7 @@ static struct symbol *get_mcount_sym(struct reloc *reloc)
 	if (symname[0] == '.')
 		++symname;  /* ppc64 hack */
 	if (strcmp(mcount, symname) == 0 ||
-	    (altmcount && strcmp(altmcount, symname) == 0) ||
+	    (strcmp("__gnu_mcount_nc", symname) == 0) ||
 	    (strcmp(fentry, symname) == 0))
 		return sym;
 	return NULL;
@@ -567,7 +566,6 @@ static int do_file(char const *const fname)
 		break;
 	case EM_ARM:
 		reltype = R_ARM_ABS32;
-		altmcount = "__gnu_mcount_nc";
 		make_nop = make_nop_arm;
 		rel_type_nop = R_ARM_NONE;
 		is_fake_mcount = arm_is_fake_mcount;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 38/51] objtool: mcount: mcount symbol name simplification
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (36 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 37/51] objtool: mcount: Simplify mcount name matching Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 39/51] objtool: mcount: Verify x86 instruction with memcmp() Matt Helsley
                   ` (13 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Remove gpfx -- the recognized prefix for the mcount symbol
-- and just recognize any of the prefixes. This allows us
to further substitute the various strings directly into the
code rather than using variables.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 7e621769c488..4d6596a031bf 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -43,7 +43,6 @@
 
 #define R_ARM_THM_CALL		10
 
-static char gpfx;	/* prefix for global symbol name (sometimes '_') */
 extern int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
 
 static struct elf *lf;
@@ -166,14 +165,16 @@ static struct symbol *get_mcount_sym(struct reloc *reloc)
 {
 	struct symbol *sym = reloc->sym;
 	char const *symname = sym->name;
-	char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
-	char const *fentry = "__fentry__";
 
 	if (symname[0] == '.')
-		++symname;  /* ppc64 hack */
-	if (strcmp(mcount, symname) == 0 ||
+		symname++;  /* ppc64 hack */
+
+	if (symname[0] == '_')
+		symname++;
+
+	if (strcmp("mcount", symname) == 0 ||
 	    (strcmp("__gnu_mcount_nc", symname) == 0) ||
-	    (strcmp(fentry, symname) == 0))
+	    (strcmp("_fentry__", symname) == 0))
 		return sym;
 	return NULL;
 }
@@ -550,7 +551,6 @@ static int do_file(char const *const fname)
 		goto out;
 	}
 
-	gpfx = '_';
 	switch (lf->ehdr.e_machine) {
 	default:
 		fprintf(stderr, "unrecognized e_machine %u %s\n",
@@ -562,14 +562,12 @@ static int do_file(char const *const fname)
 		make_nop = make_nop_x86;
 		ideal_nop = ideal_nop5_x86_32;
 		mcount_adjust = -1;
-		gpfx = 0;
 		break;
 	case EM_ARM:
 		reltype = R_ARM_ABS32;
 		make_nop = make_nop_arm;
 		rel_type_nop = R_ARM_NONE;
 		is_fake_mcount = arm_is_fake_mcount;
-		gpfx = 0;
 		break;
 	case EM_AARCH64:
 		reltype = R_AARCH64_ABS64;
@@ -582,7 +580,7 @@ static int do_file(char const *const fname)
 	case EM_PPC:	reltype = R_PPC_ADDR32; break;
 	case EM_PPC64:	reltype = R_PPC64_ADDR64; break;
 	case EM_S390:	/* reltype: e_class    */ break;
-	case EM_SH:	reltype = R_SH_DIR32; gpfx = 0; break;
+	case EM_SH:	reltype = R_SH_DIR32;  break;
 	case EM_SPARCV9: reltype = R_SPARC_64; break;
 	case EM_X86_64:
 		make_nop = make_nop_x86;
@@ -590,7 +588,6 @@ static int do_file(char const *const fname)
 		reltype = R_X86_64_64;
 		rel_type_nop = R_X86_64_NONE;
 		mcount_adjust = -1;
-		gpfx = 0;
 		break;
 	}  /* end switch */
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 39/51] objtool: mcount: Verify x86 instruction with memcmp()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (37 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 38/51] objtool: mcount: mcount symbol name simplification Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 40/51] objtool: mcount: const-ify ARM instruction patterns Matt Helsley
                   ` (12 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Instead of hard-coding what amounts to a memcmp() use memcmp to
determine if the instruction we wish to replace matches what we
expect. This makes the x86 code more like that of, for instance,
ARM.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 4d6596a031bf..5c59df0df97b 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -47,9 +47,10 @@ extern int warn_on_notrace_sect; /* warn when section has mcount not being recor
 
 static struct elf *lf;
 
-static unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
-static unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
-static unsigned char *ideal_nop;
+static const unsigned char ip_relative_call_x86[5] = { 0xe8, 0x00, 0x00, 0x00, 0x00 };
+static const unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
+static const unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
+static const unsigned char *ideal_nop;
 
 static char rel_type_nop;
 
@@ -57,20 +58,12 @@ static int (*make_nop)(struct section *, size_t const offset);
 
 static int make_nop_x86(struct section *txts, size_t const offset)
 {
-	uint32_t *ptr;
-	unsigned char *op;
-	void *map = txts->data->d_buf;
+	unsigned char *op = txts->data->d_buf + offset - 1;
 
 	if (offset < 1)
 		return -1;
 
-	/* Confirm we have 0xe8 0x0 0x0 0x0 0x0 */
-	ptr = map + offset;
-	if (*ptr != 0)
-		return -1;
-
-	op = map + offset - 1;
-	if (*op != 0xe8)
+	if (memcmp(op, ip_relative_call_x86, 5) != 0)
 		return -1;
 
 	/* convert to nop */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 40/51] objtool: mcount: const-ify ARM instruction patterns
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (38 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 39/51] objtool: mcount: Verify x86 instruction with memcmp() Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 41/51] objtool: mcount: Convert nop writes to elf_write_insn() Matt Helsley
                   ` (11 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Let the compiler know we won't be modifying the instruction
patterns we use to determine how to turn ARM instruction(s)
into nops, and the nop instruction(s) we'll put in their
place.

Also, while we're at it, convert to unsigned char because the
next patch will need that as well.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 5c59df0df97b..629eb7222ef3 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -47,10 +47,10 @@ extern int warn_on_notrace_sect; /* warn when section has mcount not being recor
 
 static struct elf *lf;
 
-static const unsigned char ip_relative_call_x86[5] = { 0xe8, 0x00, 0x00, 0x00, 0x00 };
-static const unsigned char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
-static const unsigned char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
-static const unsigned char *ideal_nop;
+static const char ip_relative_call_x86[5] = { 0xe8, 0x00, 0x00, 0x00, 0x00 };
+static const char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
+static const char ideal_nop5_x86_32[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
+static const char *ideal_nop;
 
 static char rel_type_nop;
 
@@ -58,7 +58,7 @@ static int (*make_nop)(struct section *, size_t const offset);
 
 static int make_nop_x86(struct section *txts, size_t const offset)
 {
-	unsigned char *op = txts->data->d_buf + offset - 1;
+	char *op = txts->data->d_buf + offset - 1;
 
 	if (offset < 1)
 		return -1;
@@ -71,25 +71,25 @@ static int make_nop_x86(struct section *txts, size_t const offset)
 	return 0;
 }
 
-static unsigned char ideal_nop4_arm_le[4] = { 0x00, 0x00, 0xa0, 0xe1 }; /* mov r0, r0 */
-static unsigned char ideal_nop4_arm_be[4] = { 0xe1, 0xa0, 0x00, 0x00 }; /* mov r0, r0 */
-static unsigned char *ideal_nop4_arm;
+static const char ideal_nop4_arm_le[4] = { 0x00, 0x00, 0xa0, 0xe1 }; /* mov r0, r0 */
+static const char ideal_nop4_arm_be[4] = { 0xe1, 0xa0, 0x00, 0x00 }; /* mov r0, r0 */
+static const char *ideal_nop4_arm;
 
-static unsigned char bl_mcount_arm_le[4] = { 0xfe, 0xff, 0xff, 0xeb }; /* bl */
-static unsigned char bl_mcount_arm_be[4] = { 0xeb, 0xff, 0xff, 0xfe }; /* bl */
-static unsigned char *bl_mcount_arm;
+static const char bl_mcount_arm_le[4] = { 0xfe, 0xff, 0xff, 0xeb }; /* bl */
+static const char bl_mcount_arm_be[4] = { 0xeb, 0xff, 0xff, 0xfe }; /* bl */
+static const char *bl_mcount_arm;
 
-static unsigned char push_arm_le[4] = { 0x04, 0xe0, 0x2d, 0xe5 }; /* push {lr} */
-static unsigned char push_arm_be[4] = { 0xe5, 0x2d, 0xe0, 0x04 }; /* push {lr} */
-static unsigned char *push_arm;
+static const char push_arm_le[4] = { 0x04, 0xe0, 0x2d, 0xe5 }; /* push {lr} */
+static const char push_arm_be[4] = { 0xe5, 0x2d, 0xe0, 0x04 }; /* push {lr} */
+static const char *push_arm;
 
-static unsigned char ideal_nop2_thumb_le[2] = { 0x00, 0xbf }; /* nop */
-static unsigned char ideal_nop2_thumb_be[2] = { 0xbf, 0x00 }; /* nop */
-static unsigned char *ideal_nop2_thumb;
+static const char ideal_nop2_thumb_le[2] = { 0x00, 0xbf }; /* nop */
+static const char ideal_nop2_thumb_be[2] = { 0xbf, 0x00 }; /* nop */
+static const char *ideal_nop2_thumb;
 
-static unsigned char push_bl_mcount_thumb_le[6] = { 0x00, 0xb5, 0xff, 0xf7, 0xfe, 0xff }; /* push {lr}, bl */
-static unsigned char push_bl_mcount_thumb_be[6] = { 0xb5, 0x00, 0xf7, 0xff, 0xff, 0xfe }; /* push {lr}, bl */
-static unsigned char *push_bl_mcount_thumb;
+static const char push_bl_mcount_thumb_le[6] = { 0x00, 0xb5, 0xff, 0xf7, 0xfe, 0xff }; /* push {lr}, bl */
+static const char push_bl_mcount_thumb_be[6] = { 0xb5, 0x00, 0xf7, 0xff, 0xff, 0xfe }; /* push {lr}, bl */
+static const char *push_bl_mcount_thumb;
 
 static int make_nop_arm(struct section *txts, size_t const offset)
 {
@@ -124,7 +124,7 @@ static int make_nop_arm(struct section *txts, size_t const offset)
 	return 0;
 }
 
-static unsigned char ideal_nop4_arm64[4] = {0x1f, 0x20, 0x03, 0xd5};
+static const char ideal_nop4_arm64[4] = {0x1f, 0x20, 0x03, 0xd5};
 static int make_nop_arm64(struct section *txts, size_t const offset)
 {
 	uint32_t *ptr;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 41/51] objtool: mcount: Convert nop writes to elf_write_insn()
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (39 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 40/51] objtool: mcount: const-ify ARM instruction patterns Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 42/51] objtool: mcount: Move mcount symbol name testing Matt Helsley
                   ` (10 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

objtool's elf_write_insn() does extra checking when writing to
an instruction so use that rather than a plain memcpy().

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 629eb7222ef3..029e6e72c972 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -66,9 +66,7 @@ static int make_nop_x86(struct section *txts, size_t const offset)
 	if (memcmp(op, ip_relative_call_x86, 5) != 0)
 		return -1;
 
-	/* convert to nop */
-	memcpy(op, ideal_nop, 5);
-	return 0;
+	return elf_write_insn(lf, txts, offset, 5, ideal_nop);
 }
 
 static const char ideal_nop4_arm_le[4] = { 0x00, 0x00, 0xa0, 0xe1 }; /* mov r0, r0 */
@@ -117,7 +115,8 @@ static int make_nop_arm(struct section *txts, size_t const offset)
 
 	/* Convert to nop */
 	do {
-		memcpy(map + off, ideal_nop, nop_size);
+		if (elf_write_insn(lf, txts, off, nop_size, ideal_nop))
+			return -1;
 		off += nop_size;
 	} while (--cnt > 0);
 
@@ -136,8 +135,7 @@ static int make_nop_arm64(struct section *txts, size_t const offset)
 		return -1;
 
 	/* Convert to nop */
-	memcpy(map + offset, ideal_nop, 4);
-	return 0;
+	return elf_write_insn(lf, txts, offset, 4, ideal_nop);
 }
 
 /* Names of the sections that could contain calls to mcount. */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 42/51] objtool: mcount: Move mcount symbol name testing
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (40 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 41/51] objtool: mcount: Convert nop writes to elf_write_insn() Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 43/51] objtool: check: Use class to recognize kcov calls Matt Helsley
                   ` (9 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Move the test for mcount symbols into the ELF code itself
and set a class on indicator on the symbol. This simplifies
mcount a little and tests the symbols names near where they're
first touched so should be cache-hot and may also help us
reduce the number of passes through the ELF contents needed
for individual subcommands. Finally, if we manage to combine
subcommands into a single exec of objtool the number of
passes through the ELF data could be even further reduced.

Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c    | 18 ++++++++++++++++++
 tools/objtool/elf.h    |  6 ++++++
 tools/objtool/mcount.c | 31 +++----------------------------
 3 files changed, 27 insertions(+), 28 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 8dcdea8020a5..d55d8fef11b4 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -387,6 +387,21 @@ static int read_sections(struct elf *elf)
 	return 0;
 }
 
+static bool is_mcount_sym(const char *name)
+{
+	if (name[0] == '.')
+		name++;  /* ppc64 hack */
+
+	if (name[0] == '_')
+		name++;
+
+	if (strcmp("mcount", name) == 0 ||
+	    (strcmp("__gnu_mcount_nc", name) == 0) ||
+	    (strcmp("_fentry__", name) == 0))
+		return true;
+	return false;
+}
+
 static int read_symbols(struct elf *elf)
 {
 	struct section *symtab, *symtab_shndx, *sec;
@@ -456,6 +471,9 @@ static int read_symbols(struct elf *elf)
 		} else
 			sym->sec = find_section_by_index(elf, 0);
 
+		if (is_mcount_sym(sym->name))
+			sym->class = SYM_MCOUNT;
+
 		sym->offset = sym->sym.st_value;
 		sym->len = sym->sym.st_size;
 
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 09fa0d085341..13935edaff54 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -42,6 +42,11 @@ struct section {
 	bool changed, text, rodata, noinstr;
 };
 
+enum symbol_class {
+	SYM_REGULAR = 0,
+	SYM_MCOUNT = 1,
+};
+
 struct symbol {
 	struct list_head list;
 	struct rb_node node;
@@ -55,6 +60,7 @@ struct symbol {
 	unsigned long offset;
 	unsigned int len;
 	struct symbol *pfunc, *cfunc, *alias;
+	enum symbol_class class;
 	bool uaccess_safe;
 };
 
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 029e6e72c972..7fbde6ce6eb8 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -152,24 +152,6 @@ static int is_mcounted_section_name(char const *const txtname)
 		strcmp(".cpuidle.text", txtname) == 0;
 }
 
-static struct symbol *get_mcount_sym(struct reloc *reloc)
-{
-	struct symbol *sym = reloc->sym;
-	char const *symname = sym->name;
-
-	if (symname[0] == '.')
-		symname++;  /* ppc64 hack */
-
-	if (symname[0] == '_')
-		symname++;
-
-	if (strcmp("mcount", symname) == 0 ||
-	    (strcmp("__gnu_mcount_nc", symname) == 0) ||
-	    (strcmp("_fentry__", symname) == 0))
-		return sym;
-	return NULL;
-}
-
 /*
  * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
  * _mcount symbol is needed for dynamic function tracer, with it, to disable
@@ -266,16 +248,13 @@ static int nop_mcount(struct section * const rels,
 {
 	struct reloc *reloc;
 	struct section *txts = find_section_by_index(lf, rels->sh.sh_info);
-	struct symbol *mcount_sym = NULL;
 	int once = 0;
 
 	list_for_each_entry(reloc, &rels->reloc_list, list) {
 		int ret = -1;
 
-		if (!mcount_sym)
-			mcount_sym = get_mcount_sym(reloc);
-
-		if (mcount_sym == reloc->sym && !is_fake_mcount(reloc)) {
+		if (reloc->sym->class == SYM_MCOUNT &&
+		    !is_fake_mcount(reloc)) {
 			if (make_nop) {
 				ret = make_nop(txts, reloc->offset);
 				if (ret < 0)
@@ -355,16 +334,12 @@ static void sift_rel_mcount(GElf_Addr **mlocpp,
 {
 	GElf_Rel *mrelp = *mrelpp;
 	GElf_Rela *mrelap = *mrelpp;
-	struct symbol *mcount_sym = NULL;
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &rels->reloc_list, list) {
 		unsigned long addend;
 
-		if (!mcount_sym)
-			mcount_sym = get_mcount_sym(reloc);
-
-		if (mcount_sym != reloc->sym || is_fake_mcount(reloc))
+		if (reloc->sym->class == SYM_MCOUNT || is_fake_mcount(reloc))
 			continue;
 
 		addend = reloc->offset - recval + mcount_adjust;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 43/51] objtool: check: Use class to recognize kcov calls
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (41 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 42/51] objtool: mcount: Move mcount symbol name testing Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 44/51] objtool: mcount: Keep lists locations and relocations Matt Helsley
                   ` (8 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/check.c | 3 +--
 tools/objtool/elf.c   | 7 +++++++
 tools/objtool/elf.h   | 1 +
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 78375908acda..d08714b878c5 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -771,8 +771,7 @@ static int add_call_destinations(struct objtool_file *file)
 		 * so they need a little help, NOP out any KCOV calls from noinstr
 		 * text.
 		 */
-		if (insn->sec->noinstr &&
-		    !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) {
+		if (insn->sec->noinstr && insn->call_dest->class == SYM_KCOV) {
 			if (reloc) {
 				reloc->type = R_NONE;
 				elf_write_reloc(file->elf, reloc);
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index d55d8fef11b4..666cbc01c332 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -402,6 +402,11 @@ static bool is_mcount_sym(const char *name)
 	return false;
 }
 
+static bool is_kcov_symbol(const char *name)
+{
+	return !strncmp(name, "__sanitize_cov_", 16);
+}
+
 static int read_symbols(struct elf *elf)
 {
 	struct section *symtab, *symtab_shndx, *sec;
@@ -473,6 +478,8 @@ static int read_symbols(struct elf *elf)
 
 		if (is_mcount_sym(sym->name))
 			sym->class = SYM_MCOUNT;
+		else if (is_kcov_symbol(sym->name))
+			sym->class = SYM_KCOV;
 
 		sym->offset = sym->sym.st_value;
 		sym->len = sym->sym.st_size;
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 13935edaff54..f0b02824f9d3 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -45,6 +45,7 @@ struct section {
 enum symbol_class {
 	SYM_REGULAR = 0,
 	SYM_MCOUNT = 1,
+	SYM_KCOV = 2,
 };
 
 struct symbol {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 44/51] objtool: mcount: Keep lists locations and relocations
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (42 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 43/51] objtool: check: Use class to recognize kcov calls Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 45/51] objtool: mcount: Move mcount section test to objtool ELF Matt Helsley
                   ` (7 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

To reduce the need for an initial pass through the sections
we need to keep lists of mcount call locations and suitable
relocations. A subsequent patch will eliminate the need for
the first pass entirely.

Introduce a new list for the locations and reuse objtool's
relocation lists respectively.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 133 +++++++++++++++++++++++------------------
 1 file changed, 75 insertions(+), 58 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 7fbde6ce6eb8..7d7843f7cd44 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -43,9 +43,15 @@
 
 #define R_ARM_THM_CALL		10
 
+struct mcount_loc {
+	struct list_head list;
+	GElf_Addr loc;
+};
+
 extern int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
 
 static struct elf *lf;
+static struct list_head mcount_locs;
 
 static const char ip_relative_call_x86[5] = { 0xe8, 0x00, 0x00, 0x00, 0x00 };
 static const char ideal_nop5_x86_64[5] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
@@ -294,20 +300,17 @@ static char const *has_rel_mcount(const struct section * const rels)
 	return txts->name;
 }
 
-static unsigned tot_relsize(unsigned int *rel_entsize)
+static void tot_relsize(unsigned int *rel_entsize)
 {
 	const struct section *sec;
-	unsigned totrelsz = 0;
 	char const *txtname;
 
 	list_for_each_entry(sec, &lf->sections, list) {
 		txtname = has_rel_mcount(sec);
 		if (!(txtname && is_mcounted_section_name(txtname)))
 			continue;
-		totrelsz += sec->sh.sh_size;
 		*rel_entsize = sec->sh.sh_entsize;
 	}
-	return totrelsz;
 }
 
 /* zero or a small negative offset added to get the start of the call
@@ -323,55 +326,89 @@ static size_t loc_size;
  * Accumulate the section offsets that are found, and their relocation info,
  * onto the end of the existing arrays.
  */
-static void sift_rel_mcount(GElf_Addr **mlocpp,
-			       GElf_Sxword *r_offsetp,
-			       void **const mrelpp,
+static void sift_rel_mcount(GElf_Sxword *r_offsetp,
 			       const struct section * const rels,
+			       struct section *mc_relocs,
+			       struct section *mc_locs,
 			       unsigned const recsym_index,
 			       unsigned long const recval,
 			       unsigned const reltype,
 			       bool is_rela)
 {
-	GElf_Rel *mrelp = *mrelpp;
-	GElf_Rela *mrelap = *mrelpp;
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &rels->reloc_list, list) {
 		unsigned long addend;
+		struct mcount_loc *mc_loc;
+		struct reloc *mc_reloc;
+
+		if (reloc->sym->class != SYM_MCOUNT || is_fake_mcount(reloc))
+			continue;
 
-		if (reloc->sym->class == SYM_MCOUNT || is_fake_mcount(reloc))
+		mc_loc = malloc(sizeof(*mc_loc));
+		if (!mc_loc) {
+			perror("malloc");
 			continue;
+		}
+		mc_reloc = malloc(sizeof(*mc_reloc));
+		if (!mc_reloc) {
+			perror("malloc");
+			free(mc_loc);
+			continue;
+		}
+		memset(mc_reloc, 0, sizeof(*mc_reloc));
+		memset(mc_loc, 0, sizeof(*mc_loc));
+		mc_reloc->sec = mc_relocs;
 
 		addend = reloc->offset - recval + mcount_adjust;
 		if (is_rela) {
-			mrelap->r_offset = *r_offsetp;
-			mrelap->r_info = GELF_R_INFO(recsym_index, reltype);
-			mrelap->r_addend = addend;
-			mrelap++;
-			**mlocpp = 0;
+			mc_reloc->rela.r_offset = *r_offsetp;
+			mc_reloc->rela.r_info = GELF_R_INFO(recsym_index, reltype);
+			mc_reloc->rela.r_addend = addend;
+			mc_loc->loc = 0;
 		} else {
-			mrelp->r_offset = *r_offsetp;
-			mrelp->r_info = GELF_R_INFO(recsym_index, reltype);
-			mrelp++;
-			**mlocpp = addend;
+			mc_reloc->rel.r_offset = *r_offsetp;
+			mc_reloc->rel.r_info = GELF_R_INFO(recsym_index, reltype);
+			mc_loc->loc = addend;
 		}
-		(*mlocpp)++;
+		mc_reloc->offset = *r_offsetp;
+		mc_reloc->type = reltype;
+		mc_reloc->sec = mc_locs;
+		elf_add_reloc(lf, mc_reloc);
+
+		list_add_tail(&mc_loc->list, &mcount_locs);
 		*r_offsetp += loc_size;
 	}
-	*mrelpp = is_rela ? (void *)mrelap : (void *)mrelp;
 }
 
-/* Overall supervision for Elf32 ET_REL file. */
-static int do_mcount(unsigned const reltype, size_t rela_size)
+/* Convert list of mcount locations to an array/buffer for libelf */
+static void fill_mcount_locs(GElf_Sxword r_offset, GElf_Addr **rbuf,
+			     size_t *rsize)
 {
-	/* Upper bound on space: assume all relevant relocs are for mcount. */
-	unsigned       totrelsz;
+	GElf_Addr *buf, *loc;
+	struct mcount_loc *entry, *next;
+	size_t size = sizeof(*loc) * r_offset / loc_size;
+
+	buf = malloc(size);
+	if (!buf) {
+		perror("malloc");
+		return;
+	}
 
-	void *mrel0;
-	void *mrelp;
+	loc = buf;
+	list_for_each_entry_safe(entry, next, &mcount_locs, list) {
+		*loc = entry->loc;
+		list_del(&entry->list);
+		free(entry);
+		loc++;
+	}
+	*rbuf = buf;
+	*rsize = size;
+}
 
-	GElf_Addr *mloc0;
-	GElf_Addr *mlocp;
+/* Overall supervision for Elf32 ET_REL file. */
+static int do_mcount(unsigned const reltype, size_t rela_size)
+{
 	GElf_Sxword r_offset = 0;
 
 	struct section *sec, *mlocs, *mrels;
@@ -384,33 +421,16 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
 
-	totrelsz = tot_relsize(&rel_entsize);
-	if (totrelsz == 0)
-		return 0;
-
-	mrel0 = malloc(totrelsz);
-	mrelp = mrel0;
-	if (!mrel0)
-		return -1;
-
-	/* 2*sizeof(address) <= sizeof(Elf_Rel) */
-	mloc0 = malloc(totrelsz>>1);
-	mlocp = mloc0;
-	if (!mloc0) {
-		free(mrel0);
-		return -1;
-	}
-
+	tot_relsize(&rel_entsize);
 	is_rela = (rela_size == rel_entsize);
 
 	/* add section: __mcount_loc */
-	mlocs = elf_create_section(lf, mc_name, sizeof(*mloc0), 0);
+	mlocs = elf_create_section(lf, mc_name, sizeof(GElf_Addr), 0);
 	if (!mlocs)
 		goto out;
 	mlocs->sh.sh_link = 0;
 	mlocs->sh.sh_info = 0;
 	mlocs->sh.sh_addralign = 8;
-	mlocs->data->d_buf = mloc0;
 	mlocs->data->d_type = ELF_T_ADDR; /* elf_xlatetof() conversion */
 
 	/* add section .rel[a]__mcount_loc */
@@ -419,7 +439,6 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 	if (!mrels)
 		goto out;
 	mrels->sh.sh_flags = 0; /* clear SHF_INFO_LINK */
-	mrels->data->d_buf = mrel0;
 
 	list_for_each_entry(sec, &lf->sections, list) {
 		char const *txtname;
@@ -433,7 +452,7 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 						txtname, &recval, &recsym))
 				goto out;
 
-			sift_rel_mcount(&mlocp, &r_offset, &mrelp, sec,
+			sift_rel_mcount(&r_offset, sec, mrels, mlocs,
 				recsym, recval, reltype, is_rela);
 		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
 			/*
@@ -445,25 +464,21 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 		}
 	}
 
-	if (mloc0 != mlocp) {
+	if (!list_empty(&mcount_locs)) {
+		fill_mcount_locs(r_offset, (GElf_Addr **)&mlocs->data->d_buf,
+				 &mlocs->sh.sh_size);
 		/* Update the section size and Elf_Data size */
-		mlocs->sh.sh_size = (void *)mlocp - (void *)mloc0;
 		mlocs->len = mlocs->sh.sh_size;
 		mlocs->data->d_size = mlocs->len;
 		elf_flagdata(mlocs->data, ELF_C_SET, ELF_F_DIRTY);
 
-		mrels->sh.sh_size = mrelp - mrel0;
-		mrels->len = mrels->sh.sh_size;
-		mrels->data->d_size = mrels->len;
-		elf_flagdata(mrels->data, ELF_C_SET, ELF_F_DIRTY);
+		elf_rebuild_reloc_section(lf, mrels);
 
 		/* overwrite the ELF file */
 		result = elf_write(lf);
 	} else
 		result = 0;
 out:
-	free(mrel0);
-	free(mloc0);
 	return result;
 }
 
@@ -490,6 +505,8 @@ static int do_file(char const *const fname)
 		goto out;
 	}
 
+	INIT_LIST_HEAD(&mcount_locs);
+
 	switch (lf->ehdr.e_ident[EI_DATA]) {
 	default:
 		fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 45/51] objtool: mcount: Move mcount section test to objtool ELF
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (43 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 44/51] objtool: mcount: Keep lists locations and relocations Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 46/51] objtool: mcount: Flag mcount relocation sections Matt Helsley
                   ` (6 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

In preparation for removing this first pass by mcount move
the test for whether a section is mcountable into objtool's
ELF read code, much like we did with the symbol name. A
subsequent patch will eliminate the tot_relsize() function
and thereby reduce the number of passes through the ELF
data.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c    | 16 ++++++++++++++++
 tools/objtool/elf.h    |  2 +-
 tools/objtool/mcount.c | 36 +++++++++++-------------------------
 3 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 666cbc01c332..dffdc3264a25 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -308,6 +308,20 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
 	return find_reloc_by_dest_range(elf, sec, offset, 1);
 }
 
+/* Names of the sections that could contain calls to mcount. */
+static int is_mcounted_section_name(char const *const txtname)
+{
+	return strncmp(".text",          txtname, 5) == 0 ||
+		strcmp(".init.text",     txtname) == 0 ||
+		strcmp(".ref.text",      txtname) == 0 ||
+		strcmp(".sched.text",    txtname) == 0 ||
+		strcmp(".spinlock.text", txtname) == 0 ||
+		strcmp(".irqentry.text", txtname) == 0 ||
+		strcmp(".softirqentry.text", txtname) == 0 ||
+		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".cpuidle.text", txtname) == 0;
+}
+
 static int read_sections(struct elf *elf)
 {
 	Elf_Scn *s = NULL;
@@ -370,6 +384,8 @@ static int read_sections(struct elf *elf)
 		}
 		sec->len = sec->sh.sh_size;
 
+		sec->mcounted = is_mcounted_section_name(sec->name);
+
 		list_add_tail(&sec->list, &elf->sections);
 		elf_hash_add(elf->section_hash, &sec->hash, sec->idx);
 		elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index f0b02824f9d3..db207e93a1e6 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -39,7 +39,7 @@ struct section {
 	char *name;
 	int idx;
 	unsigned int len;
-	bool changed, text, rodata, noinstr;
+	bool changed, text, rodata, noinstr, mcounted;
 };
 
 enum symbol_class {
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 7d7843f7cd44..a75d918a9fa5 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -144,20 +144,6 @@ static int make_nop_arm64(struct section *txts, size_t const offset)
 	return elf_write_insn(lf, txts, offset, 4, ideal_nop);
 }
 
-/* Names of the sections that could contain calls to mcount. */
-static int is_mcounted_section_name(char const *const txtname)
-{
-	return strncmp(".text",          txtname, 5) == 0 ||
-		strcmp(".init.text",     txtname) == 0 ||
-		strcmp(".ref.text",      txtname) == 0 ||
-		strcmp(".sched.text",    txtname) == 0 ||
-		strcmp(".spinlock.text", txtname) == 0 ||
-		strcmp(".irqentry.text", txtname) == 0 ||
-		strcmp(".softirqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
-		strcmp(".cpuidle.text", txtname) == 0;
-}
-
 /*
  * MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
  * _mcount symbol is needed for dynamic function tracer, with it, to disable
@@ -288,7 +274,7 @@ static int nop_mcount(struct section * const rels,
 	return 0;
 }
 
-static char const *has_rel_mcount(const struct section * const rels)
+static struct section const *has_rel_mcount(const struct section * const rels)
 {
 	const struct section *txts;
 	if (rels->sh.sh_type != SHT_REL && rels->sh.sh_type != SHT_RELA)
@@ -297,17 +283,17 @@ static char const *has_rel_mcount(const struct section * const rels)
 	if ((txts->sh.sh_type != SHT_PROGBITS) ||
 	    !(txts->sh.sh_flags & SHF_EXECINSTR))
 		return NULL;
-	return txts->name;
+	return txts;
 }
 
 static void tot_relsize(unsigned int *rel_entsize)
 {
 	const struct section *sec;
-	char const *txtname;
+	const struct section *txts;
 
 	list_for_each_entry(sec, &lf->sections, list) {
-		txtname = has_rel_mcount(sec);
-		if (!(txtname && is_mcounted_section_name(txtname)))
+		txts = has_rel_mcount(sec);
+		if (!(txts && txts->mcounted))
 			continue;
 		*rel_entsize = sec->sh.sh_entsize;
 	}
@@ -441,25 +427,25 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 	mrels->sh.sh_flags = 0; /* clear SHF_INFO_LINK */
 
 	list_for_each_entry(sec, &lf->sections, list) {
-		char const *txtname;
+		struct section const *txts;
 
-		txtname = has_rel_mcount(sec);
-		if (txtname && is_mcounted_section_name(txtname)) {
+		txts = has_rel_mcount(sec);
+		if (txts && txts->mcounted) {
 			unsigned long recval = 0;
 			unsigned int recsym;
 
 			if (find_section_sym_index(sec->sh.sh_info,
-						txtname, &recval, &recsym))
+						txts->name, &recval, &recsym))
 				goto out;
 
 			sift_rel_mcount(&r_offset, sec, mrels, mlocs,
 				recsym, recval, reltype, is_rela);
-		} else if (txtname && (warn_on_notrace_sect || make_nop)) {
+		} else if (txts && (warn_on_notrace_sect || make_nop)) {
 			/*
 			 * This section is ignored by ftrace, but still
 			 * has mcount calls. Convert them to nops now.
 			 */
-			if (nop_mcount(sec, txtname) < 0)
+			if (nop_mcount(sec, txts->name) < 0)
 				goto out;
 		}
 	}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 46/51] objtool: mcount: Flag mcount relocation sections
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (44 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 45/51] objtool: mcount: Move mcount section test to objtool ELF Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 47/51] objtool: mcount: Merge section mcount flags Matt Helsley
                   ` (5 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Move the check for relocations sections that apply to
mcountable text sections into objtool's ELF code.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c    | 13 +++++++++++++
 tools/objtool/elf.h    |  2 +-
 tools/objtool/mcount.c | 36 ++++++++++++++++--------------------
 3 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index dffdc3264a25..3708f85fe36d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -385,6 +385,7 @@ static int read_sections(struct elf *elf)
 		sec->len = sec->sh.sh_size;
 
 		sec->mcounted = is_mcounted_section_name(sec->name);
+		sec->relocs_mcountable = false;
 
 		list_add_tail(&sec->list, &elf->sections);
 		elf_hash_add(elf->section_hash, &sec->hash, sec->idx);
@@ -609,6 +610,17 @@ static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsi
 	return 0;
 }
 
+static bool relocs_mcountable(const struct section * const rels)
+{
+       const struct section *txts;
+
+       txts = rels->base;
+       if ((txts->sh.sh_type != SHT_PROGBITS) ||
+           !(txts->sh.sh_flags & SHF_EXECINSTR))
+               return false;
+       return true;
+}
+
 static int read_relocs(struct elf *elf)
 {
 	struct section *sec;
@@ -630,6 +642,7 @@ static int read_relocs(struct elf *elf)
 		}
 
 		sec->base->reloc = sec;
+		sec->relocs_mcountable = relocs_mcountable(sec);
 
 		nr_reloc = 0;
 		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index db207e93a1e6..92d3e68abf59 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -39,7 +39,7 @@ struct section {
 	char *name;
 	int idx;
 	unsigned int len;
-	bool changed, text, rodata, noinstr, mcounted;
+	bool changed, text, rodata, noinstr, mcounted, relocs_mcountable;
 };
 
 enum symbol_class {
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index a75d918a9fa5..9cd52beed871 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -274,28 +274,13 @@ static int nop_mcount(struct section * const rels,
 	return 0;
 }
 
-static struct section const *has_rel_mcount(const struct section * const rels)
-{
-	const struct section *txts;
-	if (rels->sh.sh_type != SHT_REL && rels->sh.sh_type != SHT_RELA)
-		return NULL;
-	txts = find_section_by_index(lf, rels->sh.sh_info);
-	if ((txts->sh.sh_type != SHT_PROGBITS) ||
-	    !(txts->sh.sh_flags & SHF_EXECINSTR))
-		return NULL;
-	return txts;
-}
-
 static void tot_relsize(unsigned int *rel_entsize)
 {
 	const struct section *sec;
-	const struct section *txts;
 
 	list_for_each_entry(sec, &lf->sections, list) {
-		txts = has_rel_mcount(sec);
-		if (!(txts && txts->mcounted))
-			continue;
-		*rel_entsize = sec->sh.sh_entsize;
+		if (sec->relocs_mcountable)
+			*rel_entsize = sec->sh.sh_entsize;
 	}
 }
 
@@ -429,8 +414,19 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 	list_for_each_entry(sec, &lf->sections, list) {
 		struct section const *txts;
 
-		txts = has_rel_mcount(sec);
-		if (txts && txts->mcounted) {
+		/* Find relocation sections.. */
+		if (sec->sh.sh_type != SHT_REL &&
+		    sec->sh.sh_type != SHT_RELA)
+			continue;
+		/* Which may relocate mcount calls.. */
+		if (!sec->relocs_mcountable)
+			continue;
+		txts = sec->base;
+		if (!txts)
+			continue;
+
+		if (txts->mcounted) {
+			/* In mcountable text sections */
 			unsigned long recval = 0;
 			unsigned int recsym;
 
@@ -440,7 +436,7 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 
 			sift_rel_mcount(&r_offset, sec, mrels, mlocs,
 				recsym, recval, reltype, is_rela);
-		} else if (txts && (warn_on_notrace_sect || make_nop)) {
+		} else if (warn_on_notrace_sect || make_nop) {
 			/*
 			 * This section is ignored by ftrace, but still
 			 * has mcount calls. Convert them to nops now.
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 47/51] objtool: mcount: Merge section mcount flags
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (45 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 46/51] objtool: mcount: Flag mcount relocation sections Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 48/51] objtool: mcount: Eliminate first pass Matt Helsley
                   ` (4 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

One flag is only for relocation sections and the other only
for text (not relocation) sections so we can share the same
flag and test the section type when we need to.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c    | 5 ++---
 tools/objtool/elf.h    | 2 +-
 tools/objtool/mcount.c | 9 ++++++---
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 3708f85fe36d..12bd889a62ba 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -384,8 +384,7 @@ static int read_sections(struct elf *elf)
 		}
 		sec->len = sec->sh.sh_size;
 
-		sec->mcounted = is_mcounted_section_name(sec->name);
-		sec->relocs_mcountable = false;
+		sec->mcountable = is_mcounted_section_name(sec->name);
 
 		list_add_tail(&sec->list, &elf->sections);
 		elf_hash_add(elf->section_hash, &sec->hash, sec->idx);
@@ -642,7 +641,7 @@ static int read_relocs(struct elf *elf)
 		}
 
 		sec->base->reloc = sec;
-		sec->relocs_mcountable = relocs_mcountable(sec);
+		sec->mcountable = relocs_mcountable(sec);
 
 		nr_reloc = 0;
 		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 92d3e68abf59..fb10f470d1a4 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -39,7 +39,7 @@ struct section {
 	char *name;
 	int idx;
 	unsigned int len;
-	bool changed, text, rodata, noinstr, mcounted, relocs_mcountable;
+	bool changed, text, rodata, noinstr, mcountable;
 };
 
 enum symbol_class {
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 9cd52beed871..80daf0e17eab 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -279,7 +279,10 @@ static void tot_relsize(unsigned int *rel_entsize)
 	const struct section *sec;
 
 	list_for_each_entry(sec, &lf->sections, list) {
-		if (sec->relocs_mcountable)
+		if (sec->sh.sh_type != SHT_REL &&
+		    sec->sh.sh_type != SHT_RELA)
+			continue;
+		if (sec->mcountable)
 			*rel_entsize = sec->sh.sh_entsize;
 	}
 }
@@ -419,13 +422,13 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 		    sec->sh.sh_type != SHT_RELA)
 			continue;
 		/* Which may relocate mcount calls.. */
-		if (!sec->relocs_mcountable)
+		if (!sec->mcountable)
 			continue;
 		txts = sec->base;
 		if (!txts)
 			continue;
 
-		if (txts->mcounted) {
+		if (txts->mcountable) {
 			/* In mcountable text sections */
 			unsigned long recval = 0;
 			unsigned int recsym;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 48/51] objtool: mcount: Eliminate first pass
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (46 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 47/51] objtool: mcount: Merge section mcount flags Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 49/51] objtool: mcount: Remove relocation size check Matt Helsley
                   ` (3 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Determine the size of the mcount relocations in objtool's
ELF reading code. This reduces the number of passes we make
through the list of sections (which can become large due to
things like -ffunction-sections).

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c    |  2 ++
 tools/objtool/elf.h    |  1 +
 tools/objtool/mcount.c | 16 +---------------
 3 files changed, 4 insertions(+), 15 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 12bd889a62ba..733e10d4a574 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -642,6 +642,8 @@ static int read_relocs(struct elf *elf)
 
 		sec->base->reloc = sec;
 		sec->mcountable = relocs_mcountable(sec);
+		if (sec->mcountable && !elf->mcount_rel_entsize)
+			elf->mcount_rel_entsize = sec->sh.sh_entsize;
 
 		nr_reloc = 0;
 		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index fb10f470d1a4..8ece1ca79cca 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -87,6 +87,7 @@ struct elf {
 	Elf *elf;
 	GElf_Ehdr ehdr;
 	int fd;
+	size_t mcount_rel_entsize;
 	bool changed;
 	char *name;
 	struct list_head sections;
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 80daf0e17eab..9527924af56b 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -274,19 +274,6 @@ static int nop_mcount(struct section * const rels,
 	return 0;
 }
 
-static void tot_relsize(unsigned int *rel_entsize)
-{
-	const struct section *sec;
-
-	list_for_each_entry(sec, &lf->sections, list) {
-		if (sec->sh.sh_type != SHT_REL &&
-		    sec->sh.sh_type != SHT_RELA)
-			continue;
-		if (sec->mcountable)
-			*rel_entsize = sec->sh.sh_entsize;
-	}
-}
-
 /* zero or a small negative offset added to get the start of the call
  * instruction
  */
@@ -388,14 +375,13 @@ static int do_mcount(unsigned const reltype, size_t rela_size)
 	struct section *sec, *mlocs, *mrels;
 	const char * const mc_name =  "__mcount_loc";
 
-	unsigned int rel_entsize = 0;
+	const unsigned int rel_entsize = lf->mcount_rel_entsize;
 	int result = -1;
 	bool is_rela;
 
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
 
-	tot_relsize(&rel_entsize);
 	is_rela = (rela_size == rel_entsize);
 
 	/* add section: __mcount_loc */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 49/51] objtool: mcount: Remove relocation size check
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (47 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 48/51] objtool: mcount: Eliminate first pass Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 50/51] objtool: mcount: Remove useless lookup Matt Helsley
                   ` (2 subsequent siblings)
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Rather than use the size of the relocations check the section
header type directly to see if the mcount relocations should
be rel or rela relocations.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/elf.c    |  4 ++--
 tools/objtool/elf.h    |  2 +-
 tools/objtool/mcount.c | 15 +++++----------
 3 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 733e10d4a574..4948df31bba0 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -642,8 +642,8 @@ static int read_relocs(struct elf *elf)
 
 		sec->base->reloc = sec;
 		sec->mcountable = relocs_mcountable(sec);
-		if (sec->mcountable && !elf->mcount_rel_entsize)
-			elf->mcount_rel_entsize = sec->sh.sh_entsize;
+		if (sec->mcountable)
+			elf->mcount_r_addends = (sec->sh.sh_type == SHT_RELA);
 
 		nr_reloc = 0;
 		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 8ece1ca79cca..f298e327af01 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -87,8 +87,8 @@ struct elf {
 	Elf *elf;
 	GElf_Ehdr ehdr;
 	int fd;
-	size_t mcount_rel_entsize;
 	bool changed;
+	bool mcount_r_addends;
 	char *name;
 	struct list_head sections;
 	DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS);
diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 9527924af56b..084bbc02de0c 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -368,22 +368,17 @@ static void fill_mcount_locs(GElf_Sxword r_offset, GElf_Addr **rbuf,
 }
 
 /* Overall supervision for Elf32 ET_REL file. */
-static int do_mcount(unsigned const reltype, size_t rela_size)
+static int do_mcount(unsigned const reltype)
 {
-	GElf_Sxword r_offset = 0;
-
 	struct section *sec, *mlocs, *mrels;
 	const char * const mc_name =  "__mcount_loc";
-
-	const unsigned int rel_entsize = lf->mcount_rel_entsize;
+	GElf_Sxword r_offset = 0;
 	int result = -1;
-	bool is_rela;
+	const bool is_rela = lf->mcount_r_addends;
 
 	if (find_section_by_name(lf, "__mcount_loc") != NULL)
 		return 0;
 
-	is_rela = (rela_size == rel_entsize);
-
 	/* add section: __mcount_loc */
 	mlocs = elf_create_section(lf, mc_name, sizeof(GElf_Addr), 0);
 	if (!mlocs)
@@ -562,7 +557,7 @@ static int do_file(char const *const fname)
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		loc_size = 4;
-		rc = do_mcount(reltype, sizeof(Elf32_Rela));
+		rc = do_mcount(reltype);
 		break;
 	case ELFCLASS64: {
 		if (lf->ehdr.e_ehsize != sizeof(Elf64_Ehdr)
@@ -580,7 +575,7 @@ static int do_file(char const *const fname)
 			is_fake_mcount = MIPS_is_fake_mcount;
 		}
 		loc_size = 8;
-		rc = do_mcount(reltype, sizeof(Elf64_Rela));
+		rc = do_mcount(reltype);
 		break;
 	}
 	}  /* end switch */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 50/51] objtool: mcount: Remove useless lookup
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (48 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 49/51] objtool: mcount: Remove relocation size check Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-18 20:38 ` [RFC][PATCH v5 51/51] objtool: mcount: Remove stale description Matt Helsley
  2020-06-23 14:12 ` [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

Since the relocation section's sh_info points back to the text
section it applies to and we already have that we can just pass
it in and greatly simplify find_section_sym_index().

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 39 +++++++++++++++------------------------
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index 084bbc02de0c..a74625aed09b 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -198,35 +198,27 @@ static const unsigned int missing_sym = (unsigned int)-1;
  *    Num:    Value  Size Type    Bind   Vis      Ndx Name
  *      2: 00000000     0 SECTION LOCAL  DEFAULT    1
  */
-static int find_section_sym_index(unsigned const txtndx,
-				char const *const txtname,
-				unsigned long *const recvalp,
-				unsigned int *sym_index)
+static int find_section_sym_index(const struct section * const txts,
+				  unsigned long *const recvalp,
+				  unsigned int *sym_index)
 {
 	struct symbol *sym;
-	struct section *txts = find_section_by_index(lf, txtndx);
-
-	if (!txts) {
-		fprintf(stderr, "Cannot find section %u: %s.\n",
-			txtndx, txtname);
-		return missing_sym;
-	}
 
 	list_for_each_entry(sym, &txts->symbol_list, list) {
 		/* avoid symbols with weak binding */
-		if ((sym->bind == STB_LOCAL) || (sym->bind == STB_GLOBAL)) {
-			/* function symbols on ARM have quirks, avoid them */
-			if (lf->ehdr.e_machine == EM_ARM
-			    && sym->type == STT_FUNC)
-				continue;
-
-			*recvalp = sym->sym.st_value;
-			*sym_index = sym->idx;
-			return 0;
-		}
+		if ((sym->bind != STB_LOCAL) && (sym->bind != STB_GLOBAL))
+			continue;
+
+		/* function symbols on ARM have quirks, avoid them */
+		if (lf->ehdr.e_machine == EM_ARM && sym->type == STT_FUNC)
+			continue;
+
+		*recvalp = sym->sym.st_value;
+		*sym_index = sym->idx;
+		return 0;
 	}
 	fprintf(stderr, "Cannot find symbol for section %u: %s.\n",
-		txtndx, txtname);
+		txts->idx, txts->name);
 	return missing_sym;
 }
 
@@ -414,8 +406,7 @@ static int do_mcount(unsigned const reltype)
 			unsigned long recval = 0;
 			unsigned int recsym;
 
-			if (find_section_sym_index(sec->sh.sh_info,
-						txts->name, &recval, &recsym))
+			if (find_section_sym_index(txts, &recval, &recsym))
 				goto out;
 
 			sift_rel_mcount(&r_offset, sec, mrels, mlocs,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC][PATCH v5 51/51] objtool: mcount: Remove stale description
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (49 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 50/51] objtool: mcount: Remove useless lookup Matt Helsley
@ 2020-06-18 20:38 ` Matt Helsley
  2020-06-23 14:12 ` [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-18 20:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal, Matt Helsley

The comments at the top no longer reflect how we process the ELF
contents. More helpful comments are inline with the code so we
don't need the top comments either.

Signed-off-by: Matt Helsley <mhelsley@vmware.com>
---
 tools/objtool/mcount.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/tools/objtool/mcount.c b/tools/objtool/mcount.c
index a74625aed09b..fa99bd2e9195 100644
--- a/tools/objtool/mcount.c
+++ b/tools/objtool/mcount.c
@@ -8,19 +8,6 @@
  *  Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  */
 
-/*
- * Strategy: alter the .o file in-place.
- *
- * Append a new STRTAB that has the new section names, followed by a new array
- * ElfXX_Shdr[] that has the new section headers, followed by the section
- * contents for __mcount_loc and its relocations.  The old shstrtab strings,
- * and the old ElfXX_Shdr[] array, remain as "garbage" (commonly, a couple
- * kilobytes.)  Subsequent processing by /bin/ld (or the kernel module loader)
- * will ignore the garbage regions, because they are not designated by the
- * new .e_shoff nor the new ElfXX_Shdr[].  [In order to remove the garbage,
- * then use "ld -r" to create a new file that omits the garbage.]
- */
-
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand
  2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
                   ` (50 preceding siblings ...)
  2020-06-18 20:38 ` [RFC][PATCH v5 51/51] objtool: mcount: Remove stale description Matt Helsley
@ 2020-06-23 14:12 ` Matt Helsley
  51 siblings, 0 replies; 55+ messages in thread
From: Matt Helsley @ 2020-06-23 14:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, Julien Thierry,
	Kamalesh Babulal

On Thu, Jun 18, 2020 at 01:37:46PM -0700, Matt Helsley wrote:
> recordmcount has its own ELF wrapper code and could utilize
> objtool's ELF code to more-portably handle architecture variations.
> This series makes recordmcount a subcommand of objtool. It very
> gradually converts recordmcount to become a subcommand of objtool and
> then reuses parts of objtool's ELF code.
> 
> recordmcount maps the file in and collects simple information it needs to
> append a section to the object file. The only part of the original file it
> modifies is the address of new section tables -- interestingly enough this
> resembles RCU in that we don't really trim the old tables so
> much as unlink them via a critical offset and then rely on
> future tooling, in this case, to drop the unused bits.
> 
> Much of the recordmcount ELF code is only reading and walking the data
> structures to collect the mcount locations it records in a separate
> area of memory. This means it's safe to mix access to the mapped
> file with access to the objtool-style linked data
> structures as we gradually convert it to using only the linked data
> structures. Once the old ELF code is no longer in use we can drop it
> and use objtool to take over the task of writing the results without
> using the RCU-like trick any more.
> 
> After that we greatly simplify the mcount subcommand by adding a
> few flags to the ELF reading code in objtool. Overall the series
> removes about 600 lines of recordmcount while adding little to
> objtool's ELF code.
> 
> Testing so far:
> 
> I've been using scripts to test cross compilation and execution of
> objtool, and mcount on objects built for x86, ppc64le, arm64, s390, and
> sparc.
> 
> 
> Applies on top of:
> 	objtool/core
> 
> 	Peter Zijlstra's "x86/entry: noinstr fixes" [2]

Just thought I'd note for anyone reviewing/playing with this series:

Peter's patches are now in objtool/core

> 	Sami Tolvanen's patch enabling support for more than 64k
> 	sections in recordmcount, already going upstream. [3]

Sami's patch is now in Linus' master branch

Cheers,
    -Matt

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC][PATCH v5 01/51] objtool: Factor out reasons to build objtool
  2020-06-18 20:37 ` [RFC][PATCH v5 01/51] objtool: Factor out reasons to build objtool Matt Helsley
@ 2020-06-24 15:37   ` Miroslav Benes
  0 siblings, 0 replies; 55+ messages in thread
From: Miroslav Benes @ 2020-06-24 15:37 UTC (permalink / raw)
  To: Matt Helsley
  Cc: linux-kernel, Josh Poimboeuf, Peter Zijlstra, Steven Rostedt,
	Julien Thierry, Kamalesh Babulal

Hi,

this is a nice improvement.

> diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
> index 7770edcda3a0..aa0c6d3d2d46 100644
> --- a/tools/objtool/Makefile
> +++ b/tools/objtool/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0
>  include ../scripts/Makefile.include
>  include ../scripts/Makefile.arch
> +include $(OUTPUT)/../../include/config/auto.conf
>  
>  # always use the host compiler
>  ifneq ($(LLVM),)
> @@ -47,8 +48,8 @@ CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
>  
>  AWK = awk
>  
> -SUBCMD_CHECK := n
> -SUBCMD_ORC := n
> +SUBCMD_CHECK := $(CONFIG_OBJTOOL_SUBCMD_CHECK)
> +SUBCMD_ORC := $(CONFIG_OBJTOOL_SUBCMD_ORC)
>  
>  ifeq ($(SRCARCH),x86)
>  	SUBCMD_CHECK := y

I guess you can remove ifeq for x86 in this patch, right? You do it later 
in 3/51, but it seems to belong here.

Miroslav

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC][PATCH v5 03/51] objtool: Make recordmcount into mcount subcmd
  2020-06-18 20:37 ` [RFC][PATCH v5 03/51] objtool: Make recordmcount into mcount subcmd Matt Helsley
@ 2020-06-25 10:39   ` Miroslav Benes
  0 siblings, 0 replies; 55+ messages in thread
From: Miroslav Benes @ 2020-06-25 10:39 UTC (permalink / raw)
  To: Matt Helsley
  Cc: linux-kernel, Josh Poimboeuf, Peter Zijlstra, Steven Rostedt,
	Julien Thierry, Kamalesh Babulal

On Thu, 18 Jun 2020, Matt Helsley wrote:

> Rather than a standalone executable merge recordmcount as a sub command
> of objtool. This is a small step towards cleaning up recordmcount and
> eventually sharing  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.

I'll try to leave only relevant parts for a question below...

>  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;

> +int cmd_mcount(int argc, const char **argv)
> +{
> +	argc--; argv++;
> +	if (argc <= 0)
> +		usage_with_options(mcount_usage, mcount_options);
> +
> +	if (!strncmp(argv[0], "record", 6)) {
> +		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;
> +}

> -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");
> -		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;

Do you expect that mcount subcmd would be called on more than one object 
file at a time? I don't see a reason for that with all the Makefile 
changes, but I may be missing something (Kbuild is a maze for me).

Because if not, I think it would be nice to make record_mcount() more 
similar to what we have for check(). After Julien's changes 
(20200608071203.4055-1-jthierry@redhat.com) at least. So that 
record_mcount() could accept struct objtool_file and work directly on 
that.

It would also impact several other patches in the series. For example, 
is there a need for a private 'struct elf *lf' in mcount.c?

Thanks
Miroslav

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2020-06-25 10:39 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-18 20:37 [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 01/51] objtool: Factor out reasons to build objtool Matt Helsley
2020-06-24 15:37   ` Miroslav Benes
2020-06-18 20:37 ` [RFC][PATCH v5 02/51] objtool: Prepare to merge recordmcount Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 03/51] objtool: Make recordmcount into mcount subcmd Matt Helsley
2020-06-25 10:39   ` Miroslav Benes
2020-06-18 20:37 ` [RFC][PATCH v5 04/51] objtool: recordmcount: Start using objtool's elf wrapper Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 05/51] objtool: recordmcount: Search for __mcount_loc before walking the sections Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 06/51] objtool: recordmcount: Convert do_func() relhdrs Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 07/51] objtool: mcount: Move nhdr into find_symtab() Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 08/51] objtool: mcount: Remove unused fname parameter Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 09/51] objtool: mcount: Use libelf for section header names Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 10/51] objtool: mcount: Walk objtool Elf structs in find_secsym_ndx Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 11/51] objtool: mcount: Use symbol structs to find mcount relocations Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 12/51] objtool: mcount: Walk relocation lists Matt Helsley
2020-06-18 20:37 ` [RFC][PATCH v5 13/51] objtool: mcount: Return symbol from mcountsym Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 14/51] objtool: mcount: Move get_mcountsym Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 15/51] objtool: mcount: Replace MIPS offset types Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 16/51] objtool: mcount: Move is_fake_mcount() Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 17/51] objtool: mcount: Stop using ehdr in find_section_sym_index Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 18/51] objtool: mcount: Move find_section_sym_index() Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 19/51] objtool: mcount: Restrict using ehdr in append_func() Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 20/51] objtool: mcount: Use objtool ELF to write Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 21/51] objtool: mcount: Move nop_mcount() Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 22/51] objtool: mcount: Move has_rel_mcount() and tot_relsize() Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 23/51] objtool: mcount: Move relocation entry size detection Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 24/51] objtool: mcount: Only keep ELF file size Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 25/51] objtool: mcount: Use ELF header from objtool Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 26/51] objtool: mcount: Remove unused file mapping Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 27/51] objtool: mcount: Reduce usage of _size wrapper Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 28/51] objtool: mcount: Move mcount_adjust out of wrapper Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 29/51] objtool: mcount: Pre-allocate new ELF sections Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 30/51] objtool: mcount: Generic location and relocation table types Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 31/51] objtool: mcount: Use objtool relocation section Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 32/51] objtool: mcount: Move sift_rel_mcount out of wrapper file Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 33/51] objtool: mcount: Remove wrapper for ELF relocation type Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 34/51] objtool: mcount: Remove wrapper double-include trick Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 35/51] objtool: mcount: Remove endian wrappers Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 36/51] objtool: mcount: Rename to mcount.c Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 37/51] objtool: mcount: Simplify mcount name matching Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 38/51] objtool: mcount: mcount symbol name simplification Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 39/51] objtool: mcount: Verify x86 instruction with memcmp() Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 40/51] objtool: mcount: const-ify ARM instruction patterns Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 41/51] objtool: mcount: Convert nop writes to elf_write_insn() Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 42/51] objtool: mcount: Move mcount symbol name testing Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 43/51] objtool: check: Use class to recognize kcov calls Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 44/51] objtool: mcount: Keep lists locations and relocations Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 45/51] objtool: mcount: Move mcount section test to objtool ELF Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 46/51] objtool: mcount: Flag mcount relocation sections Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 47/51] objtool: mcount: Merge section mcount flags Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 48/51] objtool: mcount: Eliminate first pass Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 49/51] objtool: mcount: Remove relocation size check Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 50/51] objtool: mcount: Remove useless lookup Matt Helsley
2020-06-18 20:38 ` [RFC][PATCH v5 51/51] objtool: mcount: Remove stale description Matt Helsley
2020-06-23 14:12 ` [RFC][PATCH v5 00/51] objtool: Make recordmcount a subcommand Matt Helsley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).