2020-08-25 13:12:09

by Julien Thierry

[permalink] [raw]
Subject: [PATCH v4 0/4] Remove dependency of check subcmd upon orc

Hi,

Matt Helsley's change[1] provided a base framework to opt-in/out
objtool subcommands at compile time. This makes it easier for
architectures to port objtool, one subcommand at a time.

Orc generation relies on the check operation implementation. However,
the way this is done causes the check implementation to depend on the
implementation of orc generation functions to call if orc generation is
requested. This means that in order to implement check subcmd, orc
subcmd also need to be implemented.

These patches aim at removing that dependency, having orc subcmd
being built on top of the check subcmd.


Changes since v3 [2]:
- Rebased on v5.9-rc1
- Renamed objtool_setup_file() to objtool_open_read()
- Fixed misplaced elf_write() when file->elf->changed is true
- Avoid additional allocation for orc data and compile out orc
definition when not needed instead

[1] https://www.spinics.net/lists/kernel/msg3510844.html
[2] https://lkml.org/lkml/2020/7/30/415

Cheers,

Julien

-->

Julien Thierry (4):
objtool: Move object file loading out of check
objtool: Move orc outside of check
objtool: orc: Skip setting orc_entry for non-text sections
objtool: check: Use orc definition only when needed

tools/objtool/Makefile | 4 +++
tools/objtool/arch.h | 2 ++
tools/objtool/builtin-check.c | 15 ++++++++++-
tools/objtool/builtin-orc.c | 27 +++++++++++++++++++-
tools/objtool/check.c | 47 ++++++-----------------------------
tools/objtool/check.h | 2 ++
tools/objtool/objtool.c | 29 +++++++++++++++++++++
tools/objtool/objtool.h | 4 ++-
tools/objtool/orc_gen.c | 3 +++
tools/objtool/weak.c | 4 +--
10 files changed, 92 insertions(+), 45 deletions(-)

--
2.21.3


2020-08-25 13:14:58

by Julien Thierry

[permalink] [raw]
Subject: [PATCH v4 3/4] objtool: orc: Skip setting orc_entry for non-text sections

Orc generation is only done for text sections, but some instructions
can be found in non-text sections (e.g. .discard.text sections).

Skip setting their orc sections since their whole sections will be
skipped for orc generation.

Reviewed-by: Miroslav Benes <[email protected]>
Signed-off-by: Julien Thierry <[email protected]>
---
tools/objtool/orc_gen.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index 968f55e6dd94..66fd56c33303 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -18,6 +18,9 @@ int create_orc(struct objtool_file *file)
struct cfi_reg *cfa = &insn->cfi.cfa;
struct cfi_reg *bp = &insn->cfi.regs[CFI_BP];

+ if (!insn->sec->text)
+ continue;
+
orc->end = insn->cfi.end;

