blob: 208ef0b7db3c065001fa1dd9775673a81fd20502 [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"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000033#include "llvm/Support/Errc.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000034#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/FileOutputBuffer.h"
Nick Kledzik141330a2014-09-03 19:52:50 +000036#include "llvm/Support/Format.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000037#include "llvm/Support/Host.h"
Nick Kledzik00a15d92013-11-09 01:00:51 +000038#include "llvm/Support/LEB128.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000039#include "llvm/Support/MachO.h"
40#include "llvm/Support/MemoryBuffer.h"
41#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000042#include <functional>
43#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000044#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000045
46using namespace llvm::MachO;
47
48namespace lld {
49namespace mach_o {
50namespace normalized {
51
52/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +000053/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +000054class MachOFileLayout {
55public:
Joey Goulyb275d7f2013-12-23 23:29:50 +000056 /// All layout computation is done in the constructor.
57 MachOFileLayout(const NormalizedFile &file);
58
Nick Kledzike34182f2013-11-06 21:36:55 +000059 /// Returns the final file size as computed in the constructor.
60 size_t size() const;
61
Nick Kledzik2fcbe822014-07-30 00:58:06 +000062 // Returns size of the mach_header and load commands.
63 size_t headerAndLoadCommandsSize() const;
64
Shankar Easwaran3d8de472014-01-27 03:09:26 +000065 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +000066 /// path. This does not have a stream interface because the generated
67 /// file may need the 'x' bit set.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000068 std::error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000069
Nick Kledzike34182f2013-11-06 21:36:55 +000070private:
71 uint32_t loadCommandsSize(uint32_t &count);
72 void buildFileOffsets();
73 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000074 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +000075 void writeSectionContent();
76 void writeRelocations();
77 void writeSymbolTable();
78 void writeRebaseInfo();
79 void writeBindingInfo();
80 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +000081 void writeExportInfo();
Nick Kledzik21921372014-07-24 23:06:56 +000082 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +000083 void writeLinkEditContent();
84 void buildLinkEditInfo();
85 void buildRebaseInfo();
86 void buildBindInfo();
87 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +000088 void buildExportTrie();
Nick Kledzik21921372014-07-24 23:06:56 +000089 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +000090 void computeSymbolTableSizes();
91 void buildSectionRelocations();
92 void appendSymbols(const std::vector<Symbol> &symbols,
93 uint32_t &symOffset, uint32_t &strOffset);
94 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
95 uint32_t indirectSymbolElementSize(const Section &sect);
96
Nick Kledzik29f749e2013-11-09 00:07:28 +000097 // For use as template parameter to load command methods.
98 struct MachO64Trait {
99 typedef llvm::MachO::segment_command_64 command;
100 typedef llvm::MachO::section_64 section;
101 enum { LC = llvm::MachO::LC_SEGMENT_64 };
102 };
103
104 // For use as template parameter to load command methods.
105 struct MachO32Trait {
106 typedef llvm::MachO::segment_command command;
107 typedef llvm::MachO::section section;
108 enum { LC = llvm::MachO::LC_SEGMENT };
109 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000110
Nick Kledzik29f749e2013-11-09 00:07:28 +0000111 template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000112 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
113 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000114
Nick Kledzike34182f2013-11-06 21:36:55 +0000115 uint32_t pointerAlign(uint32_t value);
116 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000117
Nick Kledzike34182f2013-11-06 21:36:55 +0000118 class ByteBuffer {
119 public:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000120 ByteBuffer() : _ostream(_bytes) { }
Nick Kledzik141330a2014-09-03 19:52:50 +0000121
Nick Kledzik00a15d92013-11-09 01:00:51 +0000122 void append_byte(uint8_t b) {
123 _ostream << b;
124 }
125 void append_uleb128(uint64_t value) {
126 llvm::encodeULEB128(value, _ostream);
127 }
128 void append_sleb128(int64_t value) {
129 llvm::encodeSLEB128(value, _ostream);
130 }
131 void append_string(StringRef str) {
132 _ostream << str;
133 append_byte(0);
134 }
135 void align(unsigned alignment) {
136 while ( (_ostream.tell() % alignment) != 0 )
137 append_byte(0);
138 }
139 size_t size() {
140 return _ostream.tell();
141 }
142 const uint8_t *bytes() {
143 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
144 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000145 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000146 SmallVector<char, 128> _bytes;
147 // Stream ivar must be after SmallVector ivar to construct properly.
148 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000149 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000150
Nick Kledzik141330a2014-09-03 19:52:50 +0000151 struct TrieNode; // Forward declaration.
152
153 struct TrieEdge {
154 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
155 ~TrieEdge() {}
156
157 StringRef _subString;
158 struct TrieNode *_child;
159 };
160
161 struct TrieNode {
162 TrieNode(StringRef s)
163 : _cummulativeString(s), _address(0), _flags(0), _other(0),
164 _trieOffset(0), _hasExportInfo(false) {}
165 ~TrieNode() {}
166
167 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
168 std::vector<TrieNode *> &allNodes);
169 bool updateOffset(uint32_t &offset);
170 void appendToByteBuffer(ByteBuffer &out);
171
172private:
173 StringRef _cummulativeString;
174 SmallVector<TrieEdge, 8> _children;
175 uint64_t _address;
176 uint64_t _flags;
177 uint64_t _other;
178 StringRef _importedName;
179 uint32_t _trieOffset;
180 bool _hasExportInfo;
181 };
Nick Kledzik00a15d92013-11-09 01:00:51 +0000182
Nick Kledzike34182f2013-11-06 21:36:55 +0000183 struct SegExtraInfo {
184 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000185 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000186 std::vector<const Section*> sections;
187 };
188 typedef std::map<const Segment*, SegExtraInfo> SegMap;
189 struct SectionExtraInfo {
190 uint32_t fileOffset;
191 };
192 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000193
Nick Kledzike34182f2013-11-06 21:36:55 +0000194 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000195 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000196 uint8_t *_buffer;
197 const bool _is64;
198 const bool _swap;
199 const bool _bigEndianArch;
200 uint64_t _seg1addr;
201 uint32_t _startOfLoadCommands;
202 uint32_t _countOfLoadCommands;
203 uint32_t _endOfLoadCommands;
204 uint32_t _startOfRelocations;
Nick Kledzik21921372014-07-24 23:06:56 +0000205 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000206 uint32_t _startOfSymbols;
207 uint32_t _startOfIndirectSymbols;
208 uint32_t _startOfSymbolStrings;
209 uint32_t _endOfSymbolStrings;
210 uint32_t _symbolTableLocalsStartIndex;
211 uint32_t _symbolTableGlobalsStartIndex;
212 uint32_t _symbolTableUndefinesStartIndex;
213 uint32_t _symbolStringPoolSize;
214 uint32_t _symbolTableSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000215 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000216 uint32_t _indirectSymbolTableCount;
217 // Used in object file creation only
218 uint32_t _startOfSectionsContent;
219 uint32_t _endOfSectionsContent;
220 // Used in final linked image only
221 uint32_t _startOfLinkEdit;
222 uint32_t _startOfRebaseInfo;
223 uint32_t _endOfRebaseInfo;
224 uint32_t _startOfBindingInfo;
225 uint32_t _endOfBindingInfo;
226 uint32_t _startOfLazyBindingInfo;
227 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000228 uint32_t _startOfExportTrie;
229 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000230 uint32_t _endOfLinkEdit;
231 uint64_t _addressOfLinkEdit;
232 SegMap _segInfo;
233 SectionMap _sectInfo;
234 ByteBuffer _rebaseInfo;
235 ByteBuffer _bindingInfo;
236 ByteBuffer _lazyBindingInfo;
237 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000238 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000239};
240
241size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
242 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000243 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000244}
245
246StringRef MachOFileLayout::dyldPath() {
247 return "/usr/lib/dyld";
248}
249
250uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
251 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000252}
Nick Kledzike34182f2013-11-06 21:36:55 +0000253
254
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000255size_t MachOFileLayout::headerAndLoadCommandsSize() const {
256 return _endOfLoadCommands;
257}
Nick Kledzike34182f2013-11-06 21:36:55 +0000258
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000259
260MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000261 : _file(file),
262 _is64(MachOLinkingContext::is64Bit(file.arch)),
263 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
264 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
265 _seg1addr(INT64_MAX) {
266 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000267 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000268 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
269 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
270 if (file.fileType == llvm::MachO::MH_OBJECT) {
271 // object files have just one segment load command containing all sections
272 _endOfLoadCommands = _startOfLoadCommands
273 + segCommandBaseSize
274 + file.sections.size() * sectsSize
275 + sizeof(symtab_command);
276 _countOfLoadCommands = 2;
Nick Kledzik21921372014-07-24 23:06:56 +0000277 if (!_file.dataInCode.empty()) {
278 _endOfLoadCommands += sizeof(linkedit_data_command);
279 _countOfLoadCommands++;
280 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000281 // Accumulate size of each section.
282 _startOfSectionsContent = _endOfLoadCommands;
283 _endOfSectionsContent = _startOfSectionsContent;
284 unsigned relocCount = 0;
285 for (const Section &sect : file.sections) {
286 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
287 _endOfSectionsContent += sect.content.size();
288 relocCount += sect.relocations.size();
289 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000290
Nick Kledzike34182f2013-11-06 21:36:55 +0000291 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000292 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000293
Nick Kledzike34182f2013-11-06 21:36:55 +0000294 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000295 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzik21921372014-07-24 23:06:56 +0000296 _startOfDataInCode = _startOfRelocations + relocCount * 8;
297 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000298 // Add Indirect symbol table.
299 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
300 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000301 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000302 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000303 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000304 + pointerAlign(_symbolStringPoolSize);
305 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000306 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000307 llvm::dbgs() << "MachOFileLayout()\n"
308 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
309 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
310 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
311 << " startOfRelocations=" << _startOfRelocations << "\n"
312 << " startOfSymbols=" << _startOfSymbols << "\n"
313 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
314 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
315 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
316 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
317 } else {
318 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000319 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000320 + loadCommandsSize(_countOfLoadCommands);
321
322 // Assign section file offsets.
323 buildFileOffsets();
324 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000325
Nick Kledzike34182f2013-11-06 21:36:55 +0000326 // LINKEDIT of final linked images has in order:
327 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000328 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000329 _startOfRebaseInfo = _startOfLinkEdit;
330 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
331 _startOfBindingInfo = _endOfRebaseInfo;
332 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
333 _startOfLazyBindingInfo = _endOfBindingInfo;
334 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000335 _startOfExportTrie = _endOfLazyBindingInfo;
336 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
337 _startOfDataInCode = _endOfExportTrie;
Nick Kledzik21921372014-07-24 23:06:56 +0000338 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000339 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000340 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000341 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000342 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000343 + pointerAlign(_symbolStringPoolSize);
344 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000345 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000346 llvm::dbgs() << "MachOFileLayout()\n"
347 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
348 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
349 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
350 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
351 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
352 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
353 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
354 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
355 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
356 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000357 << " startOfExportTrie=" << _startOfExportTrie << "\n"
358 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000359 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000360 << " startOfSymbols=" << _startOfSymbols << "\n"
361 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
362 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
363 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
364 }
365}
366
367uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
368 uint32_t size = 0;
369 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000370
371 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000372 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
373 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
374
375 // Add LC_SEGMENT for each segment.
376 size += _file.segments.size() * segCommandSize;
377 count += _file.segments.size();
378 // Add section record for each section.
379 size += _file.sections.size() * sectionSize;
380 // Add one LC_SEGMENT for implicit __LINKEDIT segment
381 size += segCommandSize;
382 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000383
Tim Northover301c4e62014-07-01 08:15:41 +0000384 // If creating a dylib, add LC_ID_DYLIB.
385 if (_file.fileType == llvm::MachO::MH_DYLIB) {
386 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
387 ++count;
388 }
389
Nick Kledzike34182f2013-11-06 21:36:55 +0000390 // Add LC_DYLD_INFO
391 size += sizeof(dyld_info_command);
392 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000393
Nick Kledzike34182f2013-11-06 21:36:55 +0000394 // Add LC_SYMTAB
395 size += sizeof(symtab_command);
396 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000397
Nick Kledzike34182f2013-11-06 21:36:55 +0000398 // Add LC_DYSYMTAB
399 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
400 size += sizeof(dysymtab_command);
401 ++count;
402 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000403
Nick Kledzike34182f2013-11-06 21:36:55 +0000404 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
405 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
406 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
407 ++count;
408 size += sizeof(entry_point_command);
409 ++count;
410 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000411
Nick Kledzike34182f2013-11-06 21:36:55 +0000412 // Add LC_LOAD_DYLIB for each dependent dylib.
413 for (const DependentDylib &dep : _file.dependentDylibs) {
414 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
415 ++count;
416 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000417
Nick Kledzike34182f2013-11-06 21:36:55 +0000418 return size;
419}
420
421static bool overlaps(const Segment &s1, const Segment &s2) {
422 if (s2.address >= s1.address+s1.size)
423 return false;
424 if (s1.address >= s2.address+s2.size)
425 return false;
426 return true;
427}
428
429static bool overlaps(const Section &s1, const Section &s2) {
430 if (s2.address >= s1.address+s1.content.size())
431 return false;
432 if (s1.address >= s2.address+s2.content.size())
433 return false;
434 return true;
435}
436
437void MachOFileLayout::buildFileOffsets() {
438 // Verify no segments overlap
439 for (const Segment &sg1 : _file.segments) {
440 for (const Segment &sg2 : _file.segments) {
441 if (&sg1 == &sg2)
442 continue;
443 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000444 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000445 return;
446 }
447 }
448 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000449
450 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000451 for (const Section &s1 : _file.sections) {
452 for (const Section &s2 : _file.sections) {
453 if (&s1 == &s2)
454 continue;
455 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000456 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000457 return;
458 }
459 }
460 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000461
Nick Kledzike34182f2013-11-06 21:36:55 +0000462 // Build side table of extra info about segments and sections.
463 SegExtraInfo t;
464 t.fileOffset = 0;
465 for (const Segment &sg : _file.segments) {
466 _segInfo[&sg] = t;
467 }
468 SectionExtraInfo t2;
469 t2.fileOffset = 0;
470 // Assign sections to segments.
471 for (const Section &s : _file.sections) {
472 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000473 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000474 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000475 if (sg.name.equals(s.segmentName)) {
476 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000477 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000478 _segInfo[&sg].sections.push_back(&s);
479 foundSegment = true;
480 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000481 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000482 }
483 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000484 if (!foundSegment) {
485 _ec = make_error_code(llvm::errc::executable_format_error);
486 return;
487 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000488 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000489
Nick Kledzike34182f2013-11-06 21:36:55 +0000490 // Assign file offsets.
491 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000492 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000493 llvm::dbgs() << "buildFileOffsets()\n");
494 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000495 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000496 if ((_seg1addr == INT64_MAX) && sg.access)
497 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000498 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000499 llvm::dbgs() << " segment=" << sg.name
500 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000501
502 uint32_t segFileSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000503 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000504 uint32_t sectOffset = s->address - sg.address;
505 uint32_t sectFileSize =
506 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
507 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
508
509 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000510 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000511 llvm::dbgs() << " section=" << s->sectionName
512 << ", fileOffset=" << fileOffset << "\n");
513 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000514
Nick Kledzik1bebb282014-09-09 23:52:59 +0000515 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize,
516 _file.pageSize);
517 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize,
518 _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000519 _addressOfLinkEdit = sg.address + sg.size;
520 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000521 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000522}
523
524
525size_t MachOFileLayout::size() const {
526 return _endOfSymbolStrings;
527}
528
529void MachOFileLayout::writeMachHeader() {
530 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
531 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
532 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
533 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
534 mh->filetype = _file.fileType;
535 mh->ncmds = _countOfLoadCommands;
536 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
537 mh->flags = _file.flags;
538 if (_swap)
539 swapStruct(*mh);
540}
541
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000542uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000543 uint32_t &index) {
544 if (sect.indirectSymbols.empty())
545 return 0;
546 uint32_t result = index;
547 index += sect.indirectSymbols.size();
548 return result;
549}
550
551uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
552 if (sect.indirectSymbols.empty())
553 return 0;
554 if (sect.type != S_SYMBOL_STUBS)
555 return 0;
556 return sect.content.size() / sect.indirectSymbols.size();
557}
558
Nick Kledzik29f749e2013-11-09 00:07:28 +0000559template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000560std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000561 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
562 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000563 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000564 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000565 uint8_t *next = lc + seg->cmdsize;
566 memset(seg->segname, 0, 16);
567 seg->vmaddr = 0;
568 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
569 seg->fileoff = _endOfLoadCommands;
570 seg->filesize = seg->vmsize;
571 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
572 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
573 seg->nsects = _file.sections.size();
574 seg->flags = 0;
575 if (_swap)
576 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000577 typename T::section *sout = reinterpret_cast<typename T::section*>
578 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000579 uint32_t relOffset = _startOfRelocations;
580 uint32_t contentOffset = _startOfSectionsContent;
581 uint32_t indirectSymRunningIndex = 0;
582 for (const Section &sin : _file.sections) {
583 setString16(sin.sectionName, sout->sectname);
584 setString16(sin.segmentName, sout->segname);
585 sout->addr = sin.address;
586 sout->size = sin.content.size();
587 sout->offset = contentOffset;
588 sout->align = sin.alignment;
589 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
590 sout->nreloc = sin.relocations.size();
591 sout->flags = sin.type | sin.attributes;
592 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
593 sout->reserved2 = indirectSymbolElementSize(sin);
594 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
595 contentOffset += sin.content.size();
596 if (_swap)
597 swapStruct(*sout);
598 ++sout;
599 }
600 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000601 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000602}
603
Nick Kledzik29f749e2013-11-09 00:07:28 +0000604template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000605std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000606 uint32_t indirectSymRunningIndex = 0;
607 for (const Segment &seg : _file.segments) {
608 // Write segment command with trailing sections.
609 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000610 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
611 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000612 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000613 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000614 uint8_t *next = lc + cmd->cmdsize;
615 setString16(seg.name, cmd->segname);
616 cmd->vmaddr = seg.address;
617 cmd->vmsize = seg.size;
618 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000619 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000620 cmd->maxprot = seg.access;
621 cmd->initprot = seg.access;
622 cmd->nsects = segInfo.sections.size();
623 cmd->flags = 0;
624 if (_swap)
625 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000626 typename T::section *sect = reinterpret_cast<typename T::section*>
627 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000628 for (const Section *section : segInfo.sections) {
629 setString16(section->sectionName, sect->sectname);
630 setString16(section->segmentName, sect->segname);
631 sect->addr = section->address;
632 sect->size = section->content.size();
633 sect->offset = section->address - seg.address + segInfo.fileOffset;
634 sect->align = section->alignment;
635 sect->reloff = 0;
636 sect->nreloc = 0;
637 sect->flags = section->type | section->attributes;
638 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
639 sect->reserved2 = indirectSymbolElementSize(*section);
640 if (_swap)
641 swapStruct(*sect);
642 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000643 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000644 lc = reinterpret_cast<uint8_t*>(next);
645 }
646 // Add implicit __LINKEDIT segment
Nick Kledzik1bebb282014-09-09 23:52:59 +0000647 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000648 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
649 cmd->cmd = T::LC;
650 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000651 uint8_t *next = lc + cmd->cmdsize;
652 setString16("__LINKEDIT", cmd->segname);
653 cmd->vmaddr = _addressOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000654 cmd->vmsize = llvm::RoundUpToAlignment(linkeditSize, _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000655 cmd->fileoff = _startOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000656 cmd->filesize = linkeditSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000657 cmd->maxprot = VM_PROT_READ;
658 cmd->initprot = VM_PROT_READ;
659 cmd->nsects = 0;
660 cmd->flags = 0;
661 if (_swap)
662 swapStruct(*cmd);
663 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000664 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000665}
666
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000667std::error_code MachOFileLayout::writeLoadCommands() {
668 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000669 uint8_t *lc = &_buffer[_startOfLoadCommands];
670 if (_file.fileType == llvm::MachO::MH_OBJECT) {
671 // Object files have one unnamed segment which holds all sections.
672 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000673 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000674 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000675 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000676 // Add LC_SYMTAB with symbol table info
677 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
678 st->cmd = LC_SYMTAB;
679 st->cmdsize = sizeof(symtab_command);
680 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000681 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000682 + _file.undefinedSymbols.size();
683 st->stroff = _startOfSymbolStrings;
684 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
685 if (_swap)
686 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000687 lc += sizeof(symtab_command);
688 // Add LC_DATA_IN_CODE if needed.
689 if (_dataInCodeSize != 0) {
690 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
691 dl->cmd = LC_DATA_IN_CODE;
692 dl->cmdsize = sizeof(linkedit_data_command);
693 dl->dataoff = _startOfDataInCode;
694 dl->datasize = _dataInCodeSize;
695 if (_swap)
696 swapStruct(*dl);
697 lc += sizeof(linkedit_data_command);
698 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000699 } else {
700 // Final linked images have sections under segments.
701 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000702 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000703 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000704 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000705
Tim Northover301c4e62014-07-01 08:15:41 +0000706 // Add LC_ID_DYLIB command for dynamic libraries.
707 if (_file.fileType == llvm::MachO::MH_DYLIB) {
708 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
709 StringRef path = _file.installName;
710 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
711 dc->cmd = LC_ID_DYLIB;
712 dc->cmdsize = size;
713 dc->dylib.name = sizeof(dylib_command); // offset
714 dc->dylib.timestamp = 0; // FIXME
715 dc->dylib.current_version = 0; // FIXME
716 dc->dylib.compatibility_version = 0; // FIXME
717 if (_swap)
718 swapStruct(*dc);
719 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
720 lc[sizeof(dylib_command) + path.size()] = '\0';
721 lc += size;
722 }
723
Nick Kledzike34182f2013-11-06 21:36:55 +0000724 // Add LC_DYLD_INFO_ONLY.
725 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
726 di->cmd = LC_DYLD_INFO_ONLY;
727 di->cmdsize = sizeof(dyld_info_command);
728 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
729 di->rebase_size = _rebaseInfo.size();
730 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
731 di->bind_size = _bindingInfo.size();
732 di->weak_bind_off = 0;
733 di->weak_bind_size = 0;
734 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
735 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000736 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
737 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000738 if (_swap)
739 swapStruct(*di);
740 lc += sizeof(dyld_info_command);
741
742 // Add LC_SYMTAB with symbol table info.
743 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
744 st->cmd = LC_SYMTAB;
745 st->cmdsize = sizeof(symtab_command);
746 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000747 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000748 + _file.undefinedSymbols.size();
749 st->stroff = _startOfSymbolStrings;
750 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
751 if (_swap)
752 swapStruct(*st);
753 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000754
Nick Kledzike34182f2013-11-06 21:36:55 +0000755 // Add LC_DYSYMTAB
756 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
757 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
758 dst->cmd = LC_DYSYMTAB;
759 dst->cmdsize = sizeof(dysymtab_command);
760 dst->ilocalsym = _symbolTableLocalsStartIndex;
761 dst->nlocalsym = _file.localSymbols.size();
762 dst->iextdefsym = _symbolTableGlobalsStartIndex;
763 dst->nextdefsym = _file.globalSymbols.size();
764 dst->iundefsym = _symbolTableUndefinesStartIndex;
765 dst->nundefsym = _file.undefinedSymbols.size();
766 dst->tocoff = 0;
767 dst->ntoc = 0;
768 dst->modtaboff = 0;
769 dst->nmodtab = 0;
770 dst->extrefsymoff = 0;
771 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000772 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000773 dst->nindirectsyms = _indirectSymbolTableCount;
774 dst->extreloff = 0;
775 dst->nextrel = 0;
776 dst->locreloff = 0;
777 dst->nlocrel = 0;
778 if (_swap)
779 swapStruct(*dst);
780 lc += sizeof(dysymtab_command);
781 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000782
Nick Kledzike34182f2013-11-06 21:36:55 +0000783 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
784 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
785 // Build LC_LOAD_DYLINKER load command.
786 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
787 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
788 dl->cmd = LC_LOAD_DYLINKER;
789 dl->cmdsize = size;
790 dl->name = sizeof(dylinker_command); // offset
791 if (_swap)
792 swapStruct(*dl);
793 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
794 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
795 lc += size;
796 // Build LC_MAIN load command.
797 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
798 ep->cmd = LC_MAIN;
799 ep->cmdsize = sizeof(entry_point_command);
800 ep->entryoff = _file.entryAddress - _seg1addr;
801 ep->stacksize = 0;
802 if (_swap)
803 swapStruct(*ep);
804 lc += sizeof(entry_point_command);
805 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000806
Nick Kledzike34182f2013-11-06 21:36:55 +0000807 // Add LC_LOAD_DYLIB commands
808 for (const DependentDylib &dep : _file.dependentDylibs) {
809 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
810 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000811 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000812 dc->cmdsize = size;
813 dc->dylib.name = sizeof(dylib_command); // offset
814 dc->dylib.timestamp = 0; // FIXME
815 dc->dylib.current_version = 0; // FIXME
816 dc->dylib.compatibility_version = 0; // FIXME
817 if (_swap)
818 swapStruct(*dc);
819 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
820 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
821 lc += size;
822 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000823 }
824 return ec;
825}
826
827
828void MachOFileLayout::writeSectionContent() {
829 for (const Section &s : _file.sections) {
830 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000831 if (s.type == llvm::MachO::S_ZEROFILL)
832 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000833 if (s.content.empty())
834 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000835 uint32_t offset = _sectInfo[&s].fileOffset;
836 uint8_t *p = &_buffer[offset];
837 memcpy(p, &s.content[0], s.content.size());
838 p += s.content.size();
839 }
840}
841
842void MachOFileLayout::writeRelocations() {
843 uint32_t relOffset = _startOfRelocations;
844 for (Section sect : _file.sections) {
845 for (Relocation r : sect.relocations) {
846 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
847 &_buffer[relOffset]);
848 *rb = packRelocation(r, _swap, _bigEndianArch);
849 relOffset += sizeof(any_relocation_info);
850 }
851 }
852}
853
854
855void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
856 uint32_t &symOffset, uint32_t &strOffset) {
857 for (const Symbol &sym : symbols) {
858 if (_is64) {
859 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
860 nb->n_strx = strOffset - _startOfSymbolStrings;
861 nb->n_type = sym.type | sym.scope;
862 nb->n_sect = sym.sect;
863 nb->n_desc = sym.desc;
864 nb->n_value = sym.value;
865 if (_swap)
866 swapStruct(*nb);
867 symOffset += sizeof(nlist_64);
868 } else {
869 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
870 nb->n_strx = strOffset - _startOfSymbolStrings;
871 nb->n_type = sym.type | sym.scope;
872 nb->n_sect = sym.sect;
873 nb->n_desc = sym.desc;
874 nb->n_value = sym.value;
875 if (_swap)
876 swapStruct(*nb);
877 symOffset += sizeof(nlist);
878 }
879 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
880 strOffset += sym.name.size();
881 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
882 }
883}
884
Nick Kledzik21921372014-07-24 23:06:56 +0000885void MachOFileLayout::writeDataInCodeInfo() {
886 uint32_t offset = _startOfDataInCode;
887 for (const DataInCode &entry : _file.dataInCode) {
888 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
889 &_buffer[offset]);
890 dst->offset = entry.offset;
891 dst->length = entry.length;
892 dst->kind = entry.kind;
893 if (_swap)
894 swapStruct(*dst);
895 offset += sizeof(data_in_code_entry);
896 }
897}
898
Nick Kledzike34182f2013-11-06 21:36:55 +0000899void MachOFileLayout::writeSymbolTable() {
900 // Write symbol table and symbol strings in parallel.
901 uint32_t symOffset = _startOfSymbols;
902 uint32_t strOffset = _startOfSymbolStrings;
903 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
904 appendSymbols(_file.localSymbols, symOffset, strOffset);
905 appendSymbols(_file.globalSymbols, symOffset, strOffset);
906 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
907 // Write indirect symbol table array.
908 uint32_t *indirects = reinterpret_cast<uint32_t*>
909 (&_buffer[_startOfIndirectSymbols]);
910 if (_file.fileType == llvm::MachO::MH_OBJECT) {
911 // Object files have sections in same order as input normalized file.
912 for (const Section &section : _file.sections) {
913 for (uint32_t index : section.indirectSymbols) {
914 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000915 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000916 else
917 *indirects++ = index;
918 }
919 }
920 } else {
921 // Final linked images must sort sections from normalized file.
922 for (const Segment &seg : _file.segments) {
923 SegExtraInfo &segInfo = _segInfo[&seg];
924 for (const Section *section : segInfo.sections) {
925 for (uint32_t index : section->indirectSymbols) {
926 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000927 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000928 else
929 *indirects++ = index;
930 }
931 }
932 }
933 }
934}
935
936void MachOFileLayout::writeRebaseInfo() {
937 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
938}
939
940void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000941 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000942 _bindingInfo.bytes(), _bindingInfo.size());
943}
944
945void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000946 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000947 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
948}
949
Nick Kledzik141330a2014-09-03 19:52:50 +0000950void MachOFileLayout::writeExportInfo() {
951 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
952}
953
Nick Kledzike34182f2013-11-06 21:36:55 +0000954void MachOFileLayout::buildLinkEditInfo() {
955 buildRebaseInfo();
956 buildBindInfo();
957 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000958 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +0000959 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000960 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000961}
962
963void MachOFileLayout::buildSectionRelocations() {
964
965}
966
967void MachOFileLayout::buildRebaseInfo() {
968 // TODO: compress rebasing info.
969 for (const RebaseLocation& entry : _file.rebasingInfo) {
970 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000971 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000972 | entry.segIndex);
973 _rebaseInfo.append_uleb128(entry.segOffset);
974 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
975 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000976 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000977 _rebaseInfo.align(_is64 ? 8 : 4);
978}
979
980void MachOFileLayout::buildBindInfo() {
981 // TODO: compress bind info.
982 for (const BindLocation& entry : _file.bindingInfo) {
983 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000984 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000985 | entry.segIndex);
986 _bindingInfo.append_uleb128(entry.segOffset);
987 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
988 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
989 _bindingInfo.append_string(entry.symbolName);
990 if (entry.addend != 0) {
991 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
992 _bindingInfo.append_sleb128(entry.addend);
993 }
994 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
995 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000996 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000997 _bindingInfo.align(_is64 ? 8 : 4);
998}
999
1000void MachOFileLayout::buildLazyBindInfo() {
1001 for (const BindLocation& entry : _file.lazyBindingInfo) {
1002 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001003 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001004 | entry.segIndex);
1005 _lazyBindingInfo.append_uleb128(entry.segOffset);
1006 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1007 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1008 _lazyBindingInfo.append_string(entry.symbolName);
1009 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1010 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001011 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001012 _lazyBindingInfo.align(_is64 ? 8 : 4);
1013}
1014
Nick Kledzik141330a2014-09-03 19:52:50 +00001015void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
1016 BumpPtrAllocator &allocator,
1017 std::vector<TrieNode*> &allNodes) {
1018 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1019 for (TrieEdge &edge : _children) {
1020 StringRef edgeStr = edge._subString;
1021 if (partialStr.startswith(edgeStr)) {
1022 // Already have matching edge, go down that path.
1023 edge._child->addSymbol(entry, allocator, allNodes);
1024 return;
1025 }
1026 // See if string has commmon prefix with existing edge.
1027 for (int n=edgeStr.size()-1; n > 0; --n) {
1028 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1029 // Splice in new node: was A -> C, now A -> B -> C
1030 StringRef bNodeStr = edge._child->_cummulativeString;
1031 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
1032 TrieNode* bNode = new (allocator) TrieNode(bNodeStr);
1033 allNodes.push_back(bNode);
1034 TrieNode* cNode = edge._child;
1035 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1036 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1037 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1038 << "splice in TrieNode('" << bNodeStr
1039 << "') between edge '"
1040 << abEdgeStr << "' and edge='"
1041 << bcEdgeStr<< "'\n");
1042 TrieEdge& abEdge = edge;
1043 abEdge._subString = abEdgeStr;
1044 abEdge._child = bNode;
1045 TrieEdge bcEdge(bcEdgeStr, cNode);
1046 bNode->_children.push_back(bcEdge);
1047 bNode->addSymbol(entry, allocator, allNodes);
1048 return;
1049 }
1050 }
1051 }
1052 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1053 assert(entry.otherOffset != 0);
1054 }
1055 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1056 assert(entry.otherOffset != 0);
1057 }
1058 // No commonality with any existing child, make a new edge.
1059 TrieNode* newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1060 TrieEdge newEdge(partialStr, newNode);
1061 _children.push_back(newEdge);
1062 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1063 << "new TrieNode('" << entry.name << "') with edge '"
1064 << partialStr << "' from node='"
1065 << _cummulativeString << "'\n");
1066 newNode->_address = entry.offset;
1067 newNode->_flags = entry.flags | entry.kind;
1068 newNode->_other = entry.otherOffset;
1069 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1070 newNode->_importedName = entry.otherName.copy(allocator);
1071 newNode->_hasExportInfo = true;
1072 allNodes.push_back(newNode);
1073}
1074
1075bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
1076 uint32_t nodeSize = 1; // Length when no export info
1077 if (_hasExportInfo) {
1078 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1079 nodeSize = llvm::getULEB128Size(_flags);
1080 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1081 nodeSize += _importedName.size();
1082 ++nodeSize; // Trailing zero in imported name.
1083 } else {
1084 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1085 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1086 nodeSize += llvm::getULEB128Size(_other);
1087 }
1088 // Overall node size so far is uleb128 of export info + actual export info.
1089 nodeSize += llvm::getULEB128Size(nodeSize);
1090 }
1091 // Compute size of all child edges.
1092 ++nodeSize; // Byte for number of chidren.
1093 for (TrieEdge &edge : _children) {
1094 nodeSize += edge._subString.size() + 1 // String length.
1095 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1096 }
1097 // On input, 'offset' is new prefered location for this node.
1098 bool result = (_trieOffset != offset);
1099 // Store new location in node object for use by parents.
1100 _trieOffset = offset;
1101 // Update offset for next iteration.
1102 offset += nodeSize;
1103 // Return true if _trieOffset was changed.
1104 return result;
1105}
1106
1107void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) {
1108 if (_hasExportInfo) {
1109 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1110 if (!_importedName.empty()) {
1111 // nodes with re-export info: size, flags, ordinal, import-name
1112 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1113 + llvm::getULEB128Size(_other)
1114 + _importedName.size() + 1;
1115 assert(nodeSize < 256);
1116 out.append_byte(nodeSize);
1117 out.append_uleb128(_flags);
1118 out.append_uleb128(_other);
1119 out.append_string(_importedName);
1120 } else {
1121 // nodes without re-export info: size, flags, ordinal, empty-string
1122 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1123 + llvm::getULEB128Size(_other) + 1;
1124 assert(nodeSize < 256);
1125 out.append_byte(nodeSize);
1126 out.append_uleb128(_flags);
1127 out.append_uleb128(_other);
1128 out.append_byte(0);
1129 }
1130 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1131 // Nodes with export info: size, flags, address, other
1132 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1133 + llvm::getULEB128Size(_address)
1134 + llvm::getULEB128Size(_other);
1135 assert(nodeSize < 256);
1136 out.append_byte(nodeSize);
1137 out.append_uleb128(_flags);
1138 out.append_uleb128(_address);
1139 out.append_uleb128(_other);
1140 } else {
1141 // Nodes with export info: size, flags, address
1142 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1143 + llvm::getULEB128Size(_address);
1144 assert(nodeSize < 256);
1145 out.append_byte(nodeSize);
1146 out.append_uleb128(_flags);
1147 out.append_uleb128(_address);
1148 }
1149 } else {
1150 // Node with no export info.
1151 uint32_t nodeSize = 0;
1152 out.append_byte(nodeSize);
1153 }
1154 // Add number of children.
1155 assert(_children.size() < 256);
1156 out.append_byte(_children.size());
1157 // Append each child edge substring and node offset.
1158 for (TrieEdge &edge : _children) {
1159 out.append_string(edge._subString);
1160 out.append_uleb128(edge._child->_trieOffset);
1161 }
1162}
1163
1164void MachOFileLayout::buildExportTrie() {
1165 if (_file.exportInfo.empty())
1166 return;
1167
1168 // For all temporary strings and objects used building trie.
1169 BumpPtrAllocator allocator;
1170
1171 // Build trie of all exported symbols.
1172 TrieNode* rootNode = new (allocator) TrieNode(StringRef());
1173 std::vector<TrieNode*> allNodes;
1174 allNodes.reserve(_file.exportInfo.size()*2);
1175 allNodes.push_back(rootNode);
1176 for (const Export& entry : _file.exportInfo) {
1177 rootNode->addSymbol(entry, allocator, allNodes);
1178 }
1179
1180 // Assign each node in the vector an offset in the trie stream, iterating
1181 // until all uleb128 sizes have stabilized.
1182 bool more;
1183 do {
1184 uint32_t offset = 0;
1185 more = false;
1186 for (TrieNode* node : allNodes) {
1187 if (node->updateOffset(offset))
1188 more = true;
1189 }
1190 } while (more);
1191
1192 // Serialize trie to ByteBuffer.
1193 for (TrieNode* node : allNodes) {
1194 node->appendToByteBuffer(_exportTrie);
1195 }
1196 _exportTrie.align(_is64 ? 8 : 4);
1197}
1198
1199
Nick Kledzike34182f2013-11-06 21:36:55 +00001200void MachOFileLayout::computeSymbolTableSizes() {
1201 // MachO symbol tables have three ranges: locals, globals, and undefines
1202 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001203 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001204 + _file.globalSymbols.size()
1205 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001206 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001207 for (const Symbol &sym : _file.localSymbols) {
1208 _symbolStringPoolSize += (sym.name.size()+1);
1209 }
1210 for (const Symbol &sym : _file.globalSymbols) {
1211 _symbolStringPoolSize += (sym.name.size()+1);
1212 }
1213 for (const Symbol &sym : _file.undefinedSymbols) {
1214 _symbolStringPoolSize += (sym.name.size()+1);
1215 }
1216 _symbolTableLocalsStartIndex = 0;
1217 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001218 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001219 + _file.globalSymbols.size();
1220
1221 _indirectSymbolTableCount = 0;
1222 for (const Section &sect : _file.sections) {
1223 _indirectSymbolTableCount += sect.indirectSymbols.size();
1224 }
1225}
1226
Nick Kledzik21921372014-07-24 23:06:56 +00001227void MachOFileLayout::computeDataInCodeSize() {
1228 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1229}
Nick Kledzike34182f2013-11-06 21:36:55 +00001230
1231void MachOFileLayout::writeLinkEditContent() {
1232 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1233 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +00001234 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001235 writeSymbolTable();
1236 } else {
1237 writeRebaseInfo();
1238 writeBindingInfo();
1239 writeLazyBindingInfo();
1240 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001241 writeExportInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001242 writeSymbolTable();
1243 }
1244}
1245
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001246std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001247 // Check for pending error from constructor.
1248 if (_ec)
1249 return _ec;
1250 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +00001251 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +00001252 unsigned flags = 0;
1253 if (_file.fileType != llvm::MachO::MH_OBJECT)
1254 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001255 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001256 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
1257 if (ec)
1258 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001259
Nick Kledzike34182f2013-11-06 21:36:55 +00001260 // Write content.
1261 _buffer = fob->getBufferStart();
1262 writeMachHeader();
1263 ec = writeLoadCommands();
1264 if (ec)
1265 return ec;
1266 writeSectionContent();
1267 writeLinkEditContent();
1268 fob->commit();
1269
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001270 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001271}
1272
1273
Nick Kledzike34182f2013-11-06 21:36:55 +00001274/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001275std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001276 MachOFileLayout layout(file);
1277 return layout.writeBinary(path);
1278}
1279
1280
1281} // namespace normalized
1282} // namespace mach_o
1283} // namespace lld
1284