mirror of
https://github.com/dynup/kpatch
synced 2025-04-11 03:31:20 +00:00
create-diff-object: add aarch64 ASSERT_RTNL macro detection
On aarch64, only the ASSERT_RTNL macro is affected by source line number changes (WARN, BUG, etc. no longer embed line numbers in the instruction stream.) A small test function that invokes the macro for a line change from 42 to 43: 0000000000000000 <test_assert_rtnl>: 0: d503245f bti c 4: d503201f nop 8: d503201f nop c: d503233f paciasp 10: a9bf7bfd stp x29, x30, [sp, #-16]! 14: 910003fd mov x29, sp 18: 94000000 bl 0 <rtnl_is_locked> 18: R_AARCH64_CALL26 rtnl_is_locked 1c: 34000080 cbz w0, 2c <test_assert_rtnl+0x2c> 20: a8c17bfd ldp x29, x30, [sp], #16 24: d50323bf autiasp 28: d65f03c0 ret 2c: 90000000 adrp x0, 0 <test_assert_rtnl> 2c: R_AARCH64_ADR_PREL_PG_HI21 .data.once 30: 39400001 ldrb w1, [x0] 30: R_AARCH64_LDST8_ABS_LO12_NC .data.once 34: 35ffff61 cbnz w1, 20 <test_assert_rtnl+0x20> 38: 52800022 mov w2, #0x1 // #1 3c: 90000001 adrp x1, 0 <test_assert_rtnl> 3c: R_AARCH64_ADR_PREL_PG_HI21 .rodata.str1.8+0x8 40: 39000002 strb w2, [x0] 40: R_AARCH64_LDST8_ABS_LO12_NC .data.once 44: 91000021 add x1, x1, #0x0 44: R_AARCH64_ADD_ABS_LO12_NC .rodata.str1.8+0x8 - 48: 52800542 mov w2, #0x2a // #42 + 48: 52800562 mov w2, #0x2b // #43 4c: 90000000 adrp x0, 0 <test_assert_rtnl> 4c: R_AARCH64_ADR_PREL_PG_HI21 .rodata.str1.8+0x20 50: 91000000 add x0, x0, #0x0 50: R_AARCH64_ADD_ABS_LO12_NC .rodata.str1.8+0x20 54: 94000000 bl 0 <__warn_printk> 54: R_AARCH64_CALL26 __warn_printk 58: d4210000 brk #0x800 5c: 17fffff1 b 20 <test_assert_rtnl+0x20> Create an implementation of kpatch_line_macro_change_only() for aarch64 modeled after the other architectures. Only look for relocations to __warn_printk that ASSERT_RTNL invokes. Based-on-s390x-code-by: C. Erastus Toe <ctoe@redhat.com> Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
This commit is contained in:
parent
c9e1ae7168
commit
17cada33ad
@ -861,13 +861,74 @@ static bool _kpatch_line_macro_change_only(struct kpatch_elf *kelf,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _kpatch_line_macro_change_only_aarch64(struct kpatch_elf *kelf,
|
||||
struct section *sec)
|
||||
{
|
||||
unsigned char *start1, *start2;
|
||||
unsigned long size, offset, insn_len;
|
||||
struct rela *rela;
|
||||
int lineonly = 0, found;
|
||||
|
||||
insn_len = insn_length(kelf, NULL);
|
||||
|
||||
if (sec->status != CHANGED ||
|
||||
is_rela_section(sec) ||
|
||||
!is_text_section(sec) ||
|
||||
sec->sh.sh_size != sec->twin->sh.sh_size ||
|
||||
!sec->rela ||
|
||||
sec->rela->status != SAME)
|
||||
return false;
|
||||
|
||||
start1 = sec->twin->data->d_buf;
|
||||
start2 = sec->data->d_buf;
|
||||
size = sec->sh.sh_size;
|
||||
for (offset = 0; offset < size; offset += insn_len) {
|
||||
if (!memcmp(start1 + offset, start2 + offset, insn_len))
|
||||
continue;
|
||||
|
||||
/* Verify mov w2 <line number> */
|
||||
if (((start1[offset] & 0b11111) != 0x2) || (start1[offset+3] != 0x52) ||
|
||||
((start1[offset] & 0b11111) != 0x2) || (start2[offset+3] != 0x52))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Verify zero or more string relas followed by a
|
||||
* warn_slowpath_* or another similar rela.
|
||||
*/
|
||||
found = 0;
|
||||
list_for_each_entry(rela, &sec->rela->relas, list) {
|
||||
if (rela->offset < offset + insn_len)
|
||||
continue;
|
||||
if (rela->string)
|
||||
continue;
|
||||
if (!strncmp(rela->sym->name, "__warned.", 9) ||
|
||||
!strncmp(rela->sym->name, "__already_done.", 15))
|
||||
continue;
|
||||
if (!strcmp(rela->sym->name, "__warn_printk")) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
lineonly = 1;
|
||||
}
|
||||
|
||||
if (!lineonly)
|
||||
ERROR("no instruction changes detected for changed section %s",
|
||||
sec->name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool kpatch_line_macro_change_only(struct kpatch_elf *kelf,
|
||||
struct section *sec)
|
||||
{
|
||||
switch(kelf->arch) {
|
||||
case AARCH64:
|
||||
/* TODO */
|
||||
return false;
|
||||
return _kpatch_line_macro_change_only_aarch64(kelf, sec);
|
||||
case PPC64:
|
||||
case S390:
|
||||
case X86_64:
|
||||
|
@ -277,6 +277,8 @@ unsigned int insn_length(struct kpatch_elf *kelf, void *addr)
|
||||
char *insn = addr;
|
||||
|
||||
switch(kelf->arch) {
|
||||
case AARCH64:
|
||||
return 4;
|
||||
|
||||
case X86_64:
|
||||
insn_init(&decoded_insn, addr, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user