llvm.org GIT mirror llvm / 0f4cbb9
RuntimeDyldELF: don't create thunk if not needed This patch doesn't create thunk for branch operation when following conditions are met: - Architecture is AArch64 - Relocation target is in the same object file - Relocation target is close enough to be encoded in immediate offset In such case we branch directly to the target instead of branching to thunk Differential revision: https://reviews.llvm.org/D28108 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291431 91177308-0d34-0410-b5e6-96231b3b80d8 Eugene Leviant 3 years ago
3 changed file(s) with 61 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
895895 return ELF::R_MIPS_NONE;
896896 }
897897
898 // Sometimes we don't need to create thunk for a branch.
899 // This typically happens when branch target is located
900 // in the same object file. In such case target is either
901 // a weak symbol or symbol in a different executable section.
902 // This function checks if branch target is located in the
903 // same object file and if distance between source and target
904 // fits R_AARCH64_CALL26 relocation. If both conditions are
905 // met, it emits direct jump to the target and returns true.
906 // Otherwise false is returned and thunk is created.
907 bool RuntimeDyldELF::resolveAArch64ShortBranch(
908 unsigned SectionID, relocation_iterator RelI,
909 const RelocationValueRef &Value) {
910 uint64_t Address;
911 if (Value.SymbolName) {
912 auto Loc = GlobalSymbolTable.find(Value.SymbolName);
913
914 // Don't create direct branch for external symbols.
915 if (Loc == GlobalSymbolTable.end())
916 return false;
917
918 const auto &SymInfo = Loc->second;
919 Address = reinterpret_cast(
920 Sections[SymInfo.getSectionID()].getLoadAddressWithOffset(
921 SymInfo.getOffset()));
922 } else {
923 Address =
924 reinterpret_cast(Sections[Value.SectionID].getLoadAddress());
925 }
926 uint64_t Offset = RelI->getOffset();
927 uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset(Offset);
928
929 // R_AARCH64_CALL26 requires immediate to be in range -2^27 <= imm < 2^27
930 // If distance between source and target is out of range then we should
931 // create thunk.
932 if (!isInt<28>(Address + Value.Addend - SourceAddress))
933 return false;
934
935 resolveRelocation(Sections[SectionID], Offset, Address, RelI->getType(),
936 Value.Addend);
937
938 return true;
939 }
940
898941 Expected
899942 RuntimeDyldELF::processRelocationRef(
900943 unsigned SectionID, relocation_iterator RelI, const ObjectFile &O,
10021045 (uint64_t)Section.getAddressWithOffset(i->second),
10031046 RelType, 0);
10041047 DEBUG(dbgs() << " Stub function found\n");
1005 } else {
1048 } else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) {
10061049 // Create a new stub function.
10071050 DEBUG(dbgs() << " Create a new stub function\n");
10081051 Stubs[Value] = Section.getStubOffset();
3838
3939 void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset,
4040 uint64_t Value, uint32_t Type, int64_t Addend);
41
42 bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI,
43 const RelocationValueRef &Value);
4144
4245 void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
4346 uint32_t Value, uint32_t Type, int32_t Addend);
0 # RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %T/branch.o %s
1 # RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -check=%s %T/branch.o
2
3 .globl _main
4 .weak _label1
5
6 .section .text.1,"ax"
7 _label1:
8 nop
9 _main:
10 b _label1
11
12 ## Branch 1 instruction back from _main
13 # rtdyld-check: *{4}(_main) = 0x17ffffff