blob: 17b45b9ca827828dabe3641869c53cdc46297371 [file] [log] [blame]
Nick Kledzike34182f2013-11-06 21:36:55 +00001//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp ---------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Nick Kledzike34182f2013-11-06 21:36:55 +00006//
7//===----------------------------------------------------------------------===//
8
9///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000010/// \file For mach-o object files, this implementation converts normalized
Nick Kledzike34182f2013-11-06 21:36:55 +000011/// mach-o in memory to mach-o binary on disk.
12///
Shankar Easwaran3d8de472014-01-27 03:09:26 +000013/// +---------------+
14/// | binary mach-o |
15/// +---------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000016/// ^
17/// |
18/// |
Shankar Easwaran3d8de472014-01-27 03:09:26 +000019/// +------------+
20/// | normalized |
21/// +------------+
Nick Kledzike34182f2013-11-06 21:36:55 +000022
23#include "MachONormalizedFile.h"
24#include "MachONormalizedFileBinaryUtils.h"
Rui Ueyama3f851702017-10-02 21:00:41 +000025#include "lld/Common/LLVM.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000026#include "lld/Core/Error.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000027#include "llvm/ADT/SmallString.h"
28#include "llvm/ADT/SmallVector.h"
29#include "llvm/ADT/StringRef.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000030#include "llvm/ADT/ilist.h"
31#include "llvm/ADT/ilist_node.h"
32#include "llvm/BinaryFormat/MachO.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000033#include "llvm/Support/Casting.h"
34#include "llvm/Support/Debug.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000035#include "llvm/Support/Errc.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000036#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/FileOutputBuffer.h"
Nick Kledzik141330a2014-09-03 19:52:50 +000038#include "llvm/Support/Format.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000039#include "llvm/Support/Host.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000040#include "llvm/Support/MemoryBuffer.h"
41#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000042#include <functional>
Nick Kledzik07ba5122014-12-02 01:50:44 +000043#include <list>
Nick Kledzike34182f2013-11-06 21:36:55 +000044#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000045#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000046
47using namespace llvm::MachO;
48
49namespace lld {
50namespace mach_o {
51namespace normalized {
52
Pete Coopere420dd42016-01-25 21:50:54 +000053struct TrieNode; // Forward declaration.
54
55struct TrieEdge : public llvm::ilist_node<TrieEdge> {
56 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
57
58 StringRef _subString;
59 struct TrieNode *_child;
60};
61
62} // namespace normalized
63} // namespace mach_o
64} // namespace lld
65
66
67namespace llvm {
Duncan P. N. Exon Smith9f710572016-09-03 01:29:36 +000068using lld::mach_o::normalized::TrieEdge;
69template <>
70struct ilist_alloc_traits<TrieEdge> : ilist_noalloc_traits<TrieEdge> {};
Pete Coopere420dd42016-01-25 21:50:54 +000071} // namespace llvm
72
73
74namespace lld {
75namespace mach_o {
76namespace normalized {
77
78struct TrieNode {
79 typedef llvm::ilist<TrieEdge> TrieEdgeList;
80
81 TrieNode(StringRef s)
82 : _cummulativeString(s), _address(0), _flags(0), _other(0),
83 _trieOffset(0), _hasExportInfo(false) {}
84 ~TrieNode() = default;
85
86 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
87 std::vector<TrieNode *> &allNodes);
Pete Cooperd0de3682016-08-05 21:37:12 +000088
89 void addOrderedNodes(const Export &entry,
90 std::vector<TrieNode *> &allNodes);
Pete Coopere420dd42016-01-25 21:50:54 +000091 bool updateOffset(uint32_t &offset);
92 void appendToByteBuffer(ByteBuffer &out);
93
94private:
95 StringRef _cummulativeString;
96 TrieEdgeList _children;
97 uint64_t _address;
98 uint64_t _flags;
99 uint64_t _other;
100 StringRef _importedName;
101 uint32_t _trieOffset;
102 bool _hasExportInfo;
Pete Cooperd0de3682016-08-05 21:37:12 +0000103 bool _ordered = false;
Pete Coopere420dd42016-01-25 21:50:54 +0000104};
105
Nick Kledzike34182f2013-11-06 21:36:55 +0000106/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000107/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000108class MachOFileLayout {
109public:
Joey Goulyb275d7f2013-12-23 23:29:50 +0000110 /// All layout computation is done in the constructor.
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000111 MachOFileLayout(const NormalizedFile &file, bool alwaysIncludeFunctionStarts);
Joey Goulyb275d7f2013-12-23 23:29:50 +0000112
Nick Kledzike34182f2013-11-06 21:36:55 +0000113 /// Returns the final file size as computed in the constructor.
114 size_t size() const;
115
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000116 // Returns size of the mach_header and load commands.
117 size_t headerAndLoadCommandsSize() const;
118
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000119 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +0000120 /// path. This does not have a stream interface because the generated
121 /// file may need the 'x' bit set.
Pete Cooperfefbd222016-03-30 23:10:39 +0000122 llvm::Error writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000123
Nick Kledzike34182f2013-11-06 21:36:55 +0000124private:
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000125 uint32_t loadCommandsSize(uint32_t &count,
126 bool alwaysIncludeFunctionStarts);
Nick Kledzike34182f2013-11-06 21:36:55 +0000127 void buildFileOffsets();
128 void writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +0000129 llvm::Error writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +0000130 void writeSectionContent();
131 void writeRelocations();
132 void writeSymbolTable();
133 void writeRebaseInfo();
134 void writeBindingInfo();
135 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000136 void writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000137 void writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +0000138 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000139 void writeLinkEditContent();
140 void buildLinkEditInfo();
141 void buildRebaseInfo();
142 void buildBindInfo();
143 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000144 void buildExportTrie();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000145 void computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000146 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000147 void computeSymbolTableSizes();
148 void buildSectionRelocations();
149 void appendSymbols(const std::vector<Symbol> &symbols,
150 uint32_t &symOffset, uint32_t &strOffset);
151 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
152 uint32_t indirectSymbolElementSize(const Section &sect);
153
Nick Kledzik29f749e2013-11-09 00:07:28 +0000154 // For use as template parameter to load command methods.
155 struct MachO64Trait {
156 typedef llvm::MachO::segment_command_64 command;
157 typedef llvm::MachO::section_64 section;
158 enum { LC = llvm::MachO::LC_SEGMENT_64 };
159 };
160
161 // For use as template parameter to load command methods.
162 struct MachO32Trait {
163 typedef llvm::MachO::segment_command command;
164 typedef llvm::MachO::section section;
165 enum { LC = llvm::MachO::LC_SEGMENT };
166 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000167
Nick Kledzik29f749e2013-11-09 00:07:28 +0000168 template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000169 llvm::Error writeSingleSegmentLoadCommand(uint8_t *&lc);
170 template <typename T> llvm::Error writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000171
Nick Kledzike34182f2013-11-06 21:36:55 +0000172 uint32_t pointerAlign(uint32_t value);
173 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000174
Nick Kledzike34182f2013-11-06 21:36:55 +0000175 struct SegExtraInfo {
176 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000177 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000178 std::vector<const Section*> sections;
179 };
180 typedef std::map<const Segment*, SegExtraInfo> SegMap;
181 struct SectionExtraInfo {
182 uint32_t fileOffset;
183 };
184 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000185
Nick Kledzike34182f2013-11-06 21:36:55 +0000186 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000187 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000188 uint8_t *_buffer;
189 const bool _is64;
190 const bool _swap;
191 const bool _bigEndianArch;
192 uint64_t _seg1addr;
193 uint32_t _startOfLoadCommands;
194 uint32_t _countOfLoadCommands;
195 uint32_t _endOfLoadCommands;
196 uint32_t _startOfRelocations;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000197 uint32_t _startOfFunctionStarts;
Nick Kledzik21921372014-07-24 23:06:56 +0000198 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000199 uint32_t _startOfSymbols;
200 uint32_t _startOfIndirectSymbols;
201 uint32_t _startOfSymbolStrings;
202 uint32_t _endOfSymbolStrings;
203 uint32_t _symbolTableLocalsStartIndex;
204 uint32_t _symbolTableGlobalsStartIndex;
205 uint32_t _symbolTableUndefinesStartIndex;
206 uint32_t _symbolStringPoolSize;
207 uint32_t _symbolTableSize;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000208 uint32_t _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000209 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000210 uint32_t _indirectSymbolTableCount;
211 // Used in object file creation only
212 uint32_t _startOfSectionsContent;
213 uint32_t _endOfSectionsContent;
214 // Used in final linked image only
215 uint32_t _startOfLinkEdit;
216 uint32_t _startOfRebaseInfo;
217 uint32_t _endOfRebaseInfo;
218 uint32_t _startOfBindingInfo;
219 uint32_t _endOfBindingInfo;
220 uint32_t _startOfLazyBindingInfo;
221 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000222 uint32_t _startOfExportTrie;
223 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000224 uint32_t _endOfLinkEdit;
225 uint64_t _addressOfLinkEdit;
226 SegMap _segInfo;
227 SectionMap _sectInfo;
228 ByteBuffer _rebaseInfo;
229 ByteBuffer _bindingInfo;
230 ByteBuffer _lazyBindingInfo;
231 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000232 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000233};
234
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000235size_t headerAndLoadCommandsSize(const NormalizedFile &file,
236 bool includeFunctionStarts) {
237 MachOFileLayout layout(file, includeFunctionStarts);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000238 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000239}
240
241StringRef MachOFileLayout::dyldPath() {
242 return "/usr/lib/dyld";
243}
244
245uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
Rui Ueyama489a8062016-01-14 20:53:50 +0000246 return llvm::alignTo(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000247}
Nick Kledzike34182f2013-11-06 21:36:55 +0000248
249
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000250size_t MachOFileLayout::headerAndLoadCommandsSize() const {
251 return _endOfLoadCommands;
252}
Nick Kledzike34182f2013-11-06 21:36:55 +0000253
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000254MachOFileLayout::MachOFileLayout(const NormalizedFile &file,
255 bool alwaysIncludeFunctionStarts)
Nick Kledzike34182f2013-11-06 21:36:55 +0000256 : _file(file),
257 _is64(MachOLinkingContext::is64Bit(file.arch)),
258 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
259 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
260 _seg1addr(INT64_MAX) {
261 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000262 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000263 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
264 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
265 if (file.fileType == llvm::MachO::MH_OBJECT) {
266 // object files have just one segment load command containing all sections
267 _endOfLoadCommands = _startOfLoadCommands
268 + segCommandBaseSize
269 + file.sections.size() * sectsSize
270 + sizeof(symtab_command);
271 _countOfLoadCommands = 2;
Pete Cooperceee5de2016-02-04 02:16:08 +0000272 if (file.hasMinVersionLoadCommand) {
273 _endOfLoadCommands += sizeof(version_min_command);
274 _countOfLoadCommands++;
275 }
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000276 if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000277 _endOfLoadCommands += sizeof(linkedit_data_command);
278 _countOfLoadCommands++;
279 }
Pete Cooper9b28a452016-02-09 02:10:39 +0000280 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000281 _endOfLoadCommands += sizeof(linkedit_data_command);
282 _countOfLoadCommands++;
283 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000284 // Assign file offsets to each section.
Nick Kledzike34182f2013-11-06 21:36:55 +0000285 _startOfSectionsContent = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000286 unsigned relocCount = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000287 uint64_t offset = _startOfSectionsContent;
Nick Kledzike34182f2013-11-06 21:36:55 +0000288 for (const Section &sect : file.sections) {
Lang Hamesac2adce2015-12-11 23:25:09 +0000289 if (isZeroFillSection(sect.type))
290 _sectInfo[&sect].fileOffset = 0;
291 else {
Rui Ueyama489a8062016-01-14 20:53:50 +0000292 offset = llvm::alignTo(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000293 _sectInfo[&sect].fileOffset = offset;
294 offset += sect.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000295 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000296 relocCount += sect.relocations.size();
297 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000298 _endOfSectionsContent = offset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000299
Nick Kledzike34182f2013-11-06 21:36:55 +0000300 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000301 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000302 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000303
Nick Kledzike34182f2013-11-06 21:36:55 +0000304 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000305 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000306 _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
307 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000308 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000309 // Add Indirect symbol table.
310 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
311 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000312 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000313 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000314 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000315 + pointerAlign(_symbolStringPoolSize);
316 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000317 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000318 llvm::dbgs() << "MachOFileLayout()\n"
319 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
320 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
321 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
322 << " startOfRelocations=" << _startOfRelocations << "\n"
323 << " startOfSymbols=" << _startOfSymbols << "\n"
324 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
325 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
326 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
327 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
328 } else {
329 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000330 _endOfLoadCommands = _startOfLoadCommands
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000331 + loadCommandsSize(_countOfLoadCommands,
332 alwaysIncludeFunctionStarts);
Nick Kledzike34182f2013-11-06 21:36:55 +0000333
334 // Assign section file offsets.
335 buildFileOffsets();
336 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000337
Nick Kledzike34182f2013-11-06 21:36:55 +0000338 // LINKEDIT of final linked images has in order:
339 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000340 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000341 _startOfRebaseInfo = _startOfLinkEdit;
342 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
343 _startOfBindingInfo = _endOfRebaseInfo;
344 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
345 _startOfLazyBindingInfo = _endOfBindingInfo;
346 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000347 _startOfExportTrie = _endOfLazyBindingInfo;
348 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000349 _startOfFunctionStarts = _endOfExportTrie;
350 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000351 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000352 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000353 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000354 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000355 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000356 + pointerAlign(_symbolStringPoolSize);
357 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000358 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000359 llvm::dbgs() << "MachOFileLayout()\n"
360 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
361 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
362 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
363 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
364 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
365 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
366 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
367 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
368 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
369 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000370 << " startOfExportTrie=" << _startOfExportTrie << "\n"
371 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000372 << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000373 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000374 << " startOfSymbols=" << _startOfSymbols << "\n"
375 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
376 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
377 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
378 }
379}
380
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000381uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count,
382 bool alwaysIncludeFunctionStarts) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000383 uint32_t size = 0;
384 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000385
386 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000387 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
388 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
389
390 // Add LC_SEGMENT for each segment.
391 size += _file.segments.size() * segCommandSize;
392 count += _file.segments.size();
393 // Add section record for each section.
394 size += _file.sections.size() * sectionSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000395
Tim Northover301c4e62014-07-01 08:15:41 +0000396 // If creating a dylib, add LC_ID_DYLIB.
397 if (_file.fileType == llvm::MachO::MH_DYLIB) {
398 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
399 ++count;
400 }
401
Nick Kledzike34182f2013-11-06 21:36:55 +0000402 // Add LC_DYLD_INFO
403 size += sizeof(dyld_info_command);
404 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000405
Nick Kledzike34182f2013-11-06 21:36:55 +0000406 // Add LC_SYMTAB
407 size += sizeof(symtab_command);
408 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000409
Nick Kledzike34182f2013-11-06 21:36:55 +0000410 // Add LC_DYSYMTAB
411 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
412 size += sizeof(dysymtab_command);
413 ++count;
414 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000415
Pete Cooper354809e2016-02-03 22:28:29 +0000416 // If main executable add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000417 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
418 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
419 ++count;
Pete Cooper354809e2016-02-03 22:28:29 +0000420 }
421
422 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
423 // LC_VERSION_MIN_TVOS
424 if (_file.hasMinVersionLoadCommand) {
425 size += sizeof(version_min_command);
426 ++count;
427 }
428
Pete Cooper40576fa2016-02-04 02:45:23 +0000429 // Add LC_SOURCE_VERSION
430 size += sizeof(source_version_command);
431 ++count;
432
Pete Cooper354809e2016-02-03 22:28:29 +0000433 // If main executable add LC_MAIN
434 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000435 size += sizeof(entry_point_command);
436 ++count;
437 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000438
Nick Kledzike34182f2013-11-06 21:36:55 +0000439 // Add LC_LOAD_DYLIB for each dependent dylib.
440 for (const DependentDylib &dep : _file.dependentDylibs) {
441 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
442 ++count;
443 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000444
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000445 // Add LC_RPATH
446 for (const StringRef &path : _file.rpaths) {
Lang Hames2ed3bf92015-10-29 16:50:26 +0000447 size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000448 ++count;
449 }
450
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000451 // Add LC_FUNCTION_STARTS if needed
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +0000452 if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000453 size += sizeof(linkedit_data_command);
454 ++count;
455 }
456
Pete Cooper9b28a452016-02-09 02:10:39 +0000457 // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries.
458 // FIXME: Zero length entries is only to match ld64. Should we change this?
459 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +0000460 size += sizeof(linkedit_data_command);
461 ++count;
462 }
463
Nick Kledzike34182f2013-11-06 21:36:55 +0000464 return size;
465}
466
467static bool overlaps(const Segment &s1, const Segment &s2) {
468 if (s2.address >= s1.address+s1.size)
469 return false;
470 if (s1.address >= s2.address+s2.size)
471 return false;
472 return true;
473}
474
475static bool overlaps(const Section &s1, const Section &s2) {
476 if (s2.address >= s1.address+s1.content.size())
477 return false;
478 if (s1.address >= s2.address+s2.content.size())
479 return false;
480 return true;
481}
482
483void MachOFileLayout::buildFileOffsets() {
484 // Verify no segments overlap
485 for (const Segment &sg1 : _file.segments) {
486 for (const Segment &sg2 : _file.segments) {
487 if (&sg1 == &sg2)
488 continue;
489 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000490 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000491 return;
492 }
493 }
494 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000495
496 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000497 for (const Section &s1 : _file.sections) {
498 for (const Section &s2 : _file.sections) {
499 if (&s1 == &s2)
500 continue;
501 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000502 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000503 return;
504 }
505 }
506 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000507
Nick Kledzike34182f2013-11-06 21:36:55 +0000508 // Build side table of extra info about segments and sections.
509 SegExtraInfo t;
510 t.fileOffset = 0;
511 for (const Segment &sg : _file.segments) {
512 _segInfo[&sg] = t;
513 }
514 SectionExtraInfo t2;
515 t2.fileOffset = 0;
516 // Assign sections to segments.
517 for (const Section &s : _file.sections) {
518 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000519 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000520 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000521 if (sg.name.equals(s.segmentName)) {
522 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000523 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000524 _segInfo[&sg].sections.push_back(&s);
525 foundSegment = true;
526 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000527 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000528 }
529 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000530 if (!foundSegment) {
531 _ec = make_error_code(llvm::errc::executable_format_error);
532 return;
533 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000534 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000535
Nick Kledzike34182f2013-11-06 21:36:55 +0000536 // Assign file offsets.
537 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000538 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000539 llvm::dbgs() << "buildFileOffsets()\n");
540 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000541 _segInfo[&sg].fileOffset = fileOffset;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000542 if ((_seg1addr == INT64_MAX) && sg.init_access)
Nick Kledzike34182f2013-11-06 21:36:55 +0000543 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000544 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000545 llvm::dbgs() << " segment=" << sg.name
546 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000547
548 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000549 // A segment that is not zero-fill must use a least one page of disk space.
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000550 if (sg.init_access)
Nick Kledzik761d6542014-10-24 22:19:22 +0000551 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000552 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000553 uint32_t sectOffset = s->address - sg.address;
554 uint32_t sectFileSize =
Lang Hamesac2adce2015-12-11 23:25:09 +0000555 isZeroFillSection(s->type) ? 0 : s->content.size();
Tim Northover08d6a7b2014-06-30 09:49:30 +0000556 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
557
558 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000559 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000560 llvm::dbgs() << " section=" << s->sectionName
561 << ", fileOffset=" << fileOffset << "\n");
562 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000563
Pete Cooper353652f2016-02-06 00:14:15 +0000564 // round up all segments to page aligned, except __LINKEDIT
565 if (!sg.name.equals("__LINKEDIT")) {
566 _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
567 fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
568 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000569 _addressOfLinkEdit = sg.address + sg.size;
570 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000571 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000572}
573
Nick Kledzike34182f2013-11-06 21:36:55 +0000574size_t MachOFileLayout::size() const {
575 return _endOfSymbolStrings;
576}
577
578void MachOFileLayout::writeMachHeader() {
Pete Cooper8563e5a2016-02-04 20:43:43 +0000579 auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
580 // dynamic x86 executables on newer OS version should also set the
581 // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
582 // FIXME: Check that this is a dynamic executable, not a static one.
583 if (_file.fileType == llvm::MachO::MH_EXECUTE &&
584 cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
585 _file.os == MachOLinkingContext::OS::macOSX) {
586 uint32_t version;
587 bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
588 if (!failed && _file.minOSverson >= version)
589 cpusubtype |= CPU_SUBTYPE_LIB64;
590 }
591
Nick Kledzike34182f2013-11-06 21:36:55 +0000592 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
593 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
594 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
Pete Cooper8563e5a2016-02-04 20:43:43 +0000595 mh->cpusubtype = cpusubtype;
Nick Kledzike34182f2013-11-06 21:36:55 +0000596 mh->filetype = _file.fileType;
597 mh->ncmds = _countOfLoadCommands;
598 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
599 mh->flags = _file.flags;
600 if (_swap)
601 swapStruct(*mh);
602}
603
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000604uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000605 uint32_t &index) {
606 if (sect.indirectSymbols.empty())
607 return 0;
608 uint32_t result = index;
609 index += sect.indirectSymbols.size();
610 return result;
611}
612
613uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
614 if (sect.indirectSymbols.empty())
615 return 0;
616 if (sect.type != S_SYMBOL_STUBS)
617 return 0;
618 return sect.content.size() / sect.indirectSymbols.size();
619}
620
Nick Kledzik29f749e2013-11-09 00:07:28 +0000621template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000622llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000623 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
624 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000625 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000626 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000627 uint8_t *next = lc + seg->cmdsize;
628 memset(seg->segname, 0, 16);
Matt Davis4d17cdc2019-09-26 17:03:20 +0000629 seg->flags = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000630 seg->vmaddr = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +0000631 seg->fileoff = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000632 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
633 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
634 seg->nsects = _file.sections.size();
Matt Davis4d17cdc2019-09-26 17:03:20 +0000635 if (seg->nsects) {
636 seg->vmsize = _file.sections.back().address
637 + _file.sections.back().content.size();
638 seg->filesize = _sectInfo[&_file.sections.back()].fileOffset +
639 _file.sections.back().content.size() -
640 _sectInfo[&_file.sections.front()].fileOffset;
641 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000642 if (_swap)
643 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000644 typename T::section *sout = reinterpret_cast<typename T::section*>
645 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000646 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000647 uint32_t indirectSymRunningIndex = 0;
648 for (const Section &sin : _file.sections) {
649 setString16(sin.sectionName, sout->sectname);
650 setString16(sin.segmentName, sout->segname);
651 sout->addr = sin.address;
652 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000653 sout->offset = _sectInfo[&sin].fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000654 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000655 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
656 sout->nreloc = sin.relocations.size();
657 sout->flags = sin.type | sin.attributes;
658 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
659 sout->reserved2 = indirectSymbolElementSize(sin);
660 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000661 if (_swap)
662 swapStruct(*sout);
663 ++sout;
664 }
665 lc = next;
Mehdi Aminic1edf562016-11-11 04:29:25 +0000666 return llvm::Error::success();
Nick Kledzike34182f2013-11-06 21:36:55 +0000667}
668
Nick Kledzik29f749e2013-11-09 00:07:28 +0000669template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000670llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000671 uint32_t indirectSymRunningIndex = 0;
672 for (const Segment &seg : _file.segments) {
Pete Cooper353652f2016-02-06 00:14:15 +0000673 // Link edit has no sections and a custom range of address, so handle it
674 // specially.
Nick Kledzike34182f2013-11-06 21:36:55 +0000675 SegExtraInfo &segInfo = _segInfo[&seg];
Pete Cooper353652f2016-02-06 00:14:15 +0000676 if (seg.name.equals("__LINKEDIT")) {
677 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
678 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
679 cmd->cmd = T::LC;
680 cmd->cmdsize = sizeof(typename T::command);
681 uint8_t *next = lc + cmd->cmdsize;
682 setString16("__LINKEDIT", cmd->segname);
683 cmd->vmaddr = _addressOfLinkEdit;
684 cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
685 cmd->fileoff = _startOfLinkEdit;
686 cmd->filesize = linkeditSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000687 cmd->initprot = seg.init_access;
688 cmd->maxprot = seg.max_access;
Pete Cooper353652f2016-02-06 00:14:15 +0000689 cmd->nsects = 0;
690 cmd->flags = 0;
691 if (_swap)
692 swapStruct(*cmd);
693 lc = next;
694 continue;
695 }
696 // Write segment command with trailing sections.
Nick Kledzik29f749e2013-11-09 00:07:28 +0000697 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
698 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000699 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000700 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000701 uint8_t *next = lc + cmd->cmdsize;
702 setString16(seg.name, cmd->segname);
703 cmd->vmaddr = seg.address;
704 cmd->vmsize = seg.size;
705 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000706 cmd->filesize = segInfo.fileSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000707 cmd->initprot = seg.init_access;
708 cmd->maxprot = seg.max_access;
Nick Kledzike34182f2013-11-06 21:36:55 +0000709 cmd->nsects = segInfo.sections.size();
710 cmd->flags = 0;
711 if (_swap)
712 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000713 typename T::section *sect = reinterpret_cast<typename T::section*>
714 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000715 for (const Section *section : segInfo.sections) {
716 setString16(section->sectionName, sect->sectname);
717 setString16(section->segmentName, sect->segname);
718 sect->addr = section->address;
719 sect->size = section->content.size();
Lang Hamesac2adce2015-12-11 23:25:09 +0000720 if (isZeroFillSection(section->type))
Nick Kledzikb072c362014-11-18 00:30:29 +0000721 sect->offset = 0;
722 else
723 sect->offset = section->address - seg.address + segInfo.fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000724 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000725 sect->reloff = 0;
726 sect->nreloc = 0;
727 sect->flags = section->type | section->attributes;
728 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
729 sect->reserved2 = indirectSymbolElementSize(*section);
730 if (_swap)
731 swapStruct(*sect);
732 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000733 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000734 lc = reinterpret_cast<uint8_t*>(next);
735 }
Mehdi Aminic1edf562016-11-11 04:29:25 +0000736 return llvm::Error::success();
Nick Kledzike34182f2013-11-06 21:36:55 +0000737}
738
Pete Cooperceee5de2016-02-04 02:16:08 +0000739static void writeVersionMinLoadCommand(const NormalizedFile &_file,
740 bool _swap,
741 uint8_t *&lc) {
742 if (!_file.hasMinVersionLoadCommand)
743 return;
744 version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
745 switch (_file.os) {
746 case MachOLinkingContext::OS::unknown:
747 vm->cmd = _file.minOSVersionKind;
748 vm->cmdsize = sizeof(version_min_command);
749 vm->version = _file.minOSverson;
750 vm->sdk = 0;
751 break;
752 case MachOLinkingContext::OS::macOSX:
753 vm->cmd = LC_VERSION_MIN_MACOSX;
754 vm->cmdsize = sizeof(version_min_command);
755 vm->version = _file.minOSverson;
756 vm->sdk = _file.sdkVersion;
757 break;
758 case MachOLinkingContext::OS::iOS:
759 case MachOLinkingContext::OS::iOS_simulator:
760 vm->cmd = LC_VERSION_MIN_IPHONEOS;
761 vm->cmdsize = sizeof(version_min_command);
762 vm->version = _file.minOSverson;
763 vm->sdk = _file.sdkVersion;
764 break;
765 }
766 if (_swap)
767 swapStruct(*vm);
768 lc += sizeof(version_min_command);
769}
770
Pete Cooper514594b2016-03-31 00:08:16 +0000771llvm::Error MachOFileLayout::writeLoadCommands() {
Nick Kledzike34182f2013-11-06 21:36:55 +0000772 uint8_t *lc = &_buffer[_startOfLoadCommands];
773 if (_file.fileType == llvm::MachO::MH_OBJECT) {
774 // Object files have one unnamed segment which holds all sections.
Pete Cooper514594b2016-03-31 00:08:16 +0000775 if (_is64) {
776 if (auto ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc))
Pete Coopere487da12016-03-31 00:35:50 +0000777 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000778 } else {
779 if (auto ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000780 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000781 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000782 // Add LC_SYMTAB with symbol table info
783 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
784 st->cmd = LC_SYMTAB;
785 st->cmdsize = sizeof(symtab_command);
786 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000787 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
788 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000789 st->stroff = _startOfSymbolStrings;
790 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
791 if (_swap)
792 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000793 lc += sizeof(symtab_command);
Pete Cooperceee5de2016-02-04 02:16:08 +0000794
795 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
796 // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
797 writeVersionMinLoadCommand(_file, _swap, lc);
798
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000799 // Add LC_FUNCTION_STARTS if needed.
800 if (_functionStartsSize != 0) {
801 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
802 dl->cmd = LC_FUNCTION_STARTS;
803 dl->cmdsize = sizeof(linkedit_data_command);
804 dl->dataoff = _startOfFunctionStarts;
805 dl->datasize = _functionStartsSize;
806 if (_swap)
807 swapStruct(*dl);
808 lc += sizeof(linkedit_data_command);
809 }
810
Pete Cooper9b28a452016-02-09 02:10:39 +0000811 // Add LC_DATA_IN_CODE if requested.
812 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000813 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
814 dl->cmd = LC_DATA_IN_CODE;
815 dl->cmdsize = sizeof(linkedit_data_command);
816 dl->dataoff = _startOfDataInCode;
817 dl->datasize = _dataInCodeSize;
818 if (_swap)
819 swapStruct(*dl);
820 lc += sizeof(linkedit_data_command);
821 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000822 } else {
823 // Final linked images have sections under segments.
Pete Cooper514594b2016-03-31 00:08:16 +0000824 if (_is64) {
825 if (auto ec = writeSegmentLoadCommands<MachO64Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000826 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000827 } else {
828 if (auto ec = writeSegmentLoadCommands<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000829 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000830 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000831
Tim Northover301c4e62014-07-01 08:15:41 +0000832 // Add LC_ID_DYLIB command for dynamic libraries.
833 if (_file.fileType == llvm::MachO::MH_DYLIB) {
834 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
835 StringRef path = _file.installName;
836 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
837 dc->cmd = LC_ID_DYLIB;
838 dc->cmdsize = size;
839 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000840 // needs to be some constant value different than the one in LC_LOAD_DYLIB
841 dc->dylib.timestamp = 1;
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000842 dc->dylib.current_version = _file.currentVersion;
843 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000844 if (_swap)
845 swapStruct(*dc);
846 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
847 lc[sizeof(dylib_command) + path.size()] = '\0';
848 lc += size;
849 }
850
Nick Kledzike34182f2013-11-06 21:36:55 +0000851 // Add LC_DYLD_INFO_ONLY.
852 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
853 di->cmd = LC_DYLD_INFO_ONLY;
854 di->cmdsize = sizeof(dyld_info_command);
855 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
856 di->rebase_size = _rebaseInfo.size();
857 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
858 di->bind_size = _bindingInfo.size();
859 di->weak_bind_off = 0;
860 di->weak_bind_size = 0;
861 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
862 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000863 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
864 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000865 if (_swap)
866 swapStruct(*di);
867 lc += sizeof(dyld_info_command);
868
869 // Add LC_SYMTAB with symbol table info.
870 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
871 st->cmd = LC_SYMTAB;
872 st->cmdsize = sizeof(symtab_command);
873 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000874 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
875 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000876 st->stroff = _startOfSymbolStrings;
877 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
878 if (_swap)
879 swapStruct(*st);
880 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000881
Nick Kledzike34182f2013-11-06 21:36:55 +0000882 // Add LC_DYSYMTAB
883 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
884 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
885 dst->cmd = LC_DYSYMTAB;
886 dst->cmdsize = sizeof(dysymtab_command);
887 dst->ilocalsym = _symbolTableLocalsStartIndex;
Lang Hames436f7d62016-07-27 22:55:30 +0000888 dst->nlocalsym = _file.stabsSymbols.size() +
889 _file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000890 dst->iextdefsym = _symbolTableGlobalsStartIndex;
891 dst->nextdefsym = _file.globalSymbols.size();
892 dst->iundefsym = _symbolTableUndefinesStartIndex;
893 dst->nundefsym = _file.undefinedSymbols.size();
894 dst->tocoff = 0;
895 dst->ntoc = 0;
896 dst->modtaboff = 0;
897 dst->nmodtab = 0;
898 dst->extrefsymoff = 0;
899 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000900 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000901 dst->nindirectsyms = _indirectSymbolTableCount;
902 dst->extreloff = 0;
903 dst->nextrel = 0;
904 dst->locreloff = 0;
905 dst->nlocrel = 0;
906 if (_swap)
907 swapStruct(*dst);
908 lc += sizeof(dysymtab_command);
909 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000910
Pete Cooper354809e2016-02-03 22:28:29 +0000911 // If main executable, add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000912 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
913 // Build LC_LOAD_DYLINKER load command.
914 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
915 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
916 dl->cmd = LC_LOAD_DYLINKER;
917 dl->cmdsize = size;
918 dl->name = sizeof(dylinker_command); // offset
919 if (_swap)
920 swapStruct(*dl);
921 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
922 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
923 lc += size;
Pete Cooper354809e2016-02-03 22:28:29 +0000924 }
925
926 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
927 // LC_VERSION_MIN_TVOS
Pete Cooperceee5de2016-02-04 02:16:08 +0000928 writeVersionMinLoadCommand(_file, _swap, lc);
Pete Cooper354809e2016-02-03 22:28:29 +0000929
Pete Cooper40576fa2016-02-04 02:45:23 +0000930 // Add LC_SOURCE_VERSION
931 {
Pete Cooperb565bdf2016-03-23 22:00:09 +0000932 // Note, using a temporary here to appease UB as we may not be aligned
933 // enough for a struct containing a uint64_t when emitting a 32-bit binary
934 source_version_command sv;
935 sv.cmd = LC_SOURCE_VERSION;
936 sv.cmdsize = sizeof(source_version_command);
937 sv.version = _file.sourceVersion;
Pete Cooper40576fa2016-02-04 02:45:23 +0000938 if (_swap)
Pete Cooperb565bdf2016-03-23 22:00:09 +0000939 swapStruct(sv);
940 memcpy(lc, &sv, sizeof(source_version_command));
Pete Cooper40576fa2016-02-04 02:45:23 +0000941 lc += sizeof(source_version_command);
942 }
943
Pete Cooper354809e2016-02-03 22:28:29 +0000944 // If main executable, add LC_MAIN.
945 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000946 // Build LC_MAIN load command.
Pete Cooper07601d32016-03-24 01:05:17 +0000947 // Note, using a temporary here to appease UB as we may not be aligned
948 // enough for a struct containing a uint64_t when emitting a 32-bit binary
949 entry_point_command ep;
950 ep.cmd = LC_MAIN;
951 ep.cmdsize = sizeof(entry_point_command);
952 ep.entryoff = _file.entryAddress - _seg1addr;
953 ep.stacksize = _file.stackSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000954 if (_swap)
Pete Cooper07601d32016-03-24 01:05:17 +0000955 swapStruct(ep);
956 memcpy(lc, &ep, sizeof(entry_point_command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000957 lc += sizeof(entry_point_command);
958 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000959
Nick Kledzike34182f2013-11-06 21:36:55 +0000960 // Add LC_LOAD_DYLIB commands
961 for (const DependentDylib &dep : _file.dependentDylibs) {
962 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
963 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000964 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000965 dc->cmdsize = size;
966 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000967 // needs to be some constant value different than the one in LC_ID_DYLIB
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000968 dc->dylib.timestamp = 2;
969 dc->dylib.current_version = dep.currentVersion;
970 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000971 if (_swap)
972 swapStruct(*dc);
973 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
974 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
975 lc += size;
976 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000977
978 // Add LC_RPATH
979 for (const StringRef &path : _file.rpaths) {
980 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
Lang Hames2ed3bf92015-10-29 16:50:26 +0000981 uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000982 rpc->cmd = LC_RPATH;
983 rpc->cmdsize = size;
984 rpc->path = sizeof(rpath_command); // offset
985 if (_swap)
986 swapStruct(*rpc);
987 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
988 lc[sizeof(rpath_command)+path.size()] = '\0';
989 lc += size;
990 }
991
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000992 // Add LC_FUNCTION_STARTS if needed.
993 if (_functionStartsSize != 0) {
994 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
995 dl->cmd = LC_FUNCTION_STARTS;
996 dl->cmdsize = sizeof(linkedit_data_command);
997 dl->dataoff = _startOfFunctionStarts;
998 dl->datasize = _functionStartsSize;
999 if (_swap)
1000 swapStruct(*dl);
1001 lc += sizeof(linkedit_data_command);
1002 }
1003
Pete Cooper9b28a452016-02-09 02:10:39 +00001004 // Add LC_DATA_IN_CODE if requested.
1005 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +00001006 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
1007 dl->cmd = LC_DATA_IN_CODE;
1008 dl->cmdsize = sizeof(linkedit_data_command);
1009 dl->dataoff = _startOfDataInCode;
1010 dl->datasize = _dataInCodeSize;
1011 if (_swap)
1012 swapStruct(*dl);
1013 lc += sizeof(linkedit_data_command);
1014 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001015 }
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +00001016 assert(lc == &_buffer[_endOfLoadCommands]);
Mehdi Aminic1edf562016-11-11 04:29:25 +00001017 return llvm::Error::success();
Nick Kledzike34182f2013-11-06 21:36:55 +00001018}
1019
Nick Kledzike34182f2013-11-06 21:36:55 +00001020void MachOFileLayout::writeSectionContent() {
1021 for (const Section &s : _file.sections) {
1022 // Copy all section content to output buffer.
Lang Hamesac2adce2015-12-11 23:25:09 +00001023 if (isZeroFillSection(s.type))
Nick Kledzik61fdef62014-05-15 20:59:23 +00001024 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +00001025 if (s.content.empty())
1026 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +00001027 uint32_t offset = _sectInfo[&s].fileOffset;
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +00001028 assert(offset >= _endOfLoadCommands);
Nick Kledzike34182f2013-11-06 21:36:55 +00001029 uint8_t *p = &_buffer[offset];
1030 memcpy(p, &s.content[0], s.content.size());
1031 p += s.content.size();
1032 }
1033}
1034
1035void MachOFileLayout::writeRelocations() {
1036 uint32_t relOffset = _startOfRelocations;
1037 for (Section sect : _file.sections) {
1038 for (Relocation r : sect.relocations) {
1039 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
1040 &_buffer[relOffset]);
1041 *rb = packRelocation(r, _swap, _bigEndianArch);
1042 relOffset += sizeof(any_relocation_info);
1043 }
1044 }
1045}
1046
Nick Kledzike34182f2013-11-06 21:36:55 +00001047void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
1048 uint32_t &symOffset, uint32_t &strOffset) {
1049 for (const Symbol &sym : symbols) {
1050 if (_is64) {
1051 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
1052 nb->n_strx = strOffset - _startOfSymbolStrings;
1053 nb->n_type = sym.type | sym.scope;
1054 nb->n_sect = sym.sect;
1055 nb->n_desc = sym.desc;
1056 nb->n_value = sym.value;
1057 if (_swap)
1058 swapStruct(*nb);
1059 symOffset += sizeof(nlist_64);
1060 } else {
1061 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
1062 nb->n_strx = strOffset - _startOfSymbolStrings;
1063 nb->n_type = sym.type | sym.scope;
1064 nb->n_sect = sym.sect;
1065 nb->n_desc = sym.desc;
1066 nb->n_value = sym.value;
1067 if (_swap)
1068 swapStruct(*nb);
1069 symOffset += sizeof(nlist);
1070 }
1071 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
1072 strOffset += sym.name.size();
1073 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
1074 }
1075}
1076
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001077void MachOFileLayout::writeFunctionStartsInfo() {
Pete Cooper8e1b9a12016-03-22 22:51:03 +00001078 if (!_functionStartsSize)
1079 return;
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001080 memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
1081 _functionStartsSize);
1082}
1083
Nick Kledzik21921372014-07-24 23:06:56 +00001084void MachOFileLayout::writeDataInCodeInfo() {
1085 uint32_t offset = _startOfDataInCode;
1086 for (const DataInCode &entry : _file.dataInCode) {
1087 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
1088 &_buffer[offset]);
1089 dst->offset = entry.offset;
1090 dst->length = entry.length;
1091 dst->kind = entry.kind;
1092 if (_swap)
1093 swapStruct(*dst);
1094 offset += sizeof(data_in_code_entry);
1095 }
1096}
1097
Nick Kledzike34182f2013-11-06 21:36:55 +00001098void MachOFileLayout::writeSymbolTable() {
1099 // Write symbol table and symbol strings in parallel.
1100 uint32_t symOffset = _startOfSymbols;
1101 uint32_t strOffset = _startOfSymbolStrings;
Pete Cooper5559b242016-08-08 23:20:04 +00001102 // Reserve n_strx offset of zero to mean no name.
1103 _buffer[strOffset++] = ' ';
1104 _buffer[strOffset++] = '\0';
Lang Hames436f7d62016-07-27 22:55:30 +00001105 appendSymbols(_file.stabsSymbols, symOffset, strOffset);
Nick Kledzike34182f2013-11-06 21:36:55 +00001106 appendSymbols(_file.localSymbols, symOffset, strOffset);
1107 appendSymbols(_file.globalSymbols, symOffset, strOffset);
1108 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
1109 // Write indirect symbol table array.
1110 uint32_t *indirects = reinterpret_cast<uint32_t*>
1111 (&_buffer[_startOfIndirectSymbols]);
1112 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1113 // Object files have sections in same order as input normalized file.
1114 for (const Section &section : _file.sections) {
1115 for (uint32_t index : section.indirectSymbols) {
1116 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001117 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001118 else
1119 *indirects++ = index;
1120 }
1121 }
1122 } else {
1123 // Final linked images must sort sections from normalized file.
1124 for (const Segment &seg : _file.segments) {
1125 SegExtraInfo &segInfo = _segInfo[&seg];
1126 for (const Section *section : segInfo.sections) {
1127 for (uint32_t index : section->indirectSymbols) {
1128 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001129 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001130 else
1131 *indirects++ = index;
1132 }
1133 }
1134 }
1135 }
1136}
1137
1138void MachOFileLayout::writeRebaseInfo() {
1139 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
1140}
1141
1142void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001143 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001144 _bindingInfo.bytes(), _bindingInfo.size());
1145}
1146
1147void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001148 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001149 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1150}
1151
Nick Kledzik141330a2014-09-03 19:52:50 +00001152void MachOFileLayout::writeExportInfo() {
1153 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1154}
1155
Nick Kledzike34182f2013-11-06 21:36:55 +00001156void MachOFileLayout::buildLinkEditInfo() {
1157 buildRebaseInfo();
1158 buildBindInfo();
1159 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001160 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001161 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001162 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +00001163 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001164}
1165
1166void MachOFileLayout::buildSectionRelocations() {
1167
1168}
1169
1170void MachOFileLayout::buildRebaseInfo() {
1171 // TODO: compress rebasing info.
1172 for (const RebaseLocation& entry : _file.rebasingInfo) {
1173 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001174 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001175 | entry.segIndex);
1176 _rebaseInfo.append_uleb128(entry.segOffset);
1177 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1178 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001179 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001180 _rebaseInfo.align(_is64 ? 8 : 4);
1181}
1182
1183void MachOFileLayout::buildBindInfo() {
1184 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001185 uint64_t lastAddend = 0;
Pete Cooper21f475e2016-08-11 20:37:02 +00001186 int lastOrdinal = 0x80000000;
1187 StringRef lastSymbolName;
1188 BindType lastType = (BindType)0;
1189 Hex32 lastSegOffset = ~0U;
1190 uint8_t lastSegIndex = (uint8_t)~0U;
Nick Kledzike34182f2013-11-06 21:36:55 +00001191 for (const BindLocation& entry : _file.bindingInfo) {
Pete Cooper21f475e2016-08-11 20:37:02 +00001192 if (entry.ordinal != lastOrdinal) {
1193 if (entry.ordinal <= 0)
1194 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1195 (entry.ordinal & BIND_IMMEDIATE_MASK));
1196 else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
1197 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1198 entry.ordinal);
1199 else {
1200 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1201 _bindingInfo.append_uleb128(entry.ordinal);
1202 }
1203 lastOrdinal = entry.ordinal;
1204 }
1205
1206 if (lastSymbolName != entry.symbolName) {
1207 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1208 _bindingInfo.append_string(entry.symbolName);
1209 lastSymbolName = entry.symbolName;
1210 }
1211
1212 if (lastType != entry.kind) {
1213 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
1214 lastType = entry.kind;
1215 }
1216
1217 if (lastSegIndex != entry.segIndex || lastSegOffset != entry.segOffset) {
1218 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
1219 | entry.segIndex);
1220 _bindingInfo.append_uleb128(entry.segOffset);
1221 lastSegIndex = entry.segIndex;
1222 lastSegOffset = entry.segOffset;
1223 }
Nick Kledzikf373c772014-11-11 01:31:18 +00001224 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001225 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1226 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001227 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001228 }
1229 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1230 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001231 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001232 _bindingInfo.align(_is64 ? 8 : 4);
1233}
1234
1235void MachOFileLayout::buildLazyBindInfo() {
1236 for (const BindLocation& entry : _file.lazyBindingInfo) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001237 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001238 | entry.segIndex);
Pete Cooper1ed8f1f2016-08-11 20:59:27 +00001239 _lazyBindingInfo.append_uleb128(entry.segOffset);
1240 if (entry.ordinal <= 0)
Lang Hames5c692002015-09-28 20:25:14 +00001241 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
Pete Cooper1ed8f1f2016-08-11 20:59:27 +00001242 (entry.ordinal & BIND_IMMEDIATE_MASK));
1243 else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
1244 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1245 entry.ordinal);
1246 else {
1247 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1248 _lazyBindingInfo.append_uleb128(entry.ordinal);
1249 }
1250 // FIXME: We need to | the opcode here with flags.
Nick Kledzike34182f2013-11-06 21:36:55 +00001251 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1252 _lazyBindingInfo.append_string(entry.symbolName);
1253 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001254 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001255 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001256 _lazyBindingInfo.align(_is64 ? 8 : 4);
1257}
1258
Pete Coopere420dd42016-01-25 21:50:54 +00001259void TrieNode::addSymbol(const Export& entry,
1260 BumpPtrAllocator &allocator,
1261 std::vector<TrieNode*> &allNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001262 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1263 for (TrieEdge &edge : _children) {
1264 StringRef edgeStr = edge._subString;
1265 if (partialStr.startswith(edgeStr)) {
1266 // Already have matching edge, go down that path.
1267 edge._child->addSymbol(entry, allocator, allNodes);
1268 return;
1269 }
Kazuaki Ishizaki7ae3d332020-01-06 10:21:05 -08001270 // See if string has common prefix with existing edge.
Nick Kledzik141330a2014-09-03 19:52:50 +00001271 for (int n=edgeStr.size()-1; n > 0; --n) {
1272 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1273 // Splice in new node: was A -> C, now A -> B -> C
1274 StringRef bNodeStr = edge._child->_cummulativeString;
1275 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
Eugene Zelenko41547942015-11-10 22:37:38 +00001276 auto *bNode = new (allocator) TrieNode(bNodeStr);
Nick Kledzik141330a2014-09-03 19:52:50 +00001277 allNodes.push_back(bNode);
1278 TrieNode* cNode = edge._child;
1279 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1280 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1281 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1282 << "splice in TrieNode('" << bNodeStr
1283 << "') between edge '"
1284 << abEdgeStr << "' and edge='"
1285 << bcEdgeStr<< "'\n");
1286 TrieEdge& abEdge = edge;
1287 abEdge._subString = abEdgeStr;
1288 abEdge._child = bNode;
Eugene Zelenko41547942015-11-10 22:37:38 +00001289 auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001290 bNode->_children.insert(bNode->_children.end(), bcEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001291 bNode->addSymbol(entry, allocator, allNodes);
1292 return;
1293 }
1294 }
1295 }
1296 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1297 assert(entry.otherOffset != 0);
1298 }
1299 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1300 assert(entry.otherOffset != 0);
1301 }
1302 // No commonality with any existing child, make a new edge.
Eugene Zelenko41547942015-11-10 22:37:38 +00001303 auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1304 auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001305 _children.insert(_children.end(), newEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001306 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1307 << "new TrieNode('" << entry.name << "') with edge '"
1308 << partialStr << "' from node='"
1309 << _cummulativeString << "'\n");
1310 newNode->_address = entry.offset;
1311 newNode->_flags = entry.flags | entry.kind;
1312 newNode->_other = entry.otherOffset;
1313 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1314 newNode->_importedName = entry.otherName.copy(allocator);
1315 newNode->_hasExportInfo = true;
1316 allNodes.push_back(newNode);
1317}
1318
Pete Cooperd0de3682016-08-05 21:37:12 +00001319void TrieNode::addOrderedNodes(const Export& entry,
1320 std::vector<TrieNode*> &orderedNodes) {
1321 if (!_ordered) {
1322 orderedNodes.push_back(this);
1323 _ordered = true;
1324 }
1325
1326 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1327 for (TrieEdge &edge : _children) {
1328 StringRef edgeStr = edge._subString;
1329 if (partialStr.startswith(edgeStr)) {
1330 // Already have matching edge, go down that path.
1331 edge._child->addOrderedNodes(entry, orderedNodes);
1332 return;
1333 }
1334 }
1335}
1336
Pete Coopere420dd42016-01-25 21:50:54 +00001337bool TrieNode::updateOffset(uint32_t& offset) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001338 uint32_t nodeSize = 1; // Length when no export info
1339 if (_hasExportInfo) {
1340 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1341 nodeSize = llvm::getULEB128Size(_flags);
1342 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1343 nodeSize += _importedName.size();
1344 ++nodeSize; // Trailing zero in imported name.
1345 } else {
1346 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1347 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1348 nodeSize += llvm::getULEB128Size(_other);
1349 }
1350 // Overall node size so far is uleb128 of export info + actual export info.
1351 nodeSize += llvm::getULEB128Size(nodeSize);
1352 }
1353 // Compute size of all child edges.
Kazuaki Ishizaki7ae3d332020-01-06 10:21:05 -08001354 ++nodeSize; // Byte for number of children.
Nick Kledzik141330a2014-09-03 19:52:50 +00001355 for (TrieEdge &edge : _children) {
1356 nodeSize += edge._subString.size() + 1 // String length.
1357 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1358 }
1359 // On input, 'offset' is new prefered location for this node.
1360 bool result = (_trieOffset != offset);
1361 // Store new location in node object for use by parents.
1362 _trieOffset = offset;
1363 // Update offset for next iteration.
1364 offset += nodeSize;
1365 // Return true if _trieOffset was changed.
1366 return result;
1367}
1368
Pete Coopere420dd42016-01-25 21:50:54 +00001369void TrieNode::appendToByteBuffer(ByteBuffer &out) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001370 if (_hasExportInfo) {
1371 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1372 if (!_importedName.empty()) {
1373 // nodes with re-export info: size, flags, ordinal, import-name
1374 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1375 + llvm::getULEB128Size(_other)
1376 + _importedName.size() + 1;
1377 assert(nodeSize < 256);
1378 out.append_byte(nodeSize);
1379 out.append_uleb128(_flags);
1380 out.append_uleb128(_other);
1381 out.append_string(_importedName);
1382 } else {
1383 // nodes without re-export info: size, flags, ordinal, empty-string
1384 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1385 + llvm::getULEB128Size(_other) + 1;
1386 assert(nodeSize < 256);
1387 out.append_byte(nodeSize);
1388 out.append_uleb128(_flags);
1389 out.append_uleb128(_other);
1390 out.append_byte(0);
1391 }
1392 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1393 // Nodes with export info: size, flags, address, other
1394 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1395 + llvm::getULEB128Size(_address)
1396 + llvm::getULEB128Size(_other);
1397 assert(nodeSize < 256);
1398 out.append_byte(nodeSize);
1399 out.append_uleb128(_flags);
1400 out.append_uleb128(_address);
1401 out.append_uleb128(_other);
1402 } else {
1403 // Nodes with export info: size, flags, address
1404 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1405 + llvm::getULEB128Size(_address);
1406 assert(nodeSize < 256);
1407 out.append_byte(nodeSize);
1408 out.append_uleb128(_flags);
1409 out.append_uleb128(_address);
1410 }
1411 } else {
1412 // Node with no export info.
1413 uint32_t nodeSize = 0;
1414 out.append_byte(nodeSize);
1415 }
1416 // Add number of children.
1417 assert(_children.size() < 256);
1418 out.append_byte(_children.size());
1419 // Append each child edge substring and node offset.
1420 for (TrieEdge &edge : _children) {
1421 out.append_string(edge._subString);
1422 out.append_uleb128(edge._child->_trieOffset);
1423 }
1424}
1425
1426void MachOFileLayout::buildExportTrie() {
1427 if (_file.exportInfo.empty())
1428 return;
1429
1430 // For all temporary strings and objects used building trie.
1431 BumpPtrAllocator allocator;
1432
1433 // Build trie of all exported symbols.
Eugene Zelenko41547942015-11-10 22:37:38 +00001434 auto *rootNode = new (allocator) TrieNode(StringRef());
Nick Kledzik141330a2014-09-03 19:52:50 +00001435 std::vector<TrieNode*> allNodes;
1436 allNodes.reserve(_file.exportInfo.size()*2);
1437 allNodes.push_back(rootNode);
1438 for (const Export& entry : _file.exportInfo) {
1439 rootNode->addSymbol(entry, allocator, allNodes);
1440 }
1441
Pete Cooperd0de3682016-08-05 21:37:12 +00001442 std::vector<TrieNode*> orderedNodes;
1443 orderedNodes.reserve(allNodes.size());
1444
1445 for (const Export& entry : _file.exportInfo)
1446 rootNode->addOrderedNodes(entry, orderedNodes);
1447
Nick Kledzik141330a2014-09-03 19:52:50 +00001448 // Assign each node in the vector an offset in the trie stream, iterating
1449 // until all uleb128 sizes have stabilized.
1450 bool more;
1451 do {
1452 uint32_t offset = 0;
1453 more = false;
Pete Cooperd0de3682016-08-05 21:37:12 +00001454 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001455 if (node->updateOffset(offset))
1456 more = true;
1457 }
1458 } while (more);
1459
1460 // Serialize trie to ByteBuffer.
Pete Cooperd0de3682016-08-05 21:37:12 +00001461 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001462 node->appendToByteBuffer(_exportTrie);
1463 }
1464 _exportTrie.align(_is64 ? 8 : 4);
1465}
1466
Nick Kledzike34182f2013-11-06 21:36:55 +00001467void MachOFileLayout::computeSymbolTableSizes() {
1468 // MachO symbol tables have three ranges: locals, globals, and undefines
1469 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Lang Hames436f7d62016-07-27 22:55:30 +00001470 _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
1471 + _file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001472 + _file.globalSymbols.size()
1473 + _file.undefinedSymbols.size());
Pete Cooper5559b242016-08-08 23:20:04 +00001474 // Always reserve 1-byte for the empty string and 1-byte for its terminator.
1475 _symbolStringPoolSize = 2;
Lang Hames436f7d62016-07-27 22:55:30 +00001476 for (const Symbol &sym : _file.stabsSymbols) {
1477 _symbolStringPoolSize += (sym.name.size()+1);
1478 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001479 for (const Symbol &sym : _file.localSymbols) {
1480 _symbolStringPoolSize += (sym.name.size()+1);
1481 }
1482 for (const Symbol &sym : _file.globalSymbols) {
1483 _symbolStringPoolSize += (sym.name.size()+1);
1484 }
1485 for (const Symbol &sym : _file.undefinedSymbols) {
1486 _symbolStringPoolSize += (sym.name.size()+1);
1487 }
1488 _symbolTableLocalsStartIndex = 0;
Lang Hames436f7d62016-07-27 22:55:30 +00001489 _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
1490 _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001491 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001492 + _file.globalSymbols.size();
1493
1494 _indirectSymbolTableCount = 0;
1495 for (const Section &sect : _file.sections) {
1496 _indirectSymbolTableCount += sect.indirectSymbols.size();
1497 }
1498}
1499
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001500void MachOFileLayout::computeFunctionStartsSize() {
1501 _functionStartsSize = _file.functionStarts.size();
1502}
1503
Nick Kledzik21921372014-07-24 23:06:56 +00001504void MachOFileLayout::computeDataInCodeSize() {
1505 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1506}
Nick Kledzike34182f2013-11-06 21:36:55 +00001507
1508void MachOFileLayout::writeLinkEditContent() {
1509 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1510 writeRelocations();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001511 writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +00001512 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001513 writeSymbolTable();
1514 } else {
1515 writeRebaseInfo();
1516 writeBindingInfo();
1517 writeLazyBindingInfo();
1518 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001519 writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001520 writeFunctionStartsInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001521 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001522 writeSymbolTable();
1523 }
1524}
1525
Pete Cooperfefbd222016-03-30 23:10:39 +00001526llvm::Error MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001527 // Check for pending error from constructor.
1528 if (_ec)
Pete Cooperfefbd222016-03-30 23:10:39 +00001529 return llvm::errorCodeToError(_ec);
Nick Kledzike34182f2013-11-06 21:36:55 +00001530 // Create FileOutputBuffer with calculated size.
Nick Kledzike34182f2013-11-06 21:36:55 +00001531 unsigned flags = 0;
1532 if (_file.fileType != llvm::MachO::MH_OBJECT)
1533 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolaf7a57292017-11-08 01:05:52 +00001534 Expected<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001535 llvm::FileOutputBuffer::create(path, size(), flags);
Rafael Espindolaf7a57292017-11-08 01:05:52 +00001536 if (Error E = fobOrErr.takeError())
1537 return E;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001538 std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
Nick Kledzike34182f2013-11-06 21:36:55 +00001539 // Write content.
1540 _buffer = fob->getBufferStart();
1541 writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +00001542 if (auto ec = writeLoadCommands())
Pete Cooperdc59c792016-03-31 00:38:02 +00001543 return ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001544 writeSectionContent();
1545 writeLinkEditContent();
Rafael Espindola5f903f32017-11-08 01:50:34 +00001546 if (Error E = fob->commit())
1547 return E;
Nick Kledzike34182f2013-11-06 21:36:55 +00001548
Mehdi Aminic1edf562016-11-11 04:29:25 +00001549 return llvm::Error::success();
Nick Kledzike34182f2013-11-06 21:36:55 +00001550}
1551
Nick Kledzike34182f2013-11-06 21:36:55 +00001552/// Takes in-memory normalized view and writes a mach-o object file.
Pete Cooperfefbd222016-03-30 23:10:39 +00001553llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
Rui Ueyama7f8ca6e2019-04-17 01:47:16 +00001554 MachOFileLayout layout(file, false);
Nick Kledzike34182f2013-11-06 21:36:55 +00001555 return layout.writeBinary(path);
1556}
1557
Nick Kledzike34182f2013-11-06 21:36:55 +00001558} // namespace normalized
1559} // namespace mach_o
1560} // namespace lld