blob: cf0a9cf58d88ef202c86c4f1db2869050a9eea28 [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"
Nick Kledzik2458bec2014-07-16 19:49:02 +000024
25#include "ArchHandler.h"
Nick Kledzikec140832014-06-10 01:50:00 +000026#include "MachONormalizedFileBinaryUtils.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000027
Nick Kledzike34182f2013-11-06 21:36:55 +000028#include "lld/Core/Error.h"
29#include "lld/Core/LLVM.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000030#include "llvm/ADT/StringRef.h"
31#include "llvm/ADT/StringSwitch.h"
32#include "llvm/Support/Casting.h"
33#include "llvm/Support/Debug.h"
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/Format.h"
36#include "llvm/Support/MachO.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000037#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000038#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000039
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 {
Nick Kledzik2fcbe822014-07-30 00:58:06 +000054 SectionInfo(StringRef seg, StringRef sect, SectionType type,
55 const MachOLinkingContext &ctxt, uint32_t attr=0);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000056
Nick Kledzike34182f2013-11-06 21:36:55 +000057 StringRef segmentName;
58 StringRef sectionName;
59 SectionType type;
60 uint32_t attributes;
61 uint64_t address;
62 uint64_t size;
63 uint32_t alignment;
64 std::vector<AtomInfo> atomsAndOffsets;
65 uint32_t normalizedSectionIndex;
66 uint32_t finalSectionIndex;
67};
68
Nick Kledzik2fcbe822014-07-30 00:58:06 +000069SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t,
70 const MachOLinkingContext &ctxt, uint32_t attrs)
71 : segmentName(sg), sectionName(sct), type(t), attributes(attrs),
Shankar Easwaran3d8de472014-01-27 03:09:26 +000072 address(0), size(0), alignment(0),
Nick Kledzike34182f2013-11-06 21:36:55 +000073 normalizedSectionIndex(0), finalSectionIndex(0) {
Nick Kledzik2fcbe822014-07-30 00:58:06 +000074 uint8_t align;
75 if (ctxt.sectionAligned(segmentName, sectionName, align)) {
76 alignment = align;
77 }
Nick Kledzike34182f2013-11-06 21:36:55 +000078}
79
80struct SegmentInfo {
81 SegmentInfo(StringRef name);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000082
Nick Kledzike34182f2013-11-06 21:36:55 +000083 StringRef name;
84 uint64_t address;
85 uint64_t size;
86 uint32_t access;
87 std::vector<SectionInfo*> sections;
Nick Kledzik2fcbe822014-07-30 00:58:06 +000088 uint32_t normalizedSegmentIndex;
Nick Kledzike34182f2013-11-06 21:36:55 +000089};
90
Shankar Easwaran3d8de472014-01-27 03:09:26 +000091SegmentInfo::SegmentInfo(StringRef n)
Nick Kledzik2fcbe822014-07-30 00:58:06 +000092 : name(n), address(0), size(0), access(0), normalizedSegmentIndex(0) {
Nick Kledzike34182f2013-11-06 21:36:55 +000093}
94
95
96class Util {
97public:
Nick Kledzik2d432352014-07-17 23:16:21 +000098 Util(const MachOLinkingContext &ctxt) : _context(ctxt),
99 _archHandler(ctxt.archHandler()), _entryAtom(nullptr) {}
Nick Kledzike34182f2013-11-06 21:36:55 +0000100
101 void assignAtomsToSections(const lld::File &atomFile);
102 void organizeSections();
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000103 void assignAddressesToSections(const NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000104 uint32_t fileFlags();
105 void copySegmentInfo(NormalizedFile &file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000106 void copySectionInfo(NormalizedFile &file);
107 void updateSectionInfo(NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000108 void buildAtomToAddressMap();
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000109 std::error_code addSymbols(const lld::File &atomFile, NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000110 void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
111 void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
112 void addSectionRelocs(const lld::File &, NormalizedFile &file);
Nick Kledzik21921372014-07-24 23:06:56 +0000113 void buildDataInCodeArray(const lld::File &, NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000114 void addDependentDylibs(const lld::File &, NormalizedFile &file);
115 void copyEntryPointAddress(NormalizedFile &file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000116 void copySectionContent(NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000117
118private:
119 typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection;
120 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000121
Nick Kledzike34182f2013-11-06 21:36:55 +0000122 struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; };
123 typedef llvm::StringMap<DylibInfo> DylibPathToInfo;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000124
Nick Kledzike34182f2013-11-06 21:36:55 +0000125 SectionInfo *sectionForAtom(const DefinedAtom*);
Nick Kledzik936d5202014-06-11 01:30:55 +0000126 SectionInfo *getRelocatableSection(DefinedAtom::ContentType type);
127 SectionInfo *getFinalSection(DefinedAtom::ContentType type);
Nick Kledzike34182f2013-11-06 21:36:55 +0000128 void appendAtom(SectionInfo *sect, const DefinedAtom *atom);
129 SegmentInfo *segmentForName(StringRef segName);
130 void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000131 void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &);
Nick Kledzike34182f2013-11-06 21:36:55 +0000132 void copySectionContent(SectionInfo *si, ContentBytes &content);
Nick Kledzik60855392014-06-11 00:24:16 +0000133 uint16_t descBits(const DefinedAtom* atom);
Nick Kledzike34182f2013-11-06 21:36:55 +0000134 int dylibOrdinal(const SharedLibraryAtom *sa);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000135 void segIndexForSection(const SectionInfo *sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000136 uint8_t &segmentIndex, uint64_t &segmentStartAddr);
137 const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom);
138 const Atom *targetOfStub(const DefinedAtom *stubAtom);
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000139 std::error_code getSymbolTableRegion(const DefinedAtom* atom,
140 bool &inGlobalsRegion,
141 SymbolScope &symbolScope);
Nick Kledzike34182f2013-11-06 21:36:55 +0000142 void appendSection(SectionInfo *si, NormalizedFile &file);
Nick Kledzik2d432352014-07-17 23:16:21 +0000143 uint32_t sectionIndexForAtom(const Atom *atom);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000144
Nick Kledzike34182f2013-11-06 21:36:55 +0000145 static uint64_t alignTo(uint64_t value, uint8_t align2);
146 typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000147 struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
Joey Gouly9d263e02013-12-25 19:39:08 +0000148 struct AtomSorter {
149 bool operator()(const AtomAndIndex &left, const AtomAndIndex &right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000150 };
Joey Gouly9d263e02013-12-25 19:39:08 +0000151 struct SegmentSorter {
152 bool operator()(const SegmentInfo *left, const SegmentInfo *right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000153 static unsigned weight(const SegmentInfo *);
154 };
Joey Gouly9d263e02013-12-25 19:39:08 +0000155 struct TextSectionSorter {
156 bool operator()(const SectionInfo *left, const SectionInfo *right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000157 static unsigned weight(const SectionInfo *);
158 };
159
160 const MachOLinkingContext &_context;
Nick Kledzik2d432352014-07-17 23:16:21 +0000161 mach_o::ArchHandler &_archHandler;
Nick Kledzike34182f2013-11-06 21:36:55 +0000162 llvm::BumpPtrAllocator _allocator;
163 std::vector<SectionInfo*> _sectionInfos;
164 std::vector<SegmentInfo*> _segmentInfos;
165 TypeToSection _sectionMap;
Nick Kledzikacfad802014-05-30 22:51:04 +0000166 std::vector<SectionInfo*> _customSections;
Nick Kledzike34182f2013-11-06 21:36:55 +0000167 AtomToAddress _atomToAddress;
168 DylibPathToInfo _dylibInfo;
169 const DefinedAtom *_entryAtom;
170 AtomToIndex _atomToSymbolIndex;
171};
172
Nick Kledzikec140832014-06-10 01:50:00 +0000173
Nick Kledzik936d5202014-06-11 01:30:55 +0000174SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
Nick Kledzikec140832014-06-10 01:50:00 +0000175 StringRef segmentName;
176 StringRef sectionName;
177 SectionType sectionType;
178 SectionAttr sectionAttrs;
179
180 // Use same table used by when parsing .o files.
181 relocatableSectionInfoForContentType(type, segmentName, sectionName,
182 sectionType, sectionAttrs);
183 // If we already have a SectionInfo with this name, re-use it.
184 // This can happen if two ContentType map to the same mach-o section.
185 for (auto sect : _sectionMap) {
186 if (sect.second->sectionName.equals(sectionName) &&
187 sect.second->segmentName.equals(segmentName)) {
188 return sect.second;
189 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000190 }
Nick Kledzikec140832014-06-10 01:50:00 +0000191 // Otherwise allocate new SectionInfo object.
Nick Kledzik936d5202014-06-11 01:30:55 +0000192 SectionInfo *sect = new (_allocator) SectionInfo(segmentName, sectionName,
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000193 sectionType, _context,
194 sectionAttrs);
Nick Kledzik936d5202014-06-11 01:30:55 +0000195 _sectionInfos.push_back(sect);
196 _sectionMap[type] = sect;
197 return sect;
Nick Kledzikec140832014-06-10 01:50:00 +0000198}
199
200#define ENTRY(seg, sect, type, atomType) \
201 {seg, sect, type, DefinedAtom::atomType }
202
203struct MachOFinalSectionFromAtomType {
204 StringRef segmentName;
205 StringRef sectionName;
206 SectionType sectionType;
207 DefinedAtom::ContentType atomType;
208};
209
210const MachOFinalSectionFromAtomType sectsToAtomType[] = {
211 ENTRY("__TEXT", "__text", S_REGULAR, typeCode),
212 ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString),
213 ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String),
214 ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
215 ENTRY("__TEXT", "__const", S_4BYTE_LITERALS, typeLiteral4),
216 ENTRY("__TEXT", "__const", S_8BYTE_LITERALS, typeLiteral8),
217 ENTRY("__TEXT", "__const", S_16BYTE_LITERALS, typeLiteral16),
218 ENTRY("__TEXT", "__stubs", S_SYMBOL_STUBS, typeStub),
219 ENTRY("__TEXT", "__stub_helper", S_REGULAR, typeStubHelper),
220 ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA),
221 ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI),
222 ENTRY("__DATA", "__data", S_REGULAR, typeData),
223 ENTRY("__DATA", "__const", S_REGULAR, typeConstData),
224 ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString),
225 ENTRY("__DATA", "__la_symbol_ptr", S_LAZY_SYMBOL_POINTERS,
226 typeLazyPointer),
227 ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS,
228 typeInitializerPtr),
229 ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS,
230 typeTerminatorPtr),
231 ENTRY("__DATA", "___got", S_NON_LAZY_SYMBOL_POINTERS,
232 typeGOT),
Tim Northover9ee99352014-06-30 09:49:37 +0000233 ENTRY("__DATA", "___bss", S_ZEROFILL, typeZeroFill),
234
235 // FIXME: __compact_unwind actually needs to be processed by a pass and put
236 // into __TEXT,__unwind_info. For now, forwarding it back to
237 // __LD,__compact_unwind is harmless (it's ignored by the unwinder, which then
238 // proceeds to process __TEXT,__eh_frame for its instructions).
239 ENTRY("__LD", "__compact_unwind", S_REGULAR, typeCompactUnwindInfo),
Nick Kledzikec140832014-06-10 01:50:00 +0000240};
241#undef ENTRY
242
243
Nick Kledzik936d5202014-06-11 01:30:55 +0000244SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
Tim Northoverb5bf6862014-06-30 10:30:00 +0000245 for (auto &p : sectsToAtomType) {
246 if (p.atomType != atomType)
Nick Kledzikec140832014-06-10 01:50:00 +0000247 continue;
248 SectionAttr sectionAttrs = 0;
249 switch (atomType) {
250 case DefinedAtom::typeCode:
251 case DefinedAtom::typeStub:
252 sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
253 break;
254 default:
255 break;
256 }
257 // If we already have a SectionInfo with this name, re-use it.
258 // This can happen if two ContentType map to the same mach-o section.
259 for (auto sect : _sectionMap) {
Tim Northoverb5bf6862014-06-30 10:30:00 +0000260 if (sect.second->sectionName.equals(p.sectionName) &&
261 sect.second->segmentName.equals(p.segmentName)) {
Nick Kledzikec140832014-06-10 01:50:00 +0000262 return sect.second;
263 }
264 }
265 // Otherwise allocate new SectionInfo object.
Tim Northoverb5bf6862014-06-30 10:30:00 +0000266 SectionInfo *sect = new (_allocator) SectionInfo(p.segmentName,
267 p.sectionName,
268 p.sectionType,
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000269 _context,
Nick Kledzik936d5202014-06-11 01:30:55 +0000270 sectionAttrs);
271 _sectionInfos.push_back(sect);
272 _sectionMap[atomType] = sect;
273 return sect;
Nick Kledzikec140832014-06-10 01:50:00 +0000274 }
275 llvm_unreachable("content type not yet supported");
Nick Kledzike34182f2013-11-06 21:36:55 +0000276}
277
278
279
280SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
Nick Kledzikacfad802014-05-30 22:51:04 +0000281 if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
282 // Section for this atom is derived from content type.
283 DefinedAtom::ContentType type = atom->contentType();
284 auto pos = _sectionMap.find(type);
285 if ( pos != _sectionMap.end() )
286 return pos->second;
Tim Northoverd30a1f22014-06-20 15:59:00 +0000287 bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
Nick Kledzik936d5202014-06-11 01:30:55 +0000288 return rMode ? getRelocatableSection(type) : getFinalSection(type);
Nick Kledzikacfad802014-05-30 22:51:04 +0000289 } else {
290 // This atom needs to be in a custom section.
291 StringRef customName = atom->customSectionName();
292 // Look to see if we have already allocated the needed custom section.
293 for(SectionInfo *sect : _customSections) {
294 const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom;
295 if (firstAtom->customSectionName().equals(customName)) {
296 return sect;
297 }
298 }
299 // Not found, so need to create a new custom section.
300 size_t seperatorIndex = customName.find('/');
301 assert(seperatorIndex != StringRef::npos);
Tim Northover7b0a1302014-06-30 09:49:33 +0000302 StringRef segName = customName.slice(0, seperatorIndex);
303 StringRef sectName = customName.drop_front(seperatorIndex + 1);
Nick Kledzikacfad802014-05-30 22:51:04 +0000304 SectionInfo *sect = new (_allocator) SectionInfo(segName, sectName,
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000305 S_REGULAR, _context);
Nick Kledzikacfad802014-05-30 22:51:04 +0000306 _customSections.push_back(sect);
Tim Northover7b0a1302014-06-30 09:49:33 +0000307 _sectionInfos.push_back(sect);
Nick Kledzikacfad802014-05-30 22:51:04 +0000308 return sect;
309 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000310}
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000311
Nick Kledzike34182f2013-11-06 21:36:55 +0000312
313void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
314 // Figure out offset for atom in this section given alignment constraints.
315 uint64_t offset = sect->size;
316 DefinedAtom::Alignment atomAlign = atom->alignment();
317 uint64_t align2 = 1 << atomAlign.powerOf2;
318 uint64_t requiredModulus = atomAlign.modulus;
319 uint64_t currentModulus = (offset % align2);
320 if ( currentModulus != requiredModulus ) {
321 if ( requiredModulus > currentModulus )
322 offset += requiredModulus-currentModulus;
323 else
324 offset += align2+requiredModulus-currentModulus;
325 }
326 // Record max alignment of any atom in this section.
327 if ( atomAlign.powerOf2 > sect->alignment )
328 sect->alignment = atomAlign.powerOf2;
329 // Assign atom to this section with this offset.
330 AtomInfo ai = {atom, offset};
331 sect->atomsAndOffsets.push_back(ai);
332 // Update section size to include this atom.
333 sect->size = offset + atom->size();
334}
335
336void Util::assignAtomsToSections(const lld::File &atomFile) {
337 for (const DefinedAtom *atom : atomFile.defined()) {
338 appendAtom(sectionForAtom(atom), atom);
339 }
340}
341
342SegmentInfo *Util::segmentForName(StringRef segName) {
343 for (SegmentInfo *si : _segmentInfos) {
344 if ( si->name.equals(segName) )
345 return si;
346 }
347 SegmentInfo *info = new (_allocator) SegmentInfo(segName);
348 if (segName.equals("__TEXT"))
349 info->access = VM_PROT_READ | VM_PROT_EXECUTE;
350 else if (segName.equals("__DATA"))
351 info->access = VM_PROT_READ | VM_PROT_WRITE;
352 else if (segName.equals("__PAGEZERO"))
353 info->access = 0;
354 _segmentInfos.push_back(info);
355 return info;
356}
357
358unsigned Util::SegmentSorter::weight(const SegmentInfo *seg) {
359 return llvm::StringSwitch<unsigned>(seg->name)
360 .Case("__PAGEZERO", 1)
361 .Case("__TEXT", 2)
362 .Case("__DATA", 3)
363 .Default(100);
364}
365
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000366bool Util::SegmentSorter::operator()(const SegmentInfo *left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000367 const SegmentInfo *right) {
368 return (weight(left) < weight(right));
369}
370
371unsigned Util::TextSectionSorter::weight(const SectionInfo *sect) {
372 return llvm::StringSwitch<unsigned>(sect->sectionName)
373 .Case("__text", 1)
374 .Case("__stubs", 2)
375 .Case("__stub_helper", 3)
376 .Case("__const", 4)
377 .Case("__cstring", 5)
378 .Case("__unwind_info", 98)
379 .Case("__eh_frame", 99)
380 .Default(10);
381}
382
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000383bool Util::TextSectionSorter::operator()(const SectionInfo *left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000384 const SectionInfo *right) {
385 return (weight(left) < weight(right));
386}
387
388
389void Util::organizeSections() {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000390 if (_context.outputMachOType() == llvm::MachO::MH_OBJECT) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000391 // Leave sections ordered as normalized file specified.
392 uint32_t sectionIndex = 1;
393 for (SectionInfo *si : _sectionInfos) {
394 si->finalSectionIndex = sectionIndex++;
395 }
396 } else {
397 // Main executables, need a zero-page segment
Tim Northoverd30a1f22014-06-20 15:59:00 +0000398 if (_context.outputMachOType() == llvm::MachO::MH_EXECUTE)
Nick Kledzike34182f2013-11-06 21:36:55 +0000399 segmentForName("__PAGEZERO");
400 // Group sections into segments.
401 for (SectionInfo *si : _sectionInfos) {
402 SegmentInfo *seg = segmentForName(si->segmentName);
403 seg->sections.push_back(si);
404 }
405 // Sort segments.
406 std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000407
Nick Kledzike34182f2013-11-06 21:36:55 +0000408 // Sort sections within segments.
409 for (SegmentInfo *seg : _segmentInfos) {
410 if (seg->name.equals("__TEXT")) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000411 std::sort(seg->sections.begin(), seg->sections.end(),
Nick Kledzike34182f2013-11-06 21:36:55 +0000412 TextSectionSorter());
413 }
414 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000415
Nick Kledzike34182f2013-11-06 21:36:55 +0000416 // Record final section indexes.
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000417 uint32_t segmentIndex = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000418 uint32_t sectionIndex = 1;
419 for (SegmentInfo *seg : _segmentInfos) {
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000420 seg->normalizedSegmentIndex = segmentIndex++;
421 for (SectionInfo *sect : seg->sections) {
422 sect->finalSectionIndex = sectionIndex++;
423 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000424 }
425 }
426
427}
428
429uint64_t Util::alignTo(uint64_t value, uint8_t align2) {
430 return llvm::RoundUpToAlignment(value, 1 << align2);
431}
432
433
434void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
435 seg->address = addr;
436 for (SectionInfo *sect : seg->sections) {
437 sect->address = alignTo(addr, sect->alignment);
438 addr += sect->size;
439 }
440 seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
441}
442
443
444// __TEXT segment lays out backwards so padding is at front after load commands.
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000445void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
446 uint64_t &addr) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000447 seg->address = addr;
448 // Walks sections starting at end to calculate padding for start.
449 int64_t taddr = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000450 for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000451 SectionInfo *sect = *it;
452 taddr -= sect->size;
453 taddr = taddr & (0 - (1 << sect->alignment));
454 }
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000455 int64_t padding = taddr - hlcSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000456 while (padding < 0)
457 padding += _context.pageSize();
458 // Start assigning section address starting at padded offset.
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000459 addr += (padding + hlcSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000460 for (SectionInfo *sect : seg->sections) {
461 sect->address = alignTo(addr, sect->alignment);
462 addr = sect->address + sect->size;
463 }
464 seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
465}
466
467
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000468void Util::assignAddressesToSections(const NormalizedFile &file) {
469 size_t hlcSize = headerAndLoadCommandsSize(file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000470 uint64_t address = 0; // FIXME
Tim Northoverd30a1f22014-06-20 15:59:00 +0000471 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000472 for (SegmentInfo *seg : _segmentInfos) {
473 if (seg->name.equals("__PAGEZERO")) {
474 seg->size = _context.pageZeroSize();
475 address += seg->size;
476 }
477 else if (seg->name.equals("__TEXT"))
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000478 layoutSectionsInTextSegment(hlcSize, seg, address);
Nick Kledzike34182f2013-11-06 21:36:55 +0000479 else
480 layoutSectionsInSegment(seg, address);
Tim Northover7b0a1302014-06-30 09:49:33 +0000481
482 address = llvm::RoundUpToAlignment(address, _context.pageSize());
Nick Kledzike34182f2013-11-06 21:36:55 +0000483 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000484 DEBUG_WITH_TYPE("WriterMachO-norm",
Nick Kledzik020a49c2013-11-06 21:57:52 +0000485 llvm::dbgs() << "assignAddressesToSections()\n";
486 for (SegmentInfo *sgi : _segmentInfos) {
487 llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000488 << ", size=" << llvm::format("0x%08llX", sgi->size)
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000489 << ", segment-name='" << sgi->name
Nick Kledzik020a49c2013-11-06 21:57:52 +0000490 << "'\n";
491 for (SectionInfo *si : sgi->sections) {
492 llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000493 << ", size=" << llvm::format("0x%08llX", si->size)
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000494 << ", section-name='" << si->sectionName
Nick Kledzik020a49c2013-11-06 21:57:52 +0000495 << "\n";
496 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000497 }
Nick Kledzik020a49c2013-11-06 21:57:52 +0000498 );
Nick Kledzike34182f2013-11-06 21:36:55 +0000499 } else {
500 for (SectionInfo *sect : _sectionInfos) {
501 sect->address = alignTo(address, sect->alignment);
502 address = sect->address + sect->size;
503 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000504 DEBUG_WITH_TYPE("WriterMachO-norm",
Nick Kledzik020a49c2013-11-06 21:57:52 +0000505 llvm::dbgs() << "assignAddressesToSections()\n";
506 for (SectionInfo *si : _sectionInfos) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000507 llvm::dbgs() << " section=" << si->sectionName
Nick Kledzike34182f2013-11-06 21:36:55 +0000508 << " address= " << llvm::format("0x%08X", si->address)
509 << " size= " << llvm::format("0x%08X", si->size)
Nick Kledzik020a49c2013-11-06 21:57:52 +0000510 << "\n";
511 }
512 );
Nick Kledzike34182f2013-11-06 21:36:55 +0000513 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000514}
515
516
517void Util::copySegmentInfo(NormalizedFile &file) {
518 for (SegmentInfo *sgi : _segmentInfos) {
519 Segment seg;
520 seg.name = sgi->name;
521 seg.address = sgi->address;
522 seg.size = sgi->size;
523 seg.access = sgi->access;
524 file.segments.push_back(seg);
525 }
526}
527
528void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000529 // Add new empty section to end of file.sections.
Nick Kledzike34182f2013-11-06 21:36:55 +0000530 Section temp;
531 file.sections.push_back(std::move(temp));
532 Section* normSect = &file.sections.back();
533 // Copy fields to normalized section.
534 normSect->segmentName = si->segmentName;
535 normSect->sectionName = si->sectionName;
536 normSect->type = si->type;
537 normSect->attributes = si->attributes;
538 normSect->address = si->address;
539 normSect->alignment = si->alignment;
540 // Record where normalized section is.
541 si->normalizedSectionIndex = file.sections.size()-1;
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000542}
543
544void Util::copySectionContent(NormalizedFile &file) {
545 const bool r = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
546
547 // Utility function for ArchHandler to find address of atom in output file.
548 auto addrForAtom = [&] (const Atom &atom) -> uint64_t {
549 auto pos = _atomToAddress.find(&atom);
550 assert(pos != _atomToAddress.end());
551 return pos->second;
552 };
553
554 for (SectionInfo *si : _sectionInfos) {
555 if (si->type == llvm::MachO::S_ZEROFILL)
556 continue;
557 // Copy content from atoms to content buffer for section.
558 uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
559 Section *normSect = &file.sections[si->normalizedSectionIndex];
560 normSect->content = llvm::makeArrayRef(sectionContent, si->size);
561 for (AtomInfo &ai : si->atomsAndOffsets) {
562 uint8_t *atomContent = reinterpret_cast<uint8_t*>
Nick Kledzike34182f2013-11-06 21:36:55 +0000563 (&sectionContent[ai.offsetInSection]);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000564 _archHandler.generateAtomContent(*ai.atom, r, addrForAtom, atomContent);
565 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000566 }
567}
568
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000569
570void Util::copySectionInfo(NormalizedFile &file) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000571 file.sections.reserve(_sectionInfos.size());
572 // For final linked images, write sections grouped by segment.
Tim Northoverd30a1f22014-06-20 15:59:00 +0000573 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000574 for (SegmentInfo *sgi : _segmentInfos) {
575 for (SectionInfo *si : sgi->sections) {
576 appendSection(si, file);
577 }
578 }
579 } else {
580 // Object files write sections in default order.
581 for (SectionInfo *si : _sectionInfos) {
582 appendSection(si, file);
583 }
584 }
585}
586
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000587void Util::updateSectionInfo(NormalizedFile &file) {
588 file.sections.reserve(_sectionInfos.size());
589 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
590 // For final linked images, sections grouped by segment.
591 for (SegmentInfo *sgi : _segmentInfos) {
592 Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex];
593 normSeg->address = sgi->address;
594 normSeg->size = sgi->size;
595 for (SectionInfo *si : sgi->sections) {
596 Section *normSect = &file.sections[si->normalizedSectionIndex];
597 normSect->address = si->address;
598 }
599 }
600 } else {
601 // Object files write sections in default order.
602 for (SectionInfo *si : _sectionInfos) {
603 Section *normSect = &file.sections[si->normalizedSectionIndex];
604 normSect->address = si->address;
605 }
606 }
607}
608
Nick Kledzike34182f2013-11-06 21:36:55 +0000609void Util::copyEntryPointAddress(NormalizedFile &nFile) {
610 if (_context.outputTypeHasEntry()) {
Nick Kledzik54fd4e52014-07-28 23:06:09 +0000611 if (_archHandler.isThumbFunction(*_entryAtom))
612 nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
613 else
614 nFile.entryAddress = _atomToAddress[_entryAtom];
Nick Kledzike34182f2013-11-06 21:36:55 +0000615 }
616}
617
618void Util::buildAtomToAddressMap() {
619 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
620 << "assign atom addresses:\n");
621 const bool lookForEntry = _context.outputTypeHasEntry();
622 for (SectionInfo *sect : _sectionInfos) {
623 for (const AtomInfo &info : sect->atomsAndOffsets) {
624 _atomToAddress[info.atom] = sect->address + info.offsetInSection;
625 if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
626 (info.atom->size() != 0) &&
627 info.atom->name() == _context.entrySymbolName()) {
628 _entryAtom = info.atom;
629 }
630 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
631 << " address="
632 << llvm::format("0x%016X", _atomToAddress[info.atom])
633 << " atom=" << info.atom
634 << " name=" << info.atom->name() << "\n");
635 }
636 }
637}
638
Nick Kledzik60855392014-06-11 00:24:16 +0000639uint16_t Util::descBits(const DefinedAtom* atom) {
640 uint16_t desc = 0;
641 switch (atom->merge()) {
642 case lld::DefinedAtom::mergeNo:
643 case lld::DefinedAtom::mergeAsTentative:
644 break;
645 case lld::DefinedAtom::mergeAsWeak:
646 case lld::DefinedAtom::mergeAsWeakAndAddressUsed:
647 desc |= N_WEAK_DEF;
648 break;
649 case lld::DefinedAtom::mergeSameNameAndSize:
650 case lld::DefinedAtom::mergeByLargestSection:
651 case lld::DefinedAtom::mergeByContent:
652 llvm_unreachable("Unsupported DefinedAtom::merge()");
653 break;
654 }
655 if (atom->contentType() == lld::DefinedAtom::typeResolver)
656 desc |= N_SYMBOL_RESOLVER;
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000657 if (_archHandler.isThumbFunction(*atom))
658 desc |= N_ARM_THUMB_DEF;
Nick Kledzik7820c802014-08-21 22:18:30 +0000659 if (atom->deadStrip() == DefinedAtom::deadStripNever) {
660 if ((atom->contentType() != DefinedAtom::typeInitializerPtr)
661 && (atom->contentType() != DefinedAtom::typeTerminatorPtr))
662 desc |= N_NO_DEAD_STRIP;
663 }
Nick Kledzik60855392014-06-11 00:24:16 +0000664 return desc;
665}
666
667
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000668bool Util::AtomSorter::operator()(const AtomAndIndex &left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000669 const AtomAndIndex &right) {
670 return (left.atom->name().compare(right.atom->name()) < 0);
671}
672
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000673
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000674std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom,
675 bool &inGlobalsRegion,
676 SymbolScope &scope) {
677 bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
678 switch (atom->scope()) {
679 case Atom::scopeTranslationUnit:
680 scope = 0;
681 inGlobalsRegion = false;
682 return std::error_code();
683 case Atom::scopeLinkageUnit:
684 if ((_context.exportMode() == MachOLinkingContext::ExportMode::whiteList)
685 && _context.exportSymbolNamed(atom->name())) {
686 return make_dynamic_error_code(Twine("cannot export hidden symbol ")
687 + atom->name());
688 }
689 if (rMode) {
690 if (_context.keepPrivateExterns()) {
691 // -keep_private_externs means keep in globals region as N_PEXT.
692 scope = N_PEXT | N_EXT;
693 inGlobalsRegion = true;
694 return std::error_code();
695 }
696 }
697 // scopeLinkageUnit symbols are no longer global once linked.
698 scope = N_PEXT;
699 inGlobalsRegion = false;
700 return std::error_code();
701 case Atom::scopeGlobal:
702 if (_context.exportRestrictMode()) {
703 if (_context.exportSymbolNamed(atom->name())) {
704 scope = N_EXT;
705 inGlobalsRegion = true;
706 return std::error_code();
707 } else {
708 scope = N_PEXT;
709 inGlobalsRegion = false;
710 return std::error_code();
711 }
712 } else {
713 scope = N_EXT;
714 inGlobalsRegion = true;
715 return std::error_code();
716 }
717 break;
718 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000719}
720
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000721std::error_code Util::addSymbols(const lld::File &atomFile,
722 NormalizedFile &file) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000723 bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
Nick Kledzike34182f2013-11-06 21:36:55 +0000724 // Mach-O symbol table has three regions: locals, globals, undefs.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000725
Nick Kledzike34182f2013-11-06 21:36:55 +0000726 // Add all local (non-global) symbols in address order
727 std::vector<AtomAndIndex> globals;
728 globals.reserve(512);
729 for (SectionInfo *sect : _sectionInfos) {
730 for (const AtomInfo &info : sect->atomsAndOffsets) {
731 const DefinedAtom *atom = info.atom;
732 if (!atom->name().empty()) {
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000733 SymbolScope symbolScope;
734 bool inGlobalsRegion;
735 if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){
736 return ec;
737 }
738 if (inGlobalsRegion) {
739 AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
Nick Kledzike34182f2013-11-06 21:36:55 +0000740 globals.push_back(ai);
741 } else {
742 Symbol sym;
743 sym.name = atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000744 sym.type = N_SECT;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000745 sym.scope = symbolScope;
Nick Kledzike34182f2013-11-06 21:36:55 +0000746 sym.sect = sect->finalSectionIndex;
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000747 sym.desc = descBits(atom);
Nick Kledzike34182f2013-11-06 21:36:55 +0000748 sym.value = _atomToAddress[atom];
Nick Kledzik2d432352014-07-17 23:16:21 +0000749 _atomToSymbolIndex[atom] = file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000750 file.localSymbols.push_back(sym);
751 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000752 } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){
753 // Create 'Lxxx' labels for anonymous atoms if archHandler says so.
754 static unsigned tempNum = 1;
755 char tmpName[16];
756 sprintf(tmpName, "L%04u", tempNum++);
757 StringRef tempRef(tmpName);
758 Symbol sym;
759 sym.name = tempRef.copy(file.ownedAllocations);
760 sym.type = N_SECT;
761 sym.scope = 0;
762 sym.sect = sect->finalSectionIndex;
763 sym.desc = 0;
764 sym.value = _atomToAddress[atom];
765 _atomToSymbolIndex[atom] = file.localSymbols.size();
766 file.localSymbols.push_back(sym);
Nick Kledzike34182f2013-11-06 21:36:55 +0000767 }
768 }
769 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000770
Nick Kledzike34182f2013-11-06 21:36:55 +0000771 // Sort global symbol alphabetically, then add to symbol table.
772 std::sort(globals.begin(), globals.end(), AtomSorter());
Nick Kledzik2d432352014-07-17 23:16:21 +0000773 const uint32_t globalStartIndex = file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000774 for (AtomAndIndex &ai : globals) {
775 Symbol sym;
776 sym.name = ai.atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000777 sym.type = N_SECT;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000778 sym.scope = ai.scope;
Nick Kledzike34182f2013-11-06 21:36:55 +0000779 sym.sect = ai.index;
Nick Kledzik60855392014-06-11 00:24:16 +0000780 sym.desc = descBits(static_cast<const DefinedAtom*>(ai.atom));
Nick Kledzike34182f2013-11-06 21:36:55 +0000781 sym.value = _atomToAddress[ai.atom];
Nick Kledzik2d432352014-07-17 23:16:21 +0000782 _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000783 file.globalSymbols.push_back(sym);
784 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000785
786
Nick Kledzike34182f2013-11-06 21:36:55 +0000787 // Sort undefined symbol alphabetically, then add to symbol table.
788 std::vector<AtomAndIndex> undefs;
789 undefs.reserve(128);
790 for (const UndefinedAtom *atom : atomFile.undefined()) {
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000791 AtomAndIndex ai = { atom, 0, N_EXT };
Nick Kledzike34182f2013-11-06 21:36:55 +0000792 undefs.push_back(ai);
793 }
794 for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) {
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000795 AtomAndIndex ai = { atom, 0, N_EXT };
Nick Kledzike34182f2013-11-06 21:36:55 +0000796 undefs.push_back(ai);
797 }
798 std::sort(undefs.begin(), undefs.end(), AtomSorter());
799 const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
800 for (AtomAndIndex &ai : undefs) {
801 Symbol sym;
Nick Kledzikb4768322014-08-13 23:11:42 +0000802 uint16_t desc = 0;
803 if (!rMode) {
804 uint8_t ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom));
805 llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal);
806 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000807 sym.name = ai.atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000808 sym.type = N_UNDF;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000809 sym.scope = ai.scope;
Nick Kledzike34182f2013-11-06 21:36:55 +0000810 sym.sect = 0;
Nick Kledzikb4768322014-08-13 23:11:42 +0000811 sym.desc = desc;
Nick Kledzike34182f2013-11-06 21:36:55 +0000812 sym.value = 0;
813 _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start;
814 file.undefinedSymbols.push_back(sym);
815 }
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000816
817 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000818}
819
820const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
821 for (const Reference *ref : *lpAtom) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000822 if (_archHandler.isLazyPointer(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000823 return ref->target();
824 }
825 }
826 return nullptr;
827}
828
829const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) {
830 for (const Reference *ref : *stubAtom) {
831 if (const Atom *ta = ref->target()) {
832 if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) {
833 const Atom *target = targetOfLazyPointer(lpAtom);
834 if (target)
835 return target;
836 }
837 }
838 }
839 return nullptr;
840}
841
842
843void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
844 for (SectionInfo *si : _sectionInfos) {
845 Section &normSect = file.sections[si->normalizedSectionIndex];
846 switch (si->type) {
847 case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS:
848 for (const AtomInfo &info : si->atomsAndOffsets) {
849 bool foundTarget = false;
850 for (const Reference *ref : *info.atom) {
851 const Atom *target = ref->target();
852 if (target) {
853 if (isa<const SharedLibraryAtom>(target)) {
854 uint32_t index = _atomToSymbolIndex[target];
855 normSect.indirectSymbols.push_back(index);
856 foundTarget = true;
857 } else {
858 normSect.indirectSymbols.push_back(
859 llvm::MachO::INDIRECT_SYMBOL_LOCAL);
860 }
861 }
862 }
863 if (!foundTarget) {
864 normSect.indirectSymbols.push_back(
865 llvm::MachO::INDIRECT_SYMBOL_ABS);
866 }
867 }
868 break;
869 case llvm::MachO::S_LAZY_SYMBOL_POINTERS:
870 for (const AtomInfo &info : si->atomsAndOffsets) {
871 const Atom *target = targetOfLazyPointer(info.atom);
872 if (target) {
873 uint32_t index = _atomToSymbolIndex[target];
874 normSect.indirectSymbols.push_back(index);
875 }
876 }
877 break;
878 case llvm::MachO::S_SYMBOL_STUBS:
879 for (const AtomInfo &info : si->atomsAndOffsets) {
880 const Atom *target = targetOfStub(info.atom);
881 if (target) {
882 uint32_t index = _atomToSymbolIndex[target];
883 normSect.indirectSymbols.push_back(index);
884 }
885 }
886 break;
887 default:
888 break;
889 }
890 }
891
892}
893
894void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
895 // Scan all imported symbols and build up list of dylibs they are from.
896 int ordinal = 1;
897 for (const SharedLibraryAtom *slAtom : atomFile.sharedLibrary()) {
898 StringRef loadPath = slAtom->loadName();
899 DylibPathToInfo::iterator pos = _dylibInfo.find(loadPath);
900 if (pos == _dylibInfo.end()) {
901 DylibInfo info;
902 info.ordinal = ordinal++;
903 info.hasWeak = slAtom->canBeNullAtRuntime();
904 info.hasNonWeak = !info.hasWeak;
905 _dylibInfo[loadPath] = info;
906 DependentDylib depInfo;
907 depInfo.path = loadPath;
908 depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
909 nFile.dependentDylibs.push_back(depInfo);
910 } else {
911 if ( slAtom->canBeNullAtRuntime() )
912 pos->second.hasWeak = true;
913 else
914 pos->second.hasNonWeak = true;
915 }
916 }
917 // Automatically weak link dylib in which all symbols are weak (canBeNull).
918 for (DependentDylib &dep : nFile.dependentDylibs) {
919 DylibInfo &info = _dylibInfo[dep.path];
920 if (info.hasWeak && !info.hasNonWeak)
921 dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB;
922 }
923}
924
925
926int Util::dylibOrdinal(const SharedLibraryAtom *sa) {
927 return _dylibInfo[sa->loadName()].ordinal;
928}
929
930void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex,
931 uint64_t &segmentStartAddr) {
932 segmentIndex = 0;
933 for (const SegmentInfo *seg : _segmentInfos) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000934 if ((seg->address <= sect->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000935 && (seg->address+seg->size >= sect->address+sect->size)) {
936 segmentStartAddr = seg->address;
937 return;
938 }
939 ++segmentIndex;
940 }
941 llvm_unreachable("section not in any segment");
942}
943
944
Nick Kledzik2d432352014-07-17 23:16:21 +0000945uint32_t Util::sectionIndexForAtom(const Atom *atom) {
946 uint64_t address = _atomToAddress[atom];
947 uint32_t index = 1;
948 for (const SectionInfo *si : _sectionInfos) {
949 if ((si->address <= address) && (address < si->address+si->size))
950 return index;
951 ++index;
952 }
953 llvm_unreachable("atom not in any section");
Nick Kledzike34182f2013-11-06 21:36:55 +0000954}
955
956void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000957 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT)
Nick Kledzike34182f2013-11-06 21:36:55 +0000958 return;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000959
Nick Kledzik2d432352014-07-17 23:16:21 +0000960
961 // Utility function for ArchHandler to find symbol index for an atom.
962 auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t {
963 auto pos = _atomToSymbolIndex.find(&atom);
964 assert(pos != _atomToSymbolIndex.end());
965 return pos->second;
966 };
967
968 // Utility function for ArchHandler to find section index for an atom.
969 auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t {
970 return sectionIndexForAtom(&atom);
971 };
972
973 // Utility function for ArchHandler to find address of atom in output file.
974 auto addressForAtom = [&] (const Atom &atom) -> uint64_t {
975 auto pos = _atomToAddress.find(&atom);
976 assert(pos != _atomToAddress.end());
977 return pos->second;
978 };
979
Nick Kledzike34182f2013-11-06 21:36:55 +0000980 for (SectionInfo *si : _sectionInfos) {
981 Section &normSect = file.sections[si->normalizedSectionIndex];
982 for (const AtomInfo &info : si->atomsAndOffsets) {
983 const DefinedAtom *atom = info.atom;
984 for (const Reference *ref : *atom) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000985 _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
986 symIndexForAtom,
987 sectIndexForAtom,
988 addressForAtom,
989 normSect.relocations);
Nick Kledzike34182f2013-11-06 21:36:55 +0000990 }
991 }
992 }
993}
994
Nick Kledzik21921372014-07-24 23:06:56 +0000995void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
996 for (SectionInfo *si : _sectionInfos) {
997 for (const AtomInfo &info : si->atomsAndOffsets) {
998 // Atoms that contain data-in-code have "transition" references
999 // which mark a point where the embedded data starts of ends.
1000 // This needs to be converted to the mach-o format which is an array
1001 // of data-in-code ranges.
1002 uint32_t startOffset = 0;
1003 DataRegionType mode = DataRegionType(0);
1004 for (const Reference *ref : *info.atom) {
1005 if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
1006 continue;
1007 if (_archHandler.isDataInCodeTransition(ref->kindValue())) {
1008 DataRegionType nextMode = (DataRegionType)ref->addend();
1009 if (mode != nextMode) {
1010 if (mode != 0) {
1011 // Found end data range, so make range entry.
1012 DataInCode entry;
1013 entry.offset = si->address + info.offsetInSection + startOffset;
1014 entry.length = ref->offsetInAtom() - startOffset;
1015 entry.kind = mode;
1016 file.dataInCode.push_back(entry);
1017 }
1018 }
1019 mode = nextMode;
1020 startOffset = ref->offsetInAtom();
1021 }
1022 }
1023 if (mode != 0) {
1024 // Function ends with data (no end transition).
1025 DataInCode entry;
1026 entry.offset = si->address + info.offsetInSection + startOffset;
1027 entry.length = info.atom->size() - startOffset;
1028 entry.kind = mode;
1029 file.dataInCode.push_back(entry);
1030 }
1031 }
1032 }
1033}
1034
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001035void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
Nick Kledzike34182f2013-11-06 21:36:55 +00001036 NormalizedFile &nFile) {
Tim Northoverd30a1f22014-06-20 15:59:00 +00001037 if (_context.outputMachOType() == llvm::MachO::MH_OBJECT)
Nick Kledzike34182f2013-11-06 21:36:55 +00001038 return;
1039
1040 uint8_t segmentIndex;
1041 uint64_t segmentStartAddr;
1042 for (SectionInfo *sect : _sectionInfos) {
1043 segIndexForSection(sect, segmentIndex, segmentStartAddr);
1044 for (const AtomInfo &info : sect->atomsAndOffsets) {
1045 const DefinedAtom *atom = info.atom;
1046 for (const Reference *ref : *atom) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001047 uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom()
Nick Kledzike34182f2013-11-06 21:36:55 +00001048 - segmentStartAddr;
1049 const Atom* targ = ref->target();
Nick Kledzik2d432352014-07-17 23:16:21 +00001050 if (_archHandler.isPointer(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001051 // A pointer to a DefinedAtom requires rebasing.
1052 if (dyn_cast<DefinedAtom>(targ)) {
1053 RebaseLocation rebase;
1054 rebase.segIndex = segmentIndex;
1055 rebase.segOffset = segmentOffset;
1056 rebase.kind = llvm::MachO::REBASE_TYPE_POINTER;
1057 nFile.rebasingInfo.push_back(rebase);
1058 }
1059 // A pointer to an SharedLibraryAtom requires binding.
1060 if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
1061 BindLocation bind;
1062 bind.segIndex = segmentIndex;
1063 bind.segOffset = segmentOffset;
1064 bind.kind = llvm::MachO::BIND_TYPE_POINTER;
1065 bind.canBeNull = sa->canBeNullAtRuntime();
1066 bind.ordinal = dylibOrdinal(sa);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001067 bind.symbolName = targ->name();
Nick Kledzike34182f2013-11-06 21:36:55 +00001068 bind.addend = ref->addend();
1069 nFile.bindingInfo.push_back(bind);
1070 }
1071 }
Nick Kledzik2d432352014-07-17 23:16:21 +00001072 if (_archHandler.isLazyPointer(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001073 BindLocation bind;
1074 bind.segIndex = segmentIndex;
1075 bind.segOffset = segmentOffset;
1076 bind.kind = llvm::MachO::BIND_TYPE_POINTER;
1077 bind.canBeNull = false; //sa->canBeNullAtRuntime();
Nick Kledzik2d432352014-07-17 23:16:21 +00001078 bind.ordinal = 1; // FIXME
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001079 bind.symbolName = targ->name();
Nick Kledzike34182f2013-11-06 21:36:55 +00001080 bind.addend = ref->addend();
1081 nFile.lazyBindingInfo.push_back(bind);
1082 }
1083 }
1084 }
1085 }
1086}
1087
1088uint32_t Util::fileFlags() {
Nick Kledzike1aaced2014-07-22 00:49:49 +00001089 // FIXME: these need to determined at runtime.
1090 if (_context.outputMachOType() == MH_OBJECT) {
1091 return MH_SUBSECTIONS_VIA_SYMBOLS;
1092 } else {
1093 return MH_DYLDLINK | MH_NOUNDEFS | MH_TWOLEVEL;
1094 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001095}
1096
1097} // end anonymous namespace
1098
1099
1100namespace lld {
1101namespace mach_o {
1102namespace normalized {
1103
1104/// Convert a set of Atoms into a normalized mach-o file.
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001105ErrorOr<std::unique_ptr<NormalizedFile>>
1106normalizedFromAtoms(const lld::File &atomFile,
Nick Kledzike34182f2013-11-06 21:36:55 +00001107 const MachOLinkingContext &context) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001108 // The util object buffers info until the normalized file can be made.
Nick Kledzike34182f2013-11-06 21:36:55 +00001109 Util util(context);
1110 util.assignAtomsToSections(atomFile);
1111 util.organizeSections();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001112
Nick Kledzike34182f2013-11-06 21:36:55 +00001113 std::unique_ptr<NormalizedFile> f(new NormalizedFile());
1114 NormalizedFile &normFile = *f.get();
Nick Kledzik2fcbe822014-07-30 00:58:06 +00001115 normFile.arch = context.arch();
1116 normFile.fileType = context.outputMachOType();
1117 normFile.flags = util.fileFlags();
1118 normFile.installName = context.installName();
Nick Kledzike34182f2013-11-06 21:36:55 +00001119 util.addDependentDylibs(atomFile, normFile);
Nick Kledzik2fcbe822014-07-30 00:58:06 +00001120 util.copySegmentInfo(normFile);
1121 util.copySectionInfo(normFile);
1122 util.assignAddressesToSections(normFile);
1123 util.buildAtomToAddressMap();
1124 util.updateSectionInfo(normFile);
1125 util.copySectionContent(normFile);
Nick Kledzik8c0bf752014-08-21 01:59:11 +00001126 if (auto ec = util.addSymbols(atomFile, normFile)) {
1127 return ec;
1128 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001129 util.addIndirectSymbols(atomFile, normFile);
1130 util.addRebaseAndBindingInfo(atomFile, normFile);
1131 util.addSectionRelocs(atomFile, normFile);
Nick Kledzik21921372014-07-24 23:06:56 +00001132 util.buildDataInCodeArray(atomFile, normFile);
Nick Kledzike34182f2013-11-06 21:36:55 +00001133 util.copyEntryPointAddress(normFile);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001134
Nick Kledzike34182f2013-11-06 21:36:55 +00001135 return std::move(f);
1136}
1137
1138
1139} // namespace normalized
1140} // namespace mach_o
1141} // namespace lld
1142