blob: a0609a5e926e10b7d9b7d38cf27fd267df29af63 [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);
Pete Cooperd0de3682016-08-05 21:37:12 +0000106
107 void addOrderedNodes(const Export &entry,
108 std::vector<TrieNode *> &allNodes);
Pete Coopere420dd42016-01-25 21:50:54 +0000109 bool updateOffset(uint32_t &offset);
110 void appendToByteBuffer(ByteBuffer &out);
111
112private:
113 StringRef _cummulativeString;
114 TrieEdgeList _children;
115 uint64_t _address;
116 uint64_t _flags;
117 uint64_t _other;
118 StringRef _importedName;
119 uint32_t _trieOffset;
120 bool _hasExportInfo;
Pete Cooperd0de3682016-08-05 21:37:12 +0000121 bool _ordered = false;
Pete Coopere420dd42016-01-25 21:50:54 +0000122};
123
Nick Kledzike34182f2013-11-06 21:36:55 +0000124/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000125/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000126class MachOFileLayout {
127public:
Joey Goulyb275d7f2013-12-23 23:29:50 +0000128 /// All layout computation is done in the constructor.
129 MachOFileLayout(const NormalizedFile &file);
130
Nick Kledzike34182f2013-11-06 21:36:55 +0000131 /// Returns the final file size as computed in the constructor.
132 size_t size() const;
133
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000134 // Returns size of the mach_header and load commands.
135 size_t headerAndLoadCommandsSize() const;
136
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000137 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +0000138 /// path. This does not have a stream interface because the generated
139 /// file may need the 'x' bit set.
Pete Cooperfefbd222016-03-30 23:10:39 +0000140 llvm::Error writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000141
Nick Kledzike34182f2013-11-06 21:36:55 +0000142private:
143 uint32_t loadCommandsSize(uint32_t &count);
144 void buildFileOffsets();
145 void writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +0000146 llvm::Error writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +0000147 void writeSectionContent();
148 void writeRelocations();
149 void writeSymbolTable();
150 void writeRebaseInfo();
151 void writeBindingInfo();
152 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000153 void writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000154 void writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +0000155 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000156 void writeLinkEditContent();
157 void buildLinkEditInfo();
158 void buildRebaseInfo();
159 void buildBindInfo();
160 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000161 void buildExportTrie();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000162 void computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000163 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000164 void computeSymbolTableSizes();
165 void buildSectionRelocations();
166 void appendSymbols(const std::vector<Symbol> &symbols,
167 uint32_t &symOffset, uint32_t &strOffset);
168 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
169 uint32_t indirectSymbolElementSize(const Section &sect);
170
Nick Kledzik29f749e2013-11-09 00:07:28 +0000171 // For use as template parameter to load command methods.
172 struct MachO64Trait {
173 typedef llvm::MachO::segment_command_64 command;
174 typedef llvm::MachO::section_64 section;
175 enum { LC = llvm::MachO::LC_SEGMENT_64 };
176 };
177
178 // For use as template parameter to load command methods.
179 struct MachO32Trait {
180 typedef llvm::MachO::segment_command command;
181 typedef llvm::MachO::section section;
182 enum { LC = llvm::MachO::LC_SEGMENT };
183 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000184
Nick Kledzik29f749e2013-11-09 00:07:28 +0000185 template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000186 llvm::Error writeSingleSegmentLoadCommand(uint8_t *&lc);
187 template <typename T> llvm::Error writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000188
Nick Kledzike34182f2013-11-06 21:36:55 +0000189 uint32_t pointerAlign(uint32_t value);
190 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000191
Nick Kledzike34182f2013-11-06 21:36:55 +0000192 struct SegExtraInfo {
193 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000194 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000195 std::vector<const Section*> sections;
196 };
197 typedef std::map<const Segment*, SegExtraInfo> SegMap;
198 struct SectionExtraInfo {
199 uint32_t fileOffset;
200 };
201 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000202
Nick Kledzike34182f2013-11-06 21:36:55 +0000203 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000204 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000205 uint8_t *_buffer;
206 const bool _is64;
207 const bool _swap;
208 const bool _bigEndianArch;
209 uint64_t _seg1addr;
210 uint32_t _startOfLoadCommands;
211 uint32_t _countOfLoadCommands;
212 uint32_t _endOfLoadCommands;
213 uint32_t _startOfRelocations;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000214 uint32_t _startOfFunctionStarts;
Nick Kledzik21921372014-07-24 23:06:56 +0000215 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000216 uint32_t _startOfSymbols;
217 uint32_t _startOfIndirectSymbols;
218 uint32_t _startOfSymbolStrings;
219 uint32_t _endOfSymbolStrings;
220 uint32_t _symbolTableLocalsStartIndex;
221 uint32_t _symbolTableGlobalsStartIndex;
222 uint32_t _symbolTableUndefinesStartIndex;
223 uint32_t _symbolStringPoolSize;
224 uint32_t _symbolTableSize;
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000225 uint32_t _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000226 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000227 uint32_t _indirectSymbolTableCount;
228 // Used in object file creation only
229 uint32_t _startOfSectionsContent;
230 uint32_t _endOfSectionsContent;
231 // Used in final linked image only
232 uint32_t _startOfLinkEdit;
233 uint32_t _startOfRebaseInfo;
234 uint32_t _endOfRebaseInfo;
235 uint32_t _startOfBindingInfo;
236 uint32_t _endOfBindingInfo;
237 uint32_t _startOfLazyBindingInfo;
238 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000239 uint32_t _startOfExportTrie;
240 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000241 uint32_t _endOfLinkEdit;
242 uint64_t _addressOfLinkEdit;
243 SegMap _segInfo;
244 SectionMap _sectInfo;
245 ByteBuffer _rebaseInfo;
246 ByteBuffer _bindingInfo;
247 ByteBuffer _lazyBindingInfo;
248 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000249 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000250};
251
252size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
253 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000254 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000255}
256
257StringRef MachOFileLayout::dyldPath() {
258 return "/usr/lib/dyld";
259}
260
261uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
Rui Ueyama489a8062016-01-14 20:53:50 +0000262 return llvm::alignTo(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000263}
Nick Kledzike34182f2013-11-06 21:36:55 +0000264
265
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000266size_t MachOFileLayout::headerAndLoadCommandsSize() const {
267 return _endOfLoadCommands;
268}
Nick Kledzike34182f2013-11-06 21:36:55 +0000269
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000270MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000271 : _file(file),
272 _is64(MachOLinkingContext::is64Bit(file.arch)),
273 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
274 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
275 _seg1addr(INT64_MAX) {
276 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000277 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000278 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
279 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
280 if (file.fileType == llvm::MachO::MH_OBJECT) {
281 // object files have just one segment load command containing all sections
282 _endOfLoadCommands = _startOfLoadCommands
283 + segCommandBaseSize
284 + file.sections.size() * sectsSize
285 + sizeof(symtab_command);
286 _countOfLoadCommands = 2;
Pete Cooperceee5de2016-02-04 02:16:08 +0000287 if (file.hasMinVersionLoadCommand) {
288 _endOfLoadCommands += sizeof(version_min_command);
289 _countOfLoadCommands++;
290 }
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000291 if (!_file.functionStarts.empty()) {
292 _endOfLoadCommands += sizeof(linkedit_data_command);
293 _countOfLoadCommands++;
294 }
Pete Cooper9b28a452016-02-09 02:10:39 +0000295 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000296 _endOfLoadCommands += sizeof(linkedit_data_command);
297 _countOfLoadCommands++;
298 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000299 // Assign file offsets to each section.
Nick Kledzike34182f2013-11-06 21:36:55 +0000300 _startOfSectionsContent = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000301 unsigned relocCount = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000302 uint64_t offset = _startOfSectionsContent;
Nick Kledzike34182f2013-11-06 21:36:55 +0000303 for (const Section &sect : file.sections) {
Lang Hamesac2adce2015-12-11 23:25:09 +0000304 if (isZeroFillSection(sect.type))
305 _sectInfo[&sect].fileOffset = 0;
306 else {
Rui Ueyama489a8062016-01-14 20:53:50 +0000307 offset = llvm::alignTo(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000308 _sectInfo[&sect].fileOffset = offset;
309 offset += sect.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000310 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000311 relocCount += sect.relocations.size();
312 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000313 _endOfSectionsContent = offset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000314
Nick Kledzike34182f2013-11-06 21:36:55 +0000315 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000316 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +0000317 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000318
Nick Kledzike34182f2013-11-06 21:36:55 +0000319 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000320 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000321 _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
322 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000323 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000324 // Add Indirect symbol table.
325 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
326 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000327 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000328 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000329 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000330 + pointerAlign(_symbolStringPoolSize);
331 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000332 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000333 llvm::dbgs() << "MachOFileLayout()\n"
334 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
335 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
336 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
337 << " startOfRelocations=" << _startOfRelocations << "\n"
338 << " startOfSymbols=" << _startOfSymbols << "\n"
339 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
340 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
341 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
342 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
343 } else {
344 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000345 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000346 + loadCommandsSize(_countOfLoadCommands);
347
348 // Assign section file offsets.
349 buildFileOffsets();
350 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000351
Nick Kledzike34182f2013-11-06 21:36:55 +0000352 // LINKEDIT of final linked images has in order:
353 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000354 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000355 _startOfRebaseInfo = _startOfLinkEdit;
356 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
357 _startOfBindingInfo = _endOfRebaseInfo;
358 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
359 _startOfLazyBindingInfo = _endOfBindingInfo;
360 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000361 _startOfExportTrie = _endOfLazyBindingInfo;
362 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000363 _startOfFunctionStarts = _endOfExportTrie;
364 _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000365 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000366 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000367 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000368 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000369 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000370 + pointerAlign(_symbolStringPoolSize);
371 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000372 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000373 llvm::dbgs() << "MachOFileLayout()\n"
374 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
375 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
376 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
377 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
378 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
379 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
380 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
381 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
382 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
383 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000384 << " startOfExportTrie=" << _startOfExportTrie << "\n"
385 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000386 << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000387 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000388 << " startOfSymbols=" << _startOfSymbols << "\n"
389 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
390 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
391 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
392 }
393}
394
395uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
396 uint32_t size = 0;
397 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000398
399 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000400 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
401 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
402
403 // Add LC_SEGMENT for each segment.
404 size += _file.segments.size() * segCommandSize;
405 count += _file.segments.size();
406 // Add section record for each section.
407 size += _file.sections.size() * sectionSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000408
Tim Northover301c4e62014-07-01 08:15:41 +0000409 // If creating a dylib, add LC_ID_DYLIB.
410 if (_file.fileType == llvm::MachO::MH_DYLIB) {
411 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
412 ++count;
413 }
414
Nick Kledzike34182f2013-11-06 21:36:55 +0000415 // Add LC_DYLD_INFO
416 size += sizeof(dyld_info_command);
417 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000418
Nick Kledzike34182f2013-11-06 21:36:55 +0000419 // Add LC_SYMTAB
420 size += sizeof(symtab_command);
421 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000422
Nick Kledzike34182f2013-11-06 21:36:55 +0000423 // Add LC_DYSYMTAB
424 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
425 size += sizeof(dysymtab_command);
426 ++count;
427 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000428
Pete Cooper354809e2016-02-03 22:28:29 +0000429 // If main executable add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000430 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
431 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
432 ++count;
Pete Cooper354809e2016-02-03 22:28:29 +0000433 }
434
435 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
436 // LC_VERSION_MIN_TVOS
437 if (_file.hasMinVersionLoadCommand) {
438 size += sizeof(version_min_command);
439 ++count;
440 }
441
Pete Cooper40576fa2016-02-04 02:45:23 +0000442 // Add LC_SOURCE_VERSION
443 size += sizeof(source_version_command);
444 ++count;
445
Pete Cooper354809e2016-02-03 22:28:29 +0000446 // If main executable add LC_MAIN
447 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000448 size += sizeof(entry_point_command);
449 ++count;
450 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000451
Nick Kledzike34182f2013-11-06 21:36:55 +0000452 // Add LC_LOAD_DYLIB for each dependent dylib.
453 for (const DependentDylib &dep : _file.dependentDylibs) {
454 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
455 ++count;
456 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000457
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000458 // Add LC_RPATH
459 for (const StringRef &path : _file.rpaths) {
Lang Hames2ed3bf92015-10-29 16:50:26 +0000460 size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000461 ++count;
462 }
463
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000464 // Add LC_FUNCTION_STARTS if needed
465 if (!_file.functionStarts.empty()) {
466 size += sizeof(linkedit_data_command);
467 ++count;
468 }
469
Pete Cooper9b28a452016-02-09 02:10:39 +0000470 // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries.
471 // FIXME: Zero length entries is only to match ld64. Should we change this?
472 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +0000473 size += sizeof(linkedit_data_command);
474 ++count;
475 }
476
Nick Kledzike34182f2013-11-06 21:36:55 +0000477 return size;
478}
479
480static bool overlaps(const Segment &s1, const Segment &s2) {
481 if (s2.address >= s1.address+s1.size)
482 return false;
483 if (s1.address >= s2.address+s2.size)
484 return false;
485 return true;
486}
487
488static bool overlaps(const Section &s1, const Section &s2) {
489 if (s2.address >= s1.address+s1.content.size())
490 return false;
491 if (s1.address >= s2.address+s2.content.size())
492 return false;
493 return true;
494}
495
496void MachOFileLayout::buildFileOffsets() {
497 // Verify no segments overlap
498 for (const Segment &sg1 : _file.segments) {
499 for (const Segment &sg2 : _file.segments) {
500 if (&sg1 == &sg2)
501 continue;
502 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000503 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000504 return;
505 }
506 }
507 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000508
509 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000510 for (const Section &s1 : _file.sections) {
511 for (const Section &s2 : _file.sections) {
512 if (&s1 == &s2)
513 continue;
514 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000515 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000516 return;
517 }
518 }
519 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000520
Nick Kledzike34182f2013-11-06 21:36:55 +0000521 // Build side table of extra info about segments and sections.
522 SegExtraInfo t;
523 t.fileOffset = 0;
524 for (const Segment &sg : _file.segments) {
525 _segInfo[&sg] = t;
526 }
527 SectionExtraInfo t2;
528 t2.fileOffset = 0;
529 // Assign sections to segments.
530 for (const Section &s : _file.sections) {
531 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000532 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000533 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000534 if (sg.name.equals(s.segmentName)) {
535 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000536 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000537 _segInfo[&sg].sections.push_back(&s);
538 foundSegment = true;
539 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000540 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000541 }
542 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000543 if (!foundSegment) {
544 _ec = make_error_code(llvm::errc::executable_format_error);
545 return;
546 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000547 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000548
Nick Kledzike34182f2013-11-06 21:36:55 +0000549 // Assign file offsets.
550 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000551 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000552 llvm::dbgs() << "buildFileOffsets()\n");
553 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000554 _segInfo[&sg].fileOffset = fileOffset;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000555 if ((_seg1addr == INT64_MAX) && sg.init_access)
Nick Kledzike34182f2013-11-06 21:36:55 +0000556 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000557 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000558 llvm::dbgs() << " segment=" << sg.name
559 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000560
561 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000562 // A segment that is not zero-fill must use a least one page of disk space.
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000563 if (sg.init_access)
Nick Kledzik761d6542014-10-24 22:19:22 +0000564 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000565 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000566 uint32_t sectOffset = s->address - sg.address;
567 uint32_t sectFileSize =
Lang Hamesac2adce2015-12-11 23:25:09 +0000568 isZeroFillSection(s->type) ? 0 : s->content.size();
Tim Northover08d6a7b2014-06-30 09:49:30 +0000569 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
570
571 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000572 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000573 llvm::dbgs() << " section=" << s->sectionName
574 << ", fileOffset=" << fileOffset << "\n");
575 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000576
Pete Cooper353652f2016-02-06 00:14:15 +0000577 // round up all segments to page aligned, except __LINKEDIT
578 if (!sg.name.equals("__LINKEDIT")) {
579 _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
580 fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
581 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000582 _addressOfLinkEdit = sg.address + sg.size;
583 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000584 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000585}
586
Nick Kledzike34182f2013-11-06 21:36:55 +0000587size_t MachOFileLayout::size() const {
588 return _endOfSymbolStrings;
589}
590
591void MachOFileLayout::writeMachHeader() {
Pete Cooper8563e5a2016-02-04 20:43:43 +0000592 auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
593 // dynamic x86 executables on newer OS version should also set the
594 // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
595 // FIXME: Check that this is a dynamic executable, not a static one.
596 if (_file.fileType == llvm::MachO::MH_EXECUTE &&
597 cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
598 _file.os == MachOLinkingContext::OS::macOSX) {
599 uint32_t version;
600 bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
601 if (!failed && _file.minOSverson >= version)
602 cpusubtype |= CPU_SUBTYPE_LIB64;
603 }
604
Nick Kledzike34182f2013-11-06 21:36:55 +0000605 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
606 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
607 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
Pete Cooper8563e5a2016-02-04 20:43:43 +0000608 mh->cpusubtype = cpusubtype;
Nick Kledzike34182f2013-11-06 21:36:55 +0000609 mh->filetype = _file.fileType;
610 mh->ncmds = _countOfLoadCommands;
611 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
612 mh->flags = _file.flags;
613 if (_swap)
614 swapStruct(*mh);
615}
616
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000617uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000618 uint32_t &index) {
619 if (sect.indirectSymbols.empty())
620 return 0;
621 uint32_t result = index;
622 index += sect.indirectSymbols.size();
623 return result;
624}
625
626uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
627 if (sect.indirectSymbols.empty())
628 return 0;
629 if (sect.type != S_SYMBOL_STUBS)
630 return 0;
631 return sect.content.size() / sect.indirectSymbols.size();
632}
633
Nick Kledzik29f749e2013-11-09 00:07:28 +0000634template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000635llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000636 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
637 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000638 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000639 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000640 uint8_t *next = lc + seg->cmdsize;
641 memset(seg->segname, 0, 16);
642 seg->vmaddr = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000643 seg->vmsize = _file.sections.back().address
644 + _file.sections.back().content.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000645 seg->fileoff = _endOfLoadCommands;
646 seg->filesize = seg->vmsize;
647 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
648 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
649 seg->nsects = _file.sections.size();
650 seg->flags = 0;
651 if (_swap)
652 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000653 typename T::section *sout = reinterpret_cast<typename T::section*>
654 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000655 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000656 uint32_t indirectSymRunningIndex = 0;
657 for (const Section &sin : _file.sections) {
658 setString16(sin.sectionName, sout->sectname);
659 setString16(sin.segmentName, sout->segname);
660 sout->addr = sin.address;
661 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000662 sout->offset = _sectInfo[&sin].fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000663 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000664 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
665 sout->nreloc = sin.relocations.size();
666 sout->flags = sin.type | sin.attributes;
667 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
668 sout->reserved2 = indirectSymbolElementSize(sin);
669 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000670 if (_swap)
671 swapStruct(*sout);
672 ++sout;
673 }
674 lc = next;
Pete Cooper514594b2016-03-31 00:08:16 +0000675 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +0000676}
677
Nick Kledzik29f749e2013-11-09 00:07:28 +0000678template <typename T>
Pete Cooper514594b2016-03-31 00:08:16 +0000679llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000680 uint32_t indirectSymRunningIndex = 0;
681 for (const Segment &seg : _file.segments) {
Pete Cooper353652f2016-02-06 00:14:15 +0000682 // Link edit has no sections and a custom range of address, so handle it
683 // specially.
Nick Kledzike34182f2013-11-06 21:36:55 +0000684 SegExtraInfo &segInfo = _segInfo[&seg];
Pete Cooper353652f2016-02-06 00:14:15 +0000685 if (seg.name.equals("__LINKEDIT")) {
686 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
687 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
688 cmd->cmd = T::LC;
689 cmd->cmdsize = sizeof(typename T::command);
690 uint8_t *next = lc + cmd->cmdsize;
691 setString16("__LINKEDIT", cmd->segname);
692 cmd->vmaddr = _addressOfLinkEdit;
693 cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
694 cmd->fileoff = _startOfLinkEdit;
695 cmd->filesize = linkeditSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000696 cmd->initprot = seg.init_access;
697 cmd->maxprot = seg.max_access;
Pete Cooper353652f2016-02-06 00:14:15 +0000698 cmd->nsects = 0;
699 cmd->flags = 0;
700 if (_swap)
701 swapStruct(*cmd);
702 lc = next;
703 continue;
704 }
705 // Write segment command with trailing sections.
Nick Kledzik29f749e2013-11-09 00:07:28 +0000706 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
707 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000708 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000709 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000710 uint8_t *next = lc + cmd->cmdsize;
711 setString16(seg.name, cmd->segname);
712 cmd->vmaddr = seg.address;
713 cmd->vmsize = seg.size;
714 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000715 cmd->filesize = segInfo.fileSize;
Pete Cooperb8fec3e2016-02-06 00:51:16 +0000716 cmd->initprot = seg.init_access;
717 cmd->maxprot = seg.max_access;
Nick Kledzike34182f2013-11-06 21:36:55 +0000718 cmd->nsects = segInfo.sections.size();
719 cmd->flags = 0;
720 if (_swap)
721 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000722 typename T::section *sect = reinterpret_cast<typename T::section*>
723 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000724 for (const Section *section : segInfo.sections) {
725 setString16(section->sectionName, sect->sectname);
726 setString16(section->segmentName, sect->segname);
727 sect->addr = section->address;
728 sect->size = section->content.size();
Lang Hamesac2adce2015-12-11 23:25:09 +0000729 if (isZeroFillSection(section->type))
Nick Kledzikb072c362014-11-18 00:30:29 +0000730 sect->offset = 0;
731 else
732 sect->offset = section->address - seg.address + segInfo.fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000733 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000734 sect->reloff = 0;
735 sect->nreloc = 0;
736 sect->flags = section->type | section->attributes;
737 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
738 sect->reserved2 = indirectSymbolElementSize(*section);
739 if (_swap)
740 swapStruct(*sect);
741 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000742 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000743 lc = reinterpret_cast<uint8_t*>(next);
744 }
Pete Cooper514594b2016-03-31 00:08:16 +0000745 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +0000746}
747
Pete Cooperceee5de2016-02-04 02:16:08 +0000748static void writeVersionMinLoadCommand(const NormalizedFile &_file,
749 bool _swap,
750 uint8_t *&lc) {
751 if (!_file.hasMinVersionLoadCommand)
752 return;
753 version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
754 switch (_file.os) {
755 case MachOLinkingContext::OS::unknown:
756 vm->cmd = _file.minOSVersionKind;
757 vm->cmdsize = sizeof(version_min_command);
758 vm->version = _file.minOSverson;
759 vm->sdk = 0;
760 break;
761 case MachOLinkingContext::OS::macOSX:
762 vm->cmd = LC_VERSION_MIN_MACOSX;
763 vm->cmdsize = sizeof(version_min_command);
764 vm->version = _file.minOSverson;
765 vm->sdk = _file.sdkVersion;
766 break;
767 case MachOLinkingContext::OS::iOS:
768 case MachOLinkingContext::OS::iOS_simulator:
769 vm->cmd = LC_VERSION_MIN_IPHONEOS;
770 vm->cmdsize = sizeof(version_min_command);
771 vm->version = _file.minOSverson;
772 vm->sdk = _file.sdkVersion;
773 break;
774 }
775 if (_swap)
776 swapStruct(*vm);
777 lc += sizeof(version_min_command);
778}
779
Pete Cooper514594b2016-03-31 00:08:16 +0000780llvm::Error MachOFileLayout::writeLoadCommands() {
Nick Kledzike34182f2013-11-06 21:36:55 +0000781 uint8_t *lc = &_buffer[_startOfLoadCommands];
782 if (_file.fileType == llvm::MachO::MH_OBJECT) {
783 // Object files have one unnamed segment which holds all sections.
Pete Cooper514594b2016-03-31 00:08:16 +0000784 if (_is64) {
785 if (auto ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc))
Pete Coopere487da12016-03-31 00:35:50 +0000786 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000787 } else {
788 if (auto ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000789 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000790 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000791 // Add LC_SYMTAB with symbol table info
792 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
793 st->cmd = LC_SYMTAB;
794 st->cmdsize = sizeof(symtab_command);
795 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000796 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
797 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000798 st->stroff = _startOfSymbolStrings;
799 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
800 if (_swap)
801 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000802 lc += sizeof(symtab_command);
Pete Cooperceee5de2016-02-04 02:16:08 +0000803
804 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
805 // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
806 writeVersionMinLoadCommand(_file, _swap, lc);
807
Pete Cooper41f3e8e2016-02-09 01:38:13 +0000808 // Add LC_FUNCTION_STARTS if needed.
809 if (_functionStartsSize != 0) {
810 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
811 dl->cmd = LC_FUNCTION_STARTS;
812 dl->cmdsize = sizeof(linkedit_data_command);
813 dl->dataoff = _startOfFunctionStarts;
814 dl->datasize = _functionStartsSize;
815 if (_swap)
816 swapStruct(*dl);
817 lc += sizeof(linkedit_data_command);
818 }
819
Pete Cooper9b28a452016-02-09 02:10:39 +0000820 // Add LC_DATA_IN_CODE if requested.
821 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik21921372014-07-24 23:06:56 +0000822 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
823 dl->cmd = LC_DATA_IN_CODE;
824 dl->cmdsize = sizeof(linkedit_data_command);
825 dl->dataoff = _startOfDataInCode;
826 dl->datasize = _dataInCodeSize;
827 if (_swap)
828 swapStruct(*dl);
829 lc += sizeof(linkedit_data_command);
830 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000831 } else {
832 // Final linked images have sections under segments.
Pete Cooper514594b2016-03-31 00:08:16 +0000833 if (_is64) {
834 if (auto ec = writeSegmentLoadCommands<MachO64Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000835 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000836 } else {
837 if (auto ec = writeSegmentLoadCommands<MachO32Trait>(lc))
Pete Cooperdc59c792016-03-31 00:38:02 +0000838 return ec;
Pete Cooper514594b2016-03-31 00:08:16 +0000839 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000840
Tim Northover301c4e62014-07-01 08:15:41 +0000841 // Add LC_ID_DYLIB command for dynamic libraries.
842 if (_file.fileType == llvm::MachO::MH_DYLIB) {
843 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
844 StringRef path = _file.installName;
845 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
846 dc->cmd = LC_ID_DYLIB;
847 dc->cmdsize = size;
848 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000849 // needs to be some constant value different than the one in LC_LOAD_DYLIB
850 dc->dylib.timestamp = 1;
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000851 dc->dylib.current_version = _file.currentVersion;
852 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000853 if (_swap)
854 swapStruct(*dc);
855 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
856 lc[sizeof(dylib_command) + path.size()] = '\0';
857 lc += size;
858 }
859
Nick Kledzike34182f2013-11-06 21:36:55 +0000860 // Add LC_DYLD_INFO_ONLY.
861 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
862 di->cmd = LC_DYLD_INFO_ONLY;
863 di->cmdsize = sizeof(dyld_info_command);
864 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
865 di->rebase_size = _rebaseInfo.size();
866 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
867 di->bind_size = _bindingInfo.size();
868 di->weak_bind_off = 0;
869 di->weak_bind_size = 0;
870 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
871 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000872 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
873 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000874 if (_swap)
875 swapStruct(*di);
876 lc += sizeof(dyld_info_command);
877
878 // Add LC_SYMTAB with symbol table info.
879 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
880 st->cmd = LC_SYMTAB;
881 st->cmdsize = sizeof(symtab_command);
882 st->symoff = _startOfSymbols;
Lang Hames436f7d62016-07-27 22:55:30 +0000883 st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
884 _file.globalSymbols.size() + _file.undefinedSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000885 st->stroff = _startOfSymbolStrings;
886 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
887 if (_swap)
888 swapStruct(*st);
889 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000890
Nick Kledzike34182f2013-11-06 21:36:55 +0000891 // Add LC_DYSYMTAB
892 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
893 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
894 dst->cmd = LC_DYSYMTAB;
895 dst->cmdsize = sizeof(dysymtab_command);
896 dst->ilocalsym = _symbolTableLocalsStartIndex;
Lang Hames436f7d62016-07-27 22:55:30 +0000897 dst->nlocalsym = _file.stabsSymbols.size() +
898 _file.localSymbols.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000899 dst->iextdefsym = _symbolTableGlobalsStartIndex;
900 dst->nextdefsym = _file.globalSymbols.size();
901 dst->iundefsym = _symbolTableUndefinesStartIndex;
902 dst->nundefsym = _file.undefinedSymbols.size();
903 dst->tocoff = 0;
904 dst->ntoc = 0;
905 dst->modtaboff = 0;
906 dst->nmodtab = 0;
907 dst->extrefsymoff = 0;
908 dst->nextrefsyms = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000909 dst->indirectsymoff = _startOfIndirectSymbols;
Nick Kledzike34182f2013-11-06 21:36:55 +0000910 dst->nindirectsyms = _indirectSymbolTableCount;
911 dst->extreloff = 0;
912 dst->nextrel = 0;
913 dst->locreloff = 0;
914 dst->nlocrel = 0;
915 if (_swap)
916 swapStruct(*dst);
917 lc += sizeof(dysymtab_command);
918 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000919
Pete Cooper354809e2016-02-03 22:28:29 +0000920 // If main executable, add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000921 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
922 // Build LC_LOAD_DYLINKER load command.
923 uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
924 dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
925 dl->cmd = LC_LOAD_DYLINKER;
926 dl->cmdsize = size;
927 dl->name = sizeof(dylinker_command); // offset
928 if (_swap)
929 swapStruct(*dl);
930 memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
931 lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
932 lc += size;
Pete Cooper354809e2016-02-03 22:28:29 +0000933 }
934
935 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
936 // LC_VERSION_MIN_TVOS
Pete Cooperceee5de2016-02-04 02:16:08 +0000937 writeVersionMinLoadCommand(_file, _swap, lc);
Pete Cooper354809e2016-02-03 22:28:29 +0000938
Pete Cooper40576fa2016-02-04 02:45:23 +0000939 // Add LC_SOURCE_VERSION
940 {
Pete Cooperb565bdf2016-03-23 22:00:09 +0000941 // Note, using a temporary here to appease UB as we may not be aligned
942 // enough for a struct containing a uint64_t when emitting a 32-bit binary
943 source_version_command sv;
944 sv.cmd = LC_SOURCE_VERSION;
945 sv.cmdsize = sizeof(source_version_command);
946 sv.version = _file.sourceVersion;
Pete Cooper40576fa2016-02-04 02:45:23 +0000947 if (_swap)
Pete Cooperb565bdf2016-03-23 22:00:09 +0000948 swapStruct(sv);
949 memcpy(lc, &sv, sizeof(source_version_command));
Pete Cooper40576fa2016-02-04 02:45:23 +0000950 lc += sizeof(source_version_command);
951 }
952
Pete Cooper354809e2016-02-03 22:28:29 +0000953 // If main executable, add LC_MAIN.
954 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000955 // Build LC_MAIN load command.
Pete Cooper07601d32016-03-24 01:05:17 +0000956 // Note, using a temporary here to appease UB as we may not be aligned
957 // enough for a struct containing a uint64_t when emitting a 32-bit binary
958 entry_point_command ep;
959 ep.cmd = LC_MAIN;
960 ep.cmdsize = sizeof(entry_point_command);
961 ep.entryoff = _file.entryAddress - _seg1addr;
962 ep.stacksize = _file.stackSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000963 if (_swap)
Pete Cooper07601d32016-03-24 01:05:17 +0000964 swapStruct(ep);
965 memcpy(lc, &ep, sizeof(entry_point_command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000966 lc += sizeof(entry_point_command);
967 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000968
Nick Kledzike34182f2013-11-06 21:36:55 +0000969 // Add LC_LOAD_DYLIB commands
970 for (const DependentDylib &dep : _file.dependentDylibs) {
971 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
972 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000973 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000974 dc->cmdsize = size;
975 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000976 // needs to be some constant value different than the one in LC_ID_DYLIB
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000977 dc->dylib.timestamp = 2;
978 dc->dylib.current_version = dep.currentVersion;
979 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000980 if (_swap)
981 swapStruct(*dc);
982 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
983 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
984 lc += size;
985 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000986
987 // Add LC_RPATH
988 for (const StringRef &path : _file.rpaths) {
989 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
Lang Hames2ed3bf92015-10-29 16:50:26 +0000990 uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000991 rpc->cmd = LC_RPATH;
992 rpc->cmdsize = size;
993 rpc->path = sizeof(rpath_command); // offset
994 if (_swap)
995 swapStruct(*rpc);
996 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
997 lc[sizeof(rpath_command)+path.size()] = '\0';
998 lc += size;
999 }
1000
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001001 // Add LC_FUNCTION_STARTS if needed.
1002 if (_functionStartsSize != 0) {
1003 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
1004 dl->cmd = LC_FUNCTION_STARTS;
1005 dl->cmdsize = sizeof(linkedit_data_command);
1006 dl->dataoff = _startOfFunctionStarts;
1007 dl->datasize = _functionStartsSize;
1008 if (_swap)
1009 swapStruct(*dl);
1010 lc += sizeof(linkedit_data_command);
1011 }
1012
Pete Cooper9b28a452016-02-09 02:10:39 +00001013 // Add LC_DATA_IN_CODE if requested.
1014 if (_file.generateDataInCodeLoadCommand) {
Nick Kledzik54ce29582014-10-28 22:21:10 +00001015 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
1016 dl->cmd = LC_DATA_IN_CODE;
1017 dl->cmdsize = sizeof(linkedit_data_command);
1018 dl->dataoff = _startOfDataInCode;
1019 dl->datasize = _dataInCodeSize;
1020 if (_swap)
1021 swapStruct(*dl);
1022 lc += sizeof(linkedit_data_command);
1023 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001024 }
Pete Cooper514594b2016-03-31 00:08:16 +00001025 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +00001026}
1027
Nick Kledzike34182f2013-11-06 21:36:55 +00001028void MachOFileLayout::writeSectionContent() {
1029 for (const Section &s : _file.sections) {
1030 // Copy all section content to output buffer.
Lang Hamesac2adce2015-12-11 23:25:09 +00001031 if (isZeroFillSection(s.type))
Nick Kledzik61fdef62014-05-15 20:59:23 +00001032 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +00001033 if (s.content.empty())
1034 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +00001035 uint32_t offset = _sectInfo[&s].fileOffset;
1036 uint8_t *p = &_buffer[offset];
1037 memcpy(p, &s.content[0], s.content.size());
1038 p += s.content.size();
1039 }
1040}
1041
1042void MachOFileLayout::writeRelocations() {
1043 uint32_t relOffset = _startOfRelocations;
1044 for (Section sect : _file.sections) {
1045 for (Relocation r : sect.relocations) {
1046 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
1047 &_buffer[relOffset]);
1048 *rb = packRelocation(r, _swap, _bigEndianArch);
1049 relOffset += sizeof(any_relocation_info);
1050 }
1051 }
1052}
1053
Nick Kledzike34182f2013-11-06 21:36:55 +00001054void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
1055 uint32_t &symOffset, uint32_t &strOffset) {
1056 for (const Symbol &sym : symbols) {
1057 if (_is64) {
1058 nlist_64* nb = reinterpret_cast<nlist_64*>(&_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_64);
1067 } else {
1068 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
1069 nb->n_strx = strOffset - _startOfSymbolStrings;
1070 nb->n_type = sym.type | sym.scope;
1071 nb->n_sect = sym.sect;
1072 nb->n_desc = sym.desc;
1073 nb->n_value = sym.value;
1074 if (_swap)
1075 swapStruct(*nb);
1076 symOffset += sizeof(nlist);
1077 }
1078 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
1079 strOffset += sym.name.size();
1080 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
1081 }
1082}
1083
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001084void MachOFileLayout::writeFunctionStartsInfo() {
Pete Cooper8e1b9a12016-03-22 22:51:03 +00001085 if (!_functionStartsSize)
1086 return;
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001087 memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
1088 _functionStartsSize);
1089}
1090
Nick Kledzik21921372014-07-24 23:06:56 +00001091void MachOFileLayout::writeDataInCodeInfo() {
1092 uint32_t offset = _startOfDataInCode;
1093 for (const DataInCode &entry : _file.dataInCode) {
1094 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
1095 &_buffer[offset]);
1096 dst->offset = entry.offset;
1097 dst->length = entry.length;
1098 dst->kind = entry.kind;
1099 if (_swap)
1100 swapStruct(*dst);
1101 offset += sizeof(data_in_code_entry);
1102 }
1103}
1104
Nick Kledzike34182f2013-11-06 21:36:55 +00001105void MachOFileLayout::writeSymbolTable() {
1106 // Write symbol table and symbol strings in parallel.
1107 uint32_t symOffset = _startOfSymbols;
1108 uint32_t strOffset = _startOfSymbolStrings;
1109 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
Lang Hames436f7d62016-07-27 22:55:30 +00001110 appendSymbols(_file.stabsSymbols, symOffset, strOffset);
Nick Kledzike34182f2013-11-06 21:36:55 +00001111 appendSymbols(_file.localSymbols, symOffset, strOffset);
1112 appendSymbols(_file.globalSymbols, symOffset, strOffset);
1113 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
1114 // Write indirect symbol table array.
1115 uint32_t *indirects = reinterpret_cast<uint32_t*>
1116 (&_buffer[_startOfIndirectSymbols]);
1117 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1118 // Object files have sections in same order as input normalized file.
1119 for (const Section &section : _file.sections) {
1120 for (uint32_t index : section.indirectSymbols) {
1121 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001122 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001123 else
1124 *indirects++ = index;
1125 }
1126 }
1127 } else {
1128 // Final linked images must sort sections from normalized file.
1129 for (const Segment &seg : _file.segments) {
1130 SegExtraInfo &segInfo = _segInfo[&seg];
1131 for (const Section *section : segInfo.sections) {
1132 for (uint32_t index : section->indirectSymbols) {
1133 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001134 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001135 else
1136 *indirects++ = index;
1137 }
1138 }
1139 }
1140 }
1141}
1142
1143void MachOFileLayout::writeRebaseInfo() {
1144 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
1145}
1146
1147void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001148 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001149 _bindingInfo.bytes(), _bindingInfo.size());
1150}
1151
1152void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001153 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001154 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1155}
1156
Nick Kledzik141330a2014-09-03 19:52:50 +00001157void MachOFileLayout::writeExportInfo() {
1158 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1159}
1160
Nick Kledzike34182f2013-11-06 21:36:55 +00001161void MachOFileLayout::buildLinkEditInfo() {
1162 buildRebaseInfo();
1163 buildBindInfo();
1164 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001165 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001166 computeSymbolTableSizes();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001167 computeFunctionStartsSize();
Nick Kledzik21921372014-07-24 23:06:56 +00001168 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001169}
1170
1171void MachOFileLayout::buildSectionRelocations() {
1172
1173}
1174
1175void MachOFileLayout::buildRebaseInfo() {
1176 // TODO: compress rebasing info.
1177 for (const RebaseLocation& entry : _file.rebasingInfo) {
1178 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001179 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001180 | entry.segIndex);
1181 _rebaseInfo.append_uleb128(entry.segOffset);
1182 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1183 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001184 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001185 _rebaseInfo.align(_is64 ? 8 : 4);
1186}
1187
1188void MachOFileLayout::buildBindInfo() {
1189 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001190 uint64_t lastAddend = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001191 for (const BindLocation& entry : _file.bindingInfo) {
1192 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001193 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001194 | entry.segIndex);
1195 _bindingInfo.append_uleb128(entry.segOffset);
Lang Hames5c692002015-09-28 20:25:14 +00001196 if (entry.ordinal > 0)
1197 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1198 (entry.ordinal & 0xF));
1199 else
1200 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1201 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001202 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1203 _bindingInfo.append_string(entry.symbolName);
Nick Kledzikf373c772014-11-11 01:31:18 +00001204 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001205 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1206 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001207 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001208 }
1209 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1210 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001211 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001212 _bindingInfo.align(_is64 ? 8 : 4);
1213}
1214
1215void MachOFileLayout::buildLazyBindInfo() {
1216 for (const BindLocation& entry : _file.lazyBindingInfo) {
1217 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001218 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001219 | entry.segIndex);
Nick Kledzikf373c772014-11-11 01:31:18 +00001220 _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
Lang Hames5c692002015-09-28 20:25:14 +00001221 if (entry.ordinal > 0)
1222 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1223 (entry.ordinal & 0xF));
1224 else
1225 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1226 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001227 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1228 _lazyBindingInfo.append_string(entry.symbolName);
1229 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001230 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001231 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001232 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001233 _lazyBindingInfo.align(_is64 ? 8 : 4);
1234}
1235
Pete Coopere420dd42016-01-25 21:50:54 +00001236void TrieNode::addSymbol(const Export& entry,
1237 BumpPtrAllocator &allocator,
1238 std::vector<TrieNode*> &allNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001239 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1240 for (TrieEdge &edge : _children) {
1241 StringRef edgeStr = edge._subString;
1242 if (partialStr.startswith(edgeStr)) {
1243 // Already have matching edge, go down that path.
1244 edge._child->addSymbol(entry, allocator, allNodes);
1245 return;
1246 }
1247 // See if string has commmon prefix with existing edge.
1248 for (int n=edgeStr.size()-1; n > 0; --n) {
1249 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1250 // Splice in new node: was A -> C, now A -> B -> C
1251 StringRef bNodeStr = edge._child->_cummulativeString;
1252 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
Eugene Zelenko41547942015-11-10 22:37:38 +00001253 auto *bNode = new (allocator) TrieNode(bNodeStr);
Nick Kledzik141330a2014-09-03 19:52:50 +00001254 allNodes.push_back(bNode);
1255 TrieNode* cNode = edge._child;
1256 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1257 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1258 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1259 << "splice in TrieNode('" << bNodeStr
1260 << "') between edge '"
1261 << abEdgeStr << "' and edge='"
1262 << bcEdgeStr<< "'\n");
1263 TrieEdge& abEdge = edge;
1264 abEdge._subString = abEdgeStr;
1265 abEdge._child = bNode;
Eugene Zelenko41547942015-11-10 22:37:38 +00001266 auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001267 bNode->_children.insert(bNode->_children.end(), bcEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001268 bNode->addSymbol(entry, allocator, allNodes);
1269 return;
1270 }
1271 }
1272 }
1273 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1274 assert(entry.otherOffset != 0);
1275 }
1276 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1277 assert(entry.otherOffset != 0);
1278 }
1279 // No commonality with any existing child, make a new edge.
Eugene Zelenko41547942015-11-10 22:37:38 +00001280 auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1281 auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001282 _children.insert(_children.end(), newEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001283 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1284 << "new TrieNode('" << entry.name << "') with edge '"
1285 << partialStr << "' from node='"
1286 << _cummulativeString << "'\n");
1287 newNode->_address = entry.offset;
1288 newNode->_flags = entry.flags | entry.kind;
1289 newNode->_other = entry.otherOffset;
1290 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1291 newNode->_importedName = entry.otherName.copy(allocator);
1292 newNode->_hasExportInfo = true;
1293 allNodes.push_back(newNode);
1294}
1295
Pete Cooperd0de3682016-08-05 21:37:12 +00001296void TrieNode::addOrderedNodes(const Export& entry,
1297 std::vector<TrieNode*> &orderedNodes) {
1298 if (!_ordered) {
1299 orderedNodes.push_back(this);
1300 _ordered = true;
1301 }
1302
1303 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1304 for (TrieEdge &edge : _children) {
1305 StringRef edgeStr = edge._subString;
1306 if (partialStr.startswith(edgeStr)) {
1307 // Already have matching edge, go down that path.
1308 edge._child->addOrderedNodes(entry, orderedNodes);
1309 return;
1310 }
1311 }
1312}
1313
Pete Coopere420dd42016-01-25 21:50:54 +00001314bool TrieNode::updateOffset(uint32_t& offset) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001315 uint32_t nodeSize = 1; // Length when no export info
1316 if (_hasExportInfo) {
1317 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1318 nodeSize = llvm::getULEB128Size(_flags);
1319 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1320 nodeSize += _importedName.size();
1321 ++nodeSize; // Trailing zero in imported name.
1322 } else {
1323 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1324 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1325 nodeSize += llvm::getULEB128Size(_other);
1326 }
1327 // Overall node size so far is uleb128 of export info + actual export info.
1328 nodeSize += llvm::getULEB128Size(nodeSize);
1329 }
1330 // Compute size of all child edges.
1331 ++nodeSize; // Byte for number of chidren.
1332 for (TrieEdge &edge : _children) {
1333 nodeSize += edge._subString.size() + 1 // String length.
1334 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1335 }
1336 // On input, 'offset' is new prefered location for this node.
1337 bool result = (_trieOffset != offset);
1338 // Store new location in node object for use by parents.
1339 _trieOffset = offset;
1340 // Update offset for next iteration.
1341 offset += nodeSize;
1342 // Return true if _trieOffset was changed.
1343 return result;
1344}
1345
Pete Coopere420dd42016-01-25 21:50:54 +00001346void TrieNode::appendToByteBuffer(ByteBuffer &out) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001347 if (_hasExportInfo) {
1348 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1349 if (!_importedName.empty()) {
1350 // nodes with re-export info: size, flags, ordinal, import-name
1351 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1352 + llvm::getULEB128Size(_other)
1353 + _importedName.size() + 1;
1354 assert(nodeSize < 256);
1355 out.append_byte(nodeSize);
1356 out.append_uleb128(_flags);
1357 out.append_uleb128(_other);
1358 out.append_string(_importedName);
1359 } else {
1360 // nodes without re-export info: size, flags, ordinal, empty-string
1361 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1362 + llvm::getULEB128Size(_other) + 1;
1363 assert(nodeSize < 256);
1364 out.append_byte(nodeSize);
1365 out.append_uleb128(_flags);
1366 out.append_uleb128(_other);
1367 out.append_byte(0);
1368 }
1369 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1370 // Nodes with export info: size, flags, address, other
1371 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1372 + llvm::getULEB128Size(_address)
1373 + llvm::getULEB128Size(_other);
1374 assert(nodeSize < 256);
1375 out.append_byte(nodeSize);
1376 out.append_uleb128(_flags);
1377 out.append_uleb128(_address);
1378 out.append_uleb128(_other);
1379 } else {
1380 // Nodes with export info: size, flags, address
1381 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1382 + llvm::getULEB128Size(_address);
1383 assert(nodeSize < 256);
1384 out.append_byte(nodeSize);
1385 out.append_uleb128(_flags);
1386 out.append_uleb128(_address);
1387 }
1388 } else {
1389 // Node with no export info.
1390 uint32_t nodeSize = 0;
1391 out.append_byte(nodeSize);
1392 }
1393 // Add number of children.
1394 assert(_children.size() < 256);
1395 out.append_byte(_children.size());
1396 // Append each child edge substring and node offset.
1397 for (TrieEdge &edge : _children) {
1398 out.append_string(edge._subString);
1399 out.append_uleb128(edge._child->_trieOffset);
1400 }
1401}
1402
1403void MachOFileLayout::buildExportTrie() {
1404 if (_file.exportInfo.empty())
1405 return;
1406
1407 // For all temporary strings and objects used building trie.
1408 BumpPtrAllocator allocator;
1409
1410 // Build trie of all exported symbols.
Eugene Zelenko41547942015-11-10 22:37:38 +00001411 auto *rootNode = new (allocator) TrieNode(StringRef());
Nick Kledzik141330a2014-09-03 19:52:50 +00001412 std::vector<TrieNode*> allNodes;
1413 allNodes.reserve(_file.exportInfo.size()*2);
1414 allNodes.push_back(rootNode);
1415 for (const Export& entry : _file.exportInfo) {
1416 rootNode->addSymbol(entry, allocator, allNodes);
1417 }
1418
Pete Cooperd0de3682016-08-05 21:37:12 +00001419 std::vector<TrieNode*> orderedNodes;
1420 orderedNodes.reserve(allNodes.size());
1421
1422 for (const Export& entry : _file.exportInfo)
1423 rootNode->addOrderedNodes(entry, orderedNodes);
1424
Nick Kledzik141330a2014-09-03 19:52:50 +00001425 // Assign each node in the vector an offset in the trie stream, iterating
1426 // until all uleb128 sizes have stabilized.
1427 bool more;
1428 do {
1429 uint32_t offset = 0;
1430 more = false;
Pete Cooperd0de3682016-08-05 21:37:12 +00001431 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001432 if (node->updateOffset(offset))
1433 more = true;
1434 }
1435 } while (more);
1436
1437 // Serialize trie to ByteBuffer.
Pete Cooperd0de3682016-08-05 21:37:12 +00001438 for (TrieNode* node : orderedNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001439 node->appendToByteBuffer(_exportTrie);
1440 }
1441 _exportTrie.align(_is64 ? 8 : 4);
1442}
1443
Nick Kledzike34182f2013-11-06 21:36:55 +00001444void MachOFileLayout::computeSymbolTableSizes() {
1445 // MachO symbol tables have three ranges: locals, globals, and undefines
1446 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Lang Hames436f7d62016-07-27 22:55:30 +00001447 _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
1448 + _file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001449 + _file.globalSymbols.size()
1450 + _file.undefinedSymbols.size());
Lang Hames201c08f2015-12-10 00:12:24 +00001451 _symbolStringPoolSize = 1; // Always reserve 1-byte for the empty string.
Lang Hames436f7d62016-07-27 22:55:30 +00001452 for (const Symbol &sym : _file.stabsSymbols) {
1453 _symbolStringPoolSize += (sym.name.size()+1);
1454 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001455 for (const Symbol &sym : _file.localSymbols) {
1456 _symbolStringPoolSize += (sym.name.size()+1);
1457 }
1458 for (const Symbol &sym : _file.globalSymbols) {
1459 _symbolStringPoolSize += (sym.name.size()+1);
1460 }
1461 for (const Symbol &sym : _file.undefinedSymbols) {
1462 _symbolStringPoolSize += (sym.name.size()+1);
1463 }
1464 _symbolTableLocalsStartIndex = 0;
Lang Hames436f7d62016-07-27 22:55:30 +00001465 _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
1466 _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001467 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001468 + _file.globalSymbols.size();
1469
1470 _indirectSymbolTableCount = 0;
1471 for (const Section &sect : _file.sections) {
1472 _indirectSymbolTableCount += sect.indirectSymbols.size();
1473 }
1474}
1475
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001476void MachOFileLayout::computeFunctionStartsSize() {
1477 _functionStartsSize = _file.functionStarts.size();
1478}
1479
Nick Kledzik21921372014-07-24 23:06:56 +00001480void MachOFileLayout::computeDataInCodeSize() {
1481 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1482}
Nick Kledzike34182f2013-11-06 21:36:55 +00001483
1484void MachOFileLayout::writeLinkEditContent() {
1485 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1486 writeRelocations();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001487 writeFunctionStartsInfo();
Nick Kledzik21921372014-07-24 23:06:56 +00001488 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001489 writeSymbolTable();
1490 } else {
1491 writeRebaseInfo();
1492 writeBindingInfo();
1493 writeLazyBindingInfo();
1494 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001495 writeExportInfo();
Pete Cooper41f3e8e2016-02-09 01:38:13 +00001496 writeFunctionStartsInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001497 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001498 writeSymbolTable();
1499 }
1500}
1501
Pete Cooperfefbd222016-03-30 23:10:39 +00001502llvm::Error MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001503 // Check for pending error from constructor.
1504 if (_ec)
Pete Cooperfefbd222016-03-30 23:10:39 +00001505 return llvm::errorCodeToError(_ec);
Nick Kledzike34182f2013-11-06 21:36:55 +00001506 // Create FileOutputBuffer with calculated size.
Nick Kledzike34182f2013-11-06 21:36:55 +00001507 unsigned flags = 0;
1508 if (_file.fileType != llvm::MachO::MH_OBJECT)
1509 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001510 ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
1511 llvm::FileOutputBuffer::create(path, size(), flags);
1512 if (std::error_code ec = fobOrErr.getError())
Pete Cooperfefbd222016-03-30 23:10:39 +00001513 return llvm::errorCodeToError(ec);
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001514 std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
Nick Kledzike34182f2013-11-06 21:36:55 +00001515 // Write content.
1516 _buffer = fob->getBufferStart();
1517 writeMachHeader();
Pete Cooper514594b2016-03-31 00:08:16 +00001518 if (auto ec = writeLoadCommands())
Pete Cooperdc59c792016-03-31 00:38:02 +00001519 return ec;
Nick Kledzike34182f2013-11-06 21:36:55 +00001520 writeSectionContent();
1521 writeLinkEditContent();
1522 fob->commit();
1523
Pete Cooperfefbd222016-03-30 23:10:39 +00001524 return llvm::Error();
Nick Kledzike34182f2013-11-06 21:36:55 +00001525}
1526
Nick Kledzike34182f2013-11-06 21:36:55 +00001527/// Takes in-memory normalized view and writes a mach-o object file.
Pete Cooperfefbd222016-03-30 23:10:39 +00001528llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001529 MachOFileLayout layout(file);
1530 return layout.writeBinary(path);
1531}
1532
Nick Kledzike34182f2013-11-06 21:36:55 +00001533} // namespace normalized
1534} // namespace mach_o
1535} // namespace lld