Skip to content

Commit

Permalink
create-diff-object: add aarch64 ASSERT_RTNL macro detection
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Joe Lawrence <[email protected]>
  • Loading branch information
joe-lawrence authored and swine committed Jul 28, 2023
1 parent 5dfe85a commit 307ceff
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
65 changes: 63 additions & 2 deletions kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -859,13 +859,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:
Expand Down
2 changes: 2 additions & 0 deletions kpatch-build/kpatch-elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,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);
Expand Down

0 comments on commit 307ceff

Please sign in to comment.