blob: a071771000f624cfb9336fbb8f927cee64b2f2f4 [file] [log] [blame]
Nick Kledzike34182f2013-11-06 21:36:55 +00001//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.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///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000011/// \file For mach-o object files, this implementation converts normalized
Nick Kledzike34182f2013-11-06 21:36:55 +000012/// mach-o in memory to mach-o binary on disk.
13///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000014/// +---------------+
15/// | binary mach-o |
16/// +---------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000017/// ^
18/// |
19/// |
Shankar Easwaran3d8de472014-01-27 03:09:26 +000020/// +------------+
21/// | normalized |
22/// +------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000023
24#include "MachONormalizedFile.h"
25#include "MachONormalizedFileBinaryUtils.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000026#include "lld/Core/Error.h"
27#include "lld/Core/LLVM.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000028#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/StringRef.h"
31#include "llvm/Support/Casting.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/FileOutputBuffer.h"
35#include "llvm/Support/Host.h"
Nick Kledzik00a15d92013-11-09 01:00:51 +000036#include "llvm/Support/LEB128.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000037#include "llvm/Support/MachO.h"
38#include "llvm/Support/MemoryBuffer.h"
39#include "llvm/Support/raw_ostream.h"
40#include "llvm/Support/system_error.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000041#include <functional>
42#include <map>
43
44using namespace llvm::MachO;
45
46namespace lld {
47namespace mach_o {
48namespace normalized {
49
50/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +000051/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +000052class MachOFileLayout {
53public:
Joey Goulyb275d7f2013-12-23 23:29:50 +000054 /// All layout computation is done in the constructor.
55 MachOFileLayout(const NormalizedFile &file);
56
Nick Kledzike34182f2013-11-06 21:36:55 +000057 /// Returns the final file size as computed in the constructor.
58 size_t size() const;
59
Shankar Easwaran3d8de472014-01-27 03:09:26 +000060 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +000061 /// path. This does not have a stream interface because the generated
62 /// file may need the 'x' bit set.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000063 std::error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000064
Nick Kledzike34182f2013-11-06 21:36:55 +000065private:
66 uint32_t loadCommandsSize(uint32_t &count);
67 void buildFileOffsets();
68 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000069 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +000070 void writeSectionContent();
71 void writeRelocations();
72 void writeSymbolTable();
73 void writeRebaseInfo();
74 void writeBindingInfo();
75 void writeLazyBindingInfo();
76 void writeLinkEditContent();
77 void buildLinkEditInfo();
78 void buildRebaseInfo();
79 void buildBindInfo();
80 void buildLazyBindInfo();
81 void computeSymbolTableSizes();
82 void buildSectionRelocations();
83 void appendSymbols(const std::vector<Symbol> &symbols,
84 uint32_t &symOffset, uint32_t &strOffset);
85 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
86 uint32_t indirectSymbolElementSize(const Section &sect);
87
Nick Kledzik29f749e2013-11-09 00:07:28 +000088 // For use as template parameter to load command methods.
89 struct MachO64Trait {
90 typedef llvm::MachO::segment_command_64 command;
91 typedef llvm::MachO::section_64 section;
92 enum { LC = llvm::MachO::LC_SEGMENT_64 };
93 };
94
95 // For use as template parameter to load command methods.
96 struct MachO32Trait {
97 typedef llvm::MachO::segment_command command;
98 typedef llvm::MachO::section section;
99 enum { LC = llvm::MachO::LC_SEGMENT };
100 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000101
Nick Kledzik29f749e2013-11-09 00:07:28 +0000102 template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000103 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
104 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000105
Nick Kledzike34182f2013-11-06 21:36:55 +0000106 uint32_t pointerAlign(uint32_t value);
107 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000108
Nick Kledzike34182f2013-11-06 21:36:55 +0000109 class ByteBuffer {
110 public:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000111 ByteBuffer() : _ostream(_bytes) { }
112 void append_byte(uint8_t b) {
113 _ostream << b;
114 }
115 void append_uleb128(uint64_t value) {
116 llvm::encodeULEB128(value, _ostream);
117 }
118 void append_sleb128(int64_t value) {
119 llvm::encodeSLEB128(value, _ostream);
120 }
121 void append_string(StringRef str) {
122 _ostream << str;
123 append_byte(0);
124 }
125 void align(unsigned alignment) {
126 while ( (_ostream.tell() % alignment) != 0 )
127 append_byte(0);
128 }
129 size_t size() {
130 return _ostream.tell();
131 }
132 const uint8_t *bytes() {
133 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
134 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000135 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000136 SmallVector<char, 128> _bytes;
137 // Stream ivar must be after SmallVector ivar to construct properly.
138 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000139 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000140
Nick Kledzik00a15d92013-11-09 01:00:51 +0000141
Nick Kledzike34182f2013-11-06 21:36:55 +0000142 struct SegExtraInfo {
143 uint32_t fileOffset;
144 std::vector<const Section*> sections;
145 };
146 typedef std::map<const Segment*, SegExtraInfo> SegMap;
147 struct SectionExtraInfo {
148 uint32_t fileOffset;
149 };
150 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000151
Nick Kledzike34182f2013-11-06 21:36:55 +0000152 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000153 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000154 uint8_t *_buffer;
155 const bool _is64;
156 const bool _swap;
157 const bool _bigEndianArch;
158 uint64_t _seg1addr;
159 uint32_t _startOfLoadCommands;
160 uint32_t _countOfLoadCommands;
161 uint32_t _endOfLoadCommands;
162 uint32_t _startOfRelocations;
163 uint32_t _startOfSymbols;
164 uint32_t _startOfIndirectSymbols;
165 uint32_t _startOfSymbolStrings;
166 uint32_t _endOfSymbolStrings;
167 uint32_t _symbolTableLocalsStartIndex;
168 uint32_t _symbolTableGlobalsStartIndex;
169 uint32_t _symbolTableUndefinesStartIndex;
170 uint32_t _symbolStringPoolSize;
171 uint32_t _symbolTableSize;
172 uint32_t _indirectSymbolTableCount;
173 // Used in object file creation only
174 uint32_t _startOfSectionsContent;
175 uint32_t _endOfSectionsContent;
176 // Used in final linked image only
177 uint32_t _startOfLinkEdit;
178 uint32_t _startOfRebaseInfo;
179 uint32_t _endOfRebaseInfo;
180 uint32_t _startOfBindingInfo;
181 uint32_t _endOfBindingInfo;
182 uint32_t _startOfLazyBindingInfo;
183 uint32_t _endOfLazyBindingInfo;
184 uint32_t _endOfLinkEdit;
185 uint64_t _addressOfLinkEdit;
186 SegMap _segInfo;
187 SectionMap _sectInfo;
188 ByteBuffer _rebaseInfo;
189 ByteBuffer _bindingInfo;
190 ByteBuffer _lazyBindingInfo;
191 ByteBuffer _weakBindingInfo;
192 ByteBuffer _exportInfo;
193};
194
195size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
196 MachOFileLayout layout(file);
197 return layout.size();
198}
199
200StringRef MachOFileLayout::dyldPath() {
201 return "/usr/lib/dyld";
202}
203
204uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
205 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000206}
Nick Kledzike34182f2013-11-06 21:36:55 +0000207
208
Nick Kledzike34182f2013-11-06 21:36:55 +0000209
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000210
211MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000212 : _file(file),
213 _is64(MachOLinkingContext::is64Bit(file.arch)),
214 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
215 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
216 _seg1addr(INT64_MAX) {
217 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000218 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000219 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
220 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
221 if (file.fileType == llvm::MachO::MH_OBJECT) {
222 // object files have just one segment load command containing all sections
223 _endOfLoadCommands = _startOfLoadCommands
224 + segCommandBaseSize
225 + file.sections.size() * sectsSize
226 + sizeof(symtab_command);
227 _countOfLoadCommands = 2;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000228
Nick Kledzike34182f2013-11-06 21:36:55 +0000229 // Accumulate size of each section.
230 _startOfSectionsContent = _endOfLoadCommands;
231 _endOfSectionsContent = _startOfSectionsContent;
232 unsigned relocCount = 0;
233 for (const Section &sect : file.sections) {
234 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
235 _endOfSectionsContent += sect.content.size();
236 relocCount += sect.relocations.size();
237 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000238
Nick Kledzike34182f2013-11-06 21:36:55 +0000239 computeSymbolTableSizes();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000240
Nick Kledzike34182f2013-11-06 21:36:55 +0000241 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000242 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzike34182f2013-11-06 21:36:55 +0000243 _startOfSymbols = _startOfRelocations + relocCount * 8;
244 // Add Indirect symbol table.
245 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
246 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000247 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000248 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000249 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000250 + pointerAlign(_symbolStringPoolSize);
251 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000252 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000253 llvm::dbgs() << "MachOFileLayout()\n"
254 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
255 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
256 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
257 << " startOfRelocations=" << _startOfRelocations << "\n"
258 << " startOfSymbols=" << _startOfSymbols << "\n"
259 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
260 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
261 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
262 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
263 } else {
264 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000265 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000266 + loadCommandsSize(_countOfLoadCommands);
267
268 // Assign section file offsets.
269 buildFileOffsets();
270 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000271
Nick Kledzike34182f2013-11-06 21:36:55 +0000272 // LINKEDIT of final linked images has in order:
273 // rebase info, binding info, lazy binding info, weak binding info,
274 // indirect symbol table, symbol table, symbol table strings.
275 _startOfRebaseInfo = _startOfLinkEdit;
276 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
277 _startOfBindingInfo = _endOfRebaseInfo;
278 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
279 _startOfLazyBindingInfo = _endOfBindingInfo;
280 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
281
282 _startOfSymbols = _endOfLazyBindingInfo;
283 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000284 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000285 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000286 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000287 + pointerAlign(_symbolStringPoolSize);
288 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000289 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000290 llvm::dbgs() << "MachOFileLayout()\n"
291 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
292 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
293 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
294 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
295 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
296 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
297 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
298 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
299 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
300 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
301 << " startOfSymbols=" << _startOfSymbols << "\n"
302 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
303 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
304 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
305 }
306}
307
308uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
309 uint32_t size = 0;
310 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000311
312 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000313 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
314 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
315
316 // Add LC_SEGMENT for each segment.
317 size += _file.segments.size() * segCommandSize;
318 count += _file.segments.size();
319 // Add section record for each section.
320 size += _file.sections.size() * sectionSize;
321 // Add one LC_SEGMENT for implicit __LINKEDIT segment
322 size += segCommandSize;
323 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000324
Nick Kledzike34182f2013-11-06 21:36:55 +0000325 // Add LC_DYLD_INFO
326 size += sizeof(dyld_info_command);
327 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000328
Nick Kledzike34182f2013-11-06 21:36:55 +0000329 // Add LC_SYMTAB
330 size += sizeof(symtab_command);
331 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000332
Nick Kledzike34182f2013-11-06 21:36:55 +0000333 // Add LC_DYSYMTAB
334 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
335 size += sizeof(dysymtab_command);
336 ++count;
337 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000338
Nick Kledzike34182f2013-11-06 21:36:55 +0000339 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
340 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
341 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
342 ++count;
343 size += sizeof(entry_point_command);
344 ++count;
345 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000346
Nick Kledzike34182f2013-11-06 21:36:55 +0000347 // Add LC_LOAD_DYLIB for each dependent dylib.
348 for (const DependentDylib &dep : _file.dependentDylibs) {
349 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
350 ++count;
351 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000352
Nick Kledzike34182f2013-11-06 21:36:55 +0000353 return size;
354}
355
356static bool overlaps(const Segment &s1, const Segment &s2) {
357 if (s2.address >= s1.address+s1.size)
358 return false;
359 if (s1.address >= s2.address+s2.size)
360 return false;
361 return true;
362}
363
364static bool overlaps(const Section &s1, const Section &s2) {
365 if (s2.address >= s1.address+s1.content.size())
366 return false;
367 if (s1.address >= s2.address+s2.content.size())
368 return false;
369 return true;
370}
371
372void MachOFileLayout::buildFileOffsets() {
373 // Verify no segments overlap
374 for (const Segment &sg1 : _file.segments) {
375 for (const Segment &sg2 : _file.segments) {
376 if (&sg1 == &sg2)
377 continue;
378 if (overlaps(sg1,sg2)) {
Rafael Espindola99c78a92014-06-12 03:13:49 +0000379 _ec = std::make_error_code(std::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000380 return;
381 }
382 }
383 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000384
385 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000386 for (const Section &s1 : _file.sections) {
387 for (const Section &s2 : _file.sections) {
388 if (&s1 == &s2)
389 continue;
390 if (overlaps(s1,s2)) {
Rafael Espindola99c78a92014-06-12 03:13:49 +0000391 _ec = std::make_error_code(std::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000392 return;
393 }
394 }
395 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000396
Nick Kledzike34182f2013-11-06 21:36:55 +0000397 // Build side table of extra info about segments and sections.
398 SegExtraInfo t;
399 t.fileOffset = 0;
400 for (const Segment &sg : _file.segments) {
401 _segInfo[&sg] = t;
402 }
403 SectionExtraInfo t2;
404 t2.fileOffset = 0;
405 // Assign sections to segments.
406 for (const Section &s : _file.sections) {
407 _sectInfo[&s] = t2;
408 for (const Segment &sg : _file.segments) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000409 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000410 && (s.address+s.content.size() <= sg.address+sg.size)) {
411 if (!sg.name.equals(s.segmentName)) {
Rafael Espindola99c78a92014-06-12 03:13:49 +0000412 _ec = std::make_error_code(std::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000413 return;
414 }
415 _segInfo[&sg].sections.push_back(&s);
416 }
417 }
418 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000419
Nick Kledzike34182f2013-11-06 21:36:55 +0000420 // Assign file offsets.
421 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000422 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000423 llvm::dbgs() << "buildFileOffsets()\n");
424 for (const Segment &sg : _file.segments) {
Alp Toker32e8bef2013-12-01 23:51:36 +0000425 // FIXME: 4096 should be inferred from segments in normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000426 _segInfo[&sg].fileOffset = llvm::RoundUpToAlignment(fileOffset, 4096);
427 if ((_seg1addr == INT64_MAX) && sg.access)
428 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000429 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000430 llvm::dbgs() << " segment=" << sg.name
431 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
432 for (const Section *s : _segInfo[&sg].sections) {
433 fileOffset = s->address - sg.address + _segInfo[&sg].fileOffset;
434 _sectInfo[s].fileOffset = fileOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000435 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000436 llvm::dbgs() << " section=" << s->sectionName
437 << ", fileOffset=" << fileOffset << "\n");
438 }
439 _addressOfLinkEdit = sg.address + sg.size;
440 }
441 _startOfLinkEdit = llvm::RoundUpToAlignment(fileOffset, 4096);
442}
443
444
445size_t MachOFileLayout::size() const {
446 return _endOfSymbolStrings;
447}
448
449void MachOFileLayout::writeMachHeader() {
450 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
451 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
452 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
453 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
454 mh->filetype = _file.fileType;
455 mh->ncmds = _countOfLoadCommands;
456 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
457 mh->flags = _file.flags;
458 if (_swap)
459 swapStruct(*mh);
460}
461
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000462uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000463 uint32_t &index) {
464 if (sect.indirectSymbols.empty())
465 return 0;
466 uint32_t result = index;
467 index += sect.indirectSymbols.size();
468 return result;
469}
470
471uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
472 if (sect.indirectSymbols.empty())
473 return 0;
474 if (sect.type != S_SYMBOL_STUBS)
475 return 0;
476 return sect.content.size() / sect.indirectSymbols.size();
477}
478
Nick Kledzik29f749e2013-11-09 00:07:28 +0000479template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000480std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000481 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
482 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000483 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000484 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000485 uint8_t *next = lc + seg->cmdsize;
486 memset(seg->segname, 0, 16);
487 seg->vmaddr = 0;
488 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
489 seg->fileoff = _endOfLoadCommands;
490 seg->filesize = seg->vmsize;
491 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
492 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
493 seg->nsects = _file.sections.size();
494 seg->flags = 0;
495 if (_swap)
496 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000497 typename T::section *sout = reinterpret_cast<typename T::section*>
498 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000499 uint32_t relOffset = _startOfRelocations;
500 uint32_t contentOffset = _startOfSectionsContent;
501 uint32_t indirectSymRunningIndex = 0;
502 for (const Section &sin : _file.sections) {
503 setString16(sin.sectionName, sout->sectname);
504 setString16(sin.segmentName, sout->segname);
505 sout->addr = sin.address;
506 sout->size = sin.content.size();
507 sout->offset = contentOffset;
508 sout->align = sin.alignment;
509 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
510 sout->nreloc = sin.relocations.size();
511 sout->flags = sin.type | sin.attributes;
512 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
513 sout->reserved2 = indirectSymbolElementSize(sin);
514 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
515 contentOffset += sin.content.size();
516 if (_swap)
517 swapStruct(*sout);
518 ++sout;
519 }
520 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000521 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000522}
523
Nick Kledzik29f749e2013-11-09 00:07:28 +0000524template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000525std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000526 uint32_t indirectSymRunningIndex = 0;
527 for (const Segment &seg : _file.segments) {
528 // Write segment command with trailing sections.
529 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000530 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
531 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000532 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000533 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000534 uint8_t *next = lc + cmd->cmdsize;
535 setString16(seg.name, cmd->segname);
536 cmd->vmaddr = seg.address;
537 cmd->vmsize = seg.size;
538 cmd->fileoff = segInfo.fileOffset;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000539 cmd->filesize = seg.access ? seg.size : Hex64(0);
Nick Kledzike34182f2013-11-06 21:36:55 +0000540 cmd->maxprot = seg.access;
541 cmd->initprot = seg.access;
542 cmd->nsects = segInfo.sections.size();
543 cmd->flags = 0;
544 if (_swap)
545 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000546 typename T::section *sect = reinterpret_cast<typename T::section*>
547 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000548 for (const Section *section : segInfo.sections) {
549 setString16(section->sectionName, sect->sectname);
550 setString16(section->segmentName, sect->segname);
551 sect->addr = section->address;
552 sect->size = section->content.size();
553 sect->offset = section->address - seg.address + segInfo.fileOffset;
554 sect->align = section->alignment;
555 sect->reloff = 0;
556 sect->nreloc = 0;
557 sect->flags = section->type | section->attributes;
558 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
559 sect->reserved2 = indirectSymbolElementSize(*section);
560 if (_swap)
561 swapStruct(*sect);
562 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000563 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000564 lc = reinterpret_cast<uint8_t*>(next);
565 }
566 // Add implicit __LINKEDIT segment
Nick Kledzik29f749e2013-11-09 00:07:28 +0000567 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
568 cmd->cmd = T::LC;
569 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000570 uint8_t *next = lc + cmd->cmdsize;
571 setString16("__LINKEDIT", cmd->segname);
572 cmd->vmaddr = _addressOfLinkEdit;
573 cmd->vmsize = _endOfLinkEdit - _startOfLinkEdit;
574 cmd->fileoff = _startOfLinkEdit;
575 cmd->filesize = _endOfLinkEdit - _startOfLinkEdit;
576 cmd->maxprot = VM_PROT_READ;
577 cmd->initprot = VM_PROT_READ;
578 cmd->nsects = 0;
579 cmd->flags = 0;
580 if (_swap)
581 swapStruct(*cmd);
582 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000583 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000584}
585
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000586std::error_code MachOFileLayout::writeLoadCommands() {
587 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000588 uint8_t *lc = &_buffer[_startOfLoadCommands];
589 if (_file.fileType == llvm::MachO::MH_OBJECT) {
590 // Object files have one unnamed segment which holds all sections.
591 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000592 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000593 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000594 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000595 // Add LC_SYMTAB with symbol table info
596 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
597 st->cmd = LC_SYMTAB;
598 st->cmdsize = sizeof(symtab_command);
599 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000600 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000601 + _file.undefinedSymbols.size();
602 st->stroff = _startOfSymbolStrings;
603 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
604 if (_swap)
605 swapStruct(*st);
606 } else {
607 // Final linked images have sections under segments.
608 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000609 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000610 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000611 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000612
Nick Kledzike34182f2013-11-06 21:36:55 +0000613 // Add LC_DYLD_INFO_ONLY.
614 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
615 di->cmd = LC_DYLD_INFO_ONLY;
616 di->cmdsize = sizeof(dyld_info_command);
617 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
618 di->rebase_size = _rebaseInfo.size();
619 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
620 di->bind_size = _bindingInfo.size();
621 di->weak_bind_off = 0;
622 di->weak_bind_size = 0;
623 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
624 di->lazy_bind_size = _lazyBindingInfo.size();
625 di->export_off = 0;
626 di->export_size = 0;
627 if (_swap)
628 swapStruct(*di);
629 lc += sizeof(dyld_info_command);
630
631 // Add LC_SYMTAB with symbol table info.
632 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
633 st->cmd = LC_SYMTAB;
634 st->cmdsize = sizeof(symtab_command);
635 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000636 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000637 + _file.undefinedSymbols.size();
638 st->stroff = _startOfSymbolStrings;
639 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
640 if (_swap)
641 swapStruct(*st);
642 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000643
Nick Kledzike34182f2013-11-06 21:36:55 +0000644 // Add LC_DYSYMTAB
645 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
646 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
647 dst->cmd = LC_DYSYMTAB;
648 dst->cmdsize = sizeof(dysymtab_command);
649 dst->ilocalsym = _symbolTableLocalsStartIndex;
650 dst->nlocalsym = _file.localSymbols.size();
651 dst->iextdefsym = _symbolTableGlobalsStartIndex;
652 dst->nextdefsym = _file.globalSymbols.size();
653 dst->iundefsym = _symbolTableUndefinesStartIndex;
654 dst->nundefsym = _file.undefinedSymbols.size();
655 dst->tocoff = 0;
656 dst->ntoc = 0;
657 dst->modtaboff = 0;
658 dst->nmodtab = 0;
659 dst->extrefsymoff = 0;
660 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000661 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000662 dst->nindirectsyms = _indirectSymbolTableCount;
663 dst->extreloff = 0;
664 dst->nextrel = 0;
665 dst->locreloff = 0;
666 dst->nlocrel = 0;
667 if (_swap)
668 swapStruct(*dst);
669 lc += sizeof(dysymtab_command);
670 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000671
Nick Kledzike34182f2013-11-06 21:36:55 +0000672 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
673 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
674 // Build LC_LOAD_DYLINKER load command.
675 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
676 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
677 dl->cmd = LC_LOAD_DYLINKER;
678 dl->cmdsize = size;
679 dl->name = sizeof(dylinker_command); // offset
680 if (_swap)
681 swapStruct(*dl);
682 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
683 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
684 lc += size;
685 // Build LC_MAIN load command.
686 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
687 ep->cmd = LC_MAIN;
688 ep->cmdsize = sizeof(entry_point_command);
689 ep->entryoff = _file.entryAddress - _seg1addr;
690 ep->stacksize = 0;
691 if (_swap)
692 swapStruct(*ep);
693 lc += sizeof(entry_point_command);
694 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000695
Nick Kledzike34182f2013-11-06 21:36:55 +0000696 // Add LC_LOAD_DYLIB commands
697 for (const DependentDylib &dep : _file.dependentDylibs) {
698 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
699 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
700 dc->cmd = LC_LOAD_DYLIB;
701 dc->cmdsize = size;
702 dc->dylib.name = sizeof(dylib_command); // offset
703 dc->dylib.timestamp = 0; // FIXME
704 dc->dylib.current_version = 0; // FIXME
705 dc->dylib.compatibility_version = 0; // FIXME
706 if (_swap)
707 swapStruct(*dc);
708 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
709 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
710 lc += size;
711 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000712
Nick Kledzike34182f2013-11-06 21:36:55 +0000713 }
714 return ec;
715}
716
717
718void MachOFileLayout::writeSectionContent() {
719 for (const Section &s : _file.sections) {
720 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000721 if (s.type == llvm::MachO::S_ZEROFILL)
722 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000723 uint32_t offset = _sectInfo[&s].fileOffset;
724 uint8_t *p = &_buffer[offset];
725 memcpy(p, &s.content[0], s.content.size());
726 p += s.content.size();
727 }
728}
729
730void MachOFileLayout::writeRelocations() {
731 uint32_t relOffset = _startOfRelocations;
732 for (Section sect : _file.sections) {
733 for (Relocation r : sect.relocations) {
734 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
735 &_buffer[relOffset]);
736 *rb = packRelocation(r, _swap, _bigEndianArch);
737 relOffset += sizeof(any_relocation_info);
738 }
739 }
740}
741
742
743void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
744 uint32_t &symOffset, uint32_t &strOffset) {
745 for (const Symbol &sym : symbols) {
746 if (_is64) {
747 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
748 nb->n_strx = strOffset - _startOfSymbolStrings;
749 nb->n_type = sym.type | sym.scope;
750 nb->n_sect = sym.sect;
751 nb->n_desc = sym.desc;
752 nb->n_value = sym.value;
753 if (_swap)
754 swapStruct(*nb);
755 symOffset += sizeof(nlist_64);
756 } else {
757 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
758 nb->n_strx = strOffset - _startOfSymbolStrings;
759 nb->n_type = sym.type | sym.scope;
760 nb->n_sect = sym.sect;
761 nb->n_desc = sym.desc;
762 nb->n_value = sym.value;
763 if (_swap)
764 swapStruct(*nb);
765 symOffset += sizeof(nlist);
766 }
767 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
768 strOffset += sym.name.size();
769 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
770 }
771}
772
773void MachOFileLayout::writeSymbolTable() {
774 // Write symbol table and symbol strings in parallel.
775 uint32_t symOffset = _startOfSymbols;
776 uint32_t strOffset = _startOfSymbolStrings;
777 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
778 appendSymbols(_file.localSymbols, symOffset, strOffset);
779 appendSymbols(_file.globalSymbols, symOffset, strOffset);
780 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
781 // Write indirect symbol table array.
782 uint32_t *indirects = reinterpret_cast<uint32_t*>
783 (&_buffer[_startOfIndirectSymbols]);
784 if (_file.fileType == llvm::MachO::MH_OBJECT) {
785 // Object files have sections in same order as input normalized file.
786 for (const Section &section : _file.sections) {
787 for (uint32_t index : section.indirectSymbols) {
788 if (_swap)
789 *indirects++ = SwapByteOrder(index);
790 else
791 *indirects++ = index;
792 }
793 }
794 } else {
795 // Final linked images must sort sections from normalized file.
796 for (const Segment &seg : _file.segments) {
797 SegExtraInfo &segInfo = _segInfo[&seg];
798 for (const Section *section : segInfo.sections) {
799 for (uint32_t index : section->indirectSymbols) {
800 if (_swap)
801 *indirects++ = SwapByteOrder(index);
802 else
803 *indirects++ = index;
804 }
805 }
806 }
807 }
808}
809
810void MachOFileLayout::writeRebaseInfo() {
811 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
812}
813
814void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000815 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000816 _bindingInfo.bytes(), _bindingInfo.size());
817}
818
819void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000820 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000821 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
822}
823
824void MachOFileLayout::buildLinkEditInfo() {
825 buildRebaseInfo();
826 buildBindInfo();
827 buildLazyBindInfo();
828 computeSymbolTableSizes();
829}
830
831void MachOFileLayout::buildSectionRelocations() {
832
833}
834
835void MachOFileLayout::buildRebaseInfo() {
836 // TODO: compress rebasing info.
837 for (const RebaseLocation& entry : _file.rebasingInfo) {
838 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000839 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000840 | entry.segIndex);
841 _rebaseInfo.append_uleb128(entry.segOffset);
842 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
843 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000844 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000845 _rebaseInfo.align(_is64 ? 8 : 4);
846}
847
848void MachOFileLayout::buildBindInfo() {
849 // TODO: compress bind info.
850 for (const BindLocation& entry : _file.bindingInfo) {
851 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000852 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000853 | entry.segIndex);
854 _bindingInfo.append_uleb128(entry.segOffset);
855 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
856 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
857 _bindingInfo.append_string(entry.symbolName);
858 if (entry.addend != 0) {
859 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
860 _bindingInfo.append_sleb128(entry.addend);
861 }
862 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
863 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000864 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000865 _bindingInfo.align(_is64 ? 8 : 4);
866}
867
868void MachOFileLayout::buildLazyBindInfo() {
869 for (const BindLocation& entry : _file.lazyBindingInfo) {
870 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000871 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000872 | entry.segIndex);
873 _lazyBindingInfo.append_uleb128(entry.segOffset);
874 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
875 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
876 _lazyBindingInfo.append_string(entry.symbolName);
877 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
878 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000879 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000880 _lazyBindingInfo.align(_is64 ? 8 : 4);
881}
882
883void MachOFileLayout::computeSymbolTableSizes() {
884 // MachO symbol tables have three ranges: locals, globals, and undefines
885 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000886 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000887 + _file.globalSymbols.size()
888 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000889 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000890 for (const Symbol &sym : _file.localSymbols) {
891 _symbolStringPoolSize += (sym.name.size()+1);
892 }
893 for (const Symbol &sym : _file.globalSymbols) {
894 _symbolStringPoolSize += (sym.name.size()+1);
895 }
896 for (const Symbol &sym : _file.undefinedSymbols) {
897 _symbolStringPoolSize += (sym.name.size()+1);
898 }
899 _symbolTableLocalsStartIndex = 0;
900 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000901 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +0000902 + _file.globalSymbols.size();
903
904 _indirectSymbolTableCount = 0;
905 for (const Section &sect : _file.sections) {
906 _indirectSymbolTableCount += sect.indirectSymbols.size();
907 }
908}
909
910
911void MachOFileLayout::writeLinkEditContent() {
912 if (_file.fileType == llvm::MachO::MH_OBJECT) {
913 writeRelocations();
914 writeSymbolTable();
915 } else {
916 writeRebaseInfo();
917 writeBindingInfo();
918 writeLazyBindingInfo();
919 // TODO: add weak binding info
920 writeSymbolTable();
921 }
922}
923
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000924std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000925 // Check for pending error from constructor.
926 if (_ec)
927 return _ec;
928 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +0000929 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +0000930 unsigned flags = 0;
931 if (_file.fileType != llvm::MachO::MH_OBJECT)
932 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000933 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000934 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
935 if (ec)
936 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000937
Nick Kledzike34182f2013-11-06 21:36:55 +0000938 // Write content.
939 _buffer = fob->getBufferStart();
940 writeMachHeader();
941 ec = writeLoadCommands();
942 if (ec)
943 return ec;
944 writeSectionContent();
945 writeLinkEditContent();
946 fob->commit();
947
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000948 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000949}
950
951
952
953/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000954std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000955 MachOFileLayout layout(file);
956 return layout.writeBinary(path);
957}
958
959
960} // namespace normalized
961} // namespace mach_o
962} // namespace lld
963