The set of registers that can be included in an unwind hint and their
encoding will depend on the architecture. Have arch specific code to
decode that register.

Signed-off-by: Julien Thierry <[email protected]>
---
 tools/objtool/arch.h            |  2 ++
 tools/objtool/arch/x86/decode.c | 37 +++++++++++++++++++++++++++++++++
 tools/objtool/check.c           | 27 +-----------------------
 3 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index b18c5f61d42d..4a84c3081b8e 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -88,4 +88,6 @@ unsigned long arch_dest_reloc_offset(int addend);
 
 const char *arch_nop_insn(int len);
 
+int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg);
+
 #endif /* _ARCH_H */
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 1967370440b3..cde9c36e40ae 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -15,6 +15,7 @@
 #include "../../elf.h"
 #include "../../arch.h"
 #include "../../warn.h"
+#include <asm/orc_types.h>
 
 static unsigned char op_to_cfi_reg[][2] = {
        {CFI_AX, CFI_R8},
@@ -583,3 +584,39 @@ const char *arch_nop_insn(int len)
 
        return nops[len-1];
 }
+
+int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg)
+{
+       struct cfi_reg *cfa = &insn->cfi.cfa;
+
+       switch (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:
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 60e23c8f93e0..8630a2d5e68c 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1261,32 +1261,7 @@ static int read_unwind_hints(struct objtool_file *file)
 
                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:
+               if (arch_decode_hint_reg(insn, hint->sp_reg)) {
                        WARN_FUNC("unsupported unwind_hint sp base reg %d",
                                  insn->sec, insn->offset, hint->sp_reg);
                        return -1;
-- 
2.21.3

Reply via email to