Merge pull request #773 from kamalesh-babulal/ppc64le_fixes

More ppc64le fixes
This commit is contained in:
Joe Lawrence 2018-03-19 16:53:06 -04:00 committed by GitHub
commit 613794e85a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 20 deletions

View File

@ -47,7 +47,8 @@
#define HAVE_SYMPOS #define HAVE_SYMPOS
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) || \ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) && \
LINUX_VERSION_CODE <= KERNEL_VERSION(4, 15, 0)) || \
defined(RHEL_RELEASE_CODE) defined(RHEL_RELEASE_CODE)
#define HAVE_IMMEDIATE #define HAVE_IMMEDIATE
#endif #endif

View File

@ -245,6 +245,7 @@ static int rela_equal(struct rela *rela1, struct rela *rela2)
#ifdef __powerpc__ #ifdef __powerpc__
struct section *toc_relasec1, *toc_relasec2; struct section *toc_relasec1, *toc_relasec2;
struct rela *r_toc_relasec1, *r_toc_relasec2; struct rela *r_toc_relasec1, *r_toc_relasec2;
unsigned long toc_data1, toc_data2;
#endif #endif
if (rela1->type != rela2->type || if (rela1->type != rela2->type ||
@ -288,16 +289,59 @@ static int rela_equal(struct rela *rela1, struct rela *rela2)
ERROR("cannot find .rela.toc"); ERROR("cannot find .rela.toc");
r_toc_relasec1 = find_rela_by_offset(toc_relasec1, rela1->addend); r_toc_relasec1 = find_rela_by_offset(toc_relasec1, rela1->addend);
if (!r_toc_relasec1) if (!r_toc_relasec1) {
/*
* .toc section entries are mostly place holder for relocation entries, specified
* in .rela.toc section. Sometimes, .toc section may have constants as entries.
* These constants are not reference to any symbols, but plain instructions mostly
* due to some arithmetics in the functions referring them.
*
* They are referred by the functions like normal .toc entries, these entries can
* not be resolved to any symbols.
*
* Disassembly of section .toc:
*
* 0000000000000000 <.toc>:
* ...
* 148: R_PPC64_ADDR64 .data.capacity_margin
* 150: 0b d7 a3 70 andi. r3,r5,55051
* 154: 3d 0a d7 a3 lhz r30,2621(r23)
* 158: R_PPC64_ADDR64 sched_max_numa_distance
*
* Relocation section '.rela.toc' at offset 0xadac0 contains 160 entries:
* Offset Info Type Symbol's Value Symbol's Name + Addend
* ...
* 0000000000000148 0000009100000026 R_PPC64_ADDR64 0000000000000000 .data.capacity_margin + 0
* 0000000000000158 000001a500000026 R_PPC64_ADDR64 0000000000000000 sched_max_numa_distance + 0
*
* Relocation section '.rela.text.select_task_rq_fair' at offset 0x90e98 contains 37 entries:
* Offset Info Type Symbol's Value Symbol's Name + Addend
* ...
* 0000000000000498 000000c90000000a R_PPC64_REL24 0000000000000000 __update_load_avg_blocked_se.isra.0 + 0
* 00000000000004a0 0000008800000032 R_PPC64_TOC16_HA 0000000000000000 .toc + 148
* 00000000000004ac 0000008800000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + 148
* 0000000000000514 0000008800000032 R_PPC64_TOC16_HA 0000000000000000 .toc + 150
* 000000000000051c 0000008800000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + 150
* 00000000000005e0 000001870000000a R_PPC64_REL24 0000000000000000 __bitmap_intersects + 0
*/
memcpy(&toc_data1, rela1->sym->sec->data->d_buf + rela1->addend, sizeof(toc_data1));
if (!toc_data1)
ERROR(".toc entry not found %s + %x", rela1->sym->name, rela1->addend); ERROR(".toc entry not found %s + %x", rela1->sym->name, rela1->addend);
}
toc_relasec2 = rela2->sym->sec->rela; toc_relasec2 = rela2->sym->sec->rela;
if (!toc_relasec2) if (!toc_relasec2)
ERROR("cannot find .rela.toc"); ERROR("cannot find .rela.toc");
r_toc_relasec2 = find_rela_by_offset(toc_relasec2, rela2->addend); r_toc_relasec2 = find_rela_by_offset(toc_relasec2, rela2->addend);
if (!r_toc_relasec2) if (!r_toc_relasec2) {
memcpy(&toc_data2, rela2->sym->sec->data->d_buf + rela2->addend, sizeof(toc_data2));
if (!toc_data2)
ERROR(".toc entry not found %s + %x", rela2->sym->name, rela2->addend); ERROR(".toc entry not found %s + %x", rela2->sym->name, rela2->addend);
}
if (!r_toc_relasec1 && !r_toc_relasec2)
return toc_data1 == toc_data2;
if (r_toc_relasec1->string) if (r_toc_relasec1->string)
return r_toc_relasec2->string && return r_toc_relasec2->string &&
@ -1118,17 +1162,6 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
} }
#ifdef __powerpc__ #ifdef __powerpc__
/*
* With -mcmodel=large, R_PPC64_REL24 is only used for
* functions. Assuming the function is bundled in a
* section, the section symbol should have been
* replaced with a text symbol already. Otherwise,
* bail out. If we hit this situation, more core is
* needed here to calculate the value of 'add_off'.
*/
if (rela->type == R_PPC64_REL24)
ERROR("Unexpected relocation type R_PPC64_REL24 for %s\n", rela->sym->name);
add_off = 0; add_off = 0;
#else #else
if (rela->type == R_X86_64_PC32) { if (rela->type == R_X86_64_PC32) {
@ -1257,12 +1290,11 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
/* /*
* ensure we aren't including .data.* or .bss.* * ensure we aren't including .data.* or .bss.*
* (.data.unlikely is ok b/c it only has __warned vars) * (.data.unlikely and .data.once is ok b/c it only has __warned vars)
*/ */
if (sec->include && sec->status != NEW && if (sec->include && sec->status != NEW &&
(!strncmp(sec->name, ".data", 5) || (!strncmp(sec->name, ".data", 5) || !strncmp(sec->name, ".bss", 4)) &&
!strncmp(sec->name, ".bss", 4)) && (strcmp(sec->name, ".data.unlikely") && strcmp(sec->name, ".data.once"))) {
strcmp(sec->name, ".data.unlikely")) {
log_normal("data section %s selected for inclusion\n", log_normal("data section %s selected for inclusion\n",
sec->name); sec->name);
errs++; errs++;