blob: 102b185df522c4ba4979fd6a76e68d4386f22a2c [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 }
Nick Kledzikf373c772014-11-11 01:31:18 +0000128 void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
129 unsigned min = llvm::getULEB128Size(value);
130 assert(min <= byteCount);
131 unsigned pad = byteCount - min;
132 llvm::encodeULEB128(value, _ostream, pad);
133 }
Nick Kledzik00a15d92013-11-09 01:00:51 +0000134 void append_sleb128(int64_t value) {
135 llvm::encodeSLEB128(value, _ostream);
136 }
137 void append_string(StringRef str) {
138 _ostream << str;
139 append_byte(0);
140 }
141 void align(unsigned alignment) {
142 while ( (_ostream.tell() % alignment) != 0 )
143 append_byte(0);
144 }
145 size_t size() {
146 return _ostream.tell();
147 }
148 const uint8_t *bytes() {
149 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
150 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000151 private:
Nick Kledzik00a15d92013-11-09 01:00:51 +0000152 SmallVector<char, 128> _bytes;
153 // Stream ivar must be after SmallVector ivar to construct properly.
154 llvm::raw_svector_ostream _ostream;
Nick Kledzike34182f2013-11-06 21:36:55 +0000155 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000156
Nick Kledzik141330a2014-09-03 19:52:50 +0000157 struct TrieNode; // Forward declaration.
158
159 struct TrieEdge {
160 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
161 ~TrieEdge() {}
162
163 StringRef _subString;
164 struct TrieNode *_child;
165 };
166
167 struct TrieNode {
168 TrieNode(StringRef s)
169 : _cummulativeString(s), _address(0), _flags(0), _other(0),
170 _trieOffset(0), _hasExportInfo(false) {}
171 ~TrieNode() {}
172
173 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
174 std::vector<TrieNode *> &allNodes);
175 bool updateOffset(uint32_t &offset);
176 void appendToByteBuffer(ByteBuffer &out);
177
178private:
179 StringRef _cummulativeString;
180 SmallVector<TrieEdge, 8> _children;
181 uint64_t _address;
182 uint64_t _flags;
183 uint64_t _other;
184 StringRef _importedName;
185 uint32_t _trieOffset;
186 bool _hasExportInfo;
187 };
Nick Kledzik00a15d92013-11-09 01:00:51 +0000188
Nick Kledzike34182f2013-11-06 21:36:55 +0000189 struct SegExtraInfo {
190 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000191 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000192 std::vector<const Section*> sections;
193 };
194 typedef std::map<const Segment*, SegExtraInfo> SegMap;
195 struct SectionExtraInfo {
196 uint32_t fileOffset;
197 };
198 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000199
Nick Kledzike34182f2013-11-06 21:36:55 +0000200 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000201 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000202 uint8_t *_buffer;
203 const bool _is64;
204 const bool _swap;
205 const bool _bigEndianArch;
206 uint64_t _seg1addr;
207 uint32_t _startOfLoadCommands;
208 uint32_t _countOfLoadCommands;
209 uint32_t _endOfLoadCommands;
210 uint32_t _startOfRelocations;
Nick Kledzik21921372014-07-24 23:06:56 +0000211 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000212 uint32_t _startOfSymbols;
213 uint32_t _startOfIndirectSymbols;
214 uint32_t _startOfSymbolStrings;
215 uint32_t _endOfSymbolStrings;
216 uint32_t _symbolTableLocalsStartIndex;
217 uint32_t _symbolTableGlobalsStartIndex;
218 uint32_t _symbolTableUndefinesStartIndex;
219 uint32_t _symbolStringPoolSize;
220 uint32_t _symbolTableSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000221 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000222 uint32_t _indirectSymbolTableCount;
223 // Used in object file creation only
224 uint32_t _startOfSectionsContent;
225 uint32_t _endOfSectionsContent;
226 // Used in final linked image only
227 uint32_t _startOfLinkEdit;
228 uint32_t _startOfRebaseInfo;
229 uint32_t _endOfRebaseInfo;
230 uint32_t _startOfBindingInfo;
231 uint32_t _endOfBindingInfo;
232 uint32_t _startOfLazyBindingInfo;
233 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000234 uint32_t _startOfExportTrie;
235 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000236 uint32_t _endOfLinkEdit;
237 uint64_t _addressOfLinkEdit;
238 SegMap _segInfo;
239 SectionMap _sectInfo;
240 ByteBuffer _rebaseInfo;
241 ByteBuffer _bindingInfo;
242 ByteBuffer _lazyBindingInfo;
243 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000244 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000245};
246
247size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
248 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000249 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000250}
251
252StringRef MachOFileLayout::dyldPath() {
253 return "/usr/lib/dyld";
254}
255
256uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
257 return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000258}
Nick Kledzike34182f2013-11-06 21:36:55 +0000259
260
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000261size_t MachOFileLayout::headerAndLoadCommandsSize() const {
262 return _endOfLoadCommands;
263}
Nick Kledzike34182f2013-11-06 21:36:55 +0000264
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000265
266MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000267 : _file(file),
268 _is64(MachOLinkingContext::is64Bit(file.arch)),
269 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
270 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
271 _seg1addr(INT64_MAX) {
272 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000273 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000274 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
275 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
276 if (file.fileType == llvm::MachO::MH_OBJECT) {
277 // object files have just one segment load command containing all sections
278 _endOfLoadCommands = _startOfLoadCommands
279 + segCommandBaseSize
280 + file.sections.size() * sectsSize
281 + sizeof(symtab_command);
282 _countOfLoadCommands = 2;
Nick Kledzik21921372014-07-24 23:06:56 +0000283 if (!_file.dataInCode.empty()) {
284 _endOfLoadCommands += sizeof(linkedit_data_command);
285 _countOfLoadCommands++;
286 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000287 // Accumulate size of each section.
288 _startOfSectionsContent = _endOfLoadCommands;
289 _endOfSectionsContent = _startOfSectionsContent;
290 unsigned relocCount = 0;
291 for (const Section &sect : file.sections) {
292 _sectInfo[&sect].fileOffset = _endOfSectionsContent;
293 _endOfSectionsContent += sect.content.size();
294 relocCount += sect.relocations.size();
295 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000296
Nick Kledzike34182f2013-11-06 21:36:55 +0000297 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000298 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000299
Nick Kledzike34182f2013-11-06 21:36:55 +0000300 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000301 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzik21921372014-07-24 23:06:56 +0000302 _startOfDataInCode = _startOfRelocations + relocCount * 8;
303 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000304 // Add Indirect symbol table.
305 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
306 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000307 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000308 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000309 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000310 + pointerAlign(_symbolStringPoolSize);
311 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000312 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000313 llvm::dbgs() << "MachOFileLayout()\n"
314 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
315 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
316 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
317 << " startOfRelocations=" << _startOfRelocations << "\n"
318 << " startOfSymbols=" << _startOfSymbols << "\n"
319 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
320 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
321 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
322 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
323 } else {
324 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000325 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000326 + loadCommandsSize(_countOfLoadCommands);
327
328 // Assign section file offsets.
329 buildFileOffsets();
330 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000331
Nick Kledzike34182f2013-11-06 21:36:55 +0000332 // LINKEDIT of final linked images has in order:
333 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000334 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000335 _startOfRebaseInfo = _startOfLinkEdit;
336 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
337 _startOfBindingInfo = _endOfRebaseInfo;
338 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
339 _startOfLazyBindingInfo = _endOfBindingInfo;
340 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000341 _startOfExportTrie = _endOfLazyBindingInfo;
342 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
343 _startOfDataInCode = _endOfExportTrie;
Nick Kledzik21921372014-07-24 23:06:56 +0000344 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000345 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000346 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000347 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000348 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000349 + pointerAlign(_symbolStringPoolSize);
350 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000351 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000352 llvm::dbgs() << "MachOFileLayout()\n"
353 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
354 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
355 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
356 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
357 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
358 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
359 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
360 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
361 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
362 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000363 << " startOfExportTrie=" << _startOfExportTrie << "\n"
364 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000365 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000366 << " startOfSymbols=" << _startOfSymbols << "\n"
367 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
368 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
369 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
370 }
371}
372
373uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
374 uint32_t size = 0;
375 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000376
377 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000378 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
379 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
380
381 // Add LC_SEGMENT for each segment.
382 size += _file.segments.size() * segCommandSize;
383 count += _file.segments.size();
384 // Add section record for each section.
385 size += _file.sections.size() * sectionSize;
386 // Add one LC_SEGMENT for implicit __LINKEDIT segment
387 size += segCommandSize;
388 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000389
Tim Northover301c4e62014-07-01 08:15:41 +0000390 // If creating a dylib, add LC_ID_DYLIB.
391 if (_file.fileType == llvm::MachO::MH_DYLIB) {
392 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
393 ++count;
394 }
395
Nick Kledzike34182f2013-11-06 21:36:55 +0000396 // Add LC_DYLD_INFO
397 size += sizeof(dyld_info_command);
398 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000399
Nick Kledzike34182f2013-11-06 21:36:55 +0000400 // Add LC_SYMTAB
401 size += sizeof(symtab_command);
402 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000403
Nick Kledzike34182f2013-11-06 21:36:55 +0000404 // Add LC_DYSYMTAB
405 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
406 size += sizeof(dysymtab_command);
407 ++count;
408 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000409
Nick Kledzike34182f2013-11-06 21:36:55 +0000410 // If main executable add LC_LOAD_DYLINKER and LC_MAIN
411 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
412 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
413 ++count;
414 size += sizeof(entry_point_command);
415 ++count;
416 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000417
Nick Kledzike34182f2013-11-06 21:36:55 +0000418 // Add LC_LOAD_DYLIB for each dependent dylib.
419 for (const DependentDylib &dep : _file.dependentDylibs) {
420 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
421 ++count;
422 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000423
Nick Kledzik54ce29582014-10-28 22:21:10 +0000424 // Add LC_DATA_IN_CODE if needed
425 if (!_file.dataInCode.empty()) {
426 size += sizeof(linkedit_data_command);
427 ++count;
428 }
429
Nick Kledzike34182f2013-11-06 21:36:55 +0000430 return size;
431}
432
433static bool overlaps(const Segment &s1, const Segment &s2) {
434 if (s2.address >= s1.address+s1.size)
435 return false;
436 if (s1.address >= s2.address+s2.size)
437 return false;
438 return true;
439}
440
441static bool overlaps(const Section &s1, const Section &s2) {
442 if (s2.address >= s1.address+s1.content.size())
443 return false;
444 if (s1.address >= s2.address+s2.content.size())
445 return false;
446 return true;
447}
448
449void MachOFileLayout::buildFileOffsets() {
450 // Verify no segments overlap
451 for (const Segment &sg1 : _file.segments) {
452 for (const Segment &sg2 : _file.segments) {
453 if (&sg1 == &sg2)
454 continue;
455 if (overlaps(sg1,sg2)) {
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
462 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000463 for (const Section &s1 : _file.sections) {
464 for (const Section &s2 : _file.sections) {
465 if (&s1 == &s2)
466 continue;
467 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000468 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000469 return;
470 }
471 }
472 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000473
Nick Kledzike34182f2013-11-06 21:36:55 +0000474 // Build side table of extra info about segments and sections.
475 SegExtraInfo t;
476 t.fileOffset = 0;
477 for (const Segment &sg : _file.segments) {
478 _segInfo[&sg] = t;
479 }
480 SectionExtraInfo t2;
481 t2.fileOffset = 0;
482 // Assign sections to segments.
483 for (const Section &s : _file.sections) {
484 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000485 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000486 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000487 if (sg.name.equals(s.segmentName)) {
488 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000489 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000490 _segInfo[&sg].sections.push_back(&s);
491 foundSegment = true;
492 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000493 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000494 }
495 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000496 if (!foundSegment) {
497 _ec = make_error_code(llvm::errc::executable_format_error);
498 return;
499 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000500 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000501
Nick Kledzike34182f2013-11-06 21:36:55 +0000502 // Assign file offsets.
503 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000504 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000505 llvm::dbgs() << "buildFileOffsets()\n");
506 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000507 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000508 if ((_seg1addr == INT64_MAX) && sg.access)
509 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000510 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000511 llvm::dbgs() << " segment=" << sg.name
512 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000513
514 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000515 // A segment that is not zero-fill must use a least one page of disk space.
516 if (sg.access)
517 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000518 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000519 uint32_t sectOffset = s->address - sg.address;
520 uint32_t sectFileSize =
521 s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
522 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
523
524 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000525 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000526 llvm::dbgs() << " section=" << s->sectionName
527 << ", fileOffset=" << fileOffset << "\n");
528 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000529
Nick Kledzik1bebb282014-09-09 23:52:59 +0000530 _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize,
531 _file.pageSize);
532 fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize,
533 _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000534 _addressOfLinkEdit = sg.address + sg.size;
535 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000536 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000537}
538
539
540size_t MachOFileLayout::size() const {
541 return _endOfSymbolStrings;
542}
543
544void MachOFileLayout::writeMachHeader() {
545 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
546 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
547 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
548 mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
549 mh->filetype = _file.fileType;
550 mh->ncmds = _countOfLoadCommands;
551 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
552 mh->flags = _file.flags;
553 if (_swap)
554 swapStruct(*mh);
555}
556
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000557uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000558 uint32_t &index) {
559 if (sect.indirectSymbols.empty())
560 return 0;
561 uint32_t result = index;
562 index += sect.indirectSymbols.size();
563 return result;
564}
565
566uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
567 if (sect.indirectSymbols.empty())
568 return 0;
569 if (sect.type != S_SYMBOL_STUBS)
570 return 0;
571 return sect.content.size() / sect.indirectSymbols.size();
572}
573
Nick Kledzik29f749e2013-11-09 00:07:28 +0000574template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000575std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000576 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
577 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000578 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000579 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000580 uint8_t *next = lc + seg->cmdsize;
581 memset(seg->segname, 0, 16);
582 seg->vmaddr = 0;
583 seg->vmsize = _endOfSectionsContent - _endOfLoadCommands;
584 seg->fileoff = _endOfLoadCommands;
585 seg->filesize = seg->vmsize;
586 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
587 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
588 seg->nsects = _file.sections.size();
589 seg->flags = 0;
590 if (_swap)
591 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000592 typename T::section *sout = reinterpret_cast<typename T::section*>
593 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000594 uint32_t relOffset = _startOfRelocations;
595 uint32_t contentOffset = _startOfSectionsContent;
596 uint32_t indirectSymRunningIndex = 0;
597 for (const Section &sin : _file.sections) {
598 setString16(sin.sectionName, sout->sectname);
599 setString16(sin.segmentName, sout->segname);
600 sout->addr = sin.address;
601 sout->size = sin.content.size();
602 sout->offset = contentOffset;
603 sout->align = sin.alignment;
604 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
605 sout->nreloc = sin.relocations.size();
606 sout->flags = sin.type | sin.attributes;
607 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
608 sout->reserved2 = indirectSymbolElementSize(sin);
609 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
610 contentOffset += sin.content.size();
611 if (_swap)
612 swapStruct(*sout);
613 ++sout;
614 }
615 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000616 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000617}
618
Nick Kledzik29f749e2013-11-09 00:07:28 +0000619template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000620std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000621 uint32_t indirectSymRunningIndex = 0;
622 for (const Segment &seg : _file.segments) {
623 // Write segment command with trailing sections.
624 SegExtraInfo &segInfo = _segInfo[&seg];
Nick Kledzik29f749e2013-11-09 00:07:28 +0000625 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
626 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000627 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000628 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000629 uint8_t *next = lc + cmd->cmdsize;
630 setString16(seg.name, cmd->segname);
631 cmd->vmaddr = seg.address;
632 cmd->vmsize = seg.size;
633 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000634 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000635 cmd->maxprot = seg.access;
636 cmd->initprot = seg.access;
637 cmd->nsects = segInfo.sections.size();
638 cmd->flags = 0;
639 if (_swap)
640 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000641 typename T::section *sect = reinterpret_cast<typename T::section*>
642 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000643 for (const Section *section : segInfo.sections) {
644 setString16(section->sectionName, sect->sectname);
645 setString16(section->segmentName, sect->segname);
646 sect->addr = section->address;
647 sect->size = section->content.size();
648 sect->offset = section->address - seg.address + segInfo.fileOffset;
649 sect->align = section->alignment;
650 sect->reloff = 0;
651 sect->nreloc = 0;
652 sect->flags = section->type | section->attributes;
653 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
654 sect->reserved2 = indirectSymbolElementSize(*section);
655 if (_swap)
656 swapStruct(*sect);
657 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000658 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000659 lc = reinterpret_cast<uint8_t*>(next);
660 }
661 // Add implicit __LINKEDIT segment
Nick Kledzik1bebb282014-09-09 23:52:59 +0000662 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
Nick Kledzik29f749e2013-11-09 00:07:28 +0000663 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
664 cmd->cmd = T::LC;
665 cmd->cmdsize = sizeof(typename T::command);
Nick Kledzike34182f2013-11-06 21:36:55 +0000666 uint8_t *next = lc + cmd->cmdsize;
667 setString16("__LINKEDIT", cmd->segname);
668 cmd->vmaddr = _addressOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000669 cmd->vmsize = llvm::RoundUpToAlignment(linkeditSize, _file.pageSize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000670 cmd->fileoff = _startOfLinkEdit;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000671 cmd->filesize = linkeditSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000672 cmd->maxprot = VM_PROT_READ;
673 cmd->initprot = VM_PROT_READ;
674 cmd->nsects = 0;
675 cmd->flags = 0;
676 if (_swap)
677 swapStruct(*cmd);
678 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000679 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000680}
681
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000682std::error_code MachOFileLayout::writeLoadCommands() {
683 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000684 uint8_t *lc = &_buffer[_startOfLoadCommands];
685 if (_file.fileType == llvm::MachO::MH_OBJECT) {
686 // Object files have one unnamed segment which holds all sections.
687 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000688 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000689 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000690 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000691 // Add LC_SYMTAB with symbol table info
692 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
693 st->cmd = LC_SYMTAB;
694 st->cmdsize = sizeof(symtab_command);
695 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000696 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000697 + _file.undefinedSymbols.size();
698 st->stroff = _startOfSymbolStrings;
699 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
700 if (_swap)
701 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000702 lc += sizeof(symtab_command);
703 // Add LC_DATA_IN_CODE if needed.
704 if (_dataInCodeSize != 0) {
705 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
706 dl->cmd = LC_DATA_IN_CODE;
707 dl->cmdsize = sizeof(linkedit_data_command);
708 dl->dataoff = _startOfDataInCode;
709 dl->datasize = _dataInCodeSize;
710 if (_swap)
711 swapStruct(*dl);
712 lc += sizeof(linkedit_data_command);
713 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000714 } else {
715 // Final linked images have sections under segments.
716 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000717 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000718 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000719 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000720
Tim Northover301c4e62014-07-01 08:15:41 +0000721 // Add LC_ID_DYLIB command for dynamic libraries.
722 if (_file.fileType == llvm::MachO::MH_DYLIB) {
723 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
724 StringRef path = _file.installName;
725 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
726 dc->cmd = LC_ID_DYLIB;
727 dc->cmdsize = size;
728 dc->dylib.name = sizeof(dylib_command); // offset
729 dc->dylib.timestamp = 0; // FIXME
730 dc->dylib.current_version = 0; // FIXME
731 dc->dylib.compatibility_version = 0; // FIXME
732 if (_swap)
733 swapStruct(*dc);
734 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
735 lc[sizeof(dylib_command) + path.size()] = '\0';
736 lc += size;
737 }
738
Nick Kledzike34182f2013-11-06 21:36:55 +0000739 // Add LC_DYLD_INFO_ONLY.
740 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
741 di->cmd = LC_DYLD_INFO_ONLY;
742 di->cmdsize = sizeof(dyld_info_command);
743 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
744 di->rebase_size = _rebaseInfo.size();
745 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
746 di->bind_size = _bindingInfo.size();
747 di->weak_bind_off = 0;
748 di->weak_bind_size = 0;
749 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
750 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000751 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
752 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000753 if (_swap)
754 swapStruct(*di);
755 lc += sizeof(dyld_info_command);
756
757 // Add LC_SYMTAB with symbol table info.
758 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
759 st->cmd = LC_SYMTAB;
760 st->cmdsize = sizeof(symtab_command);
761 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000762 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000763 + _file.undefinedSymbols.size();
764 st->stroff = _startOfSymbolStrings;
765 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
766 if (_swap)
767 swapStruct(*st);
768 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000769
Nick Kledzike34182f2013-11-06 21:36:55 +0000770 // Add LC_DYSYMTAB
771 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
772 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
773 dst->cmd = LC_DYSYMTAB;
774 dst->cmdsize = sizeof(dysymtab_command);
775 dst->ilocalsym = _symbolTableLocalsStartIndex;
776 dst->nlocalsym = _file.localSymbols.size();
777 dst->iextdefsym = _symbolTableGlobalsStartIndex;
778 dst->nextdefsym = _file.globalSymbols.size();
779 dst->iundefsym = _symbolTableUndefinesStartIndex;
780 dst->nundefsym = _file.undefinedSymbols.size();
781 dst->tocoff = 0;
782 dst->ntoc = 0;
783 dst->modtaboff = 0;
784 dst->nmodtab = 0;
785 dst->extrefsymoff = 0;
786 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000787 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000788 dst->nindirectsyms = _indirectSymbolTableCount;
789 dst->extreloff = 0;
790 dst->nextrel = 0;
791 dst->locreloff = 0;
792 dst->nlocrel = 0;
793 if (_swap)
794 swapStruct(*dst);
795 lc += sizeof(dysymtab_command);
796 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000797
Nick Kledzike34182f2013-11-06 21:36:55 +0000798 // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
799 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
800 // Build LC_LOAD_DYLINKER load command.
801 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
802 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
803 dl->cmd = LC_LOAD_DYLINKER;
804 dl->cmdsize = size;
805 dl->name = sizeof(dylinker_command); // offset
806 if (_swap)
807 swapStruct(*dl);
808 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
809 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
810 lc += size;
811 // Build LC_MAIN load command.
812 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
813 ep->cmd = LC_MAIN;
814 ep->cmdsize = sizeof(entry_point_command);
815 ep->entryoff = _file.entryAddress - _seg1addr;
816 ep->stacksize = 0;
817 if (_swap)
818 swapStruct(*ep);
819 lc += sizeof(entry_point_command);
820 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000821
Nick Kledzike34182f2013-11-06 21:36:55 +0000822 // Add LC_LOAD_DYLIB commands
823 for (const DependentDylib &dep : _file.dependentDylibs) {
824 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
825 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000826 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000827 dc->cmdsize = size;
828 dc->dylib.name = sizeof(dylib_command); // offset
829 dc->dylib.timestamp = 0; // FIXME
830 dc->dylib.current_version = 0; // FIXME
831 dc->dylib.compatibility_version = 0; // FIXME
832 if (_swap)
833 swapStruct(*dc);
834 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
835 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
836 lc += size;
837 }
Nick Kledzik54ce29582014-10-28 22:21:10 +0000838 // Add LC_DATA_IN_CODE if needed.
839 if (_dataInCodeSize != 0) {
840 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
841 dl->cmd = LC_DATA_IN_CODE;
842 dl->cmdsize = sizeof(linkedit_data_command);
843 dl->dataoff = _startOfDataInCode;
844 dl->datasize = _dataInCodeSize;
845 if (_swap)
846 swapStruct(*dl);
847 lc += sizeof(linkedit_data_command);
848 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000849 }
850 return ec;
851}
852
853
854void MachOFileLayout::writeSectionContent() {
855 for (const Section &s : _file.sections) {
856 // Copy all section content to output buffer.
Nick Kledzik61fdef62014-05-15 20:59:23 +0000857 if (s.type == llvm::MachO::S_ZEROFILL)
858 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000859 if (s.content.empty())
860 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +0000861 uint32_t offset = _sectInfo[&s].fileOffset;
862 uint8_t *p = &_buffer[offset];
863 memcpy(p, &s.content[0], s.content.size());
864 p += s.content.size();
865 }
866}
867
868void MachOFileLayout::writeRelocations() {
869 uint32_t relOffset = _startOfRelocations;
870 for (Section sect : _file.sections) {
871 for (Relocation r : sect.relocations) {
872 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
873 &_buffer[relOffset]);
874 *rb = packRelocation(r, _swap, _bigEndianArch);
875 relOffset += sizeof(any_relocation_info);
876 }
877 }
878}
879
880
881void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
882 uint32_t &symOffset, uint32_t &strOffset) {
883 for (const Symbol &sym : symbols) {
884 if (_is64) {
885 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
886 nb->n_strx = strOffset - _startOfSymbolStrings;
887 nb->n_type = sym.type | sym.scope;
888 nb->n_sect = sym.sect;
889 nb->n_desc = sym.desc;
890 nb->n_value = sym.value;
891 if (_swap)
892 swapStruct(*nb);
893 symOffset += sizeof(nlist_64);
894 } else {
895 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
896 nb->n_strx = strOffset - _startOfSymbolStrings;
897 nb->n_type = sym.type | sym.scope;
898 nb->n_sect = sym.sect;
899 nb->n_desc = sym.desc;
900 nb->n_value = sym.value;
901 if (_swap)
902 swapStruct(*nb);
903 symOffset += sizeof(nlist);
904 }
905 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
906 strOffset += sym.name.size();
907 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
908 }
909}
910
Nick Kledzik21921372014-07-24 23:06:56 +0000911void MachOFileLayout::writeDataInCodeInfo() {
912 uint32_t offset = _startOfDataInCode;
913 for (const DataInCode &entry : _file.dataInCode) {
914 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
915 &_buffer[offset]);
916 dst->offset = entry.offset;
917 dst->length = entry.length;
918 dst->kind = entry.kind;
919 if (_swap)
920 swapStruct(*dst);
921 offset += sizeof(data_in_code_entry);
922 }
923}
924
Nick Kledzike34182f2013-11-06 21:36:55 +0000925void MachOFileLayout::writeSymbolTable() {
926 // Write symbol table and symbol strings in parallel.
927 uint32_t symOffset = _startOfSymbols;
928 uint32_t strOffset = _startOfSymbolStrings;
929 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
930 appendSymbols(_file.localSymbols, symOffset, strOffset);
931 appendSymbols(_file.globalSymbols, symOffset, strOffset);
932 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
933 // Write indirect symbol table array.
934 uint32_t *indirects = reinterpret_cast<uint32_t*>
935 (&_buffer[_startOfIndirectSymbols]);
936 if (_file.fileType == llvm::MachO::MH_OBJECT) {
937 // Object files have sections in same order as input normalized file.
938 for (const Section &section : _file.sections) {
939 for (uint32_t index : section.indirectSymbols) {
940 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000941 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000942 else
943 *indirects++ = index;
944 }
945 }
946 } else {
947 // Final linked images must sort sections from normalized file.
948 for (const Segment &seg : _file.segments) {
949 SegExtraInfo &segInfo = _segInfo[&seg];
950 for (const Section *section : segInfo.sections) {
951 for (uint32_t index : section->indirectSymbols) {
952 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +0000953 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +0000954 else
955 *indirects++ = index;
956 }
957 }
958 }
959 }
960}
961
962void MachOFileLayout::writeRebaseInfo() {
963 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
964}
965
966void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000967 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000968 _bindingInfo.bytes(), _bindingInfo.size());
969}
970
971void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000972 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +0000973 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
974}
975
Nick Kledzik141330a2014-09-03 19:52:50 +0000976void MachOFileLayout::writeExportInfo() {
977 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
978}
979
Nick Kledzike34182f2013-11-06 21:36:55 +0000980void MachOFileLayout::buildLinkEditInfo() {
981 buildRebaseInfo();
982 buildBindInfo();
983 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000984 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +0000985 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000986 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000987}
988
989void MachOFileLayout::buildSectionRelocations() {
990
991}
992
993void MachOFileLayout::buildRebaseInfo() {
994 // TODO: compress rebasing info.
995 for (const RebaseLocation& entry : _file.rebasingInfo) {
996 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000997 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +0000998 | entry.segIndex);
999 _rebaseInfo.append_uleb128(entry.segOffset);
1000 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1001 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001002 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001003 _rebaseInfo.align(_is64 ? 8 : 4);
1004}
1005
1006void MachOFileLayout::buildBindInfo() {
1007 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001008 uint64_t lastAddend = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001009 for (const BindLocation& entry : _file.bindingInfo) {
1010 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001011 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001012 | entry.segIndex);
1013 _bindingInfo.append_uleb128(entry.segOffset);
1014 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1015 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1016 _bindingInfo.append_string(entry.symbolName);
Nick Kledzikf373c772014-11-11 01:31:18 +00001017 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001018 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1019 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001020 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001021 }
1022 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1023 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001024 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001025 _bindingInfo.align(_is64 ? 8 : 4);
1026}
1027
1028void MachOFileLayout::buildLazyBindInfo() {
1029 for (const BindLocation& entry : _file.lazyBindingInfo) {
1030 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001031 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001032 | entry.segIndex);
Nick Kledzikf373c772014-11-11 01:31:18 +00001033 _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
Nick Kledzike34182f2013-11-06 21:36:55 +00001034 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
1035 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1036 _lazyBindingInfo.append_string(entry.symbolName);
1037 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001038 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001039 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001040 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001041 _lazyBindingInfo.align(_is64 ? 8 : 4);
1042}
1043
Nick Kledzik141330a2014-09-03 19:52:50 +00001044void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
1045 BumpPtrAllocator &allocator,
1046 std::vector<TrieNode*> &allNodes) {
1047 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1048 for (TrieEdge &edge : _children) {
1049 StringRef edgeStr = edge._subString;
1050 if (partialStr.startswith(edgeStr)) {
1051 // Already have matching edge, go down that path.
1052 edge._child->addSymbol(entry, allocator, allNodes);
1053 return;
1054 }
1055 // See if string has commmon prefix with existing edge.
1056 for (int n=edgeStr.size()-1; n > 0; --n) {
1057 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1058 // Splice in new node: was A -> C, now A -> B -> C
1059 StringRef bNodeStr = edge._child->_cummulativeString;
1060 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
1061 TrieNode* bNode = new (allocator) TrieNode(bNodeStr);
1062 allNodes.push_back(bNode);
1063 TrieNode* cNode = edge._child;
1064 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1065 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1066 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1067 << "splice in TrieNode('" << bNodeStr
1068 << "') between edge '"
1069 << abEdgeStr << "' and edge='"
1070 << bcEdgeStr<< "'\n");
1071 TrieEdge& abEdge = edge;
1072 abEdge._subString = abEdgeStr;
1073 abEdge._child = bNode;
1074 TrieEdge bcEdge(bcEdgeStr, cNode);
1075 bNode->_children.push_back(bcEdge);
1076 bNode->addSymbol(entry, allocator, allNodes);
1077 return;
1078 }
1079 }
1080 }
1081 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1082 assert(entry.otherOffset != 0);
1083 }
1084 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1085 assert(entry.otherOffset != 0);
1086 }
1087 // No commonality with any existing child, make a new edge.
1088 TrieNode* newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1089 TrieEdge newEdge(partialStr, newNode);
1090 _children.push_back(newEdge);
1091 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1092 << "new TrieNode('" << entry.name << "') with edge '"
1093 << partialStr << "' from node='"
1094 << _cummulativeString << "'\n");
1095 newNode->_address = entry.offset;
1096 newNode->_flags = entry.flags | entry.kind;
1097 newNode->_other = entry.otherOffset;
1098 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1099 newNode->_importedName = entry.otherName.copy(allocator);
1100 newNode->_hasExportInfo = true;
1101 allNodes.push_back(newNode);
1102}
1103
1104bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
1105 uint32_t nodeSize = 1; // Length when no export info
1106 if (_hasExportInfo) {
1107 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1108 nodeSize = llvm::getULEB128Size(_flags);
1109 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1110 nodeSize += _importedName.size();
1111 ++nodeSize; // Trailing zero in imported name.
1112 } else {
1113 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1114 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1115 nodeSize += llvm::getULEB128Size(_other);
1116 }
1117 // Overall node size so far is uleb128 of export info + actual export info.
1118 nodeSize += llvm::getULEB128Size(nodeSize);
1119 }
1120 // Compute size of all child edges.
1121 ++nodeSize; // Byte for number of chidren.
1122 for (TrieEdge &edge : _children) {
1123 nodeSize += edge._subString.size() + 1 // String length.
1124 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1125 }
1126 // On input, 'offset' is new prefered location for this node.
1127 bool result = (_trieOffset != offset);
1128 // Store new location in node object for use by parents.
1129 _trieOffset = offset;
1130 // Update offset for next iteration.
1131 offset += nodeSize;
1132 // Return true if _trieOffset was changed.
1133 return result;
1134}
1135
1136void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) {
1137 if (_hasExportInfo) {
1138 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1139 if (!_importedName.empty()) {
1140 // nodes with re-export info: size, flags, ordinal, import-name
1141 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1142 + llvm::getULEB128Size(_other)
1143 + _importedName.size() + 1;
1144 assert(nodeSize < 256);
1145 out.append_byte(nodeSize);
1146 out.append_uleb128(_flags);
1147 out.append_uleb128(_other);
1148 out.append_string(_importedName);
1149 } else {
1150 // nodes without re-export info: size, flags, ordinal, empty-string
1151 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1152 + llvm::getULEB128Size(_other) + 1;
1153 assert(nodeSize < 256);
1154 out.append_byte(nodeSize);
1155 out.append_uleb128(_flags);
1156 out.append_uleb128(_other);
1157 out.append_byte(0);
1158 }
1159 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1160 // Nodes with export info: size, flags, address, other
1161 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1162 + llvm::getULEB128Size(_address)
1163 + llvm::getULEB128Size(_other);
1164 assert(nodeSize < 256);
1165 out.append_byte(nodeSize);
1166 out.append_uleb128(_flags);
1167 out.append_uleb128(_address);
1168 out.append_uleb128(_other);
1169 } else {
1170 // Nodes with export info: size, flags, address
1171 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1172 + llvm::getULEB128Size(_address);
1173 assert(nodeSize < 256);
1174 out.append_byte(nodeSize);
1175 out.append_uleb128(_flags);
1176 out.append_uleb128(_address);
1177 }
1178 } else {
1179 // Node with no export info.
1180 uint32_t nodeSize = 0;
1181 out.append_byte(nodeSize);
1182 }
1183 // Add number of children.
1184 assert(_children.size() < 256);
1185 out.append_byte(_children.size());
1186 // Append each child edge substring and node offset.
1187 for (TrieEdge &edge : _children) {
1188 out.append_string(edge._subString);
1189 out.append_uleb128(edge._child->_trieOffset);
1190 }
1191}
1192
1193void MachOFileLayout::buildExportTrie() {
1194 if (_file.exportInfo.empty())
1195 return;
1196
1197 // For all temporary strings and objects used building trie.
1198 BumpPtrAllocator allocator;
1199
1200 // Build trie of all exported symbols.
1201 TrieNode* rootNode = new (allocator) TrieNode(StringRef());
1202 std::vector<TrieNode*> allNodes;
1203 allNodes.reserve(_file.exportInfo.size()*2);
1204 allNodes.push_back(rootNode);
1205 for (const Export& entry : _file.exportInfo) {
1206 rootNode->addSymbol(entry, allocator, allNodes);
1207 }
1208
1209 // Assign each node in the vector an offset in the trie stream, iterating
1210 // until all uleb128 sizes have stabilized.
1211 bool more;
1212 do {
1213 uint32_t offset = 0;
1214 more = false;
1215 for (TrieNode* node : allNodes) {
1216 if (node->updateOffset(offset))
1217 more = true;
1218 }
1219 } while (more);
1220
1221 // Serialize trie to ByteBuffer.
1222 for (TrieNode* node : allNodes) {
1223 node->appendToByteBuffer(_exportTrie);
1224 }
1225 _exportTrie.align(_is64 ? 8 : 4);
1226}
1227
1228
Nick Kledzike34182f2013-11-06 21:36:55 +00001229void MachOFileLayout::computeSymbolTableSizes() {
1230 // MachO symbol tables have three ranges: locals, globals, and undefines
1231 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001232 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001233 + _file.globalSymbols.size()
1234 + _file.undefinedSymbols.size());
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001235 _symbolStringPoolSize = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001236 for (const Symbol &sym : _file.localSymbols) {
1237 _symbolStringPoolSize += (sym.name.size()+1);
1238 }
1239 for (const Symbol &sym : _file.globalSymbols) {
1240 _symbolStringPoolSize += (sym.name.size()+1);
1241 }
1242 for (const Symbol &sym : _file.undefinedSymbols) {
1243 _symbolStringPoolSize += (sym.name.size()+1);
1244 }
1245 _symbolTableLocalsStartIndex = 0;
1246 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001247 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001248 + _file.globalSymbols.size();
1249
1250 _indirectSymbolTableCount = 0;
1251 for (const Section &sect : _file.sections) {
1252 _indirectSymbolTableCount += sect.indirectSymbols.size();
1253 }
1254}
1255
Nick Kledzik21921372014-07-24 23:06:56 +00001256void MachOFileLayout::computeDataInCodeSize() {
1257 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1258}
Nick Kledzike34182f2013-11-06 21:36:55 +00001259
1260void MachOFileLayout::writeLinkEditContent() {
1261 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1262 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +00001263 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001264 writeSymbolTable();
1265 } else {
1266 writeRebaseInfo();
1267 writeBindingInfo();
1268 writeLazyBindingInfo();
1269 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001270 writeExportInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001271 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001272 writeSymbolTable();
1273 }
1274}
1275
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001276std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001277 // Check for pending error from constructor.
1278 if (_ec)
1279 return _ec;
1280 // Create FileOutputBuffer with calculated size.
Ahmed Charles13c70b62014-03-13 16:20:38 +00001281 std::unique_ptr<llvm::FileOutputBuffer> fob;
Nick Kledzike34182f2013-11-06 21:36:55 +00001282 unsigned flags = 0;
1283 if (_file.fileType != llvm::MachO::MH_OBJECT)
1284 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001285 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001286 ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
1287 if (ec)
1288 return ec;
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001289
Nick Kledzike34182f2013-11-06 21:36:55 +00001290 // Write content.
1291 _buffer = fob->getBufferStart();
1292 writeMachHeader();
1293 ec = writeLoadCommands();
1294 if (ec)
1295 return ec;
1296 writeSectionContent();
1297 writeLinkEditContent();
1298 fob->commit();
1299
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001300 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001301}
1302
1303
Nick Kledzike34182f2013-11-06 21:36:55 +00001304/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001305std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001306 MachOFileLayout layout(file);
1307 return layout.writeBinary(path);
1308}
1309
1310
1311} // namespace normalized
1312} // namespace mach_o
1313} // namespace lld
1314