|
Michel Lind |
de7e84 |
From 1a3af2aaee85bd475bda44993b3e8dc1335497d5 Mon Sep 17 00:00:00 2001
|
|
Michel Lind |
de7e84 |
From: Joe Lawrence <joe.lawrence@redhat.com>
|
|
Michel Lind |
de7e84 |
Date: Thu, 10 Oct 2024 16:58:58 -0400
|
|
Michel Lind |
de7e84 |
Subject: [PATCH 101/118] aarch64: create-diff-object implementation
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
TODO
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>
|
|
Michel Lind |
de7e84 |
Signed-off-by: Pete Swain <swine@google.com>
|
|
Michel Lind |
de7e84 |
Signed-off-by: Mihails Strasuns <mstrasun@amazon.com>
|
|
Michel Lind |
de7e84 |
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
|
|
Michel Lind |
de7e84 |
---
|
|
Michel Lind |
de7e84 |
kpatch-build/create-diff-object.c | 104 ++++++++++++++++++++++++++----
|
|
Michel Lind |
de7e84 |
kpatch-build/kpatch-elf.c | 8 +++
|
|
Michel Lind |
de7e84 |
kpatch-build/kpatch-elf.h | 1 +
|
|
Michel Lind |
de7e84 |
3 files changed, 101 insertions(+), 12 deletions(-)
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
|
|
Michel Lind |
de7e84 |
index 8170b18..e62880b 100644
|
|
Michel Lind |
de7e84 |
--- a/kpatch-build/create-diff-object.c
|
|
Michel Lind |
de7e84 |
+++ b/kpatch-build/create-diff-object.c
|
|
Michel Lind |
de7e84 |
@@ -173,6 +173,8 @@ static bool is_gcc6_localentry_bundled_sym(struct kpatch_elf *kelf,
|
|
Michel Lind |
de7e84 |
struct symbol *sym)
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
switch(kelf->arch) {
|
|
Michel Lind |
de7e84 |
+ case AARCH64:
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
case PPC64:
|
|
Michel Lind |
de7e84 |
return ((PPC64_LOCAL_ENTRY_OFFSET(sym->sym.st_other) != 0) &&
|
|
Michel Lind |
de7e84 |
sym->sym.st_value == 8);
|
|
Michel Lind |
de7e84 |
@@ -230,6 +232,25 @@ static struct rela *toc_rela(const struct rela *rela)
|
|
Michel Lind |
de7e84 |
(unsigned int)rela->addend);
|
|
Michel Lind |
de7e84 |
}
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
+/*
|
|
Michel Lind |
de7e84 |
+ * Mapping symbols are used to mark and label the transitions between code and
|
|
Michel Lind |
de7e84 |
+ * data in elf files. They begin with a "$" dollar symbol. Don't correlate them
|
|
Michel Lind |
de7e84 |
+ * as they often all have the same name either "$x" to mark the start of code
|
|
Michel Lind |
de7e84 |
+ * or "$d" to mark the start of data.
|
|
Michel Lind |
de7e84 |
+ */
|
|
Michel Lind |
de7e84 |
+static bool kpatch_is_mapping_symbol(struct kpatch_elf *kelf, struct symbol *sym)
|
|
Michel Lind |
de7e84 |
+{
|
|
Michel Lind |
de7e84 |
+ if (kelf->arch != AARCH64)
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+ if (sym->name && sym->name[0] == '$' &&
|
|
Michel Lind |
de7e84 |
+ sym->type == STT_NOTYPE &&
|
|
Michel Lind |
de7e84 |
+ sym->bind == STB_LOCAL)
|
|
Michel Lind |
de7e84 |
+ return true;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+ return false;
|
|
Michel Lind |
de7e84 |
+}
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
/*
|
|
Michel Lind |
de7e84 |
* When compiling with -ffunction-sections and -fdata-sections, almost every
|
|
Michel Lind |
de7e84 |
* symbol gets its own dedicated section. We call such symbols "bundled"
|
|
Michel Lind |
de7e84 |
@@ -667,6 +688,12 @@ static bool insn_is_load_immediate(struct kpatch_elf *kelf, void *addr)
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
switch(kelf->arch) {
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
+ case AARCH64:
|
|
Michel Lind |
de7e84 |
+ /* Verify mov w2 <line number> */
|
|
Michel Lind |
de7e84 |
+ if ((insn[0] & 0b11111) == 0x2 && insn[3] == 0x52)
|
|
Michel Lind |
de7e84 |
+ return true;
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
case X86_64:
|
|
Michel Lind |
de7e84 |
/* arg2: mov $imm, %esi */
|
|
Michel Lind |
de7e84 |
if (insn[0] == 0xbe)
|
|
Michel Lind |
de7e84 |
@@ -1076,15 +1103,15 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig,
|
|
Michel Lind |
de7e84 |
}
|
|
Michel Lind |
de7e84 |
}
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
-static void kpatch_correlate_symbols(struct list_head *symlist_orig,
|
|
Michel Lind |
de7e84 |
- struct list_head *symlist_patched)
|
|
Michel Lind |
de7e84 |
+static void kpatch_correlate_symbols(struct kpatch_elf *kelf_orig,
|
|
Michel Lind |
de7e84 |
+ struct kpatch_elf *kelf_patched)
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
struct symbol *sym_orig, *sym_patched;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
- list_for_each_entry(sym_orig, symlist_orig, list) {
|
|
Michel Lind |
de7e84 |
+ list_for_each_entry(sym_orig, &kelf_orig->symbols, list) {
|
|
Michel Lind |
de7e84 |
if (sym_orig->twin)
|
|
Michel Lind |
de7e84 |
continue;
|
|
Michel Lind |
de7e84 |
- list_for_each_entry(sym_patched, symlist_patched, list) {
|
|
Michel Lind |
de7e84 |
+ list_for_each_entry(sym_patched, &kelf_patched->symbols, list) {
|
|
Michel Lind |
de7e84 |
if (kpatch_mangled_strcmp(sym_orig->name, sym_patched->name) ||
|
|
Michel Lind |
de7e84 |
sym_orig->type != sym_patched->type || sym_patched->twin)
|
|
Michel Lind |
de7e84 |
continue;
|
|
Michel Lind |
de7e84 |
@@ -1104,6 +1131,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist_orig,
|
|
Michel Lind |
de7e84 |
!strncmp(sym_orig->name, ".LC", 3))
|
|
Michel Lind |
de7e84 |
continue;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
+ if (kpatch_is_mapping_symbol(kelf_orig, sym_orig))
|
|
Michel Lind |
de7e84 |
+ continue;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
/* group section symbols must have correlated sections */
|
|
Michel Lind |
de7e84 |
if (sym_orig->sec &&
|
|
Michel Lind |
de7e84 |
sym_orig->sec->sh.sh_type == SHT_GROUP &&
|
|
Michel Lind |
de7e84 |
@@ -1509,7 +1539,7 @@ static void kpatch_correlate_elfs(struct kpatch_elf *kelf_orig,
|
|
Michel Lind |
de7e84 |
struct kpatch_elf *kelf_patched)
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
kpatch_correlate_sections(&kelf_orig->sections, &kelf_patched->sections);
|
|
Michel Lind |
de7e84 |
- kpatch_correlate_symbols(&kelf_orig->symbols, &kelf_patched->symbols);
|
|
Michel Lind |
de7e84 |
+ kpatch_correlate_symbols(kelf_orig, kelf_patched);
|
|
Michel Lind |
de7e84 |
}
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
static void kpatch_compare_correlated_elements(struct kpatch_elf *kelf)
|
|
Michel Lind |
de7e84 |
@@ -1625,7 +1655,8 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
if (is_text_section(relasec->base) &&
|
|
Michel Lind |
de7e84 |
!is_text_section(sym->sec) &&
|
|
Michel Lind |
de7e84 |
- is_arch(X86_64) && rela->type == R_X86_64_32S &&
|
|
Michel Lind |
de7e84 |
+ ((is_arch(X86_64) && rela->type == R_X86_64_32S) ||
|
|
Michel Lind |
de7e84 |
+ (is_arch(AARCH64) && rela->type == R_AARCH64_ABS64)) &&
|
|
Michel Lind |
de7e84 |
rela->addend == (long)sym->sec->sh.sh_size &&
|
|
Michel Lind |
de7e84 |
end == (long)sym->sec->sh.sh_size) {
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
@@ -1662,6 +1693,9 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
|
|
Michel Lind |
de7e84 |
*/
|
|
Michel Lind |
de7e84 |
} else if (target_off == start && target_off == end) {
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
+ if(kpatch_is_mapping_symbol(kelf, sym))
|
|
Michel Lind |
de7e84 |
+ continue;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
/*
|
|
Michel Lind |
de7e84 |
* Allow replacement for references to
|
|
Michel Lind |
de7e84 |
* empty symbols.
|
|
Michel Lind |
de7e84 |
@@ -2422,28 +2456,28 @@ static bool static_call_sites_group_filter(struct lookup_table *lookup,
|
|
Michel Lind |
de7e84 |
static struct special_section special_sections[] = {
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
.name = "__bug_table",
|
|
Michel Lind |
de7e84 |
- .arch = X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
+ .arch = AARCH64 | X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
.group_size = bug_table_group_size,
|
|
Michel Lind |
de7e84 |
},
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
.name = ".fixup",
|
|
Michel Lind |
de7e84 |
- .arch = X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
+ .arch = AARCH64 | X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
.group_size = fixup_group_size,
|
|
Michel Lind |
de7e84 |
},
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
.name = "__ex_table", /* must come after .fixup */
|
|
Michel Lind |
de7e84 |
- .arch = X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
+ .arch = AARCH64 | X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
.group_size = ex_table_group_size,
|
|
Michel Lind |
de7e84 |
},
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
.name = "__jump_table",
|
|
Michel Lind |
de7e84 |
- .arch = X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
+ .arch = AARCH64 | X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
.group_size = jump_table_group_size,
|
|
Michel Lind |
de7e84 |
.group_filter = jump_table_group_filter,
|
|
Michel Lind |
de7e84 |
},
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
.name = ".printk_index",
|
|
Michel Lind |
de7e84 |
- .arch = X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
+ .arch = AARCH64 | X86_64 | PPC64 | S390,
|
|
Michel Lind |
de7e84 |
.group_size = printk_index_group_size,
|
|
Michel Lind |
de7e84 |
},
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
@@ -2458,7 +2492,7 @@ static struct special_section special_sections[] = {
|
|
Michel Lind |
de7e84 |
},
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
.name = ".altinstructions",
|
|
Michel Lind |
de7e84 |
- .arch = X86_64 | S390,
|
|
Michel Lind |
de7e84 |
+ .arch = AARCH64 | X86_64 | S390,
|
|
Michel Lind |
de7e84 |
.group_size = altinstructions_group_size,
|
|
Michel Lind |
de7e84 |
},
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
@@ -3774,6 +3808,47 @@ static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf, bool
|
|
Michel Lind |
de7e84 |
}
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
switch(kelf->arch) {
|
|
Michel Lind |
de7e84 |
+ case AARCH64:
|
|
Michel Lind |
de7e84 |
+ unsigned char *insn;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+ /*
|
|
Michel Lind |
de7e84 |
+ * Assume ppc64le is built with -fpatchable-function-entry=2, which means that all 2 nops are
|
|
Michel Lind |
de7e84 |
+ * after the entry point of the function.
|
|
Michel Lind |
de7e84 |
+ *
|
|
Michel Lind |
de7e84 |
+ * Disassembly of section .text.cmdline_proc_show:
|
|
Michel Lind |
de7e84 |
+ *
|
|
Michel Lind |
de7e84 |
+ * 0000000000000000 <cmdline_proc_show>:
|
|
Michel Lind |
de7e84 |
+ * 0: d503201f nop << <<
|
|
Michel Lind |
de7e84 |
+ * 4: d503201f nop
|
|
Michel Lind |
de7e84 |
+ *
|
|
Michel Lind |
de7e84 |
+ * Relocation section '.rela__patchable_function_entries'
|
|
Michel Lind |
de7e84 |
+ * Offset Info Type Symbol's Value Symbol's Name + Addend
|
|
Michel Lind |
de7e84 |
+ * 0000000000000008 0000000f00000101 R_AARCH64_ABS64 0000000000000000 .text.cmdline_proc_show + 0
|
|
Michel Lind |
de7e84 |
+ * ^
|
|
Michel Lind |
de7e84 |
+ */
|
|
Michel Lind |
de7e84 |
+ insn_offset = 0;
|
|
Michel Lind |
de7e84 |
+ insn = sym->sec->data->d_buf + insn_offset;
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+ /*
|
|
Michel Lind |
de7e84 |
+ * If BTI (Branch Target Identification) is enabled then there
|
|
Michel Lind |
de7e84 |
+ * might be an additional 'BTI C' instruction before the two
|
|
Michel Lind |
de7e84 |
+ * patchable function entry 'NOP's.
|
|
Michel Lind |
de7e84 |
+ * i.e. 0xd503245f (little endian)
|
|
Michel Lind |
de7e84 |
+ */
|
|
Michel Lind |
de7e84 |
+ if (insn[0] == 0x5f) {
|
|
Michel Lind |
de7e84 |
+ if (insn[1] != 0x24 || insn[2] != 0x03 || insn[3] != 0xd5)
|
|
Michel Lind |
de7e84 |
+ ERROR("%s: unexpected instruction in patch section of function\n", sym->name);
|
|
Michel Lind |
de7e84 |
+ insn_offset += 4;
|
|
Michel Lind |
de7e84 |
+ insn += 4;
|
|
Michel Lind |
de7e84 |
+ }
|
|
Michel Lind |
de7e84 |
+ for (int i=0; i<8; i+=4) {
|
|
Michel Lind |
de7e84 |
+ /* We expect a NOP i.e. 0xd503201f (little endian) */
|
|
Michel Lind |
de7e84 |
+ if (insn[i] != 0x1f || insn[i + 1] != 0x20 ||
|
|
Michel Lind |
de7e84 |
+ insn[i + 2] != 0x03 || insn [i + 3] != 0xd5)
|
|
Michel Lind |
de7e84 |
+ ERROR("%s: unexpected instruction in patch section of function\n", sym->name);
|
|
Michel Lind |
de7e84 |
+ }
|
|
Michel Lind |
de7e84 |
+
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
case PPC64: {
|
|
Michel Lind |
de7e84 |
unsigned char *insn;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
@@ -4067,6 +4142,11 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
|
|
Michel Lind |
de7e84 |
continue;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
switch(kelf->arch) {
|
|
Michel Lind |
de7e84 |
+ case AARCH64:
|
|
Michel Lind |
de7e84 |
+ if (kpatch_symbol_has_pfe_entry(kelf, sym)) {
|
|
Michel Lind |
de7e84 |
+ sym->has_func_profiling = 1;
|
|
Michel Lind |
de7e84 |
+ }
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
case PPC64:
|
|
Michel Lind |
de7e84 |
if (kpatch_symbol_has_pfe_entry(kelf, sym)) {
|
|
Michel Lind |
de7e84 |
sym->has_func_profiling = 1;
|
|
Michel Lind |
de7e84 |
diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c
|
|
Michel Lind |
de7e84 |
index 073b808..17c0491 100755
|
|
Michel Lind |
de7e84 |
--- a/kpatch-build/kpatch-elf.c
|
|
Michel Lind |
de7e84 |
+++ b/kpatch-build/kpatch-elf.c
|
|
Michel Lind |
de7e84 |
@@ -156,6 +156,8 @@ struct rela *find_rela_by_offset(struct section *relasec, unsigned int offset)
|
|
Michel Lind |
de7e84 |
unsigned int absolute_rela_type(struct kpatch_elf *kelf)
|
|
Michel Lind |
de7e84 |
{
|
|
Michel Lind |
de7e84 |
switch(kelf->arch) {
|
|
Michel Lind |
de7e84 |
+ case AARCH64:
|
|
Michel Lind |
de7e84 |
+ return R_AARCH64_ABS64;
|
|
Michel Lind |
de7e84 |
case PPC64:
|
|
Michel Lind |
de7e84 |
return R_PPC64_ADDR64;
|
|
Michel Lind |
de7e84 |
case X86_64:
|
|
Michel Lind |
de7e84 |
@@ -225,6 +227,7 @@ long rela_target_offset(struct kpatch_elf *kelf, struct section *relasec,
|
|
Michel Lind |
de7e84 |
struct section *sec = relasec->base;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
switch(kelf->arch) {
|
|
Michel Lind |
de7e84 |
+ case AARCH64:
|
|
Michel Lind |
de7e84 |
case PPC64:
|
|
Michel Lind |
de7e84 |
add_off = 0;
|
|
Michel Lind |
de7e84 |
break;
|
|
Michel Lind |
de7e84 |
@@ -274,6 +277,8 @@ unsigned int insn_length(struct kpatch_elf *kelf, void *addr)
|
|
Michel Lind |
de7e84 |
char *insn = addr;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
switch(kelf->arch) {
|
|
Michel Lind |
de7e84 |
+ case AARCH64:
|
|
Michel Lind |
de7e84 |
+ return 4;
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
case X86_64:
|
|
Michel Lind |
de7e84 |
insn_init(&decoded_insn, addr, 1);
|
|
Michel Lind |
de7e84 |
@@ -604,6 +609,9 @@ struct kpatch_elf *kpatch_elf_open(const char *name)
|
|
Michel Lind |
de7e84 |
if (!gelf_getehdr(kelf->elf, &ehdr))
|
|
Michel Lind |
de7e84 |
ERROR("gelf_getehdr");
|
|
Michel Lind |
de7e84 |
switch (ehdr.e_machine) {
|
|
Michel Lind |
de7e84 |
+ case EM_AARCH64:
|
|
Michel Lind |
de7e84 |
+ kelf->arch = AARCH64;
|
|
Michel Lind |
de7e84 |
+ break;
|
|
Michel Lind |
de7e84 |
case EM_PPC64:
|
|
Michel Lind |
de7e84 |
kelf->arch = PPC64;
|
|
Michel Lind |
de7e84 |
break;
|
|
Michel Lind |
de7e84 |
diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h
|
|
Michel Lind |
de7e84 |
index 3389dfe..4a3617d 100644
|
|
Michel Lind |
de7e84 |
--- a/kpatch-build/kpatch-elf.h
|
|
Michel Lind |
de7e84 |
+++ b/kpatch-build/kpatch-elf.h
|
|
Michel Lind |
de7e84 |
@@ -116,6 +116,7 @@ enum architecture {
|
|
Michel Lind |
de7e84 |
PPC64 = 0x1 << 0,
|
|
Michel Lind |
de7e84 |
X86_64 = 0x1 << 1,
|
|
Michel Lind |
de7e84 |
S390 = 0x1 << 2,
|
|
Michel Lind |
de7e84 |
+ AARCH64 = 0x1 << 3,
|
|
Michel Lind |
de7e84 |
};
|
|
Michel Lind |
de7e84 |
|
|
Michel Lind |
de7e84 |
struct kpatch_elf {
|
|
Michel Lind |
de7e84 |
--
|
|
Michel Lind |
de7e84 |
2.48.1
|
|
Michel Lind |
de7e84 |
|