create-diff-object: fix ppc64le function pointer test for large model

With -mcmodel=small|medium on ppc64le, GCC generates an entry point
prolog like:

  0000000000000000 <cmdline_proc_open>:
     0:   00 00 4c 3c     addis   r2,r12,0
                          0: R_PPC64_REL16_HA     .TOC.
     4:   00 00 42 38     addi    r2,r2,0
                          4: R_PPC64_REL16_LO     .TOC.+0x4

But with -mcmodel=large on ppc64le, GCC generates an entry point prolog
like:

  0000000000000000 <cmdline_proc_show-0x8>:
          ...
                          0: R_PPC64_REL64        .TOC.-0x8

  0000000000000008 <cmdline_proc_show>:
     8:   f8 ff 4c e8     ld      r2,-8(r12)
                          8: R_PPC64_ENTRY        *ABS*
     c:   14 62 42 7c     add     r2,r2,r12

In the small/medium memory model version, a function pointer relocation
can be verified by comparing the relocation types (R_PPC64_TOC16_HA or
R_PPC64_TOC16_LO_DS) and that the rela_toc->addend ==
rela_toc->sym->sym.st_value.

In the large memory module case, a function pointer can be verified by
its type (R_PPC64_ADDR64) and whether there exists a R_PPC64_ENTRY
relocation at the location its addend and symbol value point to in the
target .text section.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
This commit is contained in:
Joe Lawrence 2025-03-24 16:58:35 -04:00
parent 839d86a08e
commit 69828ade3e

View File

@ -3259,9 +3259,16 @@ static int function_ptr_rela(const struct rela *rela, struct kpatch_elf *kelf)
funcptr = true;
break;
case PPC64:
if (rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
(rela->type == R_PPC64_TOC16_HA || rela->type == R_PPC64_TOC16_LO_DS))
if ((rela->type == R_PPC64_TOC16_HA || rela->type == R_PPC64_TOC16_LO_DS) &&
(rela_toc->addend == (int)rela_toc->sym->sym.st_value)) {
funcptr = true;
} else if (rela->type == R_PPC64_ADDR64) {
struct rela *entry;
entry = find_rela_by_offset(rela_toc->sym->sec->rela,
(unsigned int) (rela_toc->addend + rela_toc->sym->sym.st_value));
if (entry && entry->type == R_PPC64_ENTRY)
funcptr = true;
}
break;
case S390:
if (rela->type == R_390_GOTENT)