Hi Raphaƫl,

On 16/08/19 13:23, Raphael Gault wrote:
The jump destination and relocation offset used previously are only
reliable on x86_64 architecture. We abstract these computations by calling
arch-dependent implementations.

Signed-off-by: Raphael Gault <[email protected]>
---
  tools/objtool/arch.h            |  6 ++++++
  tools/objtool/arch/x86/decode.c | 11 +++++++++++
  tools/objtool/check.c           | 15 ++++++++++-----
  3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index ced3765c4f44..a9a50a25ca66 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -66,6 +66,8 @@ struct stack_op {
        struct op_src src;
  };
+struct instruction;
+
  void arch_initial_func_cfi_state(struct cfi_state *state);
int arch_decode_instruction(struct elf *elf, struct section *sec,
@@ -75,4 +77,8 @@ int arch_decode_instruction(struct elf *elf, struct section 
*sec,
bool arch_callee_saved_reg(unsigned char reg); +unsigned long arch_jump_destination(struct instruction *insn);
+
+unsigned long arch_dest_rela_offset(int addend);
+
  #endif /* _ARCH_H */
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 0567c47a91b1..fa33b3465722 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -11,6 +11,7 @@
  #include "lib/inat.c"
  #include "lib/insn.c"
+#include "../../check.h"
  #include "../../elf.h"
  #include "../../arch.h"
  #include "../../warn.h"
@@ -66,6 +67,11 @@ bool arch_callee_saved_reg(unsigned char reg)
        }
  }
+unsigned long arch_dest_rela_offset(int addend)
+{
+       return addend + 4;
+}
+
  int arch_decode_instruction(struct elf *elf, struct section *sec,
                            unsigned long offset, unsigned int maxlen,
                            unsigned int *len, enum insn_type *type,
@@ -497,3 +503,8 @@ void arch_initial_func_cfi_state(struct cfi_state *state)
        state->regs[16].base = CFI_CFA;
        state->regs[16].offset = -8;
  }
+
+unsigned long arch_jump_destination(struct instruction *insn)
+{
+       return insn->offset + insn->len + insn->immediate;
+}
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 176f2f084060..479fab46b656 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -563,7 +563,7 @@ static int add_jump_destinations(struct objtool_file *file)
                                               insn->len);
                if (!rela) {
                        dest_sec = insn->sec;
-                       dest_off = insn->offset + insn->len + insn->immediate;
+                       dest_off = arch_jump_destination(insn);
                } else if (rela->sym->type == STT_SECTION) {
                        dest_sec = rela->sym->sec;
                        dest_off = rela->addend + 4;
@@ -659,7 +659,7 @@ static int add_call_destinations(struct objtool_file *file)
                rela = find_rela_by_dest_range(insn->sec, insn->offset,
                                               insn->len);
                if (!rela) {
-                       dest_off = insn->offset + insn->len + insn->immediate;
+                       dest_off = arch_jump_destination(insn);
                        insn->call_dest = find_symbol_by_offset(insn->sec,
                                                                dest_off);
@@ -672,14 +672,19 @@ static int add_call_destinations(struct objtool_file *file)
                        }
} else if (rela->sym->type == STT_SECTION) {
+                       /*
+                        * the original x86_64 code adds 4 to the rela->addend
+                        * which is not needed on arm64 architecture.
+                        */

I'm not sure this is worth mentioning in generic code. You might include it in the commit message to justify the change.

+                       dest_off = arch_dest_rela_offset(rela->addend);
                        insn->call_dest = find_symbol_by_offset(rela->sym->sec,
-                                                               rela->addend+4);
+                                                               dest_off);
                        if (!insn->call_dest ||
                            insn->call_dest->type != STT_FUNC) {
-                               WARN_FUNC("can't find call dest symbol at 
%s+0x%x",
+                               WARN_FUNC("can't find call dest symbol at 
%s+0x%lx",
                                          insn->sec, insn->offset,
                                          rela->sym->sec->name,
-                                         rela->addend + 4);
+                                         dest_off);
                                return -1;
                        }
                } else


Otherwise, the change looks good to me.

Thanks,

--
Julien Thierry

Reply via email to