[RFC v5 07/57] objtool: orc: Refactor ORC API for other architectures to implement.
From: Julien Thierry
Date: Thu Jan 09 2020 - 11:04:07 EST
From: Raphael Gault <raphael.gault@xxxxxxx>
The ORC unwinder is only supported on x86 at the moment and should thus be
in the x86 architecture code. In order not to break the whole structure in
case another architecture decides to support the ORC unwinder via objtool,
move the implementation be done in the architecture dependent code.
Signed-off-by: Raphael Gault <raphael.gault@xxxxxxx>
[J.T. Rebase on orc name changes,
Move arch_orc_read_unwind_hints() to orc.h,
Reword commit message to use imperative language]
Signed-off-by: Julien Thierry <jthierry@xxxxxxxxxx>
---
tools/objtool/Build | 2 -
tools/objtool/arch/x86/Build | 2 +
tools/objtool/{ => arch/x86}/orc_dump.c | 4 +-
tools/objtool/{ => arch/x86}/orc_gen.c | 104 ++++++++++++++++++++++--
tools/objtool/check.c | 99 +---------------------
tools/objtool/orc.h | 5 +-
6 files changed, 109 insertions(+), 107 deletions(-)
rename tools/objtool/{ => arch/x86}/orc_dump.c (98%)
rename tools/objtool/{ => arch/x86}/orc_gen.c (66%)
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 8dc4f0848362..d069d26d97fa 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -2,8 +2,6 @@ objtool-y += arch/$(SRCARCH)/
objtool-y += builtin-check.o
objtool-y += builtin-orc.o
objtool-y += check.o
-objtool-y += orc_gen.o
-objtool-y += orc_dump.o
objtool-y += elf.o
objtool-y += special.o
objtool-y += objtool.o
diff --git a/tools/objtool/arch/x86/Build b/tools/objtool/arch/x86/Build
index 7c5004008e97..e43fd6fa0ee1 100644
--- a/tools/objtool/arch/x86/Build
+++ b/tools/objtool/arch/x86/Build
@@ -1,4 +1,6 @@
objtool-y += decode.o
+objtool-y += orc_dump.o
+objtool-y += orc_gen.o
inat_tables_script = ../arch/x86/tools/gen-insn-attr-x86.awk
inat_tables_maps = ../arch/x86/lib/x86-opcode-map.txt
diff --git a/tools/objtool/orc_dump.c b/tools/objtool/arch/x86/orc_dump.c
similarity index 98%
rename from tools/objtool/orc_dump.c
rename to tools/objtool/arch/x86/orc_dump.c
index 13ccf775a83a..cfe8f96bdd68 100644
--- a/tools/objtool/orc_dump.c
+++ b/tools/objtool/arch/x86/orc_dump.c
@@ -4,8 +4,8 @@
*/
#include <unistd.h>
-#include "orc.h"
-#include "warn.h"
+#include "../../orc.h"
+#include "../../warn.h"
static const char *reg_name(unsigned int reg)
{
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/arch/x86/orc_gen.c
similarity index 66%
rename from tools/objtool/orc_gen.c
rename to tools/objtool/arch/x86/orc_gen.c
index 29bee7bd212a..e8be41a1bf94 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/arch/x86/orc_gen.c
@@ -6,11 +6,11 @@
#include <stdlib.h>
#include <string.h>
-#include "orc.h"
-#include "check.h"
-#include "warn.h"
+#include "../../orc.h"
+#include "../../check.h"
+#include "../../warn.h"
-int orc_init(struct objtool_file *file)
+int arch_orc_init(struct objtool_file *file)
{
struct instruction *insn;
@@ -116,7 +116,7 @@ static int orc_create_entry(struct section *u_sec, struct section *ip_relasec,
return 0;
}
-int orc_create_sections(struct objtool_file *file)
+int arch_orc_create_sections(struct objtool_file *file)
{
struct instruction *insn, *prev_insn;
struct section *sec, *u_sec, *ip_relasec;
@@ -209,3 +209,97 @@ int orc_create_sections(struct objtool_file *file)
return 0;
}
+
+int arch_orc_read_unwind_hints(struct objtool_file *file)
+{
+ struct section *sec, *relasec;
+ struct rela *rela;
+ struct unwind_hint *hint;
+ struct instruction *insn;
+ struct cfi_reg *cfa;
+ int i;
+
+ sec = find_section_by_name(file->elf, ".discard.unwind_hints");
+ if (!sec)
+ return 0;
+
+ relasec = sec->rela;
+ if (!relasec) {
+ WARN("missing .rela.discard.unwind_hints section");
+ return -1;
+ }
+
+ if (sec->len % sizeof(struct unwind_hint)) {
+ WARN("struct unwind_hint size mismatch");
+ return -1;
+ }
+
+ file->hints = true;
+
+ for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
+ hint = (struct unwind_hint *)sec->data->d_buf + i;
+
+ rela = find_rela_by_dest(sec, i * sizeof(*hint));
+ if (!rela) {
+ WARN("can't find rela for unwind_hints[%d]", i);
+ return -1;
+ }
+
+ insn = find_insn(file, rela->sym->sec, rela->addend);
+ if (!insn) {
+ WARN("can't find insn for unwind_hints[%d]", i);
+ return -1;
+ }
+
+ cfa = &insn->state.cfa;
+
+ if (hint->type == UNWIND_HINT_TYPE_SAVE) {
+ insn->save = true;
+ continue;
+
+ } else if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
+ insn->restore = true;
+ insn->hint = true;
+ continue;
+ }
+
+ insn->hint = true;
+
+ switch (hint->sp_reg) {
+ case ORC_REG_UNDEFINED:
+ cfa->base = CFI_UNDEFINED;
+ break;
+ case ORC_REG_SP:
+ cfa->base = CFI_SP;
+ break;
+ case ORC_REG_BP:
+ cfa->base = CFI_BP;
+ break;
+ case ORC_REG_SP_INDIRECT:
+ cfa->base = CFI_SP_INDIRECT;
+ break;
+ case ORC_REG_R10:
+ cfa->base = CFI_R10;
+ break;
+ case ORC_REG_R13:
+ cfa->base = CFI_R13;
+ break;
+ case ORC_REG_DI:
+ cfa->base = CFI_DI;
+ break;
+ case ORC_REG_DX:
+ cfa->base = CFI_DX;
+ break;
+ default:
+ WARN_FUNC("unsupported unwind_hint sp base reg %d",
+ insn->sec, insn->offset, hint->sp_reg);
+ return -1;
+ }
+
+ cfa->offset = hint->sp_offset;
+ insn->state.type = hint->type;
+ insn->state.end = hint->end;
+ }
+
+ return 0;
+}
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index dd155095251c..2c5ccf61510a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1167,99 +1167,6 @@ static int add_jump_table_alts(struct objtool_file *file)
return 0;
}
-static int read_unwind_hints(struct objtool_file *file)
-{
- struct section *sec, *relasec;
- struct rela *rela;
- struct unwind_hint *hint;
- struct instruction *insn;
- struct cfi_reg *cfa;
- int i;
-
- sec = find_section_by_name(file->elf, ".discard.unwind_hints");
- if (!sec)
- return 0;
-
- relasec = sec->rela;
- if (!relasec) {
- WARN("missing .rela.discard.unwind_hints section");
- return -1;
- }
-
- if (sec->len % sizeof(struct unwind_hint)) {
- WARN("struct unwind_hint size mismatch");
- return -1;
- }
-
- file->hints = true;
-
- for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
- hint = (struct unwind_hint *)sec->data->d_buf + i;
-
- rela = find_rela_by_dest(sec, i * sizeof(*hint));
- if (!rela) {
- WARN("can't find rela for unwind_hints[%d]", i);
- return -1;
- }
-
- insn = find_insn(file, rela->sym->sec, rela->addend);
- if (!insn) {
- WARN("can't find insn for unwind_hints[%d]", i);
- return -1;
- }
-
- cfa = &insn->state.cfa;
-
- if (hint->type == UNWIND_HINT_TYPE_SAVE) {
- insn->save = true;
- continue;
-
- } else if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
- insn->restore = true;
- insn->hint = true;
- continue;
- }
-
- insn->hint = true;
-
- switch (hint->sp_reg) {
- case ORC_REG_UNDEFINED:
- cfa->base = CFI_UNDEFINED;
- break;
- case ORC_REG_SP:
- cfa->base = CFI_SP;
- break;
- case ORC_REG_BP:
- cfa->base = CFI_BP;
- break;
- case ORC_REG_SP_INDIRECT:
- cfa->base = CFI_SP_INDIRECT;
- break;
- case ORC_REG_R10:
- cfa->base = CFI_R10;
- break;
- case ORC_REG_R13:
- cfa->base = CFI_R13;
- break;
- case ORC_REG_DI:
- cfa->base = CFI_DI;
- break;
- case ORC_REG_DX:
- cfa->base = CFI_DX;
- break;
- default:
- WARN_FUNC("unsupported unwind_hint sp base reg %d",
- insn->sec, insn->offset, hint->sp_reg);
- return -1;
- }
-
- cfa->offset = hint->sp_offset;
- insn->state.type = hint->type;
- insn->state.end = hint->end;
- }
-
- return 0;
-}
static int read_retpoline_hints(struct objtool_file *file)
{
@@ -1359,7 +1266,7 @@ static int decode_sections(struct objtool_file *file)
if (ret)
return ret;
- ret = read_unwind_hints(file);
+ ret = arch_orc_read_unwind_hints(file);
if (ret)
return ret;
@@ -2481,11 +2388,11 @@ int check(const char *_objname, bool orc)
}
if (orc) {
- ret = orc_init(&file);
+ ret = arch_orc_init(&file);
if (ret < 0)
goto out;
- ret = orc_create_sections(&file);
+ ret = arch_orc_create_sections(&file);
if (ret < 0)
goto out;
diff --git a/tools/objtool/orc.h b/tools/objtool/orc.h
index cd44417487e4..ffda072cf4ad 100644
--- a/tools/objtool/orc.h
+++ b/tools/objtool/orc.h
@@ -10,8 +10,9 @@
struct objtool_file;
-int orc_init(struct objtool_file *file);
-int orc_create_sections(struct objtool_file *file);
+int arch_orc_init(struct objtool_file *file);
+int arch_orc_create_sections(struct objtool_file *file);
+int arch_orc_read_unwind_hints(struct objtool_file *file);
int orc_dump(const char *objname);
--
2.21.0