lkml.org 
[lkml]   [2022]   [Jun]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v6 07/33] objtool: arm64: Decode LDR instructions
Date
Load literal instructions can generate constants inside code sections.
Record the locations of the constants in order to be able to remove
their corresponding "struct instruction".

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
tools/objtool/arch/arm64/decode.c | 88 +++++++++++++++++++++++++++-
tools/objtool/arch/x86/decode.c | 5 ++
tools/objtool/check.c | 3 +
tools/objtool/include/objtool/arch.h | 2 +
4 files changed, 97 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index 8ce9d91ff0db..30300d05c8f3 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -31,6 +31,64 @@ static unsigned long sign_extend(unsigned long x, int nbits)
return ((~0UL + (sign_bit ^ 1)) << nbits) | x;
}

+struct insn_loc {
+ const struct section *sec;
+ unsigned long offset;
+ struct hlist_node hnode;
+};
+
+DEFINE_HASHTABLE(invalid_insns, 16);
+
+static int record_invalid_insn(const struct section *sec,
+ unsigned long offset)
+{
+ struct insn_loc *loc;
+ struct hlist_head *l;
+
+ l = &invalid_insns[hash_min(offset, HASH_BITS(invalid_insns))];
+ if (!hlist_empty(l)) {
+ loc = hlist_entry(l->first, struct insn_loc, hnode);
+ return 0;
+ }
+
+ loc = malloc(sizeof(*loc));
+ if (!loc) {
+ WARN("malloc failed");
+ return -1;
+ }
+
+ loc->sec = sec;
+ loc->offset = offset;
+
+ hash_add(invalid_insns, &loc->hnode, loc->offset);
+
+ return 0;
+}
+
+int arch_post_process_instructions(struct objtool_file *file)
+{
+ struct hlist_node *tmp;
+ struct insn_loc *loc;
+ unsigned int bkt;
+ int res = 0;
+
+ hash_for_each_safe(invalid_insns, bkt, tmp, loc, hnode) {
+ struct instruction *insn;
+
+ insn = find_insn(file, (struct section *) loc->sec, loc->offset);
+ if (insn) {
+ list_del(&insn->list);
+ hash_del(&insn->hash);
+ free(insn);
+ }
+
+ hash_del(&loc->hnode);
+ free(loc);
+ }
+
+ return res;
+}
+
bool arch_callee_saved_reg(unsigned char reg)
{
switch (reg) {
@@ -351,7 +409,35 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
break;
case AARCH64_INSN_CLS_LDST:
{
- return decode_load_store(insn, immediate, ops_list);
+ int ret;
+
+ ret = decode_load_store(insn, immediate, ops_list);
+ if (ret <= 0)
+ return ret;
+
+ /*
+ * For LDR ops, assembler can generate the data to be
+ * loaded in the code section
+ * Record and remove these data because they
+ * are never excuted
+ */
+ if (aarch64_insn_is_ldr_lit(insn)) {
+ long pc_offset;
+
+ pc_offset = insn & GENMASK(23, 5);
+ /* Sign extend and multiply by 4 */
+ pc_offset = (pc_offset << (64 - 23));
+ pc_offset = ((pc_offset >> (64 - 23)) >> 5) << 2;
+
+ ret = record_invalid_insn(sec, offset + pc_offset);
+
+ /* 64-bit literal */
+ if (insn & BIT(30))
+ ret = record_invalid_insn(sec, offset + pc_offset + 4);
+
+ return ret;
+ }
+ break;
}
default:
break;
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 8b990a52aada..081b5e72f8df 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -693,6 +693,11 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
return 0;
}

+int arch_post_process_instructions(struct objtool_file *file)
+{
+ return 0;
+}
+
void arch_initial_func_cfi_state(struct cfi_init_state *state)
{
int i;
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 35d0a1bc4279..c0feb6db7c6d 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -439,6 +439,9 @@ static int decode_instructions(struct objtool_file *file)
if (opts.stats)
printf("nr_insns: %lu\n", nr_insns);

+ if (arch_post_process_instructions(file))
+ return -1;
+
return 0;

err:
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
index 9b19cc304195..651262af2655 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -77,6 +77,8 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
unsigned long *immediate,
struct list_head *ops_list);

+int arch_post_process_instructions(struct objtool_file *file);
+
bool arch_callee_saved_reg(unsigned char reg);

unsigned long arch_jump_destination(struct instruction *insn);
--
2.17.1
\
 
 \ /
  Last update: 2022-06-23 03:53    [W:0.149 / U:0.632 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site