if (cfa->base == CFI_UNDEFINED) {
--
2.21.3

2020-08-25 13:16:32

by Julien Thierry

[permalink] [raw]
Subject: [PATCH v4 2/4] objtool: Move orc outside of check

Now that the objtool_file can be obtained outside of the check function,
orc generation builtin no longer requires check to explicitly call its
orc related functions.

Signed-off-by: Julien Thierry <[email protected]>
---
tools/objtool/builtin-check.c | 10 +++++++++-
tools/objtool/builtin-orc.c | 21 ++++++++++++++++++++-
tools/objtool/check.c | 18 +-----------------
tools/objtool/objtool.h | 2 +-
tools/objtool/weak.c | 2 +-
5 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 0126ec3bb6c9..c6d199bfd0ae 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -42,6 +42,7 @@ int cmd_check(int argc, const char **argv)
{
const char *objname, *s;
struct objtool_file *file;
+ int ret;

argc = parse_options(argc, argv, check_options, check_usage, 0);

@@ -58,5 +59,12 @@ int cmd_check(int argc, const char **argv)
if (!file)
return 1;

- return check(file, false);
+ ret = check(file);
+ if (ret)
+ return ret;
+
+ if (file->elf->changed)
+ return elf_write(file->elf);
+
+ return 0;
}
diff --git a/tools/objtool/builtin-orc.c b/tools/objtool/builtin-orc.c
index 3979f275a775..53e316585a3c 100644
--- a/tools/objtool/builtin-orc.c
+++ b/tools/objtool/builtin-orc.c
@@ -32,6 +32,7 @@ int cmd_orc(int argc, const char **argv)

if (!strncmp(argv[0], "gen", 3)) {
struct objtool_file *file;
+ int ret;

argc = parse_options(argc, argv, check_options, orc_usage, 0);
if (argc != 1)
@@ -43,7 +44,25 @@ int cmd_orc(int argc, const char **argv)
if (!file)
return 1;

- return check(file, true);
+ ret = check(file);
+ if (ret)
+ return ret;
+
+ if (list_empty(&file->insn_list))
+ return 0;
+
+ ret = create_orc(file);
+ if (ret < 0)
+ return ret;
+
+ ret = create_orc_sections(file);
+ if (ret < 0)
+ return ret;
+
+ if (file->elf->changed)
+ return elf_write(file->elf);
+
+ return 0;
}

if (!strcmp(argv[0], "dump")) {
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index ef8e9300e1a3..6156bd9a687c 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2776,7 +2776,7 @@ static int validate_reachable_instructions(struct objtool_file *file)
return 0;
}

-int check(struct objtool_file *file, bool orc)
+int check(struct objtool_file *file)
{
int ret, warnings = 0;

@@ -2823,22 +2823,6 @@ int check(struct objtool_file *file, bool orc)
warnings += ret;
}

- if (orc) {
- ret = create_orc(file);
- if (ret < 0)
- goto out;
-
- ret = create_orc_sections(file);
- if (ret < 0)
- goto out;
- }
-
- if (file->elf->changed) {
- ret = elf_write(file->elf);
- if (ret < 0)
- goto out;
- }
-
out:
if (ret < 0) {
/*
diff --git a/tools/objtool/objtool.h b/tools/objtool/objtool.h
index 42b27c4ed683..46240098f08d 100644
--- a/tools/objtool/objtool.h
+++ b/tools/objtool/objtool.h
@@ -21,7 +21,7 @@ struct objtool_file {

struct objtool_file *objtool_open_read(const char *_objname);

-int check(struct objtool_file *file, bool orc);
+int check(struct objtool_file *file);
int orc_dump(const char *objname);
int create_orc(struct objtool_file *file);
int create_orc_sections(struct objtool_file *file);
diff --git a/tools/objtool/weak.c b/tools/objtool/weak.c
index 82698319f008..29180d599b08 100644
--- a/tools/objtool/weak.c
+++ b/tools/objtool/weak.c
@@ -17,7 +17,7 @@
return ENOSYS; \
})

-int __weak check(struct objtool_file *file, bool orc)
+int __weak check(struct objtool_file *file)
{
UNSUPPORTED("check subcommand");
}
--
2.21.3

2020-08-25 13:16:36

by Julien Thierry

[permalink] [raw]
Subject: [PATCH v4 4/4] objtool: check: Use orc definition only when needed

Implementation of ORC requires some definitions that are currently
provided by the target architecture headers. Do not depend on these
definitions when the orc subcommand is not implemented.

This avoid requiring arches with no orc implementation to provide dummy
orc definitions.

Signed-off-by: Julien Thierry <[email protected]>
---
tools/objtool/Makefile | 4 ++++
tools/objtool/arch.h | 2 ++
tools/objtool/check.h | 2 ++
3 files changed, 8 insertions(+)

diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 7770edcda3a0..33d1e3ca8efd 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -55,6 +55,10 @@ ifeq ($(SRCARCH),x86)
SUBCMD_ORC := y
endif

+ifeq ($(SUBCMD_ORC),y)
+ CFLAGS += -DINSN_USE_ORC
+endif
+
export SUBCMD_CHECK SUBCMD_ORC
export srctree OUTPUT CFLAGS SRCARCH AWK
include $(srctree)/tools/build/Makefile.include
diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index 2e2ce089b0e9..b18c5f61d42d 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -11,7 +11,9 @@
#include "objtool.h"
#include "cfi.h"

+#ifdef INSN_USE_ORC
#include <asm/orc_types.h>
+#endif

enum insn_type {
INSN_JUMP_CONDITIONAL,
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index 061aa96e15d3..0abdf8efdbc0 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -42,7 +42,9 @@ struct instruction {
struct symbol *func;
struct list_head stack_ops;
struct cfi_state cfi;
+#ifdef INSN_USE_ORC
struct orc_entry orc;
+#endif
};

struct instruction *find_insn(struct objtool_file *file,
--
2.21.3

2020-08-25 13:40:30

by Julien Thierry

[permalink] [raw]
Subject: [PATCH v4 1/4] objtool: Move object file loading out of check

Structure objtool_file can be used by different subcommands. In fact
it already is, by check and orc.

Provide a function that allows to initialize objtool_file, that builtin
can call, without relying on check to do the correct setup for them and
explicitly hand the objtool_file to them.

Reviewed-by: Miroslav Benes <[email protected]>
Signed-off-by: Julien Thierry <[email protected]>
---
tools/objtool/builtin-check.c | 7 ++++++-
tools/objtool/builtin-orc.c | 8 ++++++-
tools/objtool/check.c | 39 +++++++++++------------------------
tools/objtool/objtool.c | 29 ++++++++++++++++++++++++++
tools/objtool/objtool.h | 4 +++-
tools/objtool/weak.c | 4 +---
6 files changed, 58 insertions(+), 33 deletions(-)

diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 7a44174967b5..0126ec3bb6c9 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -41,6 +41,7 @@ const struct option check_options[] = {
int cmd_check(int argc, const char **argv)
{
const char *objname, *s;
+ struct objtool_file *file;

argc = parse_options(argc, argv, check_options, check_usage, 0);

@@ -53,5 +54,9 @@ int cmd_check(int argc, const char **argv)
if (s && !s[9])
vmlinux = true;

- return check(objname, false);
+ file = objtool_open_read(objname);
+ if (!file)
+ return 1;
+
+ return check(file, false);
}
diff --git a/tools/objtool/builtin-orc.c b/tools/objtool/builtin-orc.c
index b1dfe2007962..3979f275a775 100644
--- a/tools/objtool/builtin-orc.c
+++ b/tools/objtool/builtin-orc.c
@@ -31,13 +31,19 @@ int cmd_orc(int argc, const char **argv)
usage_with_options(orc_usage, check_options);

if (!strncmp(argv[0], "gen", 3)) {
+ struct objtool_file *file;
+
argc = parse_options(argc, argv, check_options, orc_usage, 0);
if (argc != 1)
usage_with_options(orc_usage, check_options);

objname = argv[0];

- return check(objname, true);
+ file = objtool_open_read(objname);
+ if (!file)
+ return 1;
+
+ return check(file, true);
}

if (!strcmp(argv[0], "dump")) {
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index e034a8f24f46..ef8e9300e1a3 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -27,7 +27,6 @@ struct alternative {
bool skip_orig;
};

-const char *objname;
struct cfi_init_state initial_func_cfi;

struct instruction *find_insn(struct objtool_file *file,
@@ -2777,36 +2776,22 @@ static int validate_reachable_instructions(struct objtool_file *file)
return 0;
}

-static struct objtool_file file;
-
-int check(const char *_objname, bool orc)
+int check(struct objtool_file *file, bool orc)
{
int ret, warnings = 0;

- objname = _objname;
-
- file.elf = elf_open_read(objname, O_RDWR);
- if (!file.elf)
- return 1;
-
- INIT_LIST_HEAD(&file.insn_list);
- hash_init(file.insn_hash);
- file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
- file.ignore_unreachables = no_unreachable;
- file.hints = false;
-
arch_initial_func_cfi_state(&initial_func_cfi);

- ret = decode_sections(&file);
+ ret = decode_sections(file);
if (ret < 0)
goto out;
warnings += ret;

- if (list_empty(&file.insn_list))
+ if (list_empty(&file->insn_list))
goto out;

if (vmlinux && !validate_dup) {
- ret = validate_vmlinux_functions(&file);
+ ret = validate_vmlinux_functions(file);
if (ret < 0)
goto out;

@@ -2815,41 +2800,41 @@ int check(const char *_objname, bool orc)
}

if (retpoline) {
- ret = validate_retpoline(&file);
+ ret = validate_retpoline(file);
if (ret < 0)
return ret;
warnings += ret;
}

- ret = validate_functions(&file);
+ ret = validate_functions(file);
if (ret < 0)
goto out;
warnings += ret;

- ret = validate_unwind_hints(&file, NULL);
+ ret = validate_unwind_hints(file, NULL);
if (ret < 0)
goto out;
warnings += ret;

if (!warnings) {
- ret = validate_reachable_instructions(&file);
+ ret = validate_reachable_instructions(file);
if (ret < 0)
goto out;
warnings += ret;
}

if (orc) {
- ret = create_orc(&file);
+ ret = create_orc(file);
if (ret < 0)
goto out;

- ret = create_orc_sections(&file);
+ ret = create_orc_sections(file);
if (ret < 0)
goto out;
}

- if (file.elf->changed) {
- ret = elf_write(file.elf);
+ if (file->elf->changed) {
+ ret = elf_write(file->elf);
if (ret < 0)
goto out;
}
diff --git a/tools/objtool/objtool.c b/tools/objtool/objtool.c
index 58fdda510653..84e89e79be9b 100644
--- a/tools/objtool/objtool.c
+++ b/tools/objtool/objtool.c
@@ -22,6 +22,8 @@
#include <linux/kernel.h>

#include "builtin.h"
+#include "objtool.h"
+#include "warn.h"

struct cmd_struct {
const char *name;
@@ -39,6 +41,33 @@ static struct cmd_struct objtool_cmds[] = {

bool help;

+const char *objname;
+static struct objtool_file file;
+
+struct objtool_file *objtool_open_read(const char *_objname)
+{
+ if (objname) {
+ if (strcmp(objname, _objname)) {
+ WARN("won't handle more than one file at a time");
+ return NULL;
+ }
+ return &file;
+ }
+ objname = _objname;
+
+ file.elf = elf_open_read(objname, O_RDWR);
+ if (!file.elf)
+ return NULL;
+
+ INIT_LIST_HEAD(&file.insn_list);
+ hash_init(file.insn_hash);
+ file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
+ file.ignore_unreachables = no_unreachable;
+ file.hints = false;
+
+ return &file;
+}
+
static void cmd_usage(void)
{
unsigned int i, longest = 0;
diff --git a/tools/objtool/objtool.h b/tools/objtool/objtool.h
index 528028a66816..42b27c4ed683 100644
--- a/tools/objtool/objtool.h
+++ b/tools/objtool/objtool.h
@@ -19,7 +19,9 @@ struct objtool_file {
bool ignore_unreachables, c_file, hints, rodata;
};

-int check(const char *objname, bool orc);
+struct objtool_file *objtool_open_read(const char *_objname);
+
+int check(struct objtool_file *file, bool orc);
int orc_dump(const char *objname);
int create_orc(struct objtool_file *file);
int create_orc_sections(struct objtool_file *file);
diff --git a/tools/objtool/weak.c b/tools/objtool/weak.c
index 942ea5e8ac36..82698319f008 100644
--- a/tools/objtool/weak.c
+++ b/tools/objtool/weak.c
@@ -17,9 +17,7 @@
return ENOSYS; \
})

-const char __weak *objname;
-
-int __weak check(const char *_objname, bool orc)
+int __weak check(struct objtool_file *file, bool orc)
{
UNSUPPORTED("check subcommand");
}
--
2.21.3

2020-08-28 09:12:59

by Miroslav Benes

[permalink] [raw]
Subject: Re: [PATCH v4 2/4] objtool: Move orc outside of check

On Tue, 25 Aug 2020, Julien Thierry wrote:

> Now that the objtool_file can be obtained outside of the check function,
> orc generation builtin no longer requires check to explicitly call its
> orc related functions.
>
> Signed-off-by: Julien Thierry <[email protected]>

Reviewed-by: Miroslav Benes <[email protected]>

M

2020-08-28 09:26:04

by Miroslav Benes

[permalink] [raw]
Subject: Re: [PATCH v4 4/4] objtool: check: Use orc definition only when needed

On Tue, 25 Aug 2020, Julien Thierry wrote:

> Implementation of ORC requires some definitions that are currently
> provided by the target architecture headers. Do not depend on these
> definitions when the orc subcommand is not implemented.
>
> This avoid requiring arches with no orc implementation to provide dummy
> orc definitions.
>
> Signed-off-by: Julien Thierry <[email protected]>

This is definitely simpler than what v3 had.

Reviewed-by: Miroslav Benes <[email protected]>

M

2020-09-01 16:08:30

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: [PATCH v4 0/4] Remove dependency of check subcmd upon orc

On Tue, Aug 25, 2020 at 01:47:38PM +0100, Julien Thierry wrote:
> Hi,
>
> Matt Helsley's change[1] provided a base framework to opt-in/out
> objtool subcommands at compile time. This makes it easier for
> architectures to port objtool, one subcommand at a time.
>
> Orc generation relies on the check operation implementation. However,
> the way this is done causes the check implementation to depend on the
> implementation of orc generation functions to call if orc generation is
> requested. This means that in order to implement check subcmd, orc
> subcmd also need to be implemented.
>
> These patches aim at removing that dependency, having orc subcmd
> being built on top of the check subcmd.
>
>
> Changes since v3 [2]:
> - Rebased on v5.9-rc1
> - Renamed objtool_setup_file() to objtool_open_read()
> - Fixed misplaced elf_write() when file->elf->changed is true
> - Avoid additional allocation for orc data and compile out orc
> definition when not needed instead
>
> [1] https://www.spinics.net/lists/kernel/msg3510844.html
> [2] https://lkml.org/lkml/2020/7/30/415

Thanks, I grabbed the patches and will work with Peter to get them
merged.

--
Josh