diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index 0336efecb9d9..829d6d73aec6 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -68,6 +68,7 @@ struct stack_op {
 	struct list_head list;
 };
 
+struct objtool_file;
 struct instruction;
 
 void arch_initial_func_cfi_state(struct cfi_state *state);
@@ -78,6 +79,8 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
 			    unsigned long *immediate,
 			    struct list_head *ops_list);
 
+int arch_post_process_file(struct objtool_file *file);
+
 bool arch_callee_saved_reg(unsigned char reg);
 
 unsigned long arch_jump_destination(struct instruction *insn);
diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index bc4c62401012..aed8ba0f812e 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -18,6 +18,47 @@ static bool stack_related_reg(int reg)
 	return reg == CFI_SP || reg == CFI_BP;
 }
 
+struct insn_loc {
+	struct section *sec;
+	unsigned long offset;
+	struct hlist_node hnode;
+};
+
+DEFINE_HASHTABLE(text_constants, 16);
+
+int arch_post_process_file(struct objtool_file *file)
+{
+	struct hlist_node *tmp;
+	struct insn_loc *loc;
+	unsigned int bkt;
+	int res = 0;
+
+	/*
+	 * Data placed in code sections could turn out to be a valid aarch64
+	 * opcode.
+	 * If that is the case, change the insn type to invalid as it should
+	 * never be reached by the execution flow.
+	 */
+	hash_for_each_safe(text_constants, bkt, tmp, loc, hnode) {
+		struct instruction *insn;
+
+		insn = find_insn(file, loc->sec, loc->offset);
+		if (insn) {
+			insn->type = INSN_INVALID;
+		} else {
+			WARN("failed to find constant at %s+0x%lx",
+			     loc->sec->name, loc->offset);
+			res = -1;
+		}
+		hash_del(&loc->hnode);
+		free(loc);
+	}
+
+	return res;
+}
+
+static struct insn_loc current_location;
+
 bool arch_callee_saved_reg(unsigned char reg)
 {
 	switch (reg) {
@@ -127,6 +168,8 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
 	//retrieve instruction (from sec->data->offset)
 	insn = *(u32 *)(sec->data->d_buf + offset);
 
+	current_location.sec = sec;
+	current_location.offset = offset;
 	//dispatch according to encoding classes
 	decode_fun = aarch64_insn_class_decode_table[INSN_CLASS(insn)];
 	if (decode_fun)
@@ -136,6 +179,9 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
 
 	if (res)
 		WARN_FUNC("Unsupported instruction", sec, offset);
+
+	memset(&current_location, 0, sizeof(current_location));
+
 	return res;
 }
 
@@ -845,6 +891,11 @@ static struct aarch64_insn_decoder ld_st_decoder[] = {
 		.value = 0b000101000000000,
 		.decode_func = arm_decode_ldapr_stlr_unsc_imm,
 	},
+	{
+		.mask = 0b001101000000000,
+		.value = 0b000100000000000,
+		.decode_func = arm_decode_ld_regs_literal,
+	},
 	{
 		.mask = 0b001101100000000,
 		.value = 0b001000000000000,
@@ -1350,6 +1401,43 @@ int arm_decode_ld_st_exclusive(u32 instr, enum insn_type *type,
 #undef LDLAR_64
 #undef LDAR_64
 
+int arm_decode_ld_regs_literal(u32 instr, enum insn_type *type,
+			       unsigned long *immediate,
+			       struct list_head *ops_list)
+{
+	unsigned char opc = 0, V = 0;
+	long pc_offset;
+	struct insn_loc *loc;
+
+	opc = (instr >> 30) & ONES(2);
+	V = EXTRACT_BIT(instr, 26);
+
+	if (((opc << 1) | V) == 0x7)
+		return arm_decode_unknown(instr, type, immediate, ops_list);
+
+	pc_offset = instr & GENMASK(23, 5);
+
+	/* Sign extend and multiply by 4 */
+	pc_offset = (pc_offset << (64 - 23));
+	pc_offset = ((pc_offset >> (64 - 23)) >> 5) << 2;
+
+	loc = malloc(sizeof(*loc));
+	loc->sec = current_location.sec;
+	loc->offset = current_location.offset + pc_offset;
+	hash_add(text_constants, &loc->hnode, loc->offset);
+
+	/* 64-bit literal */
+	if (opc & 1) {
+		loc = malloc(sizeof(*loc));
+		loc->sec = current_location.sec;
+		loc->offset = current_location.offset + pc_offset + 4;
+		hash_add(text_constants, &loc->hnode, loc->offset);
+	}
+
+	*type = INSN_OTHER;
+	return 0;
+}
+
 int arm_decode_ld_st_regs_unsc_imm(u32 instr, enum insn_type *type,
 				   unsigned long *immediate,
 				   struct list_head *ops_list)
diff --git a/tools/objtool/arch/arm64/include/insn_decode.h b/tools/objtool/arch/arm64/include/insn_decode.h
index e6a62691b487..3ec4c69547ac 100644
--- a/tools/objtool/arch/arm64/include/insn_decode.h
+++ b/tools/objtool/arch/arm64/include/insn_decode.h
@@ -112,6 +112,9 @@ int arm_decode_ld_st_mem_tags(u32 instr, enum insn_type *type,
 int arm_decode_ldapr_stlr_unsc_imm(u32 instr, enum insn_type *type,
 				   unsigned long *immediate,
 				   struct list_head *ops_list);
+int arm_decode_ld_regs_literal(u32 instr, enum insn_type *type,
+			       unsigned long *immediate,
+			       struct list_head *ops_list);
 int arm_decode_ld_st_noalloc_pair_off(u32 instr, enum insn_type *type,
 				      unsigned long *immediate,
 				      struct list_head *ops_list);
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 650e5d021486..57a5f817a63c 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -497,6 +497,11 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
 	return 0;
 }
 
+int arch_post_process_file(struct objtool_file *file)
+{
+	return 0;
+}
+
 void arch_initial_func_cfi_state(struct cfi_state *state)
 {
 	int i;
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 52a8e64e15ca..e0c6bda261c8 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -279,6 +279,9 @@ static int decode_instructions(struct objtool_file *file)
 		}
 	}
 
+	if (arch_post_process_file(file))
+		return -1;
+
 	return 0;
 
 err:
