Relocator::Result relocPCREL(Relocation& pReloc, HexagonRelocator& pParent) { ResolveInfo* rsym = pReloc.symInfo(); int64_t result; Relocator::Address S = pReloc.symValue(); Relocator::DWord A = pReloc.addend(); Relocator::DWord P = pReloc.place(); FragmentRef& target_fragref = pReloc.targetRef(); Fragment* target_frag = target_fragref.frag(); LDSection& target_sect = target_frag->getParent()->getSection(); result = (int64_t)(S + A - P); // for relocs inside non ALLOC, just apply if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0) { return applyRel(pReloc, result); } if (!rsym->isLocal()) { if (rsym->reserved() & HexagonRelocator::ReservePLT) { S = helper_get_PLT_address(*rsym, pParent); result = (int64_t)(S + A - P); applyRel(pReloc, result); return Relocator::OK; } } return applyRel(pReloc, result); }
// R_386_GOTPC: GOT_ORG + A - P X86RelocationFactory::Result gotpc32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); // Apply relocation. pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout()); return X86RelocationFactory::OK; }
// R_386_PC32: S + A - P X86RelocationFactory::Result rel32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { // perform static relocation RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout()); return X86RelocationFactory::OK; }
Relocator::Result lea(Relocation& pReloc, NyuziRelocator& pParent) { Relocator::Address S = pReloc.symValue(); Relocator::Address P = pReloc.place(); int offset = S - (P + 4); if (helper_check_signed_overflow(offset, 13)) return Relocator::Overflow; pReloc.target() = helper_replace_field(pReloc.target(), offset, 10, 13); return Relocator::OK; }
// R_HEX_PLT_B22_PCREL: PLT(S) + A - P Relocator::Result relocPLTB22PCREL(Relocation& pReloc, HexagonRelocator& pParent) { // PLT_S depends on if there is a PLT entry. Relocator::Address PLT_S; if ((pReloc.symInfo()->reserved() & HexagonRelocator::ReservePLT)) PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); else PLT_S = pReloc.symValue(); Relocator::Address P = pReloc.place(); uint32_t bitMask = FINDBITMASK(pReloc.target()); uint32_t result = (PLT_S + pReloc.addend() - P) >> 2; pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result); return Relocator::OK; }
// R_386_PLT32: PLT(S) + A - P X86RelocationFactory::Result plt32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { // PLT_S depends on if there is a PLT entry. X86RelocationFactory::Address PLT_S; if((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT)) PLT_S = helper_PLT(pReloc, pParent); else PLT_S = pReloc.symValue(); RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); X86RelocationFactory::Address P = pReloc.place(pParent.getLayout()); pReloc.target() = PLT_S + A - P; return X86RelocationFactory::OK; }
// R_386_PC32: S + A - P X86RelocationFactory::Result rel32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { ResolveInfo* rsym = pReloc.symInfo(); RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); RelocationFactory::DWord S = pReloc.symValue(); RelocationFactory::DWord P = pReloc.place(pParent.getLayout()); const LDSection* target_sect = pParent.getLayout().getOutputLDSection( *(pReloc.targetRef().frag())); assert(NULL != target_sect); // If the flag of target section is not ALLOC, we will not scan this relocation // but perform static relocation. (e.g., applying .debug section) if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { pReloc.target() = S + A - P; return X86RelocationFactory::OK; } // An external symbol may need PLT and dynamic relocation if (!rsym->isLocal()) { if (rsym->reserved() & X86GNULDBackend::ReservePLT) { S = helper_PLT(pReloc, pParent); pReloc.target() = S + A - P; } if (pParent.getTarget().symbolNeedsDynRel( *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo, pLDInfo.output(), false)) { if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) { helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); } else { helper_DynRel(pReloc, pReloc.type(), pParent); return X86RelocationFactory::OK; } } } // perform static relocation pReloc.target() = S + A - P; return X86RelocationFactory::OK; }
// R_HEX_B22_PCREL and its class of relocations, use // S + A - P : result is signed verify. // Exception: R_HEX_B32_PCREL_X : signed truncate // Another Exception: R_HEX_6_PCREL_X is unsigned truncate Relocator::Result applyRel(Relocation& pReloc, int64_t pResult) { uint32_t bitMask = 0; uint32_t effectiveBits = 0; uint32_t alignment = 1; uint32_t result; uint32_t shift = 0; switch (pReloc.type()) { case llvm::ELF::R_HEX_B22_PCREL: bitMask = 0x01ff3ffe; effectiveBits = 22; alignment = 4; shift = 2; break; case llvm::ELF::R_HEX_B15_PCREL: bitMask = 0x00df20fe; effectiveBits = 15; alignment = 4; shift = 2; break; case llvm::ELF::R_HEX_B7_PCREL: bitMask = 0x00001f18; effectiveBits = 7; alignment = 4; shift = 2; break; case llvm::ELF::R_HEX_B13_PCREL: bitMask = 0x00202ffe; effectiveBits = 13; alignment = 4; shift = 2; break; case llvm::ELF::R_HEX_B9_PCREL: bitMask = 0x003000fe; effectiveBits = 9; alignment = 4; shift = 2; break; case llvm::ELF::R_HEX_B32_PCREL_X: bitMask = 0xfff3fff; shift = 6; break; case llvm::ELF::R_HEX_B22_PCREL_X: bitMask = 0x01ff3ffe; effectiveBits = 22; pResult &= 0x3f; break; case llvm::ELF::R_HEX_B15_PCREL_X: bitMask = 0x00df20fe; effectiveBits = 15; pResult &= 0x3f; break; case llvm::ELF::R_HEX_B13_PCREL_X: bitMask = 0x00202ffe; effectiveBits = 13; pResult &= 0x3f; break; case llvm::ELF::R_HEX_B9_PCREL_X: bitMask = 0x003000fe; effectiveBits = 9; pResult &= 0x3f; break; case llvm::ELF::R_HEX_B7_PCREL_X: bitMask = 0x00001f18; effectiveBits = 7; pResult &= 0x3f; break; case llvm::ELF::R_HEX_32_PCREL: bitMask = 0xffffffff; effectiveBits = 32; break; case llvm::ELF::R_HEX_6_PCREL_X: // This is unique since it has a unsigned operand and its truncated bitMask = FINDBITMASK(pReloc.target()); result = pReloc.addend() + pReloc.symValue() - pReloc.place(); pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); return Relocator::OK; default: // show proper error fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type()) << "*****@*****.**"; } if ((shift != 0) && (pResult % alignment != 0)) return Relocator::BadReloc; pResult >>= shift; if (effectiveBits) { int64_t range = 1LL << (effectiveBits - 1); if ((pResult > (range - 1)) || (pResult < -range)) return Relocator::Overflow; } pReloc.target() |= (uint32_t)ApplyMask<int32_t>(bitMask, pResult); return Relocator::OK; }