blob: b8c739627c41a919476c572cd1a1595a526a087a [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"
Pete Coopere420dd42016-01-25 21:50:54 +000028#include "llvm/ADT/ilist.h"
29#include "llvm/ADT/ilist_node.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000030#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringRef.h"
33#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"
40#include "llvm/Support/MachO.h"
41#include "llvm/Support/MemoryBuffer.h"
42#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000043#include <functional>
Nick Kledzik07ba5122014-12-02 01:50:44 +000044#include <list>
Nick Kledzike34182f2013-11-06 21:36:55 +000045#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000046#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000047
48using namespace llvm::MachO;
49
50namespace lld {
51namespace mach_o {
52namespace normalized {
53
Pete Coopere420dd42016-01-25 21:50:54 +000054struct TrieNode; // Forward declaration.
55
56struct TrieEdge : public llvm::ilist_node<TrieEdge> {
57 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
58
59 StringRef _subString;
60 struct TrieNode *_child;
61};
62
63} // namespace normalized
64} // namespace mach_o
65} // namespace lld
66
67
68namespace llvm {
69 using lld::mach_o::normalized::TrieEdge;
70 template <>
71 struct ilist_traits<TrieEdge>
72 : public ilist_default_traits<TrieEdge> {
73 private:
74 mutable ilist_half_node<TrieEdge> Sentinel;
75 public:
76 TrieEdge *createSentinel() const {
77 return static_cast<TrieEdge*>(&Sentinel);
78 }
79 void destroySentinel(TrieEdge *) const {}
80
81 TrieEdge *provideInitialHead() const { return createSentinel(); }
82 TrieEdge *ensureHead(TrieEdge*) const { return createSentinel(); }
83 static void noteHead(TrieEdge*, TrieEdge*) {}
84 void deleteNode(TrieEdge *N) {}
85
86 private:
87 void createNode(const TrieEdge &);
88 };
89} // namespace llvm
90
91
92namespace lld {
93namespace mach_o {
94namespace normalized {
95
96struct TrieNode {
97 typedef llvm::ilist<TrieEdge> TrieEdgeList;
98
99 TrieNode(StringRef s)
100 : _cummulativeString(s), _address(0), _flags(0), _other(0),
101 _trieOffset(0), _hasExportInfo(false) {}
102 ~TrieNode() = default;
103
104 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
105 std::vector<TrieNode *> &allNodes);
106 bool updateOffset(uint32_t &offset);
107 void appendToByteBuffer(ByteBuffer &out);
108
109private:
110 StringRef _cummulativeString;
111 TrieEdgeList _children;
112 uint64_t _address;
113 uint64_t _flags;
114 uint64_t _other;
115 StringRef _importedName;
116 uint32_t _trieOffset;
117 bool _hasExportInfo;
118};
119
Nick Kledzike34182f2013-11-06 21:36:55 +0000120/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000121/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000122class MachOFileLayout {
123public:
Joey Goulyb275d7f2013-12-23 23:29:50 +0000124 /// All layout computation is done in the constructor.
125 MachOFileLayout(const NormalizedFile &file);
126
Nick Kledzike34182f2013-11-06 21:36:55 +0000127 /// Returns the final file size as computed in the constructor.
128 size_t size() const;
129
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000130 // Returns size of the mach_header and load commands.
131 size_t headerAndLoadCommandsSize() const;
132
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000133 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +0000134 /// path. This does not have a stream interface because the generated
135 /// file may need the 'x' bit set.
Pete Cooperfefbd222016-03-30 23:10:39 +0000136 llvm::Error writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000137
Nick Kledzike34182f2013-11-06 21:36:55 +0000138private:
139 uint32_t loadCommandsSize(uint32_t &count);
140 void buildFileOffsets();
141 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000142 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +0000143 void writeSectionContent();
144 void writeRelocations();
145 void writeSymbolTable();
146 void writeRebaseInfo();
147 void writeBindingInfo();
148 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000149 void writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000150 void writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +0000151 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000152 void writeLinkEditContent();
153 void buildLinkEditInfo();
154 void buildRebaseInfo();
155 void buildBindInfo();
156 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000157 void buildExportTrie();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000158 void computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000159 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000160 void computeSymbolTableSizes();
161 void buildSectionRelocations();
162 void appendSymbols(const std::vector<Symbol> &symbols,
163 uint32_t &symOffset, uint32_t &strOffset);
164 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
165 uint32_t indirectSymbolElementSize(const Section &sect);
166
Nick Kledzik29f749e2013-11-09 00:07:28 +0000167 // For use as template parameter to load command methods.
168 struct MachO64Trait {
169 typedef llvm::MachO::segment_command_64 command;
170 typedef llvm::MachO::section_64 section;
171 enum { LC = llvm::MachO::LC_SEGMENT_64 };
172 };
173
174 // For use as template parameter to load command methods.
175 struct MachO32Trait {
176 typedef llvm::MachO::segment_command command;
177 typedef llvm::MachO::section section;
178 enum { LC = llvm::MachO::LC_SEGMENT };
179 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000180
Nick Kledzik29f749e2013-11-09 00:07:28 +0000181 template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000182 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
183 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000184
Nick Kledzike34182f2013-11-06 21:36:55 +0000185 uint32_t pointerAlign(uint32_t value);
186 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000187
Nick Kledzike34182f2013-11-06 21:36:55 +0000188 struct SegExtraInfo {
189 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000190 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000191 std::vector<const Section*> sections;
192 };
193 typedef std::map<const Segment*, SegExtraInfo> SegMap;
194 struct SectionExtraInfo {
195 uint32_t fileOffset;
196 };
197 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000198
Nick Kledzike34182f2013-11-06 21:36:55 +0000199 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000200 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000201 uint8_t *_buffer;
202 const bool _is64;
203 const bool _swap;
204 const bool _bigEndianArch;
205 uint64_t _seg1addr;
206 uint32_t _startOfLoadCommands;
207 uint32_t _countOfLoadCommands;
208 uint32_t _endOfLoadCommands;
209 uint32_t _startOfRelocations;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000210 uint32_t _startOfFunctionStarts;
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;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000221 uint32_t _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000222 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000223 uint32_t _indirectSymbolTableCount;
224 // Used in object file creation only
225 uint32_t _startOfSectionsContent;
226 uint32_t _endOfSectionsContent;
227 // Used in final linked image only
228 uint32_t _startOfLinkEdit;
229 uint32_t _startOfRebaseInfo;
230 uint32_t _endOfRebaseInfo;
231 uint32_t _startOfBindingInfo;
232 uint32_t _endOfBindingInfo;
233 uint32_t _startOfLazyBindingInfo;
234 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000235 uint32_t _startOfExportTrie;
236 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000237 uint32_t _endOfLinkEdit;
238 uint64_t _addressOfLinkEdit;
239 SegMap _segInfo;
240 SectionMap _sectInfo;
241 ByteBuffer _rebaseInfo;
242 ByteBuffer _bindingInfo;
243 ByteBuffer _lazyBindingInfo;
244 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000245 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000246};
247
248size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
249 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000250 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000251}
252
253StringRef MachOFileLayout::dyldPath() {
254 return "/usr/lib/dyld";
255}
256
257uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
Rui Ueyama489a8062016-01-14 20:53:50 +0000258 return llvm::alignTo(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000259}
Nick Kledzike34182f2013-11-06 21:36:55 +0000260
261
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000262size_t MachOFileLayout::headerAndLoadCommandsSize() const {
263 return _endOfLoadCommands;
264}
Nick Kledzike34182f2013-11-06 21:36:55 +0000265
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000266MachOFileLayout::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;
Pete Cooperceee5de2016-02-04 02:16:08 +0000283 if (file.hasMinVersionLoadCommand) {
284 _endOfLoadCommands += sizeof(version_min_command);
285 _countOfLoadCommands++;
286 }
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000287 if (!_file.functionStarts.empty()) {
288 _endOfLoadCommands += sizeof(linkedit_data_command);
289 _countOfLoadCommands++;
290 }
Pete Cooper9b28a452016-02-09 02:10:39 +0000291 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000292 _endOfLoadCommands += sizeof(linkedit_data_command);
293 _countOfLoadCommands++;
294 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000295 // Assign file offsets to each section.
Nick Kledzike34182f2013-11-06 21:36:55 +0000296 _startOfSectionsContent = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000297 unsigned relocCount = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000298 uint64_t offset = _startOfSectionsContent;
Nick Kledzike34182f2013-11-06 21:36:55 +0000299 for (const Section &sect : file.sections) {
Lang Hamesac2adce2015-12-11 23:25:09 +0000300 if (isZeroFillSection(sect.type))
301 _sectInfo[&sect].fileOffset = 0;
302 else {
Rui Ueyama489a8062016-01-14 20:53:50 +0000303 offset = llvm::alignTo(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000304 _sectInfo[&sect].fileOffset = offset;
305 offset += sect.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000306 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000307 relocCount += sect.relocations.size();
308 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000309 _endOfSectionsContent = offset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000310
Nick Kledzike34182f2013-11-06 21:36:55 +0000311 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000312 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000313 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000314
Nick Kledzike34182f2013-11-06 21:36:55 +0000315 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000316 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000317 _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
318 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000319 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000320 // Add Indirect symbol table.
321 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
322 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000323 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000324 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000325 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000326 + pointerAlign(_symbolStringPoolSize);
327 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000328 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000329 llvm::dbgs() << "MachOFileLayout()\n"
330 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
331 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
332 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
333 << " startOfRelocations=" << _startOfRelocations << "\n"
334 << " startOfSymbols=" << _startOfSymbols << "\n"
335 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
336 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
337 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
338 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
339 } else {
340 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000341 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000342 + loadCommandsSize(_countOfLoadCommands);
343
344 // Assign section file offsets.
345 buildFileOffsets();
346 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000347
Nick Kledzike34182f2013-11-06 21:36:55 +0000348 // LINKEDIT of final linked images has in order:
349 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000350 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000351 _startOfRebaseInfo = _startOfLinkEdit;
352 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
353 _startOfBindingInfo = _endOfRebaseInfo;
354 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
355 _startOfLazyBindingInfo = _endOfBindingInfo;
356 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000357 _startOfExportTrie = _endOfLazyBindingInfo;
358 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000359 _startOfFunctionStarts = _endOfExportTrie;
360 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000361 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000362 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000363 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000364 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000365 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000366 + pointerAlign(_symbolStringPoolSize);
367 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000368 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000369 llvm::dbgs() << "MachOFileLayout()\n"
370 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
371 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
372 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
373 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
374 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
375 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
376 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
377 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
378 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
379 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000380 << " startOfExportTrie=" << _startOfExportTrie << "\n"
381 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000382 << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000383 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000384 << " startOfSymbols=" << _startOfSymbols << "\n"
385 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
386 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
387 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
388 }
389}
390
391uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
392 uint32_t size = 0;
393 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000394
395 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000396 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
397 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
398
399 // Add LC_SEGMENT for each segment.
400 size += _file.segments.size() * segCommandSize;
401 count += _file.segments.size();
402 // Add section record for each section.
403 size += _file.sections.size() * sectionSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000404
Tim Northover301c4e62014-07-01 08:15:41 +0000405 // If creating a dylib, add LC_ID_DYLIB.
406 if (_file.fileType == llvm::MachO::MH_DYLIB) {
407 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
408 ++count;
409 }
410
Nick Kledzike34182f2013-11-06 21:36:55 +0000411 // Add LC_DYLD_INFO
412 size += sizeof(dyld_info_command);
413 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000414
Nick Kledzike34182f2013-11-06 21:36:55 +0000415 // Add LC_SYMTAB
416 size += sizeof(symtab_command);
417 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000418
Nick Kledzike34182f2013-11-06 21:36:55 +0000419 // Add LC_DYSYMTAB
420 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
421 size += sizeof(dysymtab_command);
422 ++count;
423 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000424
Pete Cooper354809e2016-02-03 22:28:29 +0000425 // If main executable add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000426 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
427 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
428 ++count;
Pete Cooper354809e2016-02-03 22:28:29 +0000429 }
430
431 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
432 // LC_VERSION_MIN_TVOS
433 if (_file.hasMinVersionLoadCommand) {
434 size += sizeof(version_min_command);
435 ++count;
436 }
437
Pete Cooper40576fa2016-02-04 02:45:23 +0000438 // Add LC_SOURCE_VERSION
439 size += sizeof(source_version_command);
440 ++count;
441
Pete Cooper354809e2016-02-03 22:28:29 +0000442 // If main executable add LC_MAIN
443 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000444 size += sizeof(entry_point_command);
445 ++count;
446 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000447
Nick Kledzike34182f2013-11-06 21:36:55 +0000448 // Add LC_LOAD_DYLIB for each dependent dylib.
449 for (const DependentDylib &dep : _file.dependentDylibs) {
450 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
451 ++count;
452 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000453
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000454 // Add LC_RPATH
455 for (const StringRef &path : _file.rpaths) {
Lang Hames2ed3bf92015-10-29 16:50:26 +0000456 size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000457 ++count;
458 }
459
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000460 // Add LC_FUNCTION_STARTS if needed
461 if (!_file.functionStarts.empty()) {
462 size += sizeof(linkedit_data_command);
463 ++count;
464 }
465
Pete Cooper9b28a452016-02-09 02:10:39 +0000466 // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries.
467 // FIXME: Zero length entries is only to match ld64. Should we change this?
468 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +0000469 size += sizeof(linkedit_data_command);
470 ++count;
471 }
472
Nick Kledzike34182f2013-11-06 21:36:55 +0000473 return size;
474}
475
476static bool overlaps(const Segment &s1, const Segment &s2) {
477 if (s2.address >= s1.address+s1.size)
478 return false;
479 if (s1.address >= s2.address+s2.size)
480 return false;
481 return true;
482}
483
484static bool overlaps(const Section &s1, const Section &s2) {
485 if (s2.address >= s1.address+s1.content.size())
486 return false;
487 if (s1.address >= s2.address+s2.content.size())
488 return false;
489 return true;
490}
491
492void MachOFileLayout::buildFileOffsets() {
493 // Verify no segments overlap
494 for (const Segment &sg1 : _file.segments) {
495 for (const Segment &sg2 : _file.segments) {
496 if (&sg1 == &sg2)
497 continue;
498 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000499 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000500 return;
501 }
502 }
503 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000504
505 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000506 for (const Section &s1 : _file.sections) {
507 for (const Section &s2 : _file.sections) {
508 if (&s1 == &s2)
509 continue;
510 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000511 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000512 return;
513 }
514 }
515 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000516
Nick Kledzike34182f2013-11-06 21:36:55 +0000517 // Build side table of extra info about segments and sections.
518 SegExtraInfo t;
519 t.fileOffset = 0;
520 for (const Segment &sg : _file.segments) {
521 _segInfo[&sg] = t;
522 }
523 SectionExtraInfo t2;
524 t2.fileOffset = 0;
525 // Assign sections to segments.
526 for (const Section &s : _file.sections) {
527 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000528 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000529 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000530 if (sg.name.equals(s.segmentName)) {
531 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000532 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000533 _segInfo[&sg].sections.push_back(&s);
534 foundSegment = true;
535 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000536 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000537 }
538 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000539 if (!foundSegment) {
540 _ec = make_error_code(llvm::errc::executable_format_error);
541 return;
542 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000543 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000544
Nick Kledzike34182f2013-11-06 21:36:55 +0000545 // Assign file offsets.
546 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000547 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000548 llvm::dbgs() << "buildFileOffsets()\n");
549 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000550 _segInfo[&sg].fileOffset = fileOffset;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000551 if ((_seg1addr == INT64_MAX) && sg.init_access)
Nick Kledzike34182f2013-11-06 21:36:55 +0000552 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000553 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000554 llvm::dbgs() << " segment=" << sg.name
555 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000556
557 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000558 // A segment that is not zero-fill must use a least one page of disk space.
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000559 if (sg.init_access)
Nick Kledzik761d6542014-10-24 22:19:22 +0000560 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000561 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000562 uint32_t sectOffset = s->address - sg.address;
563 uint32_t sectFileSize =
Lang Hamesac2adce2015-12-11 23:25:09 +0000564 isZeroFillSection(s->type) ? 0 : s->content.size();
Tim Northover08d6a7b2014-06-30 09:49:30 +0000565 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
566
567 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000568 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000569 llvm::dbgs() << " section=" << s->sectionName
570 << ", fileOffset=" << fileOffset << "\n");
571 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000572
Pete Cooper353652f2016-02-06 00:14:15 +0000573 // round up all segments to page aligned, except __LINKEDIT
574 if (!sg.name.equals("__LINKEDIT")) {
575 _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
576 fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
577 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000578 _addressOfLinkEdit = sg.address + sg.size;
579 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000580 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000581}
582
Nick Kledzike34182f2013-11-06 21:36:55 +0000583size_t MachOFileLayout::size() const {
584 return _endOfSymbolStrings;
585}
586
587void MachOFileLayout::writeMachHeader() {
Pete Cooper8563e5a2016-02-04 20:43:43 +0000588 auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
589 // dynamic x86 executables on newer OS version should also set the
590 // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
591 // FIXME: Check that this is a dynamic executable, not a static one.
592 if (_file.fileType == llvm::MachO::MH_EXECUTE &&
593 cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
594 _file.os == MachOLinkingContext::OS::macOSX) {
595 uint32_t version;
596 bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
597 if (!failed && _file.minOSverson >= version)
598 cpusubtype |= CPU_SUBTYPE_LIB64;
599 }
600
Nick Kledzike34182f2013-11-06 21:36:55 +0000601 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
602 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
603 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
Pete Cooper8563e5a2016-02-04 20:43:43 +0000604 mh->cpusubtype = cpusubtype;
Nick Kledzike34182f2013-11-06 21:36:55 +0000605 mh->filetype = _file.fileType;
606 mh->ncmds = _countOfLoadCommands;
607 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
608 mh->flags = _file.flags;
609 if (_swap)
610 swapStruct(*mh);
611}
612
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000613uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000614 uint32_t &index) {
615 if (sect.indirectSymbols.empty())
616 return 0;
617 uint32_t result = index;
618 index += sect.indirectSymbols.size();
619 return result;
620}
621
622uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
623 if (sect.indirectSymbols.empty())
624 return 0;
625 if (sect.type != S_SYMBOL_STUBS)
626 return 0;
627 return sect.content.size() / sect.indirectSymbols.size();
628}
629
Nick Kledzik29f749e2013-11-09 00:07:28 +0000630template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000631std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000632 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
633 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000634 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000635 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000636 uint8_t *next = lc + seg->cmdsize;
637 memset(seg->segname, 0, 16);
638 seg->vmaddr = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000639 seg->vmsize = _file.sections.back().address
640 + _file.sections.back().content.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000641 seg->fileoff = _endOfLoadCommands;
642 seg->filesize = seg->vmsize;
643 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
644 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
645 seg->nsects = _file.sections.size();
646 seg->flags = 0;
647 if (_swap)
648 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000649 typename T::section *sout = reinterpret_cast<typename T::section*>
650 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000651 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000652 uint32_t indirectSymRunningIndex = 0;
653 for (const Section &sin : _file.sections) {
654 setString16(sin.sectionName, sout->sectname);
655 setString16(sin.segmentName, sout->segname);
656 sout->addr = sin.address;
657 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000658 sout->offset = _sectInfo[&sin].fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000659 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000660 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
661 sout->nreloc = sin.relocations.size();
662 sout->flags = sin.type | sin.attributes;
663 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
664 sout->reserved2 = indirectSymbolElementSize(sin);
665 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000666 if (_swap)
667 swapStruct(*sout);
668 ++sout;
669 }
670 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000671 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000672}
673
Nick Kledzik29f749e2013-11-09 00:07:28 +0000674template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000675std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000676 uint32_t indirectSymRunningIndex = 0;
677 for (const Segment &seg : _file.segments) {
Pete Cooper353652f2016-02-06 00:14:15 +0000678 // Link edit has no sections and a custom range of address, so handle it
679 // specially.
Nick Kledzike34182f2013-11-06 21:36:55 +0000680 SegExtraInfo &segInfo = _segInfo[&seg];
Pete Cooper353652f2016-02-06 00:14:15 +0000681 if (seg.name.equals("__LINKEDIT")) {
682 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
683 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
684 cmd->cmd = T::LC;
685 cmd->cmdsize = sizeof(typename T::command);
686 uint8_t *next = lc + cmd->cmdsize;
687 setString16("__LINKEDIT", cmd->segname);
688 cmd->vmaddr = _addressOfLinkEdit;
689 cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
690 cmd->fileoff = _startOfLinkEdit;
691 cmd->filesize = linkeditSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000692 cmd->initprot = seg.init_access;
693 cmd->maxprot = seg.max_access;
Pete Cooper353652f2016-02-06 00:14:15 +0000694 cmd->nsects = 0;
695 cmd->flags = 0;
696 if (_swap)
697 swapStruct(*cmd);
698 lc = next;
699 continue;
700 }
701 // Write segment command with trailing sections.
Nick Kledzik29f749e2013-11-09 00:07:28 +0000702 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
703 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000704 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000705 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000706 uint8_t *next = lc + cmd->cmdsize;
707 setString16(seg.name, cmd->segname);
708 cmd->vmaddr = seg.address;
709 cmd->vmsize = seg.size;
710 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000711 cmd->filesize = segInfo.fileSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000712 cmd->initprot = seg.init_access;
713 cmd->maxprot = seg.max_access;
Nick Kledzike34182f2013-11-06 21:36:55 +0000714 cmd->nsects = segInfo.sections.size();
715 cmd->flags = 0;
716 if (_swap)
717 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000718 typename T::section *sect = reinterpret_cast<typename T::section*>
719 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000720 for (const Section *section : segInfo.sections) {
721 setString16(section->sectionName, sect->sectname);
722 setString16(section->segmentName, sect->segname);
723 sect->addr = section->address;
724 sect->size = section->content.size();
Lang Hamesac2adce2015-12-11 23:25:09 +0000725 if (isZeroFillSection(section->type))
Nick Kledzikb072c362014-11-18 00:30:29 +0000726 sect->offset = 0;
727 else
728 sect->offset = section->address - seg.address + segInfo.fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000729 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000730 sect->reloff = 0;
731 sect->nreloc = 0;
732 sect->flags = section->type | section->attributes;
733 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
734 sect->reserved2 = indirectSymbolElementSize(*section);
735 if (_swap)
736 swapStruct(*sect);
737 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000738 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000739 lc = reinterpret_cast<uint8_t*>(next);
740 }
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000741 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000742}
743
Pete Cooperceee5de2016-02-04 02:16:08 +0000744static void writeVersionMinLoadCommand(const NormalizedFile &_file,
745 bool _swap,
746 uint8_t *&lc) {
747 if (!_file.hasMinVersionLoadCommand)
748 return;
749 version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
750 switch (_file.os) {
751 case MachOLinkingContext::OS::unknown:
752 vm->cmd = _file.minOSVersionKind;
753 vm->cmdsize = sizeof(version_min_command);
754 vm->version = _file.minOSverson;
755 vm->sdk = 0;
756 break;
757 case MachOLinkingContext::OS::macOSX:
758 vm->cmd = LC_VERSION_MIN_MACOSX;
759 vm->cmdsize = sizeof(version_min_command);
760 vm->version = _file.minOSverson;
761 vm->sdk = _file.sdkVersion;
762 break;
763 case MachOLinkingContext::OS::iOS:
764 case MachOLinkingContext::OS::iOS_simulator:
765 vm->cmd = LC_VERSION_MIN_IPHONEOS;
766 vm->cmdsize = sizeof(version_min_command);
767 vm->version = _file.minOSverson;
768 vm->sdk = _file.sdkVersion;
769 break;
770 }
771 if (_swap)
772 swapStruct(*vm);
773 lc += sizeof(version_min_command);
774}
775
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000776std::error_code MachOFileLayout::writeLoadCommands() {
777 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000778 uint8_t *lc = &_buffer[_startOfLoadCommands];
779 if (_file.fileType == llvm::MachO::MH_OBJECT) {
780 // Object files have one unnamed segment which holds all sections.
781 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000782 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000783 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000784 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000785 // Add LC_SYMTAB with symbol table info
786 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
787 st->cmd = LC_SYMTAB;
788 st->cmdsize = sizeof(symtab_command);
789 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000790 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000791 + _file.undefinedSymbols.size();
792 st->stroff = _startOfSymbolStrings;
793 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
794 if (_swap)
795 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000796 lc += sizeof(symtab_command);
Pete Cooperceee5de2016-02-04 02:16:08 +0000797
798 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
799 // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
800 writeVersionMinLoadCommand(_file, _swap, lc);
801
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000802 // Add LC_FUNCTION_STARTS if needed.
803 if (_functionStartsSize != 0) {
804 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
805 dl->cmd = LC_FUNCTION_STARTS;
806 dl->cmdsize = sizeof(linkedit_data_command);
807 dl->dataoff = _startOfFunctionStarts;
808 dl->datasize = _functionStartsSize;
809 if (_swap)
810 swapStruct(*dl);
811 lc += sizeof(linkedit_data_command);
812 }
813
Pete Cooper9b28a452016-02-09 02:10:39 +0000814 // Add LC_DATA_IN_CODE if requested.
815 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000816 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
817 dl->cmd = LC_DATA_IN_CODE;
818 dl->cmdsize = sizeof(linkedit_data_command);
819 dl->dataoff = _startOfDataInCode;
820 dl->datasize = _dataInCodeSize;
821 if (_swap)
822 swapStruct(*dl);
823 lc += sizeof(linkedit_data_command);
824 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000825 } else {
826 // Final linked images have sections under segments.
827 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000828 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000829 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000830 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
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;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000874 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000875 + _file.undefinedSymbols.size();
876 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;
888 dst->nlocalsym = _file.localSymbols.size();
889 dst->iextdefsym = _symbolTableGlobalsStartIndex;
890 dst->nextdefsym = _file.globalSymbols.size();
891 dst->iundefsym = _symbolTableUndefinesStartIndex;
892 dst->nundefsym = _file.undefinedSymbols.size();
893 dst->tocoff = 0;
894 dst->ntoc = 0;
895 dst->modtaboff = 0;
896 dst->nmodtab = 0;
897 dst->extrefsymoff = 0;
898 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000899 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000900 dst->nindirectsyms = _indirectSymbolTableCount;
901 dst->extreloff = 0;
902 dst->nextrel = 0;
903 dst->locreloff = 0;
904 dst->nlocrel = 0;
905 if (_swap)
906 swapStruct(*dst);
907 lc += sizeof(dysymtab_command);
908 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000909
Pete Cooper354809e2016-02-03 22:28:29 +0000910 // If main executable, add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000911 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
912 // Build LC_LOAD_DYLINKER load command.
913 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
914 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
915 dl->cmd = LC_LOAD_DYLINKER;
916 dl->cmdsize = size;
917 dl->name = sizeof(dylinker_command); // offset
918 if (_swap)
919 swapStruct(*dl);
920 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
921 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
922 lc += size;
Pete Cooper354809e2016-02-03 22:28:29 +0000923 }
924
925 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
926 // LC_VERSION_MIN_TVOS
Pete Cooperceee5de2016-02-04 02:16:08 +0000927 writeVersionMinLoadCommand(_file, _swap, lc);
Pete Cooper354809e2016-02-03 22:28:29 +0000928
Pete Cooper40576fa2016-02-04 02:45:23 +0000929 // Add LC_SOURCE_VERSION
930 {
Pete Cooperb565bdf2016-03-23 22:00:09 +0000931 // Note, using a temporary here to appease UB as we may not be aligned
932 // enough for a struct containing a uint64_t when emitting a 32-bit binary
933 source_version_command sv;
934 sv.cmd = LC_SOURCE_VERSION;
935 sv.cmdsize = sizeof(source_version_command);
936 sv.version = _file.sourceVersion;
Pete Cooper40576fa2016-02-04 02:45:23 +0000937 if (_swap)
Pete Cooperb565bdf2016-03-23 22:00:09 +0000938 swapStruct(sv);
939 memcpy(lc, &sv, sizeof(source_version_command));
Pete Cooper40576fa2016-02-04 02:45:23 +0000940 lc += sizeof(source_version_command);
941 }
942
Pete Cooper354809e2016-02-03 22:28:29 +0000943 // If main executable, add LC_MAIN.
944 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000945 // Build LC_MAIN load command.
Pete Cooper07601d32016-03-24 01:05:17 +0000946 // Note, using a temporary here to appease UB as we may not be aligned
947 // enough for a struct containing a uint64_t when emitting a 32-bit binary
948 entry_point_command ep;
949 ep.cmd = LC_MAIN;
950 ep.cmdsize = sizeof(entry_point_command);
951 ep.entryoff = _file.entryAddress - _seg1addr;
952 ep.stacksize = _file.stackSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000953 if (_swap)
Pete Cooper07601d32016-03-24 01:05:17 +0000954 swapStruct(ep);
955 memcpy(lc, &ep, sizeof(entry_point_command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000956 lc += sizeof(entry_point_command);
957 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000958
Nick Kledzike34182f2013-11-06 21:36:55 +0000959 // Add LC_LOAD_DYLIB commands
960 for (const DependentDylib &dep : _file.dependentDylibs) {
961 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
962 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000963 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000964 dc->cmdsize = size;
965 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000966 // needs to be some constant value different than the one in LC_ID_DYLIB
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000967 dc->dylib.timestamp = 2;
968 dc->dylib.current_version = dep.currentVersion;
969 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000970 if (_swap)
971 swapStruct(*dc);
972 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
973 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
974 lc += size;
975 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000976
977 // Add LC_RPATH
978 for (const StringRef &path : _file.rpaths) {
979 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
Lang Hames2ed3bf92015-10-29 16:50:26 +0000980 uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000981 rpc->cmd = LC_RPATH;
982 rpc->cmdsize = size;
983 rpc->path = sizeof(rpath_command); // offset
984 if (_swap)
985 swapStruct(*rpc);
986 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
987 lc[sizeof(rpath_command)+path.size()] = '\0';
988 lc += size;
989 }
990
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000991 // Add LC_FUNCTION_STARTS if needed.
992 if (_functionStartsSize != 0) {
993 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
994 dl->cmd = LC_FUNCTION_STARTS;
995 dl->cmdsize = sizeof(linkedit_data_command);
996 dl->dataoff = _startOfFunctionStarts;
997 dl->datasize = _functionStartsSize;
998 if (_swap)
999 swapStruct(*dl);
1000 lc += sizeof(linkedit_data_command);
1001 }
1002
Pete Cooper9b28a452016-02-09 02:10:39 +00001003 // Add LC_DATA_IN_CODE if requested.
1004 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +00001005 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
1006 dl->cmd = LC_DATA_IN_CODE;
1007 dl->cmdsize = sizeof(linkedit_data_command);
1008 dl->dataoff = _startOfDataInCode;
1009 dl->datasize = _dataInCodeSize;
1010 if (_swap)
1011 swapStruct(*dl);
1012 lc += sizeof(linkedit_data_command);
1013 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001014 }
1015 return ec;
1016}
1017
Nick Kledzike34182f2013-11-06 21:36:55 +00001018void MachOFileLayout::writeSectionContent() {
1019 for (const Section &s : _file.sections) {
1020 // Copy all section content to output buffer.
Lang Hamesac2adce2015-12-11 23:25:09 +00001021 if (isZeroFillSection(s.type))
Nick Kledzik61fdef62014-05-15 20:59:23 +00001022 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +00001023 if (s.content.empty())
1024 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +00001025 uint32_t offset = _sectInfo[&s].fileOffset;
1026 uint8_t *p = &_buffer[offset];
1027 memcpy(p, &s.content[0], s.content.size());
1028 p += s.content.size();
1029 }
1030}
1031
1032void MachOFileLayout::writeRelocations() {
1033 uint32_t relOffset = _startOfRelocations;
1034 for (Section sect : _file.sections) {
1035 for (Relocation r : sect.relocations) {
1036 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
1037 &_buffer[relOffset]);
1038 *rb = packRelocation(r, _swap, _bigEndianArch);
1039 relOffset += sizeof(any_relocation_info);
1040 }
1041 }
1042}
1043
Nick Kledzike34182f2013-11-06 21:36:55 +00001044void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
1045 uint32_t &symOffset, uint32_t &strOffset) {
1046 for (const Symbol &sym : symbols) {
1047 if (_is64) {
1048 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
1049 nb->n_strx = strOffset - _startOfSymbolStrings;
1050 nb->n_type = sym.type | sym.scope;
1051 nb->n_sect = sym.sect;
1052 nb->n_desc = sym.desc;
1053 nb->n_value = sym.value;
1054 if (_swap)
1055 swapStruct(*nb);
1056 symOffset += sizeof(nlist_64);
1057 } else {
1058 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
1059 nb->n_strx = strOffset - _startOfSymbolStrings;
1060 nb->n_type = sym.type | sym.scope;
1061 nb->n_sect = sym.sect;
1062 nb->n_desc = sym.desc;
1063 nb->n_value = sym.value;
1064 if (_swap)
1065 swapStruct(*nb);
1066 symOffset += sizeof(nlist);
1067 }
1068 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
1069 strOffset += sym.name.size();
1070 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
1071 }
1072}
1073
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001074void MachOFileLayout::writeFunctionStartsInfo() {
Pete Cooper8e1b9a12016-03-22 22:51:03 +00001075 if (!_functionStartsSize)
1076 return;
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001077 memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
1078 _functionStartsSize);
1079}
1080
Nick Kledzik21921372014-07-24 23:06:56 +00001081void MachOFileLayout::writeDataInCodeInfo() {
1082 uint32_t offset = _startOfDataInCode;
1083 for (const DataInCode &entry : _file.dataInCode) {
1084 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
1085 &_buffer[offset]);
1086 dst->offset = entry.offset;
1087 dst->length = entry.length;
1088 dst->kind = entry.kind;
1089 if (_swap)
1090 swapStruct(*dst);
1091 offset += sizeof(data_in_code_entry);
1092 }
1093}
1094
Nick Kledzike34182f2013-11-06 21:36:55 +00001095void MachOFileLayout::writeSymbolTable() {
1096 // Write symbol table and symbol strings in parallel.
1097 uint32_t symOffset = _startOfSymbols;
1098 uint32_t strOffset = _startOfSymbolStrings;
1099 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
1100 appendSymbols(_file.localSymbols, symOffset, strOffset);
1101 appendSymbols(_file.globalSymbols, symOffset, strOffset);
1102 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
1103 // Write indirect symbol table array.
1104 uint32_t *indirects = reinterpret_cast<uint32_t*>
1105 (&_buffer[_startOfIndirectSymbols]);
1106 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1107 // Object files have sections in same order as input normalized file.
1108 for (const Section &section : _file.sections) {
1109 for (uint32_t index : section.indirectSymbols) {
1110 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001111 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001112 else
1113 *indirects++ = index;
1114 }
1115 }
1116 } else {
1117 // Final linked images must sort sections from normalized file.
1118 for (const Segment &seg : _file.segments) {
1119 SegExtraInfo &segInfo = _segInfo[&seg];
1120 for (const Section *section : segInfo.sections) {
1121 for (uint32_t index : section->indirectSymbols) {
1122 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001123 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001124 else
1125 *indirects++ = index;
1126 }
1127 }
1128 }
1129 }
1130}
1131
1132void MachOFileLayout::writeRebaseInfo() {
1133 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
1134}
1135
1136void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001137 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001138 _bindingInfo.bytes(), _bindingInfo.size());
1139}
1140
1141void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001142 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001143 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1144}
1145
Nick Kledzik141330a2014-09-03 19:52:50 +00001146void MachOFileLayout::writeExportInfo() {
1147 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1148}
1149
Nick Kledzike34182f2013-11-06 21:36:55 +00001150void MachOFileLayout::buildLinkEditInfo() {
1151 buildRebaseInfo();
1152 buildBindInfo();
1153 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001154 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001155 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001156 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +00001157 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001158}
1159
1160void MachOFileLayout::buildSectionRelocations() {
1161
1162}
1163
1164void MachOFileLayout::buildRebaseInfo() {
1165 // TODO: compress rebasing info.
1166 for (const RebaseLocation& entry : _file.rebasingInfo) {
1167 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001168 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001169 | entry.segIndex);
1170 _rebaseInfo.append_uleb128(entry.segOffset);
1171 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1172 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001173 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001174 _rebaseInfo.align(_is64 ? 8 : 4);
1175}
1176
1177void MachOFileLayout::buildBindInfo() {
1178 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001179 uint64_t lastAddend = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001180 for (const BindLocation& entry : _file.bindingInfo) {
1181 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001182 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001183 | entry.segIndex);
1184 _bindingInfo.append_uleb128(entry.segOffset);
Lang Hames5c692002015-09-28 20:25:14 +00001185 if (entry.ordinal > 0)
1186 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1187 (entry.ordinal & 0xF));
1188 else
1189 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1190 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001191 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1192 _bindingInfo.append_string(entry.symbolName);
Nick Kledzikf373c772014-11-11 01:31:18 +00001193 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001194 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1195 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001196 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001197 }
1198 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1199 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001200 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001201 _bindingInfo.align(_is64 ? 8 : 4);
1202}
1203
1204void MachOFileLayout::buildLazyBindInfo() {
1205 for (const BindLocation& entry : _file.lazyBindingInfo) {
1206 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001207 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001208 | entry.segIndex);
Nick Kledzikf373c772014-11-11 01:31:18 +00001209 _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
Lang Hames5c692002015-09-28 20:25:14 +00001210 if (entry.ordinal > 0)
1211 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1212 (entry.ordinal & 0xF));
1213 else
1214 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1215 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001216 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1217 _lazyBindingInfo.append_string(entry.symbolName);
1218 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001219 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001220 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001221 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001222 _lazyBindingInfo.align(_is64 ? 8 : 4);
1223}
1224
Pete Coopere420dd42016-01-25 21:50:54 +00001225void TrieNode::addSymbol(const Export& entry,
1226 BumpPtrAllocator &allocator,
1227 std::vector<TrieNode*> &allNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001228 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1229 for (TrieEdge &edge : _children) {
1230 StringRef edgeStr = edge._subString;
1231 if (partialStr.startswith(edgeStr)) {
1232 // Already have matching edge, go down that path.
1233 edge._child->addSymbol(entry, allocator, allNodes);
1234 return;
1235 }
1236 // See if string has commmon prefix with existing edge.
1237 for (int n=edgeStr.size()-1; n > 0; --n) {
1238 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1239 // Splice in new node: was A -> C, now A -> B -> C
1240 StringRef bNodeStr = edge._child->_cummulativeString;
1241 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
Eugene Zelenko41547942015-11-10 22:37:38 +00001242 auto *bNode = new (allocator) TrieNode(bNodeStr);
Nick Kledzik141330a2014-09-03 19:52:50 +00001243 allNodes.push_back(bNode);
1244 TrieNode* cNode = edge._child;
1245 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1246 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1247 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1248 << "splice in TrieNode('" << bNodeStr
1249 << "') between edge '"
1250 << abEdgeStr << "' and edge='"
1251 << bcEdgeStr<< "'\n");
1252 TrieEdge& abEdge = edge;
1253 abEdge._subString = abEdgeStr;
1254 abEdge._child = bNode;
Eugene Zelenko41547942015-11-10 22:37:38 +00001255 auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001256 bNode->_children.insert(bNode->_children.end(), bcEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001257 bNode->addSymbol(entry, allocator, allNodes);
1258 return;
1259 }
1260 }
1261 }
1262 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1263 assert(entry.otherOffset != 0);
1264 }
1265 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1266 assert(entry.otherOffset != 0);
1267 }
1268 // No commonality with any existing child, make a new edge.
Eugene Zelenko41547942015-11-10 22:37:38 +00001269 auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1270 auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001271 _children.insert(_children.end(), newEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001272 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1273 << "new TrieNode('" << entry.name << "') with edge '"
1274 << partialStr << "' from node='"
1275 << _cummulativeString << "'\n");
1276 newNode->_address = entry.offset;
1277 newNode->_flags = entry.flags | entry.kind;
1278 newNode->_other = entry.otherOffset;
1279 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1280 newNode->_importedName = entry.otherName.copy(allocator);
1281 newNode->_hasExportInfo = true;
1282 allNodes.push_back(newNode);
1283}
1284
Pete Coopere420dd42016-01-25 21:50:54 +00001285bool TrieNode::updateOffset(uint32_t& offset) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001286 uint32_t nodeSize = 1; // Length when no export info
1287 if (_hasExportInfo) {
1288 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1289 nodeSize = llvm::getULEB128Size(_flags);
1290 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1291 nodeSize += _importedName.size();
1292 ++nodeSize; // Trailing zero in imported name.
1293 } else {
1294 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1295 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1296 nodeSize += llvm::getULEB128Size(_other);
1297 }
1298 // Overall node size so far is uleb128 of export info + actual export info.
1299 nodeSize += llvm::getULEB128Size(nodeSize);
1300 }
1301 // Compute size of all child edges.
1302 ++nodeSize; // Byte for number of chidren.
1303 for (TrieEdge &edge : _children) {
1304 nodeSize += edge._subString.size() + 1 // String length.
1305 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1306 }
1307 // On input, 'offset' is new prefered location for this node.
1308 bool result = (_trieOffset != offset);
1309 // Store new location in node object for use by parents.
1310 _trieOffset = offset;
1311 // Update offset for next iteration.
1312 offset += nodeSize;
1313 // Return true if _trieOffset was changed.
1314 return result;
1315}
1316
Pete Coopere420dd42016-01-25 21:50:54 +00001317void TrieNode::appendToByteBuffer(ByteBuffer &out) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001318 if (_hasExportInfo) {
1319 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1320 if (!_importedName.empty()) {
1321 // nodes with re-export info: size, flags, ordinal, import-name
1322 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1323 + llvm::getULEB128Size(_other)
1324 + _importedName.size() + 1;
1325 assert(nodeSize < 256);
1326 out.append_byte(nodeSize);
1327 out.append_uleb128(_flags);
1328 out.append_uleb128(_other);
1329 out.append_string(_importedName);
1330 } else {
1331 // nodes without re-export info: size, flags, ordinal, empty-string
1332 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1333 + llvm::getULEB128Size(_other) + 1;
1334 assert(nodeSize < 256);
1335 out.append_byte(nodeSize);
1336 out.append_uleb128(_flags);
1337 out.append_uleb128(_other);
1338 out.append_byte(0);
1339 }
1340 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1341 // Nodes with export info: size, flags, address, other
1342 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1343 + llvm::getULEB128Size(_address)
1344 + llvm::getULEB128Size(_other);
1345 assert(nodeSize < 256);
1346 out.append_byte(nodeSize);
1347 out.append_uleb128(_flags);
1348 out.append_uleb128(_address);
1349 out.append_uleb128(_other);
1350 } else {
1351 // Nodes with export info: size, flags, address
1352 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1353 + llvm::getULEB128Size(_address);
1354 assert(nodeSize < 256);
1355 out.append_byte(nodeSize);
1356 out.append_uleb128(_flags);
1357 out.append_uleb128(_address);
1358 }
1359 } else {
1360 // Node with no export info.
1361 uint32_t nodeSize = 0;
1362 out.append_byte(nodeSize);
1363 }
1364 // Add number of children.
1365 assert(_children.size() < 256);
1366 out.append_byte(_children.size());
1367 // Append each child edge substring and node offset.
1368 for (TrieEdge &edge : _children) {
1369 out.append_string(edge._subString);
1370 out.append_uleb128(edge._child->_trieOffset);
1371 }
1372}
1373
1374void MachOFileLayout::buildExportTrie() {
1375 if (_file.exportInfo.empty())
1376 return;
1377
1378 // For all temporary strings and objects used building trie.
1379 BumpPtrAllocator allocator;
1380
1381 // Build trie of all exported symbols.
Eugene Zelenko41547942015-11-10 22:37:38 +00001382 auto *rootNode = new (allocator) TrieNode(StringRef());
Nick Kledzik141330a2014-09-03 19:52:50 +00001383 std::vector<TrieNode*> allNodes;
1384 allNodes.reserve(_file.exportInfo.size()*2);
1385 allNodes.push_back(rootNode);
1386 for (const Export& entry : _file.exportInfo) {
1387 rootNode->addSymbol(entry, allocator, allNodes);
1388 }
1389
1390 // Assign each node in the vector an offset in the trie stream, iterating
1391 // until all uleb128 sizes have stabilized.
1392 bool more;
1393 do {
1394 uint32_t offset = 0;
1395 more = false;
1396 for (TrieNode* node : allNodes) {
1397 if (node->updateOffset(offset))
1398 more = true;
1399 }
1400 } while (more);
1401
1402 // Serialize trie to ByteBuffer.
1403 for (TrieNode* node : allNodes) {
1404 node->appendToByteBuffer(_exportTrie);
1405 }
1406 _exportTrie.align(_is64 ? 8 : 4);
1407}
1408
Nick Kledzike34182f2013-11-06 21:36:55 +00001409void MachOFileLayout::computeSymbolTableSizes() {
1410 // MachO symbol tables have three ranges: locals, globals, and undefines
1411 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001412 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001413 + _file.globalSymbols.size()
1414 + _file.undefinedSymbols.size());
Lang Hames201c08f2015-12-10 00:12:24 +00001415 _symbolStringPoolSize = 1; // Always reserve 1-byte for the empty string.
Nick Kledzike34182f2013-11-06 21:36:55 +00001416 for (const Symbol &sym : _file.localSymbols) {
1417 _symbolStringPoolSize += (sym.name.size()+1);
1418 }
1419 for (const Symbol &sym : _file.globalSymbols) {
1420 _symbolStringPoolSize += (sym.name.size()+1);
1421 }
1422 for (const Symbol &sym : _file.undefinedSymbols) {
1423 _symbolStringPoolSize += (sym.name.size()+1);
1424 }
1425 _symbolTableLocalsStartIndex = 0;
1426 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001427 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001428 + _file.globalSymbols.size();
1429
1430 _indirectSymbolTableCount = 0;
1431 for (const Section &sect : _file.sections) {
1432 _indirectSymbolTableCount += sect.indirectSymbols.size();
1433 }
1434}
1435
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001436void MachOFileLayout::computeFunctionStartsSize() {
1437 _functionStartsSize = _file.functionStarts.size();
1438}
1439
Nick Kledzik21921372014-07-24 23:06:56 +00001440void MachOFileLayout::computeDataInCodeSize() {
1441 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1442}
Nick Kledzike34182f2013-11-06 21:36:55 +00001443
1444void MachOFileLayout::writeLinkEditContent() {
1445 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1446 writeRelocations();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001447 writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +00001448 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001449 writeSymbolTable();
1450 } else {
1451 writeRebaseInfo();
1452 writeBindingInfo();
1453 writeLazyBindingInfo();
1454 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001455 writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001456 writeFunctionStartsInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001457 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001458 writeSymbolTable();
1459 }
1460}
1461
Pete Cooperfefbd222016-03-30 23:10:39 +00001462llvm::Error MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001463 // Check for pending error from constructor.
1464 if (_ec)
Pete Cooperfefbd222016-03-30 23:10:39 +00001465 return llvm::errorCodeToError(_ec);
Nick Kledzike34182f2013-11-06 21:36:55 +00001466 // Create FileOutputBuffer with calculated size.
Nick Kledzike34182f2013-11-06 21:36:55 +00001467 unsigned flags = 0;
1468 if (_file.fileType != llvm::MachO::MH_OBJECT)
1469 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001470 ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
1471 llvm::FileOutputBuffer::create(path, size(), flags);
1472 if (std::error_code ec = fobOrErr.getError())
Pete Cooperfefbd222016-03-30 23:10:39 +00001473 return llvm::errorCodeToError(ec);
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001474 std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
Nick Kledzike34182f2013-11-06 21:36:55 +00001475 // Write content.
1476 _buffer = fob->getBufferStart();
1477 writeMachHeader();
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001478 std::error_code ec = writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +00001479 if (ec)
Pete Cooperfefbd222016-03-30 23:10:39 +00001480 return llvm::errorCodeToError(ec);
Nick Kledzike34182f2013-11-06 21:36:55 +00001481 writeSectionContent();
1482 writeLinkEditContent();
1483 fob->commit();
1484
Pete Cooperfefbd222016-03-30 23:10:39 +00001485 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +00001486}
1487
Nick Kledzike34182f2013-11-06 21:36:55 +00001488/// Takes in-memory normalized view and writes a mach-o object file.
Pete Cooperfefbd222016-03-30 23:10:39 +00001489llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001490 MachOFileLayout layout(file);
1491 return layout.writeBinary(path);
1492}
1493
Nick Kledzike34182f2013-11-06 21:36:55 +00001494} // namespace normalized
1495} // namespace mach_o
1496} // namespace lld