blob: 3bc05c32d1ad44772b69fc38dc6447c8692a5491 [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);
Nick Kledzik141330a2014-09-03 19:52:50 +0000112 void addExportInfo(const lld::File &, NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000113 void addSectionRelocs(const lld::File &, NormalizedFile &file);
Nick Kledzik21921372014-07-24 23:06:56 +0000114 void buildDataInCodeArray(const lld::File &, NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000115 void addDependentDylibs(const lld::File &, NormalizedFile &file);
116 void copyEntryPointAddress(NormalizedFile &file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000117 void copySectionContent(NormalizedFile &file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000118
119private:
120 typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection;
121 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000122
Nick Kledzike34182f2013-11-06 21:36:55 +0000123 struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; };
124 typedef llvm::StringMap<DylibInfo> DylibPathToInfo;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000125
Nick Kledzike34182f2013-11-06 21:36:55 +0000126 SectionInfo *sectionForAtom(const DefinedAtom*);
Nick Kledzik936d5202014-06-11 01:30:55 +0000127 SectionInfo *getRelocatableSection(DefinedAtom::ContentType type);
128 SectionInfo *getFinalSection(DefinedAtom::ContentType type);
Nick Kledzike34182f2013-11-06 21:36:55 +0000129 void appendAtom(SectionInfo *sect, const DefinedAtom *atom);
130 SegmentInfo *segmentForName(StringRef segName);
131 void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000132 void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &);
Nick Kledzike34182f2013-11-06 21:36:55 +0000133 void copySectionContent(SectionInfo *si, ContentBytes &content);
Nick Kledzik60855392014-06-11 00:24:16 +0000134 uint16_t descBits(const DefinedAtom* atom);
Nick Kledzike34182f2013-11-06 21:36:55 +0000135 int dylibOrdinal(const SharedLibraryAtom *sa);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000136 void segIndexForSection(const SectionInfo *sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000137 uint8_t &segmentIndex, uint64_t &segmentStartAddr);
138 const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom);
139 const Atom *targetOfStub(const DefinedAtom *stubAtom);
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000140 std::error_code getSymbolTableRegion(const DefinedAtom* atom,
141 bool &inGlobalsRegion,
142 SymbolScope &symbolScope);
Nick Kledzike34182f2013-11-06 21:36:55 +0000143 void appendSection(SectionInfo *si, NormalizedFile &file);
Nick Kledzik2d432352014-07-17 23:16:21 +0000144 uint32_t sectionIndexForAtom(const Atom *atom);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000145
Nick Kledzike34182f2013-11-06 21:36:55 +0000146 static uint64_t alignTo(uint64_t value, uint8_t align2);
147 typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000148 struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
Joey Gouly9d263e02013-12-25 19:39:08 +0000149 struct AtomSorter {
150 bool operator()(const AtomAndIndex &left, const AtomAndIndex &right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000151 };
Joey Gouly9d263e02013-12-25 19:39:08 +0000152 struct SegmentSorter {
153 bool operator()(const SegmentInfo *left, const SegmentInfo *right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000154 static unsigned weight(const SegmentInfo *);
155 };
Joey Gouly9d263e02013-12-25 19:39:08 +0000156 struct TextSectionSorter {
157 bool operator()(const SectionInfo *left, const SectionInfo *right);
Nick Kledzike34182f2013-11-06 21:36:55 +0000158 static unsigned weight(const SectionInfo *);
159 };
160
161 const MachOLinkingContext &_context;
Nick Kledzik2d432352014-07-17 23:16:21 +0000162 mach_o::ArchHandler &_archHandler;
Nick Kledzike34182f2013-11-06 21:36:55 +0000163 llvm::BumpPtrAllocator _allocator;
164 std::vector<SectionInfo*> _sectionInfos;
165 std::vector<SegmentInfo*> _segmentInfos;
166 TypeToSection _sectionMap;
Nick Kledzikacfad802014-05-30 22:51:04 +0000167 std::vector<SectionInfo*> _customSections;
Nick Kledzike34182f2013-11-06 21:36:55 +0000168 AtomToAddress _atomToAddress;
169 DylibPathToInfo _dylibInfo;
170 const DefinedAtom *_entryAtom;
171 AtomToIndex _atomToSymbolIndex;
172};
173
Nick Kledzikec140832014-06-10 01:50:00 +0000174
Nick Kledzik936d5202014-06-11 01:30:55 +0000175SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
Nick Kledzikec140832014-06-10 01:50:00 +0000176 StringRef segmentName;
177 StringRef sectionName;
178 SectionType sectionType;
179 SectionAttr sectionAttrs;
180
181 // Use same table used by when parsing .o files.
182 relocatableSectionInfoForContentType(type, segmentName, sectionName,
183 sectionType, sectionAttrs);
184 // If we already have a SectionInfo with this name, re-use it.
185 // This can happen if two ContentType map to the same mach-o section.
186 for (auto sect : _sectionMap) {
187 if (sect.second->sectionName.equals(sectionName) &&
188 sect.second->segmentName.equals(segmentName)) {
189 return sect.second;
190 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000191 }
Nick Kledzikec140832014-06-10 01:50:00 +0000192 // Otherwise allocate new SectionInfo object.
Nick Kledzik936d5202014-06-11 01:30:55 +0000193 SectionInfo *sect = new (_allocator) SectionInfo(segmentName, sectionName,
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000194 sectionType, _context,
195 sectionAttrs);
Nick Kledzik936d5202014-06-11 01:30:55 +0000196 _sectionInfos.push_back(sect);
197 _sectionMap[type] = sect;
198 return sect;
Nick Kledzikec140832014-06-10 01:50:00 +0000199}
200
201#define ENTRY(seg, sect, type, atomType) \
202 {seg, sect, type, DefinedAtom::atomType }
203
204struct MachOFinalSectionFromAtomType {
205 StringRef segmentName;
206 StringRef sectionName;
207 SectionType sectionType;
208 DefinedAtom::ContentType atomType;
209};
210
211const MachOFinalSectionFromAtomType sectsToAtomType[] = {
212 ENTRY("__TEXT", "__text", S_REGULAR, typeCode),
213 ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString),
214 ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String),
215 ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
216 ENTRY("__TEXT", "__const", S_4BYTE_LITERALS, typeLiteral4),
217 ENTRY("__TEXT", "__const", S_8BYTE_LITERALS, typeLiteral8),
218 ENTRY("__TEXT", "__const", S_16BYTE_LITERALS, typeLiteral16),
219 ENTRY("__TEXT", "__stubs", S_SYMBOL_STUBS, typeStub),
220 ENTRY("__TEXT", "__stub_helper", S_REGULAR, typeStubHelper),
221 ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA),
222 ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI),
223 ENTRY("__DATA", "__data", S_REGULAR, typeData),
224 ENTRY("__DATA", "__const", S_REGULAR, typeConstData),
225 ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString),
226 ENTRY("__DATA", "__la_symbol_ptr", S_LAZY_SYMBOL_POINTERS,
227 typeLazyPointer),
228 ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS,
229 typeInitializerPtr),
230 ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS,
231 typeTerminatorPtr),
232 ENTRY("__DATA", "___got", S_NON_LAZY_SYMBOL_POINTERS,
233 typeGOT),
Tim Northover9ee99352014-06-30 09:49:37 +0000234 ENTRY("__DATA", "___bss", S_ZEROFILL, typeZeroFill),
235
236 // FIXME: __compact_unwind actually needs to be processed by a pass and put
237 // into __TEXT,__unwind_info. For now, forwarding it back to
238 // __LD,__compact_unwind is harmless (it's ignored by the unwinder, which then
239 // proceeds to process __TEXT,__eh_frame for its instructions).
240 ENTRY("__LD", "__compact_unwind", S_REGULAR, typeCompactUnwindInfo),
Nick Kledzikec140832014-06-10 01:50:00 +0000241};
242#undef ENTRY
243
244
Nick Kledzik936d5202014-06-11 01:30:55 +0000245SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
Tim Northoverb5bf6862014-06-30 10:30:00 +0000246 for (auto &p : sectsToAtomType) {
247 if (p.atomType != atomType)
Nick Kledzikec140832014-06-10 01:50:00 +0000248 continue;
249 SectionAttr sectionAttrs = 0;
250 switch (atomType) {
251 case DefinedAtom::typeCode:
252 case DefinedAtom::typeStub:
253 sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
254 break;
255 default:
256 break;
257 }
258 // If we already have a SectionInfo with this name, re-use it.
259 // This can happen if two ContentType map to the same mach-o section.
260 for (auto sect : _sectionMap) {
Tim Northoverb5bf6862014-06-30 10:30:00 +0000261 if (sect.second->sectionName.equals(p.sectionName) &&
262 sect.second->segmentName.equals(p.segmentName)) {
Nick Kledzikec140832014-06-10 01:50:00 +0000263 return sect.second;
264 }
265 }
266 // Otherwise allocate new SectionInfo object.
Tim Northoverb5bf6862014-06-30 10:30:00 +0000267 SectionInfo *sect = new (_allocator) SectionInfo(p.segmentName,
268 p.sectionName,
269 p.sectionType,
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000270 _context,
Nick Kledzik936d5202014-06-11 01:30:55 +0000271 sectionAttrs);
272 _sectionInfos.push_back(sect);
273 _sectionMap[atomType] = sect;
274 return sect;
Nick Kledzikec140832014-06-10 01:50:00 +0000275 }
276 llvm_unreachable("content type not yet supported");
Nick Kledzike34182f2013-11-06 21:36:55 +0000277}
278
279
280
281SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
Nick Kledzikacfad802014-05-30 22:51:04 +0000282 if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
283 // Section for this atom is derived from content type.
284 DefinedAtom::ContentType type = atom->contentType();
285 auto pos = _sectionMap.find(type);
286 if ( pos != _sectionMap.end() )
287 return pos->second;
Tim Northoverd30a1f22014-06-20 15:59:00 +0000288 bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
Nick Kledzik936d5202014-06-11 01:30:55 +0000289 return rMode ? getRelocatableSection(type) : getFinalSection(type);
Nick Kledzikacfad802014-05-30 22:51:04 +0000290 } else {
291 // This atom needs to be in a custom section.
292 StringRef customName = atom->customSectionName();
293 // Look to see if we have already allocated the needed custom section.
294 for(SectionInfo *sect : _customSections) {
295 const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom;
296 if (firstAtom->customSectionName().equals(customName)) {
297 return sect;
298 }
299 }
300 // Not found, so need to create a new custom section.
301 size_t seperatorIndex = customName.find('/');
302 assert(seperatorIndex != StringRef::npos);
Tim Northover7b0a1302014-06-30 09:49:33 +0000303 StringRef segName = customName.slice(0, seperatorIndex);
304 StringRef sectName = customName.drop_front(seperatorIndex + 1);
Nick Kledzikacfad802014-05-30 22:51:04 +0000305 SectionInfo *sect = new (_allocator) SectionInfo(segName, sectName,
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000306 S_REGULAR, _context);
Nick Kledzikacfad802014-05-30 22:51:04 +0000307 _customSections.push_back(sect);
Tim Northover7b0a1302014-06-30 09:49:33 +0000308 _sectionInfos.push_back(sect);
Nick Kledzikacfad802014-05-30 22:51:04 +0000309 return sect;
310 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000311}
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000312
Nick Kledzike34182f2013-11-06 21:36:55 +0000313
314void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
315 // Figure out offset for atom in this section given alignment constraints.
316 uint64_t offset = sect->size;
317 DefinedAtom::Alignment atomAlign = atom->alignment();
318 uint64_t align2 = 1 << atomAlign.powerOf2;
319 uint64_t requiredModulus = atomAlign.modulus;
320 uint64_t currentModulus = (offset % align2);
321 if ( currentModulus != requiredModulus ) {
322 if ( requiredModulus > currentModulus )
323 offset += requiredModulus-currentModulus;
324 else
325 offset += align2+requiredModulus-currentModulus;
326 }
327 // Record max alignment of any atom in this section.
328 if ( atomAlign.powerOf2 > sect->alignment )
329 sect->alignment = atomAlign.powerOf2;
330 // Assign atom to this section with this offset.
331 AtomInfo ai = {atom, offset};
332 sect->atomsAndOffsets.push_back(ai);
333 // Update section size to include this atom.
334 sect->size = offset + atom->size();
335}
336
337void Util::assignAtomsToSections(const lld::File &atomFile) {
338 for (const DefinedAtom *atom : atomFile.defined()) {
339 appendAtom(sectionForAtom(atom), atom);
340 }
341}
342
343SegmentInfo *Util::segmentForName(StringRef segName) {
344 for (SegmentInfo *si : _segmentInfos) {
345 if ( si->name.equals(segName) )
346 return si;
347 }
348 SegmentInfo *info = new (_allocator) SegmentInfo(segName);
349 if (segName.equals("__TEXT"))
350 info->access = VM_PROT_READ | VM_PROT_EXECUTE;
351 else if (segName.equals("__DATA"))
352 info->access = VM_PROT_READ | VM_PROT_WRITE;
353 else if (segName.equals("__PAGEZERO"))
354 info->access = 0;
355 _segmentInfos.push_back(info);
356 return info;
357}
358
359unsigned Util::SegmentSorter::weight(const SegmentInfo *seg) {
360 return llvm::StringSwitch<unsigned>(seg->name)
361 .Case("__PAGEZERO", 1)
362 .Case("__TEXT", 2)
363 .Case("__DATA", 3)
364 .Default(100);
365}
366
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000367bool Util::SegmentSorter::operator()(const SegmentInfo *left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000368 const SegmentInfo *right) {
369 return (weight(left) < weight(right));
370}
371
372unsigned Util::TextSectionSorter::weight(const SectionInfo *sect) {
373 return llvm::StringSwitch<unsigned>(sect->sectionName)
374 .Case("__text", 1)
375 .Case("__stubs", 2)
376 .Case("__stub_helper", 3)
377 .Case("__const", 4)
378 .Case("__cstring", 5)
379 .Case("__unwind_info", 98)
380 .Case("__eh_frame", 99)
381 .Default(10);
382}
383
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000384bool Util::TextSectionSorter::operator()(const SectionInfo *left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000385 const SectionInfo *right) {
386 return (weight(left) < weight(right));
387}
388
389
390void Util::organizeSections() {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000391 if (_context.outputMachOType() == llvm::MachO::MH_OBJECT) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000392 // Leave sections ordered as normalized file specified.
393 uint32_t sectionIndex = 1;
394 for (SectionInfo *si : _sectionInfos) {
395 si->finalSectionIndex = sectionIndex++;
396 }
397 } else {
398 // Main executables, need a zero-page segment
Tim Northoverd30a1f22014-06-20 15:59:00 +0000399 if (_context.outputMachOType() == llvm::MachO::MH_EXECUTE)
Nick Kledzike34182f2013-11-06 21:36:55 +0000400 segmentForName("__PAGEZERO");
401 // Group sections into segments.
402 for (SectionInfo *si : _sectionInfos) {
403 SegmentInfo *seg = segmentForName(si->segmentName);
404 seg->sections.push_back(si);
405 }
406 // Sort segments.
407 std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000408
Nick Kledzike34182f2013-11-06 21:36:55 +0000409 // Sort sections within segments.
410 for (SegmentInfo *seg : _segmentInfos) {
411 if (seg->name.equals("__TEXT")) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000412 std::sort(seg->sections.begin(), seg->sections.end(),
Nick Kledzike34182f2013-11-06 21:36:55 +0000413 TextSectionSorter());
414 }
415 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000416
Nick Kledzike34182f2013-11-06 21:36:55 +0000417 // Record final section indexes.
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000418 uint32_t segmentIndex = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000419 uint32_t sectionIndex = 1;
420 for (SegmentInfo *seg : _segmentInfos) {
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000421 seg->normalizedSegmentIndex = segmentIndex++;
422 for (SectionInfo *sect : seg->sections) {
423 sect->finalSectionIndex = sectionIndex++;
424 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000425 }
426 }
427
428}
429
430uint64_t Util::alignTo(uint64_t value, uint8_t align2) {
431 return llvm::RoundUpToAlignment(value, 1 << align2);
432}
433
434
435void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
436 seg->address = addr;
437 for (SectionInfo *sect : seg->sections) {
438 sect->address = alignTo(addr, sect->alignment);
439 addr += sect->size;
440 }
441 seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
442}
443
444
445// __TEXT segment lays out backwards so padding is at front after load commands.
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000446void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
447 uint64_t &addr) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000448 seg->address = addr;
449 // Walks sections starting at end to calculate padding for start.
450 int64_t taddr = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000451 for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000452 SectionInfo *sect = *it;
453 taddr -= sect->size;
454 taddr = taddr & (0 - (1 << sect->alignment));
455 }
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000456 int64_t padding = taddr - hlcSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000457 while (padding < 0)
458 padding += _context.pageSize();
459 // Start assigning section address starting at padded offset.
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000460 addr += (padding + hlcSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000461 for (SectionInfo *sect : seg->sections) {
462 sect->address = alignTo(addr, sect->alignment);
463 addr = sect->address + sect->size;
464 }
465 seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
466}
467
468
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000469void Util::assignAddressesToSections(const NormalizedFile &file) {
470 size_t hlcSize = headerAndLoadCommandsSize(file);
Nick Kledzike34182f2013-11-06 21:36:55 +0000471 uint64_t address = 0; // FIXME
Tim Northoverd30a1f22014-06-20 15:59:00 +0000472 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000473 for (SegmentInfo *seg : _segmentInfos) {
474 if (seg->name.equals("__PAGEZERO")) {
475 seg->size = _context.pageZeroSize();
476 address += seg->size;
477 }
478 else if (seg->name.equals("__TEXT"))
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000479 layoutSectionsInTextSegment(hlcSize, seg, address);
Nick Kledzike34182f2013-11-06 21:36:55 +0000480 else
481 layoutSectionsInSegment(seg, address);
Tim Northover7b0a1302014-06-30 09:49:33 +0000482
483 address = llvm::RoundUpToAlignment(address, _context.pageSize());
Nick Kledzike34182f2013-11-06 21:36:55 +0000484 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000485 DEBUG_WITH_TYPE("WriterMachO-norm",
Nick Kledzik020a49c2013-11-06 21:57:52 +0000486 llvm::dbgs() << "assignAddressesToSections()\n";
487 for (SegmentInfo *sgi : _segmentInfos) {
488 llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000489 << ", size=" << llvm::format("0x%08llX", sgi->size)
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000490 << ", segment-name='" << sgi->name
Nick Kledzik020a49c2013-11-06 21:57:52 +0000491 << "'\n";
492 for (SectionInfo *si : sgi->sections) {
493 llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000494 << ", size=" << llvm::format("0x%08llX", si->size)
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000495 << ", section-name='" << si->sectionName
Nick Kledzik020a49c2013-11-06 21:57:52 +0000496 << "\n";
497 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000498 }
Nick Kledzik020a49c2013-11-06 21:57:52 +0000499 );
Nick Kledzike34182f2013-11-06 21:36:55 +0000500 } else {
501 for (SectionInfo *sect : _sectionInfos) {
502 sect->address = alignTo(address, sect->alignment);
503 address = sect->address + sect->size;
504 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000505 DEBUG_WITH_TYPE("WriterMachO-norm",
Nick Kledzik020a49c2013-11-06 21:57:52 +0000506 llvm::dbgs() << "assignAddressesToSections()\n";
507 for (SectionInfo *si : _sectionInfos) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000508 llvm::dbgs() << " section=" << si->sectionName
Nick Kledzike34182f2013-11-06 21:36:55 +0000509 << " address= " << llvm::format("0x%08X", si->address)
510 << " size= " << llvm::format("0x%08X", si->size)
Nick Kledzik020a49c2013-11-06 21:57:52 +0000511 << "\n";
512 }
513 );
Nick Kledzike34182f2013-11-06 21:36:55 +0000514 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000515}
516
517
518void Util::copySegmentInfo(NormalizedFile &file) {
519 for (SegmentInfo *sgi : _segmentInfos) {
520 Segment seg;
521 seg.name = sgi->name;
522 seg.address = sgi->address;
523 seg.size = sgi->size;
524 seg.access = sgi->access;
525 file.segments.push_back(seg);
526 }
527}
528
529void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000530 // Add new empty section to end of file.sections.
Nick Kledzike34182f2013-11-06 21:36:55 +0000531 Section temp;
532 file.sections.push_back(std::move(temp));
533 Section* normSect = &file.sections.back();
534 // Copy fields to normalized section.
535 normSect->segmentName = si->segmentName;
536 normSect->sectionName = si->sectionName;
537 normSect->type = si->type;
538 normSect->attributes = si->attributes;
539 normSect->address = si->address;
540 normSect->alignment = si->alignment;
541 // Record where normalized section is.
542 si->normalizedSectionIndex = file.sections.size()-1;
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000543}
544
545void Util::copySectionContent(NormalizedFile &file) {
546 const bool r = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
547
548 // Utility function for ArchHandler to find address of atom in output file.
549 auto addrForAtom = [&] (const Atom &atom) -> uint64_t {
550 auto pos = _atomToAddress.find(&atom);
551 assert(pos != _atomToAddress.end());
552 return pos->second;
553 };
554
555 for (SectionInfo *si : _sectionInfos) {
556 if (si->type == llvm::MachO::S_ZEROFILL)
557 continue;
558 // Copy content from atoms to content buffer for section.
559 uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
560 Section *normSect = &file.sections[si->normalizedSectionIndex];
561 normSect->content = llvm::makeArrayRef(sectionContent, si->size);
562 for (AtomInfo &ai : si->atomsAndOffsets) {
563 uint8_t *atomContent = reinterpret_cast<uint8_t*>
Nick Kledzike34182f2013-11-06 21:36:55 +0000564 (&sectionContent[ai.offsetInSection]);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000565 _archHandler.generateAtomContent(*ai.atom, r, addrForAtom, atomContent);
566 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000567 }
568}
569
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000570
571void Util::copySectionInfo(NormalizedFile &file) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000572 file.sections.reserve(_sectionInfos.size());
573 // For final linked images, write sections grouped by segment.
Tim Northoverd30a1f22014-06-20 15:59:00 +0000574 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000575 for (SegmentInfo *sgi : _segmentInfos) {
576 for (SectionInfo *si : sgi->sections) {
577 appendSection(si, file);
578 }
579 }
580 } else {
581 // Object files write sections in default order.
582 for (SectionInfo *si : _sectionInfos) {
583 appendSection(si, file);
584 }
585 }
586}
587
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000588void Util::updateSectionInfo(NormalizedFile &file) {
589 file.sections.reserve(_sectionInfos.size());
590 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
591 // For final linked images, sections grouped by segment.
592 for (SegmentInfo *sgi : _segmentInfos) {
593 Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex];
594 normSeg->address = sgi->address;
595 normSeg->size = sgi->size;
596 for (SectionInfo *si : sgi->sections) {
597 Section *normSect = &file.sections[si->normalizedSectionIndex];
598 normSect->address = si->address;
599 }
600 }
601 } else {
602 // Object files write sections in default order.
603 for (SectionInfo *si : _sectionInfos) {
604 Section *normSect = &file.sections[si->normalizedSectionIndex];
605 normSect->address = si->address;
606 }
607 }
608}
609
Nick Kledzike34182f2013-11-06 21:36:55 +0000610void Util::copyEntryPointAddress(NormalizedFile &nFile) {
611 if (_context.outputTypeHasEntry()) {
Nick Kledzik54fd4e52014-07-28 23:06:09 +0000612 if (_archHandler.isThumbFunction(*_entryAtom))
613 nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
614 else
615 nFile.entryAddress = _atomToAddress[_entryAtom];
Nick Kledzike34182f2013-11-06 21:36:55 +0000616 }
617}
618
619void Util::buildAtomToAddressMap() {
620 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
621 << "assign atom addresses:\n");
622 const bool lookForEntry = _context.outputTypeHasEntry();
623 for (SectionInfo *sect : _sectionInfos) {
624 for (const AtomInfo &info : sect->atomsAndOffsets) {
625 _atomToAddress[info.atom] = sect->address + info.offsetInSection;
626 if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
627 (info.atom->size() != 0) &&
628 info.atom->name() == _context.entrySymbolName()) {
629 _entryAtom = info.atom;
630 }
631 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
632 << " address="
633 << llvm::format("0x%016X", _atomToAddress[info.atom])
634 << " atom=" << info.atom
635 << " name=" << info.atom->name() << "\n");
636 }
637 }
638}
639
Nick Kledzik60855392014-06-11 00:24:16 +0000640uint16_t Util::descBits(const DefinedAtom* atom) {
641 uint16_t desc = 0;
642 switch (atom->merge()) {
643 case lld::DefinedAtom::mergeNo:
644 case lld::DefinedAtom::mergeAsTentative:
645 break;
646 case lld::DefinedAtom::mergeAsWeak:
647 case lld::DefinedAtom::mergeAsWeakAndAddressUsed:
648 desc |= N_WEAK_DEF;
649 break;
650 case lld::DefinedAtom::mergeSameNameAndSize:
651 case lld::DefinedAtom::mergeByLargestSection:
652 case lld::DefinedAtom::mergeByContent:
653 llvm_unreachable("Unsupported DefinedAtom::merge()");
654 break;
655 }
656 if (atom->contentType() == lld::DefinedAtom::typeResolver)
657 desc |= N_SYMBOL_RESOLVER;
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000658 if (_archHandler.isThumbFunction(*atom))
659 desc |= N_ARM_THUMB_DEF;
Nick Kledzik7820c802014-08-21 22:18:30 +0000660 if (atom->deadStrip() == DefinedAtom::deadStripNever) {
661 if ((atom->contentType() != DefinedAtom::typeInitializerPtr)
662 && (atom->contentType() != DefinedAtom::typeTerminatorPtr))
663 desc |= N_NO_DEAD_STRIP;
664 }
Nick Kledzik60855392014-06-11 00:24:16 +0000665 return desc;
666}
667
668
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000669bool Util::AtomSorter::operator()(const AtomAndIndex &left,
Nick Kledzike34182f2013-11-06 21:36:55 +0000670 const AtomAndIndex &right) {
671 return (left.atom->name().compare(right.atom->name()) < 0);
672}
673
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000674
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000675std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom,
676 bool &inGlobalsRegion,
677 SymbolScope &scope) {
678 bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
679 switch (atom->scope()) {
680 case Atom::scopeTranslationUnit:
681 scope = 0;
682 inGlobalsRegion = false;
683 return std::error_code();
684 case Atom::scopeLinkageUnit:
685 if ((_context.exportMode() == MachOLinkingContext::ExportMode::whiteList)
686 && _context.exportSymbolNamed(atom->name())) {
687 return make_dynamic_error_code(Twine("cannot export hidden symbol ")
688 + atom->name());
689 }
690 if (rMode) {
691 if (_context.keepPrivateExterns()) {
692 // -keep_private_externs means keep in globals region as N_PEXT.
693 scope = N_PEXT | N_EXT;
694 inGlobalsRegion = true;
695 return std::error_code();
696 }
697 }
698 // scopeLinkageUnit symbols are no longer global once linked.
699 scope = N_PEXT;
700 inGlobalsRegion = false;
701 return std::error_code();
702 case Atom::scopeGlobal:
703 if (_context.exportRestrictMode()) {
704 if (_context.exportSymbolNamed(atom->name())) {
705 scope = N_EXT;
706 inGlobalsRegion = true;
707 return std::error_code();
708 } else {
709 scope = N_PEXT;
710 inGlobalsRegion = false;
711 return std::error_code();
712 }
713 } else {
714 scope = N_EXT;
715 inGlobalsRegion = true;
716 return std::error_code();
717 }
718 break;
719 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000720}
721
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000722std::error_code Util::addSymbols(const lld::File &atomFile,
723 NormalizedFile &file) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000724 bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
Nick Kledzike34182f2013-11-06 21:36:55 +0000725 // Mach-O symbol table has three regions: locals, globals, undefs.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000726
Nick Kledzike34182f2013-11-06 21:36:55 +0000727 // Add all local (non-global) symbols in address order
728 std::vector<AtomAndIndex> globals;
729 globals.reserve(512);
730 for (SectionInfo *sect : _sectionInfos) {
731 for (const AtomInfo &info : sect->atomsAndOffsets) {
732 const DefinedAtom *atom = info.atom;
733 if (!atom->name().empty()) {
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000734 SymbolScope symbolScope;
735 bool inGlobalsRegion;
736 if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){
737 return ec;
738 }
739 if (inGlobalsRegion) {
740 AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
Nick Kledzike34182f2013-11-06 21:36:55 +0000741 globals.push_back(ai);
742 } else {
743 Symbol sym;
744 sym.name = atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000745 sym.type = N_SECT;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000746 sym.scope = symbolScope;
Nick Kledzike34182f2013-11-06 21:36:55 +0000747 sym.sect = sect->finalSectionIndex;
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000748 sym.desc = descBits(atom);
Nick Kledzike34182f2013-11-06 21:36:55 +0000749 sym.value = _atomToAddress[atom];
Nick Kledzik2d432352014-07-17 23:16:21 +0000750 _atomToSymbolIndex[atom] = file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000751 file.localSymbols.push_back(sym);
752 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000753 } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){
754 // Create 'Lxxx' labels for anonymous atoms if archHandler says so.
755 static unsigned tempNum = 1;
756 char tmpName[16];
757 sprintf(tmpName, "L%04u", tempNum++);
758 StringRef tempRef(tmpName);
759 Symbol sym;
760 sym.name = tempRef.copy(file.ownedAllocations);
761 sym.type = N_SECT;
762 sym.scope = 0;
763 sym.sect = sect->finalSectionIndex;
764 sym.desc = 0;
765 sym.value = _atomToAddress[atom];
766 _atomToSymbolIndex[atom] = file.localSymbols.size();
767 file.localSymbols.push_back(sym);
Nick Kledzike34182f2013-11-06 21:36:55 +0000768 }
769 }
770 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000771
Nick Kledzike34182f2013-11-06 21:36:55 +0000772 // Sort global symbol alphabetically, then add to symbol table.
773 std::sort(globals.begin(), globals.end(), AtomSorter());
Nick Kledzik2d432352014-07-17 23:16:21 +0000774 const uint32_t globalStartIndex = file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000775 for (AtomAndIndex &ai : globals) {
776 Symbol sym;
777 sym.name = ai.atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000778 sym.type = N_SECT;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000779 sym.scope = ai.scope;
Nick Kledzike34182f2013-11-06 21:36:55 +0000780 sym.sect = ai.index;
Nick Kledzik60855392014-06-11 00:24:16 +0000781 sym.desc = descBits(static_cast<const DefinedAtom*>(ai.atom));
Nick Kledzike34182f2013-11-06 21:36:55 +0000782 sym.value = _atomToAddress[ai.atom];
Nick Kledzik2d432352014-07-17 23:16:21 +0000783 _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000784 file.globalSymbols.push_back(sym);
785 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000786
787
Nick Kledzike34182f2013-11-06 21:36:55 +0000788 // Sort undefined symbol alphabetically, then add to symbol table.
789 std::vector<AtomAndIndex> undefs;
790 undefs.reserve(128);
791 for (const UndefinedAtom *atom : atomFile.undefined()) {
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000792 AtomAndIndex ai = { atom, 0, N_EXT };
Nick Kledzike34182f2013-11-06 21:36:55 +0000793 undefs.push_back(ai);
794 }
795 for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) {
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000796 AtomAndIndex ai = { atom, 0, N_EXT };
Nick Kledzike34182f2013-11-06 21:36:55 +0000797 undefs.push_back(ai);
798 }
799 std::sort(undefs.begin(), undefs.end(), AtomSorter());
800 const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
801 for (AtomAndIndex &ai : undefs) {
802 Symbol sym;
Nick Kledzikb4768322014-08-13 23:11:42 +0000803 uint16_t desc = 0;
804 if (!rMode) {
805 uint8_t ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom));
806 llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal);
807 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000808 sym.name = ai.atom->name();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000809 sym.type = N_UNDF;
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000810 sym.scope = ai.scope;
Nick Kledzike34182f2013-11-06 21:36:55 +0000811 sym.sect = 0;
Nick Kledzikb4768322014-08-13 23:11:42 +0000812 sym.desc = desc;
Nick Kledzike34182f2013-11-06 21:36:55 +0000813 sym.value = 0;
814 _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start;
815 file.undefinedSymbols.push_back(sym);
816 }
Nick Kledzik8c0bf752014-08-21 01:59:11 +0000817
818 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000819}
820
821const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
822 for (const Reference *ref : *lpAtom) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000823 if (_archHandler.isLazyPointer(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000824 return ref->target();
825 }
826 }
827 return nullptr;
828}
829
830const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) {
831 for (const Reference *ref : *stubAtom) {
832 if (const Atom *ta = ref->target()) {
833 if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) {
834 const Atom *target = targetOfLazyPointer(lpAtom);
835 if (target)
836 return target;
837 }
838 }
839 }
840 return nullptr;
841}
842
843
844void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
845 for (SectionInfo *si : _sectionInfos) {
846 Section &normSect = file.sections[si->normalizedSectionIndex];
847 switch (si->type) {
848 case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS:
849 for (const AtomInfo &info : si->atomsAndOffsets) {
850 bool foundTarget = false;
851 for (const Reference *ref : *info.atom) {
852 const Atom *target = ref->target();
853 if (target) {
854 if (isa<const SharedLibraryAtom>(target)) {
855 uint32_t index = _atomToSymbolIndex[target];
856 normSect.indirectSymbols.push_back(index);
857 foundTarget = true;
858 } else {
859 normSect.indirectSymbols.push_back(
860 llvm::MachO::INDIRECT_SYMBOL_LOCAL);
861 }
862 }
863 }
864 if (!foundTarget) {
865 normSect.indirectSymbols.push_back(
866 llvm::MachO::INDIRECT_SYMBOL_ABS);
867 }
868 }
869 break;
870 case llvm::MachO::S_LAZY_SYMBOL_POINTERS:
871 for (const AtomInfo &info : si->atomsAndOffsets) {
872 const Atom *target = targetOfLazyPointer(info.atom);
873 if (target) {
874 uint32_t index = _atomToSymbolIndex[target];
875 normSect.indirectSymbols.push_back(index);
876 }
877 }
878 break;
879 case llvm::MachO::S_SYMBOL_STUBS:
880 for (const AtomInfo &info : si->atomsAndOffsets) {
881 const Atom *target = targetOfStub(info.atom);
882 if (target) {
883 uint32_t index = _atomToSymbolIndex[target];
884 normSect.indirectSymbols.push_back(index);
885 }
886 }
887 break;
888 default:
889 break;
890 }
891 }
892
893}
894
895void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
896 // Scan all imported symbols and build up list of dylibs they are from.
897 int ordinal = 1;
898 for (const SharedLibraryAtom *slAtom : atomFile.sharedLibrary()) {
899 StringRef loadPath = slAtom->loadName();
900 DylibPathToInfo::iterator pos = _dylibInfo.find(loadPath);
901 if (pos == _dylibInfo.end()) {
902 DylibInfo info;
903 info.ordinal = ordinal++;
904 info.hasWeak = slAtom->canBeNullAtRuntime();
905 info.hasNonWeak = !info.hasWeak;
906 _dylibInfo[loadPath] = info;
907 DependentDylib depInfo;
908 depInfo.path = loadPath;
909 depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
910 nFile.dependentDylibs.push_back(depInfo);
911 } else {
912 if ( slAtom->canBeNullAtRuntime() )
913 pos->second.hasWeak = true;
914 else
915 pos->second.hasNonWeak = true;
916 }
917 }
918 // Automatically weak link dylib in which all symbols are weak (canBeNull).
919 for (DependentDylib &dep : nFile.dependentDylibs) {
920 DylibInfo &info = _dylibInfo[dep.path];
921 if (info.hasWeak && !info.hasNonWeak)
922 dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB;
923 }
924}
925
926
927int Util::dylibOrdinal(const SharedLibraryAtom *sa) {
928 return _dylibInfo[sa->loadName()].ordinal;
929}
930
931void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex,
932 uint64_t &segmentStartAddr) {
933 segmentIndex = 0;
934 for (const SegmentInfo *seg : _segmentInfos) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000935 if ((seg->address <= sect->address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000936 && (seg->address+seg->size >= sect->address+sect->size)) {
937 segmentStartAddr = seg->address;
938 return;
939 }
940 ++segmentIndex;
941 }
942 llvm_unreachable("section not in any segment");
943}
944
945
Nick Kledzik2d432352014-07-17 23:16:21 +0000946uint32_t Util::sectionIndexForAtom(const Atom *atom) {
947 uint64_t address = _atomToAddress[atom];
948 uint32_t index = 1;
949 for (const SectionInfo *si : _sectionInfos) {
950 if ((si->address <= address) && (address < si->address+si->size))
951 return index;
952 ++index;
953 }
954 llvm_unreachable("atom not in any section");
Nick Kledzike34182f2013-11-06 21:36:55 +0000955}
956
957void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
Tim Northoverd30a1f22014-06-20 15:59:00 +0000958 if (_context.outputMachOType() != llvm::MachO::MH_OBJECT)
Nick Kledzike34182f2013-11-06 21:36:55 +0000959 return;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000960
Nick Kledzik2d432352014-07-17 23:16:21 +0000961
962 // Utility function for ArchHandler to find symbol index for an atom.
963 auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t {
964 auto pos = _atomToSymbolIndex.find(&atom);
965 assert(pos != _atomToSymbolIndex.end());
966 return pos->second;
967 };
968
969 // Utility function for ArchHandler to find section index for an atom.
970 auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t {
971 return sectionIndexForAtom(&atom);
972 };
973
974 // Utility function for ArchHandler to find address of atom in output file.
975 auto addressForAtom = [&] (const Atom &atom) -> uint64_t {
976 auto pos = _atomToAddress.find(&atom);
977 assert(pos != _atomToAddress.end());
978 return pos->second;
979 };
980
Nick Kledzike34182f2013-11-06 21:36:55 +0000981 for (SectionInfo *si : _sectionInfos) {
982 Section &normSect = file.sections[si->normalizedSectionIndex];
983 for (const AtomInfo &info : si->atomsAndOffsets) {
984 const DefinedAtom *atom = info.atom;
985 for (const Reference *ref : *atom) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000986 _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
987 symIndexForAtom,
988 sectIndexForAtom,
989 addressForAtom,
990 normSect.relocations);
Nick Kledzike34182f2013-11-06 21:36:55 +0000991 }
992 }
993 }
994}
995
Nick Kledzik21921372014-07-24 23:06:56 +0000996void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
997 for (SectionInfo *si : _sectionInfos) {
998 for (const AtomInfo &info : si->atomsAndOffsets) {
999 // Atoms that contain data-in-code have "transition" references
1000 // which mark a point where the embedded data starts of ends.
1001 // This needs to be converted to the mach-o format which is an array
1002 // of data-in-code ranges.
1003 uint32_t startOffset = 0;
1004 DataRegionType mode = DataRegionType(0);
1005 for (const Reference *ref : *info.atom) {
1006 if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
1007 continue;
1008 if (_archHandler.isDataInCodeTransition(ref->kindValue())) {
1009 DataRegionType nextMode = (DataRegionType)ref->addend();
1010 if (mode != nextMode) {
1011 if (mode != 0) {
1012 // Found end data range, so make range entry.
1013 DataInCode entry;
1014 entry.offset = si->address + info.offsetInSection + startOffset;
1015 entry.length = ref->offsetInAtom() - startOffset;
1016 entry.kind = mode;
1017 file.dataInCode.push_back(entry);
1018 }
1019 }
1020 mode = nextMode;
1021 startOffset = ref->offsetInAtom();
1022 }
1023 }
1024 if (mode != 0) {
1025 // Function ends with data (no end transition).
1026 DataInCode entry;
1027 entry.offset = si->address + info.offsetInSection + startOffset;
1028 entry.length = info.atom->size() - startOffset;
1029 entry.kind = mode;
1030 file.dataInCode.push_back(entry);
1031 }
1032 }
1033 }
1034}
1035
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001036void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
Nick Kledzike34182f2013-11-06 21:36:55 +00001037 NormalizedFile &nFile) {
Tim Northoverd30a1f22014-06-20 15:59:00 +00001038 if (_context.outputMachOType() == llvm::MachO::MH_OBJECT)
Nick Kledzike34182f2013-11-06 21:36:55 +00001039 return;
1040
1041 uint8_t segmentIndex;
1042 uint64_t segmentStartAddr;
1043 for (SectionInfo *sect : _sectionInfos) {
1044 segIndexForSection(sect, segmentIndex, segmentStartAddr);
1045 for (const AtomInfo &info : sect->atomsAndOffsets) {
1046 const DefinedAtom *atom = info.atom;
1047 for (const Reference *ref : *atom) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001048 uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom()
Nick Kledzike34182f2013-11-06 21:36:55 +00001049 - segmentStartAddr;
1050 const Atom* targ = ref->target();
Nick Kledzik2d432352014-07-17 23:16:21 +00001051 if (_archHandler.isPointer(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001052 // A pointer to a DefinedAtom requires rebasing.
1053 if (dyn_cast<DefinedAtom>(targ)) {
1054 RebaseLocation rebase;
1055 rebase.segIndex = segmentIndex;
1056 rebase.segOffset = segmentOffset;
1057 rebase.kind = llvm::MachO::REBASE_TYPE_POINTER;
1058 nFile.rebasingInfo.push_back(rebase);
1059 }
1060 // A pointer to an SharedLibraryAtom requires binding.
1061 if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
1062 BindLocation bind;
1063 bind.segIndex = segmentIndex;
1064 bind.segOffset = segmentOffset;
1065 bind.kind = llvm::MachO::BIND_TYPE_POINTER;
1066 bind.canBeNull = sa->canBeNullAtRuntime();
1067 bind.ordinal = dylibOrdinal(sa);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001068 bind.symbolName = targ->name();
Nick Kledzike34182f2013-11-06 21:36:55 +00001069 bind.addend = ref->addend();
1070 nFile.bindingInfo.push_back(bind);
1071 }
1072 }
Nick Kledzik2d432352014-07-17 23:16:21 +00001073 if (_archHandler.isLazyPointer(*ref)) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001074 BindLocation bind;
1075 bind.segIndex = segmentIndex;
1076 bind.segOffset = segmentOffset;
1077 bind.kind = llvm::MachO::BIND_TYPE_POINTER;
1078 bind.canBeNull = false; //sa->canBeNullAtRuntime();
Nick Kledzik2d432352014-07-17 23:16:21 +00001079 bind.ordinal = 1; // FIXME
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001080 bind.symbolName = targ->name();
Nick Kledzike34182f2013-11-06 21:36:55 +00001081 bind.addend = ref->addend();
1082 nFile.lazyBindingInfo.push_back(bind);
1083 }
1084 }
1085 }
1086 }
1087}
1088
Nick Kledzik141330a2014-09-03 19:52:50 +00001089
1090void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
1091 if (_context.outputMachOType() == llvm::MachO::MH_OBJECT)
1092 return;
1093
1094 for (SectionInfo *sect : _sectionInfos) {
1095 for (const AtomInfo &info : sect->atomsAndOffsets) {
1096 const DefinedAtom *atom = info.atom;
1097 if (atom->scope() != Atom::scopeGlobal)
1098 continue;
1099 if (_context.exportRestrictMode()) {
1100 if (!_context.exportSymbolNamed(atom->name()))
1101 continue;
1102 }
1103 Export exprt;
1104 exprt.name = atom->name();
1105 exprt.offset = _atomToAddress[atom]; // FIXME: subtract base address
1106 exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
1107 if (atom->merge() == DefinedAtom::mergeAsWeak)
1108 exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
1109 else
1110 exprt.flags = 0;
1111 exprt.otherOffset = 0;
1112 exprt.otherName = StringRef();
1113 nFile.exportInfo.push_back(exprt);
1114 }
1115 }
1116}
1117
Nick Kledzike34182f2013-11-06 21:36:55 +00001118uint32_t Util::fileFlags() {
Nick Kledzike1aaced2014-07-22 00:49:49 +00001119 // FIXME: these need to determined at runtime.
1120 if (_context.outputMachOType() == MH_OBJECT) {
1121 return MH_SUBSECTIONS_VIA_SYMBOLS;
1122 } else {
1123 return MH_DYLDLINK | MH_NOUNDEFS | MH_TWOLEVEL;
1124 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001125}
1126
1127} // end anonymous namespace
1128
1129
1130namespace lld {
1131namespace mach_o {
1132namespace normalized {
1133
1134/// Convert a set of Atoms into a normalized mach-o file.
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001135ErrorOr<std::unique_ptr<NormalizedFile>>
1136normalizedFromAtoms(const lld::File &atomFile,
Nick Kledzike34182f2013-11-06 21:36:55 +00001137 const MachOLinkingContext &context) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001138 // The util object buffers info until the normalized file can be made.
Nick Kledzike34182f2013-11-06 21:36:55 +00001139 Util util(context);
1140 util.assignAtomsToSections(atomFile);
1141 util.organizeSections();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001142
Nick Kledzike34182f2013-11-06 21:36:55 +00001143 std::unique_ptr<NormalizedFile> f(new NormalizedFile());
1144 NormalizedFile &normFile = *f.get();
Nick Kledzik2fcbe822014-07-30 00:58:06 +00001145 normFile.arch = context.arch();
1146 normFile.fileType = context.outputMachOType();
1147 normFile.flags = util.fileFlags();
1148 normFile.installName = context.installName();
Nick Kledzike34182f2013-11-06 21:36:55 +00001149 util.addDependentDylibs(atomFile, normFile);
Nick Kledzik2fcbe822014-07-30 00:58:06 +00001150 util.copySegmentInfo(normFile);
1151 util.copySectionInfo(normFile);
1152 util.assignAddressesToSections(normFile);
1153 util.buildAtomToAddressMap();
1154 util.updateSectionInfo(normFile);
1155 util.copySectionContent(normFile);
Nick Kledzik8c0bf752014-08-21 01:59:11 +00001156 if (auto ec = util.addSymbols(atomFile, normFile)) {
1157 return ec;
1158 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001159 util.addIndirectSymbols(atomFile, normFile);
1160 util.addRebaseAndBindingInfo(atomFile, normFile);
Nick Kledzik141330a2014-09-03 19:52:50 +00001161 util.addExportInfo(atomFile, normFile);
Nick Kledzike34182f2013-11-06 21:36:55 +00001162 util.addSectionRelocs(atomFile, normFile);
Nick Kledzik21921372014-07-24 23:06:56 +00001163 util.buildDataInCodeArray(atomFile, normFile);
Nick Kledzike34182f2013-11-06 21:36:55 +00001164 util.copyEntryPointAddress(normFile);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001165
Nick Kledzike34182f2013-11-06 21:36:55 +00001166 return std::move(f);
1167}
1168
1169
1170} // namespace normalized
1171} // namespace mach_o
1172} // namespace lld
1173