Skip to content

Commit 52842ef

Browse files
joe-lawrenceswine
authored andcommitted
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], dynup#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 // dynup#42 + 48: 52800562 mov w2, #0x2b // dynup#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>
1 parent 3650f3a commit 52842ef

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

kpatch-build/create-diff-object.c

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -861,13 +861,74 @@ static bool _kpatch_line_macro_change_only(struct kpatch_elf *kelf,
861861
return true;
862862
}
863863

864+
static bool _kpatch_line_macro_change_only_aarch64(struct kpatch_elf *kelf,
865+
struct section *sec)
866+
{
867+
unsigned char *start1, *start2;
868+
unsigned long size, offset, insn_len;
869+
struct rela *rela;
870+
int lineonly = 0, found;
871+
872+
insn_len = insn_length(kelf, NULL);
873+
874+
if (sec->status != CHANGED ||
875+
is_rela_section(sec) ||
876+
!is_text_section(sec) ||
877+
sec->sh.sh_size != sec->twin->sh.sh_size ||
878+
!sec->rela ||
879+
sec->rela->status != SAME)
880+
return false;
881+
882+
start1 = sec->twin->data->d_buf;
883+
start2 = sec->data->d_buf;
884+
size = sec->sh.sh_size;
885+
for (offset = 0; offset < size; offset += insn_len) {
886+
if (!memcmp(start1 + offset, start2 + offset, insn_len))
887+
continue;
888+
889+
/* Verify mov w2 <line number> */
890+
if (((start1[offset] & 0b11111) != 0x2) || (start1[offset+3] != 0x52) ||
891+
((start1[offset] & 0b11111) != 0x2) || (start2[offset+3] != 0x52))
892+
return false;
893+
894+
/*
895+
* Verify zero or more string relas followed by a
896+
* warn_slowpath_* or another similar rela.
897+
*/
898+
found = 0;
899+
list_for_each_entry(rela, &sec->rela->relas, list) {
900+
if (rela->offset < offset + insn_len)
901+
continue;
902+
if (rela->string)
903+
continue;
904+
if (!strncmp(rela->sym->name, "__warned.", 9) ||
905+
!strncmp(rela->sym->name, "__already_done.", 15))
906+
continue;
907+
if (!strcmp(rela->sym->name, "__warn_printk")) {
908+
found = 1;
909+
break;
910+
}
911+
return false;
912+
}
913+
if (!found)
914+
return false;
915+
916+
lineonly = 1;
917+
}
918+
919+
if (!lineonly)
920+
ERROR("no instruction changes detected for changed section %s",
921+
sec->name);
922+
923+
return true;
924+
}
925+
864926
static bool kpatch_line_macro_change_only(struct kpatch_elf *kelf,
865927
struct section *sec)
866928
{
867929
switch(kelf->arch) {
868930
case AARCH64:
869-
/* TODO */
870-
return false;
931+
return _kpatch_line_macro_change_only_aarch64(kelf, sec);
871932
case PPC64:
872933
case S390:
873934
case X86_64:

kpatch-build/kpatch-elf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ unsigned int insn_length(struct kpatch_elf *kelf, void *addr)
277277
char *insn = addr;
278278

279279
switch(kelf->arch) {
280+
case AARCH64:
281+
return 4;
280282

281283
case X86_64:
282284
insn_init(&decoded_insn, addr, 1);

0 commit comments

Comments
 (0)