blob: c6d1e2c2c47e408ef13149c273f6c60ecba6ce52 [file] [log] [blame]
Nick Kledzike34182f2013-11-06 21:36:55 +00001//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10///
11/// \file Converts from in-memory Atoms to in-memory normalized mach-o.
12///
13/// +------------+
14/// | normalized |
15/// +------------+
16/// ^
17/// |
18/// |
Shankar Easwaran3d8de472014-01-27 03:09:26 +000019/// +-------+
Nick Kledzike34182f2013-11-06 21:36:55 +000020/// | Atoms |
Shankar Easwaran3d8de472014-01-27 03:09:26 +000021/// +-------+
Nick Kledzike34182f2013-11-06 21:36:55 +000022
23#include "MachONormalizedFile.h"
24#include "ReferenceKinds.h"
25
26#include "lld/Core/Error.h"
27#include "lld/Core/LLVM.h"
28
29#include "llvm/ADT/StringRef.h"
30#include "llvm/ADT/StringSwitch.h"
31#include "llvm/Support/Casting.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/Format.h"
35#include "llvm/Support/MachO.h"
36#include "llvm/Support/system_error.h"
37
38#include <map>
39
40using llvm::StringRef;
Nick Kledzike34182f2013-11-06 21:36:55 +000041using llvm::isa;
42using namespace llvm::MachO;
43using namespace lld::mach_o::normalized;
44using namespace lld;
45
46namespace {
47
48struct AtomInfo {
49 const DefinedAtom *atom;
50 uint64_t offsetInSection;
51};
52
53struct SectionInfo {
54 SectionInfo(StringRef seg, StringRef sect, SectionType type, uint32_t attr=0);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000055
Nick Kledzike34182f2013-11-06 21:36:55 +000056 StringRef segmentName;
57 StringRef sectionName;
58 SectionType type;
59 uint32_t attributes;
60 uint64_t address;
61 uint64_t size;
62 uint32_t alignment;
63 std::vector<AtomInfo> atomsAndOffsets;
64 uint32_t normalizedSectionIndex;
65 uint32_t finalSectionIndex;
66};
67
Shankar Easwaran3d8de472014-01-27 03:09:26 +000068SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t, uint32_t a)
69 : segmentName(sg), sectionName(sct), type(t), attributes(a),
70 address(0), size(0), alignment(0),
Nick Kledzike34182f2013-11-06 21:36:55 +000071 normalizedSectionIndex(0), finalSectionIndex(0) {
72}
73
74struct SegmentInfo {
75 SegmentInfo(StringRef name);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000076
Nick Kledzike34182f2013-11-06 21:36:55 +000077 StringRef name;
78 uint64_t address;
79 uint64_t size;
80 uint32_t access;
81 std::vector<SectionInfo*> sections;
82};
83
Shankar Easwaran3d8de472014-01-27 03:09:26 +000084SegmentInfo::SegmentInfo(StringRef n)
Nick Kledzike34182f2013-11-06 21:36:55 +000085 : name(n), address(0), size(0), access(0) {
86}
87
88
89class Util {
90public:
91 Util(const MachOLinkingContext &ctxt) : _context(ctxt), _entryAtom(nullptr) {}
92
93 void assignAtomsToSections(const lld::File &atomFile);
94 void organizeSections();
95 void assignAddressesToSections();
96 uint32_t fileFlags();
97 void copySegmentInfo(NormalizedFile &file);
98 void copySections(NormalizedFile &file);
99 void buildAtomToAddressMap();
100 void addSymbols(const lld::File &atomFile, NormalizedFile &file);
101 void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
102 void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
103 void addSectionRelocs(const lld::File &, NormalizedFile &file);
104 void addDependentDylibs(const lld::File &, NormalizedFile &file);
105 void copyEntryPointAddress(NormalizedFile &file);
106
107private:
108 typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection;
109 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000110
Nick Kledzike34182f2013-11-06 21:36:55 +0000111 struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; };
112 typedef llvm::StringMap<DylibInfo> DylibPathToInfo;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000113
Nick Kledzike34182f2013-11-06 21:36:55 +0000114 SectionInfo *sectionForAtom(const DefinedAtom*);
115 SectionInfo *makeSection(DefinedAtom::ContentType);
116 void appendAtom(SectionInfo *sect, const DefinedAtom *atom);
117 SegmentInfo *segmentForName(StringRef segName);
118 void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr);
119 void layoutSectionsInTextSegment(SegmentInfo *seg, uint64_t &addr);
120 void copySectionContent(SectionInfo *si, ContentBytes &content);
121 uint8_t scopeBits(const DefinedAtom* atom);
122 int dylibOrdinal(const SharedLibraryAtom *sa);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000123 void segIndexForSection(const SectionInfo *sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000124 uint8_t &segmentIndex, uint64_t &segmentStartAddr);
125 const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom);
126 const Atom *targetOfStub(const DefinedAtom *stubAtom);
127 bool belongsInGlobalSymbolsSection(const DefinedAtom* atom);
128 void appendSection(SectionInfo *si, NormalizedFile &file);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000129 void appendReloc(const DefinedAtom *atom, const Reference *ref,
Nick Kledzike34182f2013-11-06 21:36:55 +0000130 Relocations &relocations);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000131
Nick Kledzike34182f2013-11-06 21:36:55 +0000132 static uint64_t alignTo(uint64_t value, uint8_t align2);
133 typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
134 struct AtomAndIndex { const Atom *atom; uint32_t index; };
Joey Gouly9d263e02013-12-25 19:39:08 +0000135 struct AtomSorter {
136 bool operator()(const AtomAndIndex &left, const AtomAndIndex &right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000137 };
Joey Gouly9d263e02013-12-25 19:39:08 +0000138 struct SegmentSorter {
139 bool operator()(const SegmentInfo *left, const SegmentInfo *right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000140 static unsigned weight(const SegmentInfo *);
141 };
Joey Gouly9d263e02013-12-25 19:39:08 +0000142 struct TextSectionSorter {
143 bool operator()(const SectionInfo *left, const SectionInfo *right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000144 static unsigned weight(const SectionInfo *);
145 };
146
147 const MachOLinkingContext &_context;
148 llvm::BumpPtrAllocator _allocator;
149 std::vector<SectionInfo*> _sectionInfos;
150 std::vector<SegmentInfo*> _segmentInfos;
151 TypeToSection _sectionMap;
152 AtomToAddress _atomToAddress;
153 DylibPathToInfo _dylibInfo;
154 const DefinedAtom *_entryAtom;
155 AtomToIndex _atomToSymbolIndex;
156};
157
158SectionInfo *Util::makeSection(DefinedAtom::ContentType type) {
159 switch ( type ) {
160 case DefinedAtom::typeCode:
161 return new (_allocator) SectionInfo("__TEXT", "__text",
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000162 S_REGULAR, S_ATTR_PURE_INSTRUCTIONS
Nick Kledzike34182f2013-11-06 21:36:55 +0000163 | S_ATTR_SOME_INSTRUCTIONS);
164 case DefinedAtom::typeCString:
165 return new (_allocator) SectionInfo("__TEXT", "__cstring",
166 S_CSTRING_LITERALS);
167 case DefinedAtom::typeStub:
168 return new (_allocator) SectionInfo("__TEXT", "__stubs",
169 S_SYMBOL_STUBS, S_ATTR_PURE_INSTRUCTIONS);
170 case DefinedAtom::typeStubHelper:
171 return new (_allocator) SectionInfo("__TEXT", "__stub_helper",
172 S_REGULAR, S_ATTR_PURE_INSTRUCTIONS);
173 case DefinedAtom::typeLazyPointer:
174 return new (_allocator) SectionInfo("__DATA", "__la_symbol_ptr",
175 S_LAZY_SYMBOL_POINTERS);
176 case DefinedAtom::typeGOT:
177 return new (_allocator) SectionInfo("__DATA", "__got",
178 S_NON_LAZY_SYMBOL_POINTERS);
Nick Kledzik61fdef62014-05-15 20:59:23 +0000179 case DefinedAtom::typeZeroFill:
180 return new (_allocator) SectionInfo("__DATA", "__bss",
181 S_ZEROFILL);
Nick Kledzika0c13a22014-05-22 01:42:06 +0000182 case DefinedAtom::typeLiteral4:
183 return new (_allocator) SectionInfo("__TEXT", "__literal4",
184 S_4BYTE_LITERALS);
185 case DefinedAtom::typeLiteral8:
186 return new (_allocator) SectionInfo("__TEXT", "__literal8",
187 S_8BYTE_LITERALS);
188 case DefinedAtom::typeLiteral16:
189 return new (_allocator) SectionInfo("__TEXT", "__literal16",
190 S_16BYTE_LITERALS);
Nick Kledzik3e90e5f2014-05-27 20:25:06 +0000191 case DefinedAtom::typeUTF16String:
192 return new (_allocator) SectionInfo("__TEXT", "__ustring",
193 S_REGULAR);
Nick Kledzike34182f2013-11-06 21:36:55 +0000194 default:
195 llvm_unreachable("TO DO: add support for more sections");
196 break;
197 }
198}
199
200
201
202SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
203 DefinedAtom::ContentType type = atom->contentType();
204 auto pos = _sectionMap.find(type);
205 if ( pos != _sectionMap.end() )
206 return pos->second;
207 SectionInfo *si = makeSection(type);
208 _sectionInfos.push_back(si);
209 _sectionMap[type] = si;
210 return si;
211}
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000212
Nick Kledzike34182f2013-11-06 21:36:55 +0000213
214void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
215 // Figure out offset for atom in this section given alignment constraints.
216 uint64_t offset = sect->size;
217 DefinedAtom::Alignment atomAlign = atom->alignment();
218 uint64_t align2 = 1 << atomAlign.powerOf2;
219 uint64_t requiredModulus = atomAlign.modulus;
220 uint64_t currentModulus = (offset % align2);
221 if ( currentModulus != requiredModulus ) {
222 if ( requiredModulus > currentModulus )
223 offset += requiredModulus-currentModulus;
224 else
225 offset += align2+requiredModulus-currentModulus;
226 }
227 // Record max alignment of any atom in this section.
228 if ( atomAlign.powerOf2 > sect->alignment )
229 sect->alignment = atomAlign.powerOf2;
230 // Assign atom to this section with this offset.
231 AtomInfo ai = {atom, offset};
232 sect->atomsAndOffsets.push_back(ai);
233 // Update section size to include this atom.
234 sect->size = offset + atom->size();
235}
236
237void Util::assignAtomsToSections(const lld::File &atomFile) {
238 for (const DefinedAtom *atom : atomFile.defined()) {
239 appendAtom(sectionForAtom(atom), atom);
240 }
241}
242
243SegmentInfo *Util::segmentForName(StringRef segName) {
244 for (SegmentInfo *si : _segmentInfos) {
245 if ( si->name.equals(segName) )
246 return si;
247 }
248 SegmentInfo *info = new (_allocator) SegmentInfo(segName);
249 if (segName.equals("__TEXT"))
250 info->access = VM_PROT_READ | VM_PROT_EXECUTE;
251 else if (segName.equals("__DATA"))
252 info->access = VM_PROT_READ | VM_PROT_WRITE;
253 else if (segName.equals("__PAGEZERO"))
254 info->access = 0;
255 _segmentInfos.push_back(info);
256 return info;
257}
258
259unsigned Util::SegmentSorter::weight(const SegmentInfo *seg) {
260 return llvm::StringSwitch<unsigned>(seg->name)
261 .Case("__PAGEZERO", 1)
262 .Case("__TEXT", 2)
263 .Case("__DATA", 3)
264 .Default(100);
265}
266
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000267bool Util::SegmentSorter::operator()(const SegmentInfo *left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000268 const SegmentInfo *right) {
269 return (weight(left) < weight(right));
270}
271
272unsigned Util::TextSectionSorter::weight(const SectionInfo *sect) {
273 return llvm::StringSwitch<unsigned>(sect->sectionName)
274 .Case("__text", 1)
275 .Case("__stubs", 2)
276 .Case("__stub_helper", 3)
277 .Case("__const", 4)
278 .Case("__cstring", 5)
279 .Case("__unwind_info", 98)
280 .Case("__eh_frame", 99)
281 .Default(10);
282}
283
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000284bool Util::TextSectionSorter::operator()(const SectionInfo *left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000285 const SectionInfo *right) {
286 return (weight(left) < weight(right));
287}
288
289
290void Util::organizeSections() {
291 if (_context.outputFileType() == llvm::MachO::MH_OBJECT) {
292 // Leave sections ordered as normalized file specified.
293 uint32_t sectionIndex = 1;
294 for (SectionInfo *si : _sectionInfos) {
295 si->finalSectionIndex = sectionIndex++;
296 }
297 } else {
298 // Main executables, need a zero-page segment
299 if (_context.outputFileType() == llvm::MachO::MH_EXECUTE)
300 segmentForName("__PAGEZERO");
301 // Group sections into segments.
302 for (SectionInfo *si : _sectionInfos) {
303 SegmentInfo *seg = segmentForName(si->segmentName);
304 seg->sections.push_back(si);
305 }
306 // Sort segments.
307 std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000308
Nick Kledzike34182f2013-11-06 21:36:55 +0000309 // Sort sections within segments.
310 for (SegmentInfo *seg : _segmentInfos) {
311 if (seg->name.equals("__TEXT")) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000312 std::sort(seg->sections.begin(), seg->sections.end(),
Nick Kledzike34182f2013-11-06 21:36:55 +0000313 TextSectionSorter());
314 }
315 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000316
Nick Kledzike34182f2013-11-06 21:36:55 +0000317 // Record final section indexes.
318 uint32_t sectionIndex = 1;
319 for (SegmentInfo *seg : _segmentInfos) {
320 for (SectionInfo *sect : seg->sections) {
321 sect->finalSectionIndex = sectionIndex++;
322 }
323 }
324 }
325
326}
327
328uint64_t Util::alignTo(uint64_t value, uint8_t align2) {
329 return llvm::RoundUpToAlignment(value, 1 << align2);
330}
331
332
333void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
334 seg->address = addr;
335 for (SectionInfo *sect : seg->sections) {
336 sect->address = alignTo(addr, sect->alignment);
337 addr += sect->size;
338 }
339 seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
340}
341
342
343// __TEXT segment lays out backwards so padding is at front after load commands.
344void Util::layoutSectionsInTextSegment(SegmentInfo *seg, uint64_t &addr) {
345 seg->address = addr;
346 // Walks sections starting at end to calculate padding for start.
347 int64_t taddr = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000348 for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000349 SectionInfo *sect = *it;
350 taddr -= sect->size;
351 taddr = taddr & (0 - (1 << sect->alignment));
352 }
353 int64_t padding = taddr;
354 while (padding < 0)
355 padding += _context.pageSize();
356 // Start assigning section address starting at padded offset.
357 addr += padding;
358 for (SectionInfo *sect : seg->sections) {
359 sect->address = alignTo(addr, sect->alignment);
360 addr = sect->address + sect->size;
361 }
362 seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
363}
364
365
366void Util::assignAddressesToSections() {
367 uint64_t address = 0; // FIXME
368 if (_context.outputFileType() != llvm::MachO::MH_OBJECT) {
369 for (SegmentInfo *seg : _segmentInfos) {
370 if (seg->name.equals("__PAGEZERO")) {
371 seg->size = _context.pageZeroSize();
372 address += seg->size;
373 }
374 else if (seg->name.equals("__TEXT"))
375 layoutSectionsInTextSegment(seg, address);
376 else
377 layoutSectionsInSegment(seg, address);
378 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000379 DEBUG_WITH_TYPE("WriterMachO-norm",
Nick Kledzik020a49c2013-11-06 21:57:52 +0000380 llvm::dbgs() << "assignAddressesToSections()\n";
381 for (SegmentInfo *sgi : _segmentInfos) {
382 llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000383 << ", size=" << llvm::format("0x%08llX", sgi->size)
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000384 << ", segment-name='" << sgi->name
Nick Kledzik020a49c2013-11-06 21:57:52 +0000385 << "'\n";
386 for (SectionInfo *si : sgi->sections) {
387 llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000388 << ", size=" << llvm::format("0x%08llX", si->size)
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000389 << ", section-name='" << si->sectionName
Nick Kledzik020a49c2013-11-06 21:57:52 +0000390 << "\n";
391 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000392 }
Nick Kledzik020a49c2013-11-06 21:57:52 +0000393 );
Nick Kledzike34182f2013-11-06 21:36:55 +0000394 } else {
395 for (SectionInfo *sect : _sectionInfos) {
396 sect->address = alignTo(address, sect->alignment);
397 address = sect->address + sect->size;
398 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000399 DEBUG_WITH_TYPE("WriterMachO-norm",
Nick Kledzik020a49c2013-11-06 21:57:52 +0000400 llvm::dbgs() << "assignAddressesToSections()\n";
401 for (SectionInfo *si : _sectionInfos) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000402 llvm::dbgs() << " section=" << si->sectionName
Nick Kledzike34182f2013-11-06 21:36:55 +0000403 << " address= " << llvm::format("0x%08X", si->address)
404 << " size= " << llvm::format("0x%08X", si->size)
Nick Kledzik020a49c2013-11-06 21:57:52 +0000405 << "\n";
406 }
407 );
Nick Kledzike34182f2013-11-06 21:36:55 +0000408 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000409}
410
411
412void Util::copySegmentInfo(NormalizedFile &file) {
413 for (SegmentInfo *sgi : _segmentInfos) {
414 Segment seg;
415 seg.name = sgi->name;
416 seg.address = sgi->address;
417 seg.size = sgi->size;
418 seg.access = sgi->access;
419 file.segments.push_back(seg);
420 }
421}
422
423void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
424 // Add new empty section to end of file.sections.
425 Section temp;
426 file.sections.push_back(std::move(temp));
427 Section* normSect = &file.sections.back();
428 // Copy fields to normalized section.
429 normSect->segmentName = si->segmentName;
430 normSect->sectionName = si->sectionName;
431 normSect->type = si->type;
432 normSect->attributes = si->attributes;
433 normSect->address = si->address;
434 normSect->alignment = si->alignment;
435 // Record where normalized section is.
436 si->normalizedSectionIndex = file.sections.size()-1;
437 // Copy content from atoms to content buffer for section.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000438 if (si->type == llvm::MachO::S_ZEROFILL)
439 return;
Nick Kledzik6edd7222014-01-11 01:07:43 +0000440 uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
441 normSect->content = llvm::makeArrayRef(sectionContent, si->size);
Nick Kledzike34182f2013-11-06 21:36:55 +0000442 for (AtomInfo &ai : si->atomsAndOffsets) {
443 // Copy raw bytes.
444 uint8_t *atomContent = reinterpret_cast<uint8_t*>
445 (&sectionContent[ai.offsetInSection]);
446 memcpy(atomContent, ai.atom->rawContent().data(), ai.atom->size());
447 // Apply fix-ups.
448 for (const Reference *ref : *ai.atom) {
449 uint32_t offset = ref->offsetInAtom();
450 uint64_t targetAddress = 0;
451 if ( ref->target() != nullptr )
452 targetAddress = _atomToAddress[ref->target()];
453 uint64_t fixupAddress = _atomToAddress[ai.atom] + offset;
Rui Ueyama170a1a82013-12-20 07:48:29 +0000454 _context.kindHandler().applyFixup(
455 ref->kindNamespace(), ref->kindArch(), ref->kindValue(),
456 ref->addend(), &atomContent[offset], fixupAddress, targetAddress);
Nick Kledzike34182f2013-11-06 21:36:55 +0000457 }
458 }
459}
460
461void Util::copySections(NormalizedFile &file) {
462 file.sections.reserve(_sectionInfos.size());
463 // For final linked images, write sections grouped by segment.
464 if (_context.outputFileType() != llvm::MachO::MH_OBJECT) {
465 for (SegmentInfo *sgi : _segmentInfos) {
466 for (SectionInfo *si : sgi->sections) {
467 appendSection(si, file);
468 }
469 }
470 } else {
471 // Object files write sections in default order.
472 for (SectionInfo *si : _sectionInfos) {
473 appendSection(si, file);
474 }
475 }
476}
477
478void Util::copyEntryPointAddress(NormalizedFile &nFile) {
479 if (_context.outputTypeHasEntry()) {
480 nFile.entryAddress = _atomToAddress[_entryAtom];
481 }
482}
483
484void Util::buildAtomToAddressMap() {
485 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
486 << "assign atom addresses:\n");
487 const bool lookForEntry = _context.outputTypeHasEntry();
488 for (SectionInfo *sect : _sectionInfos) {
489 for (const AtomInfo &info : sect->atomsAndOffsets) {
490 _atomToAddress[info.atom] = sect->address + info.offsetInSection;
491 if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
492 (info.atom->size() != 0) &&
493 info.atom->name() == _context.entrySymbolName()) {
494 _entryAtom = info.atom;
495 }
496 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
497 << " address="
498 << llvm::format("0x%016X", _atomToAddress[info.atom])
499 << " atom=" << info.atom
500 << " name=" << info.atom->name() << "\n");
501 }
502 }
503}
504
505uint8_t Util::scopeBits(const DefinedAtom* atom) {
506 switch (atom->scope()) {
507 case Atom::scopeTranslationUnit:
508 return 0;
509 case Atom::scopeLinkageUnit:
510 return N_PEXT | N_EXT;
511 case Atom::scopeGlobal:
512 return N_EXT;
513 }
Nick Kledzik020fa7f2013-11-06 22:18:09 +0000514 llvm_unreachable("Unknown scope");
Nick Kledzike34182f2013-11-06 21:36:55 +0000515}
516
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000517bool Util::AtomSorter::operator()(const AtomAndIndex &left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000518 const AtomAndIndex &right) {
519 return (left.atom->name().compare(right.atom->name()) < 0);
520}
521
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000522
Nick Kledzike34182f2013-11-06 21:36:55 +0000523bool Util::belongsInGlobalSymbolsSection(const DefinedAtom* atom) {
524 return (atom->scope() == Atom::scopeGlobal);
525}
526
527void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
528 // Mach-O symbol table has three regions: locals, globals, undefs.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000529
Nick Kledzike34182f2013-11-06 21:36:55 +0000530 // Add all local (non-global) symbols in address order
531 std::vector<AtomAndIndex> globals;
532 globals.reserve(512);
533 for (SectionInfo *sect : _sectionInfos) {
534 for (const AtomInfo &info : sect->atomsAndOffsets) {
535 const DefinedAtom *atom = info.atom;
536 if (!atom->name().empty()) {
537 if (belongsInGlobalSymbolsSection(atom)) {
538 AtomAndIndex ai = { atom, sect->finalSectionIndex };
539 globals.push_back(ai);
540 } else {
541 Symbol sym;
542 sym.name = atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000543 sym.type = N_SECT;
Nick Kledzike34182f2013-11-06 21:36:55 +0000544 sym.scope = scopeBits(atom);
545 sym.sect = sect->finalSectionIndex;
546 sym.desc = 0;
547 sym.value = _atomToAddress[atom];
548 file.localSymbols.push_back(sym);
549 }
550 }
551 }
552 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000553
Nick Kledzike34182f2013-11-06 21:36:55 +0000554 // Sort global symbol alphabetically, then add to symbol table.
555 std::sort(globals.begin(), globals.end(), AtomSorter());
556 for (AtomAndIndex &ai : globals) {
557 Symbol sym;
558 sym.name = ai.atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000559 sym.type = N_SECT;
Nick Kledzike34182f2013-11-06 21:36:55 +0000560 sym.scope = scopeBits(static_cast<const DefinedAtom*>(ai.atom));
561 sym.sect = ai.index;
562 sym.desc = 0;
563 sym.value = _atomToAddress[ai.atom];
564 file.globalSymbols.push_back(sym);
565 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000566
567
Nick Kledzike34182f2013-11-06 21:36:55 +0000568 // Sort undefined symbol alphabetically, then add to symbol table.
569 std::vector<AtomAndIndex> undefs;
570 undefs.reserve(128);
571 for (const UndefinedAtom *atom : atomFile.undefined()) {
572 AtomAndIndex ai = { atom, 0 };
573 undefs.push_back(ai);
574 }
575 for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) {
576 AtomAndIndex ai = { atom, 0 };
577 undefs.push_back(ai);
578 }
579 std::sort(undefs.begin(), undefs.end(), AtomSorter());
580 const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
581 for (AtomAndIndex &ai : undefs) {
582 Symbol sym;
583 sym.name = ai.atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000584 sym.type = N_UNDF;
Nick Kledzike34182f2013-11-06 21:36:55 +0000585 sym.scope = N_EXT;
586 sym.sect = 0;
587 sym.desc = 0;
588 sym.value = 0;
589 _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start;
590 file.undefinedSymbols.push_back(sym);
591 }
592}
593
594const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
595 for (const Reference *ref : *lpAtom) {
Nick Kledzike5552772013-12-19 21:58:00 +0000596 if (_context.kindHandler().isLazyTarget(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000597 return ref->target();
598 }
599 }
600 return nullptr;
601}
602
603const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) {
604 for (const Reference *ref : *stubAtom) {
605 if (const Atom *ta = ref->target()) {
606 if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) {
607 const Atom *target = targetOfLazyPointer(lpAtom);
608 if (target)
609 return target;
610 }
611 }
612 }
613 return nullptr;
614}
615
616
617void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
618 for (SectionInfo *si : _sectionInfos) {
619 Section &normSect = file.sections[si->normalizedSectionIndex];
620 switch (si->type) {
621 case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS:
622 for (const AtomInfo &info : si->atomsAndOffsets) {
623 bool foundTarget = false;
624 for (const Reference *ref : *info.atom) {
625 const Atom *target = ref->target();
626 if (target) {
627 if (isa<const SharedLibraryAtom>(target)) {
628 uint32_t index = _atomToSymbolIndex[target];
629 normSect.indirectSymbols.push_back(index);
630 foundTarget = true;
631 } else {
632 normSect.indirectSymbols.push_back(
633 llvm::MachO::INDIRECT_SYMBOL_LOCAL);
634 }
635 }
636 }
637 if (!foundTarget) {
638 normSect.indirectSymbols.push_back(
639 llvm::MachO::INDIRECT_SYMBOL_ABS);
640 }
641 }
642 break;
643 case llvm::MachO::S_LAZY_SYMBOL_POINTERS:
644 for (const AtomInfo &info : si->atomsAndOffsets) {
645 const Atom *target = targetOfLazyPointer(info.atom);
646 if (target) {
647 uint32_t index = _atomToSymbolIndex[target];
648 normSect.indirectSymbols.push_back(index);
649 }
650 }
651 break;
652 case llvm::MachO::S_SYMBOL_STUBS:
653 for (const AtomInfo &info : si->atomsAndOffsets) {
654 const Atom *target = targetOfStub(info.atom);
655 if (target) {
656 uint32_t index = _atomToSymbolIndex[target];
657 normSect.indirectSymbols.push_back(index);
658 }
659 }
660 break;
661 default:
662 break;
663 }
664 }
665
666}
667
668void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
669 // Scan all imported symbols and build up list of dylibs they are from.
670 int ordinal = 1;
671 for (const SharedLibraryAtom *slAtom : atomFile.sharedLibrary()) {
672 StringRef loadPath = slAtom->loadName();
673 DylibPathToInfo::iterator pos = _dylibInfo.find(loadPath);
674 if (pos == _dylibInfo.end()) {
675 DylibInfo info;
676 info.ordinal = ordinal++;
677 info.hasWeak = slAtom->canBeNullAtRuntime();
678 info.hasNonWeak = !info.hasWeak;
679 _dylibInfo[loadPath] = info;
680 DependentDylib depInfo;
681 depInfo.path = loadPath;
682 depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
683 nFile.dependentDylibs.push_back(depInfo);
684 } else {
685 if ( slAtom->canBeNullAtRuntime() )
686 pos->second.hasWeak = true;
687 else
688 pos->second.hasNonWeak = true;
689 }
690 }
691 // Automatically weak link dylib in which all symbols are weak (canBeNull).
692 for (DependentDylib &dep : nFile.dependentDylibs) {
693 DylibInfo &info = _dylibInfo[dep.path];
694 if (info.hasWeak && !info.hasNonWeak)
695 dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB;
696 }
697}
698
699
700int Util::dylibOrdinal(const SharedLibraryAtom *sa) {
701 return _dylibInfo[sa->loadName()].ordinal;
702}
703
704void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex,
705 uint64_t &segmentStartAddr) {
706 segmentIndex = 0;
707 for (const SegmentInfo *seg : _segmentInfos) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000708 if ((seg->address <= sect->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000709 && (seg->address+seg->size >= sect->address+sect->size)) {
710 segmentStartAddr = seg->address;
711 return;
712 }
713 ++segmentIndex;
714 }
715 llvm_unreachable("section not in any segment");
716}
717
718
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000719void Util::appendReloc(const DefinedAtom *atom, const Reference *ref,
Nick Kledzike34182f2013-11-06 21:36:55 +0000720 Relocations &relocations) {
721 // TODO: convert Reference to normalized relocation
722}
723
724void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
725 if (_context.outputFileType() != llvm::MachO::MH_OBJECT)
726 return;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000727
Nick Kledzike34182f2013-11-06 21:36:55 +0000728 for (SectionInfo *si : _sectionInfos) {
729 Section &normSect = file.sections[si->normalizedSectionIndex];
730 for (const AtomInfo &info : si->atomsAndOffsets) {
731 const DefinedAtom *atom = info.atom;
732 for (const Reference *ref : *atom) {
733 appendReloc(atom, ref, normSect.relocations);
734 }
735 }
736 }
737}
738
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000739void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
Nick Kledzike34182f2013-11-06 21:36:55 +0000740 NormalizedFile &nFile) {
741 if (_context.outputFileType() == llvm::MachO::MH_OBJECT)
742 return;
743
744 uint8_t segmentIndex;
745 uint64_t segmentStartAddr;
746 for (SectionInfo *sect : _sectionInfos) {
747 segIndexForSection(sect, segmentIndex, segmentStartAddr);
748 for (const AtomInfo &info : sect->atomsAndOffsets) {
749 const DefinedAtom *atom = info.atom;
750 for (const Reference *ref : *atom) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000751 uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom()
Nick Kledzike34182f2013-11-06 21:36:55 +0000752 - segmentStartAddr;
753 const Atom* targ = ref->target();
Nick Kledzike5552772013-12-19 21:58:00 +0000754 if (_context.kindHandler().isPointer(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000755 // A pointer to a DefinedAtom requires rebasing.
756 if (dyn_cast<DefinedAtom>(targ)) {
757 RebaseLocation rebase;
758 rebase.segIndex = segmentIndex;
759 rebase.segOffset = segmentOffset;
760 rebase.kind = llvm::MachO::REBASE_TYPE_POINTER;
761 nFile.rebasingInfo.push_back(rebase);
762 }
763 // A pointer to an SharedLibraryAtom requires binding.
764 if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
765 BindLocation bind;
766 bind.segIndex = segmentIndex;
767 bind.segOffset = segmentOffset;
768 bind.kind = llvm::MachO::BIND_TYPE_POINTER;
769 bind.canBeNull = sa->canBeNullAtRuntime();
770 bind.ordinal = dylibOrdinal(sa);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000771 bind.symbolName = targ->name();
Nick Kledzike34182f2013-11-06 21:36:55 +0000772 bind.addend = ref->addend();
773 nFile.bindingInfo.push_back(bind);
774 }
775 }
Nick Kledzike5552772013-12-19 21:58:00 +0000776 if (_context.kindHandler().isLazyTarget(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000777 BindLocation bind;
778 bind.segIndex = segmentIndex;
779 bind.segOffset = segmentOffset;
780 bind.kind = llvm::MachO::BIND_TYPE_POINTER;
781 bind.canBeNull = false; //sa->canBeNullAtRuntime();
782 bind.ordinal = 1;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000783 bind.symbolName = targ->name();
Nick Kledzike34182f2013-11-06 21:36:55 +0000784 bind.addend = ref->addend();
785 nFile.lazyBindingInfo.push_back(bind);
786 }
787 }
788 }
789 }
790}
791
792uint32_t Util::fileFlags() {
793 return 0; //FIX ME
794}
795
796} // end anonymous namespace
797
798
799namespace lld {
800namespace mach_o {
801namespace normalized {
802
803/// Convert a set of Atoms into a normalized mach-o file.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000804ErrorOr<std::unique_ptr<NormalizedFile>>
805normalizedFromAtoms(const lld::File &atomFile,
Nick Kledzike34182f2013-11-06 21:36:55 +0000806 const MachOLinkingContext &context) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000807 // The util object buffers info until the normalized file can be made.
Nick Kledzike34182f2013-11-06 21:36:55 +0000808 Util util(context);
809 util.assignAtomsToSections(atomFile);
810 util.organizeSections();
811 util.assignAddressesToSections();
812 util.buildAtomToAddressMap();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000813
Nick Kledzike34182f2013-11-06 21:36:55 +0000814 std::unique_ptr<NormalizedFile> f(new NormalizedFile());
815 NormalizedFile &normFile = *f.get();
816 f->arch = context.arch();
817 f->fileType = context.outputFileType();
818 f->flags = util.fileFlags();
819 util.copySegmentInfo(normFile);
820 util.copySections(normFile);
821 util.addDependentDylibs(atomFile, normFile);
822 util.addSymbols(atomFile, normFile);
823 util.addIndirectSymbols(atomFile, normFile);
824 util.addRebaseAndBindingInfo(atomFile, normFile);
825 util.addSectionRelocs(atomFile, normFile);
826 util.copyEntryPointAddress(normFile);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000827
Nick Kledzike34182f2013-11-06 21:36:55 +0000828 return std::move(f);
829}
830
831
832} // namespace normalized
833} // namespace mach_o
834} // namespace lld
835