llvm.org GIT mirror llvm / 7fdae47
[JITLink] Add support for MachO .alt_entry atoms. The MachO .alt_entry directive is applied to a symbol to indicate that it is locked (in terms of address layout and liveness) to its predecessor atom. I.e. it is an alternate entry point, at a fixed offset, for the previous atom. This patch updates MachOAtomGraphBuilder to check for the .alt_entry flag on symbols and add a corresponding LayoutNext edge to the atom-graph. It also updates MachOAtomGraphBuilder_x86_64 to generalize handling of the X86_64_RELOC_SUBTRACTOR relocation: previously either the minuend or subtrahend of the subtraction had to be the same as the atom being fixed up, now it is only necessary for the minuend or subtrahend to be locked (via any chain of alt_entry directives) to the atom being fixed up. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360194 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 1 year, 6 months ago
4 changed file(s) with 175 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
4343 CustomAtomizeFunctions[SectionName] = std::move(Atomizer);
4444 }
4545
46 bool MachOAtomGraphBuilder::areLayoutLocked(const Atom &A, const Atom &B) {
47 // If these atoms are the same then they're trivially "locked".
48 if (&A == &B)
49 return true;
50
51 // If A and B are different, check whether either is undefined. (in which
52 // case they are not locked).
53 if (!A.isDefined() || !B.isDefined())
54 return false;
55
56 // A and B are different, but they're both defined atoms. We need to check
57 // whether they're part of the same alt_entry chain.
58 auto &DA = static_cast(A);
59 auto &DB = static_cast(B);
60
61 auto AStartItr = AltEntryStarts.find(&DA);
62 if (AStartItr == AltEntryStarts.end()) // If A is not in a chain bail out.
63 return false;
64
65 auto BStartItr = AltEntryStarts.find(&DB);
66 if (BStartItr == AltEntryStarts.end()) // If B is not in a chain bail out.
67 return false;
68
69 // A and B are layout locked if they're in the same chain.
70 return AStartItr->second == BStartItr->second;
71 }
72
4673 unsigned
4774 MachOAtomGraphBuilder::getPointerSize(const object::MachOObjectFile &Obj) {
4875 return Obj.is64Bit() ? 8 : 4;
125152 DenseMap SecToAtoms;
126153
127154 DenseMap FirstOrdinal;
155 std::vector AltEntryAtoms;
156
157 DenseSet ProcessedSymbols; // Used to check for duplicate defs.
128158
129159 for (auto SymI = Obj.symbol_begin(), SymE = Obj.symbol_end(); SymI != SymE;
130160 ++SymI) {
133163 auto Name = Sym.getName();
134164 if (!Name)
135165 return Name.takeError();
166
167 // Bail out on duplicate definitions: There should never be more than one
168 // definition for a symbol in a given object file.
169 if (ProcessedSymbols.count(*Name))
170 return make_error("Duplicate definition within object: " +
171 *Name);
172 else
173 ProcessedSymbols.insert(*Name);
136174
137175 auto Addr = Sym.getAddress();
138176 if (!Addr)
188226
189227 auto &Sec = SecByIndexItr->second;
190228
191 auto &A = G->addDefinedAtom(Sec.getGenericSection(), *Name, *Addr,
192 std::max(Sym.getAlignment(), 1U));
193
194 A.setGlobal(Flags & object::SymbolRef::SF_Global);
195 A.setExported(Flags & object::SymbolRef::SF_Exported);
196 A.setWeak(Flags & object::SymbolRef::SF_Weak);
197
198 A.setCallable(*SymType & object::SymbolRef::ST_Function);
229 auto &DA = G->addDefinedAtom(Sec.getGenericSection(), *Name, *Addr,
230 std::max(Sym.getAlignment(), 1U));
231
232 DA.setGlobal(Flags & object::SymbolRef::SF_Global);
233 DA.setExported(Flags & object::SymbolRef::SF_Exported);
234 DA.setWeak(Flags & object::SymbolRef::SF_Weak);
235
236 DA.setCallable(*SymType & object::SymbolRef::ST_Function);
237
238 // Check alt-entry.
239 {
240 uint16_t NDesc = 0;
241 if (Obj.is64Bit())
242 NDesc = Obj.getSymbolTableEntry(SymI->getRawDataRefImpl()).n_desc;
243 else
244 NDesc = Obj.getSymbolTableEntry(SymI->getRawDataRefImpl()).n_desc;
245 if (NDesc & MachO::N_ALT_ENTRY)
246 AltEntryAtoms.push_back(&DA);
247 }
199248
200249 LLVM_DEBUG({
201250 dbgs() << " Added " << *Name
202251 << " addr: " << format("0x%016" PRIx64, *Addr)
203 << ", align: " << A.getAlignment()
252 << ", align: " << DA.getAlignment()
204253 << ", section: " << Sec.getGenericSection().getName() << "\n";
205254 });
206255
207256 auto &SecAtoms = SecToAtoms[&Sec];
208 SecAtoms[A.getAddress() - Sec.getAddress()] = &A;
257 SecAtoms[DA.getAddress() - Sec.getAddress()] = &DA;
209258 }
210259
211260 // Add anonymous atoms.
262311 }
263312 }
264313
314 LLVM_DEBUG(dbgs() << "Adding alt-entry starts\n");
315
316 // Sort alt-entry atoms by address in ascending order.
317 llvm::sort(AltEntryAtoms.begin(), AltEntryAtoms.end(),
318 [](const DefinedAtom *LHS, const DefinedAtom *RHS) {
319 return LHS->getAddress() < RHS->getAddress();
320 });
321
322 // Process alt-entry atoms in address order to build the table of alt-entry
323 // atoms to alt-entry chain starts.
324 for (auto *DA : AltEntryAtoms) {
325 assert(!AltEntryStarts.count(DA) && "Duplicate entry in AltEntryStarts");
326
327 // DA is an alt-entry atom. Look for the predecessor atom that it is locked
328 // to, bailing out if we do not find one.
329 auto AltEntryPred = G->findAtomByAddress(DA->getAddress() - 1);
330 if (!AltEntryPred)
331 return AltEntryPred.takeError();
332
333 // Add a LayoutNext edge from the predecessor to this atom.
334 AltEntryPred->addEdge(Edge::LayoutNext, 0, *DA, 0);
335
336 // Check to see whether the predecessor itself is an alt-entry atom.
337 auto AltEntryStartItr = AltEntryStarts.find(&*AltEntryPred);
338 if (AltEntryStartItr != AltEntryStarts.end()) {
339 // If the predecessor was an alt-entry atom then re-use its value.
340 AltEntryStarts[DA] = AltEntryStartItr->second;
341 LLVM_DEBUG({
342 dbgs() << " " << *DA << " -> " << *AltEntryStartItr->second
343 << " (based on existing entry for " << *AltEntryPred << ")\n";
344 });
345 } else {
346 // If the predecessor does not have an entry then add an entry for this
347 // atom (i.e. the alt_entry atom) and a self-reference entry for the
348 /// predecessory atom that is the start of this chain.
349 AltEntryStarts[&*AltEntryPred] = &*AltEntryPred;
350 AltEntryStarts[DA] = &*AltEntryPred;
351 LLVM_DEBUG({
352 dbgs() << " " << *AltEntryPred << " -> " << *AltEntryPred << "\n"
353 << " " << *DA << " -> " << *AltEntryPred << "\n";
354 });
355 }
356 }
357
265358 return Error::success();
266359 }
267360
9595
9696 virtual Error addRelocations() = 0;
9797
98 /// Returns true if Atom A and Atom B are at a fixed offset from one another
99 /// (i.e. if they're part of the same alt-entry chain).
100 bool areLayoutLocked(const Atom &A, const Atom &B);
101
98102 private:
99103 static unsigned getPointerSize(const object::MachOObjectFile &Obj);
100104 static support::endianness getEndianness(const object::MachOObjectFile &Obj);
107111
108112 const object::MachOObjectFile &Obj;
109113 std::unique_ptr G;
114 DenseMap AltEntryStarts;
110115 DenseMap Sections;
111116 StringMap CustomAtomizeFunctions;
112117 Optional CommonSymbolsSection;
180180 MachOX86RelocationKind DeltaKind;
181181 Atom *TargetAtom;
182182 uint64_t Addend;
183 if (&AtomToFix == &*FromAtom) {
183 if (areLayoutLocked(AtomToFix, *FromAtom)) {
184184 TargetAtom = ToAtom;
185185 DeltaKind = (SubRI.r_length == 3) ? Delta64 : Delta32;
186186 Addend = FixupValue + (FixupAddress - FromAtom->getAddress());
187187 // FIXME: handle extern 'from'.
188 } else if (&AtomToFix == ToAtom) {
188 } else if (areLayoutLocked(AtomToFix, *ToAtom)) {
189189 TargetAtom = &*FromAtom;
190190 DeltaKind = (SubRI.r_length == 3) ? NegDelta64 : NegDelta32;
191191 Addend = FixupValue - (FixupAddress - ToAtom->getAddress());
192192 } else {
193193 // AtomToFix was neither FromAtom nor ToAtom.
194194 return make_error("SUBTRACTOR relocation must fix up "
195 "either 'A' or 'B'");
195 "either 'A' or 'B' (or an atom in one "
196 "of their alt-entry groups)");
196197 }
197198
198199 return PairRelocInfo(DeltaKind, TargetAtom, Addend);
128128 Lanon_minuend_long:
129129 .long Lanon_minuend_long - named_data + 2
130130
131
132131 # Named quad storage target (first named atom in __data).
133132 .globl named_data
134133 .p2align 3
135134 named_data:
136135 .quad 0x2222222222222222
136
137 # An alt-entry point for named_data
138 .globl named_data_alt_entry
139 .p2align 3
140 .alt_entry named_data_alt_entry
141 named_data_alt_entry:
142 .quad 0
137143
138144 # Check X86_64_RELOC_UNSIGNED / extern handling by putting the address of a
139145 # local named function in a pointer variable.
200206 minuend_long3:
201207 .long minuend_long3 - named_data + 2
202208
209 # Check X86_64_RELOC_SUBTRACTOR handling for exprs of the form
210 # "A: .quad/long B - C + D", where 'B' or 'C' is at a fixed offset from 'A'
211 # (i.e. is part of an alt_entry chain that includes 'A').
212 #
213 # Check "A: .long B - C + D" where 'B' is an alt_entry for 'A'.
214 # jitlink-check: *{4}subtractor_with_alt_entry_minuend_long = (subtractor_with_alt_entry_minuend_long_B - named_data + 2)[31:0]
215 .globl subtractor_with_alt_entry_minuend_long
216 .p2align 2
217 subtractor_with_alt_entry_minuend_long:
218 .long subtractor_with_alt_entry_minuend_long_B - named_data + 2
219
220 .globl subtractor_with_alt_entry_minuend_long_B
221 .p2align 2
222 .alt_entry subtractor_with_alt_entry_minuend_long_B
223 subtractor_with_alt_entry_minuend_long_B:
224 .long 0
225
226 # Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
227 # jitlink-check: *{8}subtractor_with_alt_entry_minuend_quad = (subtractor_with_alt_entry_minuend_quad_B - named_data + 2)
228 .globl subtractor_with_alt_entry_minuend_quad
229 .p2align 3
230 subtractor_with_alt_entry_minuend_quad:
231 .quad subtractor_with_alt_entry_minuend_quad_B - named_data + 2
232
233 .globl subtractor_with_alt_entry_minuend_quad_B
234 .p2align 3
235 .alt_entry subtractor_with_alt_entry_minuend_quad_B
236 subtractor_with_alt_entry_minuend_quad_B:
237 .quad 0
238
239 # Check "A: .long B - C + D" where 'C' is an alt_entry for 'A'.
240 # jitlink-check: *{4}subtractor_with_alt_entry_subtrahend_long = (named_data - subtractor_with_alt_entry_subtrahend_long_B + 2)[31:0]
241 .globl subtractor_with_alt_entry_subtrahend_long
242 .p2align 2
243 subtractor_with_alt_entry_subtrahend_long:
244 .long named_data - subtractor_with_alt_entry_subtrahend_long_B + 2
245
246 .globl subtractor_with_alt_entry_subtrahend_long_B
247 .p2align 2
248 .alt_entry subtractor_with_alt_entry_subtrahend_long_B
249 subtractor_with_alt_entry_subtrahend_long_B:
250 .long 0
251
252 # Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
253 # jitlink-check: *{8}subtractor_with_alt_entry_subtrahend_quad = (named_data - subtractor_with_alt_entry_subtrahend_quad_B + 2)
254 .globl subtractor_with_alt_entry_subtrahend_quad
255 .p2align 3
256 subtractor_with_alt_entry_subtrahend_quad:
257 .quad named_data - subtractor_with_alt_entry_subtrahend_quad_B + 2
258
259 .globl subtractor_with_alt_entry_subtrahend_quad_B
260 .p2align 3
261 .alt_entry subtractor_with_alt_entry_subtrahend_quad_B
262 subtractor_with_alt_entry_subtrahend_quad_B:
263 .quad 0
264
203265 .subsections_via_symbols