diff options
Diffstat (limited to 'kexec')
-rw-r--r-- | kexec/arch/ppc64/kexec-elf-rel-ppc64.c | 27 | ||||
-rw-r--r-- | kexec/kexec-elf-rel.c | 10 |
2 files changed, 32 insertions, 5 deletions
diff --git a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c index 5fc2f87..9b191d0 100644 --- a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c +++ b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c @@ -144,6 +144,33 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, *(uint16_t *)location = (((uint64_t)value >> 48) & 0xffff); break; + /* R_PPC64_REL16_HA and R_PPC64_REL16_LO are handled to support + * ABIv2 r2 assignment based on r12 for PIC executable. + * Here address is know so replace + * 0: addis 2,12,.TOC.-0b@ha + * addi 2,2,.TOC.-0b@l + * by + * lis 2,.TOC.@ha + * addi 2,2,.TOC.@l + */ + case R_PPC64_REL16_HA: + /* check that we are dealing with the addis 2,12 instruction */ + if (((*(uint32_t*)location) & 0xffff0000) != 0x3c4c0000) + die("Unexpected instruction for R_PPC64_REL16_HA"); + value += my_r2(ehdr); + /* replacing by lis 2 */ + *(uint32_t *)location = 0x3c400000 + ((value >> 16) & 0xffff); + break; + + case R_PPC64_REL16_LO: + /* check that we are dealing with the addi 2,2 instruction */ + if (((*(uint32_t*)location) & 0xffff0000) != 0x38420000) + die("Unexpected instruction for R_PPC64_REL16_LO"); + + value += my_r2(ehdr) - 4; + *(uint16_t *)location = value & 0xffff; + break; + default: die("Unknown rela relocation: %lu\n", r_type); break; diff --git a/kexec/kexec-elf-rel.c b/kexec/kexec-elf-rel.c index 020cab0..c625f30 100644 --- a/kexec/kexec-elf-rel.c +++ b/kexec/kexec-elf-rel.c @@ -379,12 +379,12 @@ int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info, * Relocation Entries: If the index is STN_UNDEF, * the undefined symbol index, the relocation uses 0 * as the "symbol value". - * So, is this really an error condition to flag die? + * TOC symbols appear as undefined but should be + * resolved as well. Their type is STT_NOTYPE so allow + * such symbols to be processed. */ - /* - die("Undefined symbol: %s\n", name); - */ - continue; + if (ELF32_ST_TYPE(sym.st_info) != STT_NOTYPE) + die("Undefined symbol: %s\n", name); } sec_base = 0; if (sym.st_shndx == SHN_COMMON) { |