blob: 543b60fe8bc7871a6b745b6536be634d3cba2a5e [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 Kledzik54ce29582014-10-28 22:21:10 +0000418 // Add LC_DATA_IN_CODE if needed
419 if (!_file.dataInCode.empty()) {
420 size += sizeof(linkedit_data_command);
421 ++count;
422 }
423
Nick Kledzike34182f2013-11-06 21:36:55 +0000424 return size;
425}
426
427static bool overlaps(const Segment &s1, const Segment &s2) {
428 if (s2.address >= s1.address+s1.size)
429 return false;
430 if (s1.address >= s2.address+s2.size)
431 return false;
432 return true;
433}
434
435static bool overlaps(const Section &s1, const Section &s2) {
436 if (s2.address >= s1.address+s1.content.size())
437 return false;
438 if (s1.address >= s2.address+s2.content.size())
439 return false;
440 return true;
441}
442
443void MachOFileLayout::buildFileOffsets() {
444 // Verify no segments overlap
445 for (const Segment &sg1 : _file.segments) {
446 for (const Segment &sg2 : _file.segments) {
447 if (&sg1 == &sg2)
448 continue;
449 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000450 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000451 return;
452 }
453 }
454 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000455
456 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000457 for (const Section &s1 : _file.sections) {
458 for (const Section &s2 : _file.sections) {
459 if (&s1 == &s2)
460 continue;
461 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000462 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000463 return;
464 }
465 }
466 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000467
Nick Kledzike34182f2013-11-06 21:36:55 +0000468 // Build side table of extra info about segments and sections.
469 SegExtraInfo t;
470 t.fileOffset = 0;
471 for (const Segment &sg : _file.segments) {
472 _segInfo[&sg] = t;
473 }
474 SectionExtraInfo t2;
475 t2.fileOffset = 0;
476 // Assign sections to segments.
477 for (const Section &s : _file.sections) {
478 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000479 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000480 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000481 if (sg.name.equals(s.segmentName)) {
482 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000483 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000484 _segInfo[&sg].sections.push_back(&s);
485 foundSegment = true;
486 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000487 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000488 }
489 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000490 if (!foundSegment) {
491 _ec = make_error_code(llvm::errc::executable_format_error);
492 return;
493 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000494 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000495
Nick Kledzike34182f2013-11-06 21:36:55 +0000496 // Assign file offsets.
497 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000498 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000499 llvm::dbgs() << "buildFileOffsets()\n");
500 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000501 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000502 if ((_seg1addr == INT64_MAX) && sg.access)
503 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000504 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000505 llvm::dbgs() << " segment=" << sg.name
506 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000507
508 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000509 // A segment that is not zero-fill must use a least one page of disk space.
510 if (sg.access)
511 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000512 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000513 uint32_t sectOffset = s->address - sg.address;
514 uint32_t sectFileSize =
515 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
516 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
517
518 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000519 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000520 llvm::dbgs() << " section=" << s->sectionName
521 << ", fileOffset=" << fileOffset << "\n");
522 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000523
Nick Kledzik1bebb282014-09-09 23:52:59 +0000524 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize,
525 _file.pageSize);
526 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize,
527 _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000528 _addressOfLinkEdit = sg.address + sg.size;
529 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000530 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000531}
532
533
534size_t MachOFileLayout::size() const {
535 return _endOfSymbolStrings;
536}
537
538void MachOFileLayout::writeMachHeader() {
539 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
540 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
541 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
542 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
543 mh->filetype = _file.fileType;
544 mh->ncmds = _countOfLoadCommands;
545 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
546 mh->flags = _file.flags;
547 if (_swap)
548 swapStruct(*mh);
549}
550
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000551uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000552 uint32_t &index) {
553 if (sect.indirectSymbols.empty())
554 return 0;
555 uint32_t result = index;
556 index += sect.indirectSymbols.size();
557 return result;
558}
559
560uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
561 if (sect.indirectSymbols.empty())
562 return 0;
563 if (sect.type != S_SYMBOL_STUBS)
564 return 0;
565 return sect.content.size() / sect.indirectSymbols.size();
566}
567
Nick Kledzik29f749e2013-11-09 00:07:28 +0000568template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000569std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000570 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
571 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000572 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000573 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000574 uint8_t *next = lc + seg->cmdsize;
575 memset(seg->segname, 0, 16);
576 seg->vmaddr = 0;
577 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
578 seg->fileoff = _endOfLoadCommands;
579 seg->filesize = seg->vmsize;
580 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
581 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
582 seg->nsects = _file.sections.size();
583 seg->flags = 0;
584 if (_swap)
585 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000586 typename T::section *sout = reinterpret_cast<typename T::section*>
587 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000588 uint32_t relOffset = _startOfRelocations;
589 uint32_t contentOffset = _startOfSectionsContent;
590 uint32_t indirectSymRunningIndex = 0;
591 for (const Section &sin : _file.sections) {
592 setString16(sin.sectionName, sout->sectname);
593 setString16(sin.segmentName, sout->segname);
594 sout->addr = sin.address;
595 sout->size = sin.content.size();
596 sout->offset = contentOffset;
597 sout->align = sin.alignment;
598 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
599 sout->nreloc = sin.relocations.size();
600 sout->flags = sin.type | sin.attributes;
601 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
602 sout->reserved2 = indirectSymbolElementSize(sin);
603 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
604 contentOffset += sin.content.size();
605 if (_swap)
606 swapStruct(*sout);
607 ++sout;
608 }
609 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000610 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000611}
612
Nick Kledzik29f749e2013-11-09 00:07:28 +0000613template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000614std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000615 uint32_t indirectSymRunningIndex = 0;
616 for (const Segment &seg : _file.segments) {
617 // Write segment command with trailing sections.
618 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000619 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
620 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000621 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000622 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000623 uint8_t *next = lc + cmd->cmdsize;
624 setString16(seg.name, cmd->segname);
625 cmd->vmaddr = seg.address;
626 cmd->vmsize = seg.size;
627 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000628 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000629 cmd->maxprot = seg.access;
630 cmd->initprot = seg.access;
631 cmd->nsects = segInfo.sections.size();
632 cmd->flags = 0;
633 if (_swap)
634 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000635 typename T::section *sect = reinterpret_cast<typename T::section*>
636 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000637 for (const Section *section : segInfo.sections) {
638 setString16(section->sectionName, sect->sectname);
639 setString16(section->segmentName, sect->segname);
640 sect->addr = section->address;
641 sect->size = section->content.size();
642 sect->offset = section->address - seg.address + segInfo.fileOffset;
643 sect->align = section->alignment;
644 sect->reloff = 0;
645 sect->nreloc = 0;
646 sect->flags = section->type | section->attributes;
647 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
648 sect->reserved2 = indirectSymbolElementSize(*section);
649 if (_swap)
650 swapStruct(*sect);
651 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000652 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000653 lc = reinterpret_cast<uint8_t*>(next);
654 }
655 // Add implicit __LINKEDIT segment
Nick Kledzik1bebb282014-09-09 23:52:59 +0000656 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000657 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
658 cmd->cmd = T::LC;
659 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000660 uint8_t *next = lc + cmd->cmdsize;
661 setString16("__LINKEDIT", cmd->segname);
662 cmd->vmaddr = _addressOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000663 cmd->vmsize = llvm::RoundUpToAlignment(linkeditSize, _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000664 cmd->fileoff = _startOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000665 cmd->filesize = linkeditSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000666 cmd->maxprot = VM_PROT_READ;
667 cmd->initprot = VM_PROT_READ;
668 cmd->nsects = 0;
669 cmd->flags = 0;
670 if (_swap)
671 swapStruct(*cmd);
672 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000673 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000674}
675
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000676std::error_code MachOFileLayout::writeLoadCommands() {
677 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000678 uint8_t *lc = &_buffer[_startOfLoadCommands];
679 if (_file.fileType == llvm::MachO::MH_OBJECT) {
680 // Object files have one unnamed segment which holds all sections.
681 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000682 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000683 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000684 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000685 // Add LC_SYMTAB with symbol table info
686 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
687 st->cmd = LC_SYMTAB;
688 st->cmdsize = sizeof(symtab_command);
689 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000690 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000691 + _file.undefinedSymbols.size();
692 st->stroff = _startOfSymbolStrings;
693 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
694 if (_swap)
695 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000696 lc += sizeof(symtab_command);
697 // Add LC_DATA_IN_CODE if needed.
698 if (_dataInCodeSize != 0) {
699 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
700 dl->cmd = LC_DATA_IN_CODE;
701 dl->cmdsize = sizeof(linkedit_data_command);
702 dl->dataoff = _startOfDataInCode;
703 dl->datasize = _dataInCodeSize;
704 if (_swap)
705 swapStruct(*dl);
706 lc += sizeof(linkedit_data_command);
707 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000708 } else {
709 // Final linked images have sections under segments.
710 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000711 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000712 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000713 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000714
Tim Northover301c4e62014-07-01 08:15:41 +0000715 // Add LC_ID_DYLIB command for dynamic libraries.
716 if (_file.fileType == llvm::MachO::MH_DYLIB) {
717 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
718 StringRef path = _file.installName;
719 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
720 dc->cmd = LC_ID_DYLIB;
721 dc->cmdsize = size;
722 dc->dylib.name = sizeof(dylib_command); // offset
723 dc->dylib.timestamp = 0; // FIXME
724 dc->dylib.current_version = 0; // FIXME
725 dc->dylib.compatibility_version = 0; // FIXME
726 if (_swap)
727 swapStruct(*dc);
728 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
729 lc[sizeof(dylib_command) + path.size()] = '\0';
730 lc += size;
731 }
732
Nick Kledzike34182f2013-11-06 21:36:55 +0000733 // Add LC_DYLD_INFO_ONLY.
734 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
735 di->cmd = LC_DYLD_INFO_ONLY;
736 di->cmdsize = sizeof(dyld_info_command);
737 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
738 di->rebase_size = _rebaseInfo.size();
739 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
740 di->bind_size = _bindingInfo.size();
741 di->weak_bind_off = 0;
742 di->weak_bind_size = 0;
743 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
744 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000745 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
746 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000747 if (_swap)
748 swapStruct(*di);
749 lc += sizeof(dyld_info_command);
750
751 // Add LC_SYMTAB with symbol table info.
752 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
753 st->cmd = LC_SYMTAB;
754 st->cmdsize = sizeof(symtab_command);
755 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000756 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000757 + _file.undefinedSymbols.size();
758 st->stroff = _startOfSymbolStrings;
759 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
760 if (_swap)
761 swapStruct(*st);
762 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000763
Nick Kledzike34182f2013-11-06 21:36:55 +0000764 // Add LC_DYSYMTAB
765 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
766 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
767 dst->cmd = LC_DYSYMTAB;
768 dst->cmdsize = sizeof(dysymtab_command);
769 dst->ilocalsym = _symbolTableLocalsStartIndex;
770 dst->nlocalsym = _file.localSymbols.size();
771 dst->iextdefsym = _symbolTableGlobalsStartIndex;
772 dst->nextdefsym = _file.globalSymbols.size();
773 dst->iundefsym = _symbolTableUndefinesStartIndex;
774 dst->nundefsym = _file.undefinedSymbols.size();
775 dst->tocoff = 0;
776 dst->ntoc = 0;
777 dst->modtaboff = 0;
778 dst->nmodtab = 0;
779 dst->extrefsymoff = 0;
780 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000781 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000782 dst->nindirectsyms = _indirectSymbolTableCount;
783 dst->extreloff = 0;
784 dst->nextrel = 0;
785 dst->locreloff = 0;
786 dst->nlocrel = 0;
787 if (_swap)
788 swapStruct(*dst);
789 lc += sizeof(dysymtab_command);
790 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000791
Nick Kledzike34182f2013-11-06 21:36:55 +0000792 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
793 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
794 // Build LC_LOAD_DYLINKER load command.
795 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
796 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
797 dl->cmd = LC_LOAD_DYLINKER;
798 dl->cmdsize = size;
799 dl->name = sizeof(dylinker_command); // offset
800 if (_swap)
801 swapStruct(*dl);
802 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
803 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
804 lc += size;
805 // Build LC_MAIN load command.
806 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
807 ep->cmd = LC_MAIN;
808 ep->cmdsize = sizeof(entry_point_command);
809 ep->entryoff = _file.entryAddress - _seg1addr;
810 ep->stacksize = 0;
811 if (_swap)
812 swapStruct(*ep);
813 lc += sizeof(entry_point_command);
814 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000815
Nick Kledzike34182f2013-11-06 21:36:55 +0000816 // Add LC_LOAD_DYLIB commands
817 for (const DependentDylib &dep : _file.dependentDylibs) {
818 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
819 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000820 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000821 dc->cmdsize = size;
822 dc->dylib.name = sizeof(dylib_command); // offset
823 dc->dylib.timestamp = 0; // FIXME
824 dc->dylib.current_version = 0; // FIXME
825 dc->dylib.compatibility_version = 0; // FIXME
826 if (_swap)
827 swapStruct(*dc);
828 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
829 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
830 lc += size;
831 }
Nick Kledzik54ce29582014-10-28 22:21:10 +0000832 // Add LC_DATA_IN_CODE if needed.
833 if (_dataInCodeSize != 0) {
834 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
835 dl->cmd = LC_DATA_IN_CODE;
836 dl->cmdsize = sizeof(linkedit_data_command);
837 dl->dataoff = _startOfDataInCode;
838 dl->datasize = _dataInCodeSize;
839 if (_swap)
840 swapStruct(*dl);
841 lc += sizeof(linkedit_data_command);
842 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000843 }
844 return ec;
845}
846
847
848void MachOFileLayout::writeSectionContent() {
849 for (const Section &s : _file.sections) {
850 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000851 if (s.type == llvm::MachO::S_ZEROFILL)
852 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000853 if (s.content.empty())
854 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000855 uint32_t offset = _sectInfo[&s].fileOffset;
856 uint8_t *p = &_buffer[offset];
857 memcpy(p, &s.content[0], s.content.size());
858 p += s.content.size();
859 }
860}
861
862void MachOFileLayout::writeRelocations() {
863 uint32_t relOffset = _startOfRelocations;
864 for (Section sect : _file.sections) {
865 for (Relocation r : sect.relocations) {
866 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
867 &_buffer[relOffset]);
868 *rb = packRelocation(r, _swap, _bigEndianArch);
869 relOffset += sizeof(any_relocation_info);
870 }
871 }
872}
873
874
875void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
876 uint32_t &symOffset, uint32_t &strOffset) {
877 for (const Symbol &sym : symbols) {
878 if (_is64) {
879 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
880 nb->n_strx = strOffset - _startOfSymbolStrings;
881 nb->n_type = sym.type | sym.scope;
882 nb->n_sect = sym.sect;
883 nb->n_desc = sym.desc;
884 nb->n_value = sym.value;
885 if (_swap)
886 swapStruct(*nb);
887 symOffset += sizeof(nlist_64);
888 } else {
889 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
890 nb->n_strx = strOffset - _startOfSymbolStrings;
891 nb->n_type = sym.type | sym.scope;
892 nb->n_sect = sym.sect;
893 nb->n_desc = sym.desc;
894 nb->n_value = sym.value;
895 if (_swap)
896 swapStruct(*nb);
897 symOffset += sizeof(nlist);
898 }
899 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
900 strOffset += sym.name.size();
901 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
902 }
903}
904
Nick Kledzik21921372014-07-24 23:06:56 +0000905void MachOFileLayout::writeDataInCodeInfo() {
906 uint32_t offset = _startOfDataInCode;
907 for (const DataInCode &entry : _file.dataInCode) {
908 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
909 &_buffer[offset]);
910 dst->offset = entry.offset;
911 dst->length = entry.length;
912 dst->kind = entry.kind;
913 if (_swap)
914 swapStruct(*dst);
915 offset += sizeof(data_in_code_entry);
916 }
917}
918
Nick Kledzike34182f2013-11-06 21:36:55 +0000919void MachOFileLayout::writeSymbolTable() {
920 // Write symbol table and symbol strings in parallel.
921 uint32_t symOffset = _startOfSymbols;
922 uint32_t strOffset = _startOfSymbolStrings;
923 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
924 appendSymbols(_file.localSymbols, symOffset, strOffset);
925 appendSymbols(_file.globalSymbols, symOffset, strOffset);
926 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
927 // Write indirect symbol table array.
928 uint32_t *indirects = reinterpret_cast<uint32_t*>
929 (&_buffer[_startOfIndirectSymbols]);
930 if (_file.fileType == llvm::MachO::MH_OBJECT) {
931 // Object files have sections in same order as input normalized file.
932 for (const Section &section : _file.sections) {
933 for (uint32_t index : section.indirectSymbols) {
934 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000935 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000936 else
937 *indirects++ = index;
938 }
939 }
940 } else {
941 // Final linked images must sort sections from normalized file.
942 for (const Segment &seg : _file.segments) {
943 SegExtraInfo &segInfo = _segInfo[&seg];
944 for (const Section *section : segInfo.sections) {
945 for (uint32_t index : section->indirectSymbols) {
946 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000947 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000948 else
949 *indirects++ = index;
950 }
951 }
952 }
953 }
954}
955
956void MachOFileLayout::writeRebaseInfo() {
957 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
958}
959
960void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000961 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000962 _bindingInfo.bytes(), _bindingInfo.size());
963}
964
965void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000966 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000967 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
968}
969
Nick Kledzik141330a2014-09-03 19:52:50 +0000970void MachOFileLayout::writeExportInfo() {
971 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
972}
973
Nick Kledzike34182f2013-11-06 21:36:55 +0000974void MachOFileLayout::buildLinkEditInfo() {
975 buildRebaseInfo();
976 buildBindInfo();
977 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000978 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +0000979 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000980 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000981}
982
983void MachOFileLayout::buildSectionRelocations() {
984
985}
986
987void MachOFileLayout::buildRebaseInfo() {
988 // TODO: compress rebasing info.
989 for (const RebaseLocation& entry : _file.rebasingInfo) {
990 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000991 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000992 | entry.segIndex);
993 _rebaseInfo.append_uleb128(entry.segOffset);
994 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
995 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000996 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +0000997 _rebaseInfo.align(_is64 ? 8 : 4);
998}
999
1000void MachOFileLayout::buildBindInfo() {
1001 // TODO: compress bind info.
1002 for (const BindLocation& entry : _file.bindingInfo) {
1003 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001004 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001005 | entry.segIndex);
1006 _bindingInfo.append_uleb128(entry.segOffset);
1007 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1008 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1009 _bindingInfo.append_string(entry.symbolName);
1010 if (entry.addend != 0) {
1011 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1012 _bindingInfo.append_sleb128(entry.addend);
1013 }
1014 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1015 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001016 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001017 _bindingInfo.align(_is64 ? 8 : 4);
1018}
1019
1020void MachOFileLayout::buildLazyBindInfo() {
1021 for (const BindLocation& entry : _file.lazyBindingInfo) {
1022 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001023 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001024 | entry.segIndex);
1025 _lazyBindingInfo.append_uleb128(entry.segOffset);
1026 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1027 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1028 _lazyBindingInfo.append_string(entry.symbolName);
1029 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1030 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001031 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001032 _lazyBindingInfo.align(_is64 ? 8 : 4);
1033}
1034
Nick Kledzik141330a2014-09-03 19:52:50 +00001035void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
1036 BumpPtrAllocator &allocator,
1037 std::vector<TrieNode*> &allNodes) {
1038 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1039 for (TrieEdge &edge : _children) {
1040 StringRef edgeStr = edge._subString;
1041 if (partialStr.startswith(edgeStr)) {
1042 // Already have matching edge, go down that path.
1043 edge._child->addSymbol(entry, allocator, allNodes);
1044 return;
1045 }
1046 // See if string has commmon prefix with existing edge.
1047 for (int n=edgeStr.size()-1; n > 0; --n) {
1048 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1049 // Splice in new node: was A -> C, now A -> B -> C
1050 StringRef bNodeStr = edge._child->_cummulativeString;
1051 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
1052 TrieNode* bNode = new (allocator) TrieNode(bNodeStr);
1053 allNodes.push_back(bNode);
1054 TrieNode* cNode = edge._child;
1055 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1056 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1057 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1058 << "splice in TrieNode('" << bNodeStr
1059 << "') between edge '"
1060 << abEdgeStr << "' and edge='"
1061 << bcEdgeStr<< "'\n");
1062 TrieEdge& abEdge = edge;
1063 abEdge._subString = abEdgeStr;
1064 abEdge._child = bNode;
1065 TrieEdge bcEdge(bcEdgeStr, cNode);
1066 bNode->_children.push_back(bcEdge);
1067 bNode->addSymbol(entry, allocator, allNodes);
1068 return;
1069 }
1070 }
1071 }
1072 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1073 assert(entry.otherOffset != 0);
1074 }
1075 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1076 assert(entry.otherOffset != 0);
1077 }
1078 // No commonality with any existing child, make a new edge.
1079 TrieNode* newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1080 TrieEdge newEdge(partialStr, newNode);
1081 _children.push_back(newEdge);
1082 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1083 << "new TrieNode('" << entry.name << "') with edge '"
1084 << partialStr << "' from node='"
1085 << _cummulativeString << "'\n");
1086 newNode->_address = entry.offset;
1087 newNode->_flags = entry.flags | entry.kind;
1088 newNode->_other = entry.otherOffset;
1089 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1090 newNode->_importedName = entry.otherName.copy(allocator);
1091 newNode->_hasExportInfo = true;
1092 allNodes.push_back(newNode);
1093}
1094
1095bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
1096 uint32_t nodeSize = 1; // Length when no export info
1097 if (_hasExportInfo) {
1098 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1099 nodeSize = llvm::getULEB128Size(_flags);
1100 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1101 nodeSize += _importedName.size();
1102 ++nodeSize; // Trailing zero in imported name.
1103 } else {
1104 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1105 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1106 nodeSize += llvm::getULEB128Size(_other);
1107 }
1108 // Overall node size so far is uleb128 of export info + actual export info.
1109 nodeSize += llvm::getULEB128Size(nodeSize);
1110 }
1111 // Compute size of all child edges.
1112 ++nodeSize; // Byte for number of chidren.
1113 for (TrieEdge &edge : _children) {
1114 nodeSize += edge._subString.size() + 1 // String length.
1115 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1116 }
1117 // On input, 'offset' is new prefered location for this node.
1118 bool result = (_trieOffset != offset);
1119 // Store new location in node object for use by parents.
1120 _trieOffset = offset;
1121 // Update offset for next iteration.
1122 offset += nodeSize;
1123 // Return true if _trieOffset was changed.
1124 return result;
1125}
1126
1127void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) {
1128 if (_hasExportInfo) {
1129 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1130 if (!_importedName.empty()) {
1131 // nodes with re-export info: size, flags, ordinal, import-name
1132 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1133 + llvm::getULEB128Size(_other)
1134 + _importedName.size() + 1;
1135 assert(nodeSize < 256);
1136 out.append_byte(nodeSize);
1137 out.append_uleb128(_flags);
1138 out.append_uleb128(_other);
1139 out.append_string(_importedName);
1140 } else {
1141 // nodes without re-export info: size, flags, ordinal, empty-string
1142 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1143 + llvm::getULEB128Size(_other) + 1;
1144 assert(nodeSize < 256);
1145 out.append_byte(nodeSize);
1146 out.append_uleb128(_flags);
1147 out.append_uleb128(_other);
1148 out.append_byte(0);
1149 }
1150 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1151 // Nodes with export info: size, flags, address, other
1152 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1153 + llvm::getULEB128Size(_address)
1154 + llvm::getULEB128Size(_other);
1155 assert(nodeSize < 256);
1156 out.append_byte(nodeSize);
1157 out.append_uleb128(_flags);
1158 out.append_uleb128(_address);
1159 out.append_uleb128(_other);
1160 } else {
1161 // Nodes with export info: size, flags, address
1162 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1163 + llvm::getULEB128Size(_address);
1164 assert(nodeSize < 256);
1165 out.append_byte(nodeSize);
1166 out.append_uleb128(_flags);
1167 out.append_uleb128(_address);
1168 }
1169 } else {
1170 // Node with no export info.
1171 uint32_t nodeSize = 0;
1172 out.append_byte(nodeSize);
1173 }
1174 // Add number of children.
1175 assert(_children.size() < 256);
1176 out.append_byte(_children.size());
1177 // Append each child edge substring and node offset.
1178 for (TrieEdge &edge : _children) {
1179 out.append_string(edge._subString);
1180 out.append_uleb128(edge._child->_trieOffset);
1181 }
1182}
1183
1184void MachOFileLayout::buildExportTrie() {
1185 if (_file.exportInfo.empty())
1186 return;
1187
1188 // For all temporary strings and objects used building trie.
1189 BumpPtrAllocator allocator;
1190
1191 // Build trie of all exported symbols.
1192 TrieNode* rootNode = new (allocator) TrieNode(StringRef());
1193 std::vector<TrieNode*> allNodes;
1194 allNodes.reserve(_file.exportInfo.size()*2);
1195 allNodes.push_back(rootNode);
1196 for (const Export& entry : _file.exportInfo) {
1197 rootNode->addSymbol(entry, allocator, allNodes);
1198 }
1199
1200 // Assign each node in the vector an offset in the trie stream, iterating
1201 // until all uleb128 sizes have stabilized.
1202 bool more;
1203 do {
1204 uint32_t offset = 0;
1205 more = false;
1206 for (TrieNode* node : allNodes) {
1207 if (node->updateOffset(offset))
1208 more = true;
1209 }
1210 } while (more);
1211
1212 // Serialize trie to ByteBuffer.
1213 for (TrieNode* node : allNodes) {
1214 node->appendToByteBuffer(_exportTrie);
1215 }
1216 _exportTrie.align(_is64 ? 8 : 4);
1217}
1218
1219
Nick Kledzike34182f2013-11-06 21:36:55 +00001220void MachOFileLayout::computeSymbolTableSizes() {
1221 // MachO symbol tables have three ranges: locals, globals, and undefines
1222 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001223 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001224 + _file.globalSymbols.size()
1225 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001226 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001227 for (const Symbol &sym : _file.localSymbols) {
1228 _symbolStringPoolSize += (sym.name.size()+1);
1229 }
1230 for (const Symbol &sym : _file.globalSymbols) {
1231 _symbolStringPoolSize += (sym.name.size()+1);
1232 }
1233 for (const Symbol &sym : _file.undefinedSymbols) {
1234 _symbolStringPoolSize += (sym.name.size()+1);
1235 }
1236 _symbolTableLocalsStartIndex = 0;
1237 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001238 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001239 + _file.globalSymbols.size();
1240
1241 _indirectSymbolTableCount = 0;
1242 for (const Section &sect : _file.sections) {
1243 _indirectSymbolTableCount += sect.indirectSymbols.size();
1244 }
1245}
1246
Nick Kledzik21921372014-07-24 23:06:56 +00001247void MachOFileLayout::computeDataInCodeSize() {
1248 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1249}
Nick Kledzike34182f2013-11-06 21:36:55 +00001250
1251void MachOFileLayout::writeLinkEditContent() {
1252 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1253 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +00001254 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001255 writeSymbolTable();
1256 } else {
1257 writeRebaseInfo();
1258 writeBindingInfo();
1259 writeLazyBindingInfo();
1260 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001261 writeExportInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001262 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001263 writeSymbolTable();
1264 }
1265}
1266
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001267std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001268 // Check for pending error from constructor.
1269 if (_ec)
1270 return _ec;
1271 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +00001272 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +00001273 unsigned flags = 0;
1274 if (_file.fileType != llvm::MachO::MH_OBJECT)
1275 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001276 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001277 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
1278 if (ec)
1279 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001280
Nick Kledzike34182f2013-11-06 21:36:55 +00001281 // Write content.
1282 _buffer = fob->getBufferStart();
1283 writeMachHeader();
1284 ec = writeLoadCommands();
1285 if (ec)
1286 return ec;
1287 writeSectionContent();
1288 writeLinkEditContent();
1289 fob->commit();
1290
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001291 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001292}
1293
1294
Nick Kledzike34182f2013-11-06 21:36:55 +00001295/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001296std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001297 MachOFileLayout layout(file);
1298 return layout.writeBinary(path);
1299}
1300
1301
1302} // namespace normalized
1303} // namespace mach_o
1304} // namespace lld
1305