llvm.org GIT mirror llvm / 2c350aa
[RuntimeDyld][ORC] Add support for Thumb mode to RuntimeDyldMachOARM. This patch adds support for thumb relocations to RuntimeDyldMachOARM, and adds a target-specific flags field to JITSymbolFlags (so that on ARM we can record whether each symbol is Thumb-mode code). RuntimeDyldImpl::emitSection is modified to ensure that stubs memory is correctly aligned based on the size returned by getStubAlignment(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310517 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 2 years ago
8 changed file(s) with 282 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
3939 class JITSymbolFlags {
4040 public:
4141 using UnderlyingType = uint8_t;
42 using TargetFlagsType = uint64_t;
4243
4344 enum FlagNames : UnderlyingType {
4445 None = 0,
5556 /// @brief Construct a JITSymbolFlags instance from the given flags.
5657 JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
5758
59 /// @brief Construct a JITSymbolFlags instance from the given flags and target
60 /// flags.
61 JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
62 : Flags(Flags), TargetFlags(TargetFlags) {}
63
5864 /// @brief Return true if there was an error retrieving this symbol.
5965 bool hasError() const {
6066 return (Flags & HasError) == HasError;
7985 return (Flags & Exported) == Exported;
8086 }
8187
88 /// @brief Implicitly convert to the underlying flags type.
8289 operator UnderlyingType&() { return Flags; }
90
91 /// @brief Return a reference to the target-specific flags.
92 TargetFlagsType& getTargetFlags() { return TargetFlags; }
8393
8494 /// Construct a JITSymbolFlags value based on the flags of the given global
8595 /// value.
91101
92102 private:
93103 UnderlyingType Flags = None;
104 TargetFlagsType TargetFlags = 0;
105 };
106
107 /// @brief ARM-specific JIT symbol flags.
108 /// FIXME: This should be moved into a target-specific header.
109 class ARMJITSymbolFlags {
110 public:
111 ARMJITSymbolFlags() = default;
112
113 enum FlagNames {
114 None = 0,
115 Thumb = 1 << 0
116 };
117
118 operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
119
120 static ARMJITSymbolFlags fromObjectSymbol(
121 const object::BasicSymbolRef &Symbol);
122 private:
123 JITSymbolFlags::TargetFlagsType Flags = 0;
94124 };
95125
96126 /// @brief Represents a symbol that has been evaluated to an address already.
3838 Flags |= JITSymbolFlags::Exported;
3939 return Flags;
4040 }
41
42 ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol(
43 const object::BasicSymbolRef &Symbol) {
44 ARMJITSymbolFlags Flags;
45 if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb)
46 Flags |= ARMJITSymbolFlags::Thumb;
47 return Flags;
48 }
232232 return NameOrErr.takeError();
233233
234234 // Compute JIT symbol flags.
235 JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(*I);
235 JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I);
236236
237237 // If this is a weak definition, check to see if there's a strong one.
238238 // If there is, skip this symbol (we won't be providing it: the strong
615615 }
616616 }
617617
618 JITSymbolFlags RuntimeDyldImpl::getJITSymbolFlags(const BasicSymbolRef &SR) {
619 return JITSymbolFlags::fromObjectSymbol(SR);
620 }
621
618622 Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
619623 CommonSymbolList &CommonSymbols) {
620624 if (CommonSymbols.empty())
684688 Addr += AlignOffset;
685689 Offset += AlignOffset;
686690 }
687 JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
691 JITSymbolFlags JITSymFlags = getJITSymbolFlags(Sym);
688692 DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
689693 << format("%p", Addr) << "\n");
690694 GlobalSymbolTable[Name] =
745749 // Code section alignment needs to be at least as high as stub alignment or
746750 // padding calculations may by incorrect when the section is remapped to a
747751 // higher alignment.
748 if (IsCode)
752 if (IsCode) {
749753 Alignment = std::max(Alignment, getStubAlignment());
754 if (StubBufSize > 0)
755 PaddingSize += getStubAlignment() - 1;
756 }
750757
751758 // Some sections, such as debug info, don't need to be loaded for execution.
752759 // Process those only if explicitly requested.
770777 // Fill in any extra bytes we allocated for padding
771778 if (PaddingSize != 0) {
772779 memset(Addr + DataSize, 0, PaddingSize);
773 // Update the DataSize variable so that the stub offset is set correctly.
780 // Update the DataSize variable to include padding.
774781 DataSize += PaddingSize;
782
783 // Align DataSize to stub alignment if we have any stubs (PaddingSize will
784 // have been increased above to account for this).
785 if (StubBufSize > 0)
786 DataSize &= ~(getStubAlignment() - 1);
775787 }
776788
777789 DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name
863875 } else if (Arch == Triple::arm || Arch == Triple::armeb) {
864876 // TODO: There is only ARM far stub now. We should add the Thumb stub,
865877 // and stubs for branches Thumb - ARM and ARM - Thumb.
866 writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,
878 writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc, [pc, #-4]
867879 return Addr + 4;
868880 } else if (IsMipsO32ABI) {
869881 // 0: 3c190000 lui t9,%hi(addr).
970982 resolveRelocationList(Relocs, 0);
971983 } else {
972984 uint64_t Addr = 0;
985 JITSymbolFlags Flags;
973986 RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name);
974987 if (Loc == GlobalSymbolTable.end()) {
975988 // This is an external symbol, try to get its address from the symbol
976989 // resolver.
977990 // First search for the symbol in this logical dylib.
978991 if (auto Sym = Resolver.findSymbolInLogicalDylib(Name.data())) {
979 if (auto AddrOrErr = Sym.getAddress())
992 if (auto AddrOrErr = Sym.getAddress()) {
980993 Addr = *AddrOrErr;
981 else
994 Flags = Sym.getFlags();
995 } else
982996 return AddrOrErr.takeError();
983997 } else if (auto Err = Sym.takeError())
984998 return Err;
9861000 // If that fails, try searching for an external symbol.
9871001 if (!Addr) {
9881002 if (auto Sym = Resolver.findSymbol(Name.data())) {
989 if (auto AddrOrErr = Sym.getAddress())
1003 if (auto AddrOrErr = Sym.getAddress()) {
9901004 Addr = *AddrOrErr;
991 else
1005 Flags = Sym.getFlags();
1006 } else
9921007 return AddrOrErr.takeError();
9931008 } else if (auto Err = Sym.takeError())
9941009 return Err;
10061021 const auto &SymInfo = Loc->second;
10071022 Addr = getSectionLoadAddress(SymInfo.getSectionID()) +
10081023 SymInfo.getOffset();
1024 Flags = SymInfo.getFlags();
10091025 }
10101026
10111027 // FIXME: Implement error handling that doesn't kill the host program!
10161032 // If Resolver returned UINT64_MAX, the client wants to handle this symbol
10171033 // manually and we shouldn't resolve its relocations.
10181034 if (Addr != UINT64_MAX) {
1035
1036 // Tweak the address based on the symbol flags if necessary.
1037 // For example, this is used by RuntimeDyldMachOARM to toggle the low bit
1038 // if the target symbol is Thumb.
1039 Addr = modifyAddressBasedOnFlags(Addr, Flags);
1040
10191041 DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t"
10201042 << format("0x%lx", Addr) << "\n");
10211043 // This list may have been updated when we called getSymbolAddress, so
148148 /// The size of this relocation (MachO specific).
149149 unsigned Size;
150150
151 // COFF specific.
152 bool IsTargetThumbFunc;
151 // ARM (MachO and COFF) specific.
152 bool IsTargetThumbFunc = false;
153153
154154 RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend)
155155 : SectionID(id), Offset(offset), RelType(type), Addend(addend),
194194 uint64_t Offset;
195195 int64_t Addend;
196196 const char *SymbolName;
197 bool IsStubThumb = false;
197198 RelocationValueRef() : SectionID(0), Offset(0), Addend(0),
198199 SymbolName(nullptr) {}
199200
200201 inline bool operator==(const RelocationValueRef &Other) const {
201202 return SectionID == Other.SectionID && Offset == Other.Offset &&
202 Addend == Other.Addend && SymbolName == Other.SymbolName;
203 Addend == Other.Addend && SymbolName == Other.SymbolName &&
204 IsStubThumb == Other.IsStubThumb;
203205 }
204206 inline bool operator<(const RelocationValueRef &Other) const {
205207 if (SectionID != Other.SectionID)
208210 return Offset < Other.Offset;
209211 if (Addend != Other.Addend)
210212 return Addend < Other.Addend;
213 if (IsStubThumb != Other.IsStubThumb)
214 return IsStubThumb < Other.IsStubThumb;
211215 return SymbolName < Other.SymbolName;
212216 }
213217 };
215219 /// @brief Symbol info for RuntimeDyld.
216220 class SymbolTableEntry {
217221 public:
218 SymbolTableEntry()
219 : Offset(0), SectionID(0) {}
222 SymbolTableEntry() = default;
220223
221224 SymbolTableEntry(unsigned SectionID, uint64_t Offset, JITSymbolFlags Flags)
222225 : Offset(Offset), SectionID(SectionID), Flags(Flags) {}
223226
224227 unsigned getSectionID() const { return SectionID; }
225228 uint64_t getOffset() const { return Offset; }
229 void setOffset(uint64_t NewOffset) { Offset = NewOffset; }
226230
227231 JITSymbolFlags getFlags() const { return Flags; }
228232
229233 private:
230 uint64_t Offset;
231 unsigned SectionID;
232 JITSymbolFlags Flags;
234 uint64_t Offset = 0;
235 unsigned SectionID = 0;
236 JITSymbolFlags Flags = JITSymbolFlags::None;
233237 };
234238
235239 typedef StringMap RTDyldSymbolTable;
364368 /// Dst.
365369 void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const;
366370
371 /// Generate JITSymbolFlags from a libObject symbol.
372 virtual JITSymbolFlags getJITSymbolFlags(const BasicSymbolRef &Sym);
373
374 /// Modify the given target address based on the given symbol flags.
375 /// This can be used by subclasses to tweak addresses based on symbol flags,
376 /// For example: the MachO/ARM target uses it to set the low bit if the target
377 /// is a thumb symbol.
378 virtual uint64_t modifyAddressBasedOnFlags(uint64_t Addr,
379 JITSymbolFlags Flags) const {
380 return Addr;
381 }
382
367383 /// \brief Given the common symbols discovered in the object file, emit a
368384 /// new section for them and update the symbol mappings in the object and
369385 /// symbol table.
492508 if (SymEntry.getSectionID() != AbsoluteSymbolSection)
493509 SectionAddr = getSectionLoadAddress(SymEntry.getSectionID());
494510 uint64_t TargetAddr = SectionAddr + SymEntry.getOffset();
511
512 // FIXME: Have getSymbol should return the actual address and the client
513 // modify it based on the flags. This will require clients to be
514 // aware of the target architecture, which we should build
515 // infrastructure for.
516 TargetAddr = modifyAddressBasedOnFlags(TargetAddr, SymEntry.getFlags());
495517 return JITEvaluatedSymbol(TargetAddr, SymEntry.getFlags());
496518 }
497519
5454 RuntimeDyldMachO::processScatteredVANILLA(
5555 unsigned SectionID, relocation_iterator RelI,
5656 const ObjectFile &BaseObjT,
57 RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
57 RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID,
58 bool TargetIsLocalThumbFunc) {
5859 const MachOObjectFile &Obj =
5960 static_cast(BaseObjT);
6061 MachO::any_relocation_info RE =
8485
8586 Addend -= SectionBaseAddr;
8687 RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
88 R.IsTargetThumbFunc = TargetIsLocalThumbFunc;
8789
8890 addRelocationForSection(R, TargetSectionID);
8991
8282 Expected
8383 processScatteredVANILLA(unsigned SectionID, relocation_iterator RelI,
8484 const ObjectFile &BaseObjT,
85 RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID);
85 RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID,
86 bool TargetIsLocalThumbFunc = false);
8687
8788 /// Construct a RelocationValueRef representing the relocation target.
8889 /// For Symbols in known sections, this will return a RelocationValueRef
3333
3434 unsigned getStubAlignment() override { return 4; }
3535
36 int64_t decodeAddend(const RelocationEntry &RE) const {
36 JITSymbolFlags getJITSymbolFlags(const BasicSymbolRef &SR) override {
37 auto Flags = RuntimeDyldImpl::getJITSymbolFlags(SR);
38 Flags.getTargetFlags() = ARMJITSymbolFlags::fromObjectSymbol(SR);
39 return Flags;
40 }
41
42 uint64_t modifyAddressBasedOnFlags(uint64_t Addr,
43 JITSymbolFlags Flags) const override {
44 if (Flags.getTargetFlags() & ARMJITSymbolFlags::Thumb)
45 Addr |= 0x1;
46 return Addr;
47 }
48
49 Expected decodeAddend(const RelocationEntry &RE) const {
3750 const SectionEntry &Section = Sections[RE.SectionID];
3851 uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
3952
4558 Temp &= 0x00ffffff; // Mask out the opcode.
4659 // Now we've got the shifted immediate, shift by 2, sign extend and ret.
4760 return SignExtend32<26>(Temp << 2);
61 }
62
63 case MachO::ARM_THUMB_RELOC_BR22: {
64 // This is a pair of instructions whose operands combine to provide 22
65 // bits of displacement:
66 // Encoding for high bits 1111 0XXX XXXX XXXX
67 // Encoding for low bits 1111 1XXX XXXX XXXX
68 uint16_t HighInsn = readBytesUnaligned(LocalAddress, 2);
69 if ((HighInsn & 0xf800) != 0xf000)
70 return make_error("Unrecognized thumb branch encoding "
71 "(BR22 high bits)",
72 inconvertibleErrorCode());
73
74 uint16_t LowInsn = readBytesUnaligned(LocalAddress + 2, 2);
75 if ((LowInsn & 0xf800) != 0xf800)
76 return make_error("Unrecognized thumb branch encoding "
77 "(BR22 low bits)",
78 inconvertibleErrorCode());
79
80 return SignExtend64<23>(((HighInsn & 0x7ff) << 12) |
81 ((LowInsn & 0x7ff) << 1));
4882 }
4983 }
5084 }
6094 Obj.getRelocation(RelI->getRawDataRefImpl());
6195 uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
6296
97 // Set to true for thumb functions in this (or previous) TUs.
98 // Will be used to set the TargetIsThumbFunc member on the relocation entry.
99 bool TargetIsLocalThumbFunc = false;
100 if (Obj.getPlainRelocationExternal(RelInfo)) {
101 auto Symbol = RelI->getSymbol();
102 StringRef TargetName;
103 if (auto TargetNameOrErr = Symbol->getName())
104 TargetName = *TargetNameOrErr;
105 else
106 return TargetNameOrErr.takeError();
107
108 // If the target is external but the value doesn't have a name then we've
109 // converted the value to a section/offset pair, but we still need to set
110 // the IsTargetThumbFunc bit, so look the value up in the globla symbol table.
111 auto EntryItr = GlobalSymbolTable.find(TargetName);
112 if (EntryItr != GlobalSymbolTable.end()) {
113 TargetIsLocalThumbFunc =
114 EntryItr->second.getFlags().getTargetFlags() &
115 ARMJITSymbolFlags::Thumb;
116 }
117 }
118
63119 if (Obj.isRelocationScattered(RelInfo)) {
64120 if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF)
65121 return processHALFSECTDIFFRelocation(SectionID, RelI, Obj,
66122 ObjSectionToID);
67123 else if (RelType == MachO::GENERIC_RELOC_VANILLA)
68 return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID);
124 return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID,
125 TargetIsLocalThumbFunc);
69126 else
70127 return ++RelI;
71128 }
76133 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_SECTDIFF);
77134 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_LOCAL_SECTDIFF);
78135 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PB_LA_PTR);
79 UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_RELOC_BR22);
80136 UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_32BIT_BRANCH);
81137 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_HALF);
82138 default:
88144 }
89145
90146 RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
91 RE.Addend = decodeAddend(RE);
147 if (auto AddendOrErr = decodeAddend(RE))
148 RE.Addend = *AddendOrErr;
149 else
150 return AddendOrErr.takeError();
151 RE.IsTargetThumbFunc = TargetIsLocalThumbFunc;
152
92153 RelocationValueRef Value;
93154 if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
94155 Value = *ValueOrErr;
95156 else
96157 return ValueOrErr.takeError();
97158
159 // If this is a branch from a thumb function (BR22) then make sure we mark
160 // the value as being a thumb stub: we don't want to mix it up with an ARM
161 // stub targeting the same function.
162 if (RE.RelType == MachO::ARM_THUMB_RELOC_BR22)
163 Value.IsStubThumb = TargetIsLocalThumbFunc;
164
98165 if (RE.IsPCRel)
99 makeValueAddendPCRel(Value, RelI, 8);
100
101 if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24)
166 makeValueAddendPCRel(Value, RelI,
167 (RE.RelType == MachO::ARM_THUMB_RELOC_BR22) ? 4 : 8);
168
169 if (RE.RelType == MachO::ARM_RELOC_BR24 ||
170 RE.RelType == MachO::ARM_THUMB_RELOC_BR22)
102171 processBranchRelocation(RE, Value, Stubs);
103172 else {
104173 RE.Addend = Value.Offset;
123192 Value -= FinalAddress;
124193 // ARM PCRel relocations have an effective-PC offset of two instructions
125194 // (four bytes in Thumb mode, 8 bytes in ARM mode).
126 // FIXME: For now, assume ARM mode.
127 Value -= 8;
195 Value -= (RE.RelType == MachO::ARM_THUMB_RELOC_BR22) ? 4 : 8;
128196 }
129197
130198 switch (RE.RelType) {
199 case MachO::ARM_THUMB_RELOC_BR22: {
200 Value += RE.Addend;
201 uint16_t HighInsn = readBytesUnaligned(LocalAddress, 2);
202 assert((HighInsn & 0xf800) == 0xf000 &&
203 "Unrecognized thumb branch encoding (BR22 high bits)");
204 HighInsn = (HighInsn & 0xf800) | ((Value >> 12) & 0x7ff);
205
206 uint16_t LowInsn = readBytesUnaligned(LocalAddress + 2, 2);
207 assert((LowInsn & 0xf800) != 0xf8000 &&
208 "Unrecognized thumb branch encoding (BR22 low bits)");
209 LowInsn = (LowInsn & 0xf800) | ((Value >> 1) & 0x7ff);
210
211 writeBytesUnaligned(HighInsn, LocalAddress, 2);
212 writeBytesUnaligned(LowInsn, LocalAddress + 2, 2);
213 break;
214 }
215
131216 case MachO::ARM_RELOC_VANILLA:
217 if (RE.IsTargetThumbFunc)
218 Value |= 0x01;
132219 writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
133220 break;
134221 case MachO::ARM_RELOC_BR24: {
157244 Value = SectionABase - SectionBBase + RE.Addend;
158245 if (RE.Size & 0x1) // :upper16:
159246 Value = (Value >> 16);
247
248 bool IsThumb = RE.Size & 0x2;
249
160250 Value &= 0xffff;
161251
162252 uint32_t Insn = readBytesUnaligned(LocalAddress, 4);
163 Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff);
253
254 if (IsThumb)
255 Insn = (Insn & 0x8f00fbf0) | ((Value & 0xf000) >> 12) |
256 ((Value & 0x0800) >> 1) | ((Value & 0x0700) << 20) |
257 ((Value & 0x00ff) << 16);
258 else
259 Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff);
164260 writeBytesUnaligned(Insn, LocalAddress, 4);
165261 break;
166262 }
195291 Addr = Section.getAddressWithOffset(i->second);
196292 } else {
197293 // Create a new stub function.
294 assert(Section.getStubOffset() % 4 == 0 && "Misaligned stub");
198295 Stubs[Value] = Section.getStubOffset();
199 uint8_t *StubTargetAddr = createStubFunction(
200 Section.getAddressWithOffset(Section.getStubOffset()));
296 uint32_t StubOpcode = 0;
297 if (RE.RelType == MachO::ARM_RELOC_BR24)
298 StubOpcode = 0xe51ff004; // ldr pc, [pc, #-4]
299 else if (RE.RelType == MachO::ARM_THUMB_RELOC_BR22)
300 StubOpcode = 0xf000f8df; // ldr pc, [pc]
301 else
302 llvm_unreachable("Unrecognized relocation");
303 Addr = Section.getAddressWithOffset(Section.getStubOffset());
304 writeBytesUnaligned(StubOpcode, Addr, 4);
305 uint8_t *StubTargetAddr = Addr + 4;
201306 RelocationEntry StubRE(
202307 RE.SectionID, StubTargetAddr - Section.getAddress(),
203308 MachO::GENERIC_RELOC_VANILLA, Value.Offset, false, 2);
309 StubRE.IsTargetThumbFunc = RE.IsTargetThumbFunc;
204310 if (Value.SymbolName)
205311 addRelocationForSymbol(StubRE, Value.SymbolName);
206312 else
207313 addRelocationForSection(StubRE, Value.SectionID);
208 Addr = Section.getAddressWithOffset(Section.getStubOffset());
209314 Section.advanceStubOffset(getMaxStubSize());
210315 }
211316 RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0,
222327 MachO::any_relocation_info RE =
223328 MachO.getRelocation(RelI->getRawDataRefImpl());
224329
225
226330 // For a half-diff relocation the length bits actually record whether this
227331 // is a movw/movt, and whether this is arm or thumb.
228332 // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1).
229333 // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1).
230334 unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE);
231 if (HalfDiffKindBits & 0x2)
232 llvm_unreachable("Thumb not yet supported.");
335 bool IsThumb = HalfDiffKindBits & 0x2;
233336
234337 SectionEntry &Section = Sections[SectionID];
235338 uint32_t RelocType = MachO.getAnyRelocationType(RE);
237340 uint64_t Offset = RelI->getOffset();
238341 uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
239342 int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out.
240 Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff);
343
344 if (IsThumb)
345 Immediate = ((Immediate & 0x0000000f) << 12) |
346 ((Immediate & 0x00000400) << 1) |
347 ((Immediate & 0x70000000) >> 20) |
348 ((Immediate & 0x00ff0000) >> 16);
349 else
350 Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff);
241351
242352 ++RelI;
243353 MachO::any_relocation_info RE2 =
0 # RUN: llvm-mc -triple=thumbv7s-apple-ios7.0.0 -filetype=obj -o %T/MachO_Thumb.o %s
1 # RUN: llvm-rtdyld -triple=thumbv7s-apple-ios7.0.0 -verify -check=%s %/T/MachO_Thumb.o
2
3 .section __TEXT,__text,regular,pure_instructions
4 .syntax unified
5
6 # Add 'aaa' to the common symbols to make sure 'baz' isn't at the start of the
7 # section. This ensures that we test VANILLA relocation addends correctly.
8 .comm aaa, 4, 2
9 .comm baz, 4, 2
10
11
12 .globl bar
13 .p2align 1
14 .code 16 @ @bar
15 .thumb_func bar
16
17 bar:
18 # Check lower 16-bits of section difference relocation
19 # rtdyld-check: decode_operand(insn1, 1) = (foo-(nextPC+8))[15:0]
20 insn1:
21 movw r0, :lower16:(foo-(nextPC+8))
22 # Check upper 16-bits of section difference relocation
23 # rtdyld-check: decode_operand(insn2, 2) = (foo-(nextPC+8))[31:16]
24 insn2:
25 movt r0, :upper16:(foo-(nextPC+8))
26 nextPC:
27 nop
28
29 # Check stub generation for external symbols by referencing a common symbol, 'baz'.
30 # Check both the content of the stub, and the reference to the stub.
31 # Stub should contain '0xf000f8df' (ldr.w pc, [pc]), followed by the target.
32 #
33 # rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, baz)) = 0xf000f8df
34 # rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, baz) + 4) = baz
35 #
36 # rtdyld-check: decode_operand(insn3, 0) = stub_addr(MachO_Thumb.o, __text, baz) - (insn3 + 4)
37 insn3:
38 bl baz
39
40 # Check stub generation for internal symbols by referencing 'bar'.
41 # rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, bar) + 4) = bar & 0xfffffffffffffffe
42 insn4:
43 bl bar
44
45 .section __DATA,__data
46 .align 2
47 foo:
48 .long 0
49
50 .subsections_via_symbols