llvm.org GIT mirror llvm / 3a049ed
[JITLink] Track section alignment and make sure it is respected during layout. Previously we had only honored alignments on individual atoms, but tools/runtimes may assume that the section alignment is respected too. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360555 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 1 year, 6 months ago
6 changed file(s) with 82 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
2121 #include "llvm/Support/Endian.h"
2222 #include "llvm/Support/Error.h"
2323 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/Support/MathExtras.h"
2425 #include "llvm/Support/Memory.h"
2526 #include "llvm/Support/MemoryBuffer.h"
2627
328329 friend class AtomGraph;
329330
330331 private:
331 Section(StringRef Name, sys::Memory::ProtectionFlags Prot, unsigned Ordinal,
332 bool IsZeroFill)
333 : Name(Name), Prot(Prot), Ordinal(Ordinal), IsZeroFill(IsZeroFill) {}
332 Section(StringRef Name, uint32_t Alignment, sys::Memory::ProtectionFlags Prot,
333 unsigned Ordinal, bool IsZeroFill)
334 : Name(Name), Alignment(Alignment), Prot(Prot), Ordinal(Ordinal),
335 IsZeroFill(IsZeroFill) {
336 assert(isPowerOf2_32(Alignment) && "Alignments must be a power of 2");
337 }
334338
335339 using DefinedAtomSet = DenseSet;
336340
340344
341345 ~Section();
342346 StringRef getName() const { return Name; }
347 uint32_t getAlignment() const { return Alignment; }
343348 sys::Memory::ProtectionFlags getProtectionFlags() const { return Prot; }
344349 unsigned getSectionOrdinal() const { return Ordinal; }
345350 size_t getNextAtomOrdinal() { return ++NextAtomOrdinal; }
387392 }
388393
389394 StringRef Name;
395 uint32_t Alignment = 0;
390396 sys::Memory::ProtectionFlags Prot;
391397 unsigned Ordinal = 0;
392398 unsigned NextAtomOrdinal = 0;
402408 private:
403409 DefinedAtom(Section &Parent, JITTargetAddress Address, uint32_t Alignment)
404410 : Atom("", Address), Parent(Parent), Ordinal(Parent.getNextAtomOrdinal()),
405 Alignment(Alignment) {}
411 Alignment(Alignment) {
412 assert(isPowerOf2_32(Alignment) && "Alignments must be a power of two");
413 }
406414
407415 DefinedAtom(Section &Parent, StringRef Name, JITTargetAddress Address,
408416 uint32_t Alignment)
409417 : Atom(Name, Address), Parent(Parent),
410 Ordinal(Parent.getNextAtomOrdinal()), Alignment(Alignment) {}
418 Ordinal(Parent.getNextAtomOrdinal()), Alignment(Alignment) {
419 assert(isPowerOf2_32(Alignment) && "Alignments must be a power of two");
420 }
411421
412422 public:
413423 using edge_iterator = EdgeVector::iterator;
509519 inline SectionRange Section::getRange() const {
510520 if (atoms_empty())
511521 return SectionRange();
512 DefinedAtom *First = *DefinedAtoms.begin(), *Last = *DefinedAtoms.end();
522 DefinedAtom *First = *DefinedAtoms.begin(), *Last = *DefinedAtoms.begin();
513523 for (auto *DA : atoms()) {
514524 if (DA->getAddress() < First->getAddress())
515525 First = DA;
601611 support::endianness getEndianness() const { return Endianness; }
602612
603613 /// Create a section with the given name, protection flags, and alignment.
604 Section &createSection(StringRef Name, sys::Memory::ProtectionFlags Prot,
605 bool IsZeroFill) {
614 Section &createSection(StringRef Name, uint32_t Alignment,
615 sys::Memory::ProtectionFlags Prot, bool IsZeroFill) {
606616 std::unique_ptr
Sec(
607 new Section(Name, Prot, Sections.size(), IsZeroFill));
617 new Section(Name, Alignment, Prot, Sections.size(), IsZeroFill));
608618 Sections.push_back(std::move(Sec));
609619 return *Sections.back();
610620 }
240240 for (auto &SI : SegLayout.ContentSections) {
241241 assert(!SI.S->atoms_empty() && "Sections in layout must not be empty");
242242 assert(!SI.Atoms.empty() && "Section layouts must not be empty");
243
244 // Bump to section alignment before processing atoms.
245 SegContentSize = alignTo(SegContentSize, SI.S->getAlignment());
246
243247 for (auto *DA : SI.Atoms) {
244248 SegContentSize = alignTo(SegContentSize, DA->getAlignment());
245249 SegContentSize += DA->getSize();
248252
249253 // Get segment content alignment.
250254 unsigned SegContentAlign = 1;
251 if (!SegLayout.ContentSections.empty())
255 if (!SegLayout.ContentSections.empty()) {
256 auto &FirstContentSection = SegLayout.ContentSections.front();
252257 SegContentAlign =
253 SegLayout.ContentSections.front().Atoms.front()->getAlignment();
258 std::max(FirstContentSection.S->getAlignment(),
259 FirstContentSection.Atoms.front()->getAlignment());
260 }
254261
255262 // Calculate segment zero-fill size.
256263 uint64_t SegZeroFillSize = 0;
257264 for (auto &SI : SegLayout.ZeroFillSections) {
258265 assert(!SI.S->atoms_empty() && "Sections in layout must not be empty");
259266 assert(!SI.Atoms.empty() && "Section layouts must not be empty");
267
268 // Bump to section alignment before processing atoms.
269 SegZeroFillSize = alignTo(SegZeroFillSize, SI.S->getAlignment());
270
260271 for (auto *DA : SI.Atoms) {
261272 SegZeroFillSize = alignTo(SegZeroFillSize, DA->getAlignment());
262273 SegZeroFillSize += DA->getSize();
265276
266277 // Calculate segment zero-fill alignment.
267278 uint32_t SegZeroFillAlign = 1;
268 if (!SegLayout.ZeroFillSections.empty())
279
280 if (!SegLayout.ZeroFillSections.empty()) {
281 auto &FirstZeroFillSection = SegLayout.ZeroFillSections.front();
269282 SegZeroFillAlign =
270 SegLayout.ZeroFillSections.front().Atoms.front()->getAlignment();
283 std::max(FirstZeroFillSection.S->getAlignment(),
284 FirstZeroFillSection.Atoms.front()->getAlignment());
285 }
271286
272287 if (SegContentSize == 0)
273288 SegContentAlign = SegZeroFillAlign;
313328 Alloc->getTargetMemory(static_cast(Prot));
314329
315330 for (auto *SIList : {&SL.ContentSections, &SL.ZeroFillSections})
316 for (auto &SI : *SIList)
331 for (auto &SI : *SIList) {
332 AtomTargetAddr = alignTo(AtomTargetAddr, SI.S->getAlignment());
317333 for (auto *DA : SI.Atoms) {
318334 AtomTargetAddr = alignTo(AtomTargetAddr, DA->getAlignment());
319335 DA->setAddress(AtomTargetAddr);
320336 AtomTargetAddr += DA->getSize();
321337 }
338 }
322339 }
323340
324341 return Error::success();
149149 auto SegMem = Alloc.getWorkingMemory(
150150 static_cast(Prot));
151151 char *LastAtomEnd = SegMem.data();
152 char *AtomDataPtr = nullptr;
152 char *AtomDataPtr = LastAtomEnd;
153153
154154 LLVM_DEBUG({
155155 dbgs() << " Processing segment "
161161
162162 for (auto &SI : SegLayout.ContentSections) {
163163 LLVM_DEBUG(dbgs() << " " << SI.S->getName() << ":\n");
164
165 AtomDataPtr += alignmentAdjustment(AtomDataPtr, SI.S->getAlignment());
166
167 LLVM_DEBUG({
168 dbgs() << " Bumped atom pointer to " << (const void *)AtomDataPtr
169 << " to meet section alignment "
170 << " of " << SI.S->getAlignment() << "\n";
171 });
172
164173 for (auto *DA : SI.Atoms) {
165 AtomDataPtr = LastAtomEnd;
166174
167175 // Align.
168176 AtomDataPtr += alignmentAdjustment(AtomDataPtr, DA->getAlignment());
208216
209217 // Update atom end pointer.
210218 LastAtomEnd = AtomDataPtr + DA->getContent().size();
219 AtomDataPtr = LastAtomEnd;
211220 }
212221 }
213222
8484 if (!CommonSymbolsSection) {
8585 auto Prot = static_cast(
8686 sys::Memory::MF_READ | sys::Memory::MF_WRITE);
87 auto &GenericSection = G->createSection("", Prot, true);
87 auto &GenericSection = G->createSection("", 1, Prot, true);
8888 CommonSymbolsSection = MachOSection(GenericSection);
8989 }
9090 return *CommonSymbolsSection;
100100 return errorCodeToError(EC);
101101
102102 unsigned SectionIndex = SecRef.getIndex() + 1;
103
104 uint32_t Align = SecRef.getAlignment();
105 if (!isPowerOf2_32(Align))
106 return make_error("Section " + Name +
107 " has non-power-of-2 "
108 "alignment");
103109
104110 // FIXME: Get real section permissions
105111 // How, exactly, on MachO?
111117 Prot = static_cast(sys::Memory::MF_READ |
112118 sys::Memory::MF_WRITE);
113119
114 auto &GenericSection = G->createSection(Name, Prot, SecRef.isBSS());
120 auto &GenericSection = G->createSection(Name, Align, Prot, SecRef.isBSS());
115121
116122 LLVM_DEBUG({
117123 dbgs() << "Adding section " << Name << ": "
398398 private:
399399 Section &getGOTSection() {
400400 if (!GOTSection)
401 GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ, false);
401 GOTSection = &G.createSection("$__GOT", 8, sys::Memory::MF_READ, false);
402402 return *GOTSection;
403403 }
404404
406406 if (!StubsSection) {
407407 auto StubsProt = static_cast(
408408 sys::Memory::MF_READ | sys::Memory::MF_EXEC);
409 StubsSection = &G.createSection("$__STUBS", StubsProt, false);
409 StubsSection = &G.createSection("$__STUBS", 8, StubsProt, false);
410410 }
411411 return *StubsSection;
412412 }
276276 .globl zero_fill_test
277277 .zerofill __DATA,__zero_fill_test,zero_fill_test,8,3
278278
279 # Check that section alignments are respected.
280 # We test this by introducing two segments with alignment 8, each containing one
281 # byte of data. We require both symbols to have an aligned address.
282 #
283 # jitlink-check: section_alignment_check1[2:0] = 0
284 # jitlink-check: section_alignment_check2[2:0] = 0
285 .section __DATA,__sec_align_chk1
286 .p2align 3
287
288 .globl section_alignment_check1
289 section_alignment_check1:
290 .byte 0
291
292 .section __DATA,__sec_align_chk2
293 .p2align 3
294
295 .globl section_alignment_check2
296 section_alignment_check2:
297 .byte 0
298
279299 .subsections_via_symbols