blob: 8a11a5c7bac1d727e69ca9bed15a4698e65fde9e [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"
Nick Kledzik00a15d92013-11-09 01:00:51 +000040#include "llvm/Support/LEB128.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000041#include "llvm/Support/MachO.h"
42#include "llvm/Support/MemoryBuffer.h"
43#include "llvm/Support/raw_ostream.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000044#include <functional>
Nick Kledzik07ba5122014-12-02 01:50:44 +000045#include <list>
Nick Kledzike34182f2013-11-06 21:36:55 +000046#include <map>
Rafael Espindola54427cc2014-06-12 17:15:58 +000047#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000048
49using namespace llvm::MachO;
50
51namespace lld {
52namespace mach_o {
53namespace normalized {
54
Pete Coopere420dd42016-01-25 21:50:54 +000055class ByteBuffer {
56public:
57 ByteBuffer() : _ostream(_bytes) { }
58
59 void append_byte(uint8_t b) {
60 _ostream << b;
61 }
62 void append_uleb128(uint64_t value) {
63 llvm::encodeULEB128(value, _ostream);
64 }
65 void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
66 unsigned min = llvm::getULEB128Size(value);
67 assert(min <= byteCount);
68 unsigned pad = byteCount - min;
69 llvm::encodeULEB128(value, _ostream, pad);
70 }
71 void append_sleb128(int64_t value) {
72 llvm::encodeSLEB128(value, _ostream);
73 }
74 void append_string(StringRef str) {
75 _ostream << str;
76 append_byte(0);
77 }
78 void align(unsigned alignment) {
79 while ( (_ostream.tell() % alignment) != 0 )
80 append_byte(0);
81 }
82 size_t size() {
83 return _ostream.tell();
84 }
85 const uint8_t *bytes() {
86 return reinterpret_cast<const uint8_t*>(_ostream.str().data());
87 }
88
89private:
90 SmallVector<char, 128> _bytes;
91 // Stream ivar must be after SmallVector ivar to construct properly.
92 llvm::raw_svector_ostream _ostream;
93};
94
95struct TrieNode; // Forward declaration.
96
97struct TrieEdge : public llvm::ilist_node<TrieEdge> {
98 TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
99
100 StringRef _subString;
101 struct TrieNode *_child;
102};
103
104} // namespace normalized
105} // namespace mach_o
106} // namespace lld
107
108
109namespace llvm {
110 using lld::mach_o::normalized::TrieEdge;
111 template <>
112 struct ilist_traits<TrieEdge>
113 : public ilist_default_traits<TrieEdge> {
114 private:
115 mutable ilist_half_node<TrieEdge> Sentinel;
116 public:
117 TrieEdge *createSentinel() const {
118 return static_cast<TrieEdge*>(&Sentinel);
119 }
120 void destroySentinel(TrieEdge *) const {}
121
122 TrieEdge *provideInitialHead() const { return createSentinel(); }
123 TrieEdge *ensureHead(TrieEdge*) const { return createSentinel(); }
124 static void noteHead(TrieEdge*, TrieEdge*) {}
125 void deleteNode(TrieEdge *N) {}
126
127 private:
128 void createNode(const TrieEdge &);
129 };
130} // namespace llvm
131
132
133namespace lld {
134namespace mach_o {
135namespace normalized {
136
137struct TrieNode {
138 typedef llvm::ilist<TrieEdge> TrieEdgeList;
139
140 TrieNode(StringRef s)
141 : _cummulativeString(s), _address(0), _flags(0), _other(0),
142 _trieOffset(0), _hasExportInfo(false) {}
143 ~TrieNode() = default;
144
145 void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
146 std::vector<TrieNode *> &allNodes);
147 bool updateOffset(uint32_t &offset);
148 void appendToByteBuffer(ByteBuffer &out);
149
150private:
151 StringRef _cummulativeString;
152 TrieEdgeList _children;
153 uint64_t _address;
154 uint64_t _flags;
155 uint64_t _other;
156 StringRef _importedName;
157 uint32_t _trieOffset;
158 bool _hasExportInfo;
159};
160
Nick Kledzike34182f2013-11-06 21:36:55 +0000161/// Utility class for writing a mach-o binary file given an in-memory
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000162/// normalized file.
Nick Kledzike34182f2013-11-06 21:36:55 +0000163class MachOFileLayout {
164public:
Joey Goulyb275d7f2013-12-23 23:29:50 +0000165 /// All layout computation is done in the constructor.
166 MachOFileLayout(const NormalizedFile &file);
167
Nick Kledzike34182f2013-11-06 21:36:55 +0000168 /// Returns the final file size as computed in the constructor.
169 size_t size() const;
170
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000171 // Returns size of the mach_header and load commands.
172 size_t headerAndLoadCommandsSize() const;
173
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000174 /// Writes the normalized file as a binary mach-o file to the specified
Nick Kledzike34182f2013-11-06 21:36:55 +0000175 /// path. This does not have a stream interface because the generated
176 /// file may need the 'x' bit set.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000177 std::error_code writeBinary(StringRef path);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000178
Nick Kledzike34182f2013-11-06 21:36:55 +0000179private:
180 uint32_t loadCommandsSize(uint32_t &count);
181 void buildFileOffsets();
182 void writeMachHeader();
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000183 std::error_code writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +0000184 void writeSectionContent();
185 void writeRelocations();
186 void writeSymbolTable();
187 void writeRebaseInfo();
188 void writeBindingInfo();
189 void writeLazyBindingInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000190 void writeExportInfo();
Nick Kledzik21921372014-07-24 23:06:56 +0000191 void writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +0000192 void writeLinkEditContent();
193 void buildLinkEditInfo();
194 void buildRebaseInfo();
195 void buildBindInfo();
196 void buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +0000197 void buildExportTrie();
Nick Kledzik21921372014-07-24 23:06:56 +0000198 void computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000199 void computeSymbolTableSizes();
200 void buildSectionRelocations();
201 void appendSymbols(const std::vector<Symbol> &symbols,
202 uint32_t &symOffset, uint32_t &strOffset);
203 uint32_t indirectSymbolIndex(const Section &sect, uint32_t &index);
204 uint32_t indirectSymbolElementSize(const Section &sect);
205
Nick Kledzik29f749e2013-11-09 00:07:28 +0000206 // For use as template parameter to load command methods.
207 struct MachO64Trait {
208 typedef llvm::MachO::segment_command_64 command;
209 typedef llvm::MachO::section_64 section;
210 enum { LC = llvm::MachO::LC_SEGMENT_64 };
211 };
212
213 // For use as template parameter to load command methods.
214 struct MachO32Trait {
215 typedef llvm::MachO::segment_command command;
216 typedef llvm::MachO::section section;
217 enum { LC = llvm::MachO::LC_SEGMENT };
218 };
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000219
Nick Kledzik29f749e2013-11-09 00:07:28 +0000220 template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000221 std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
222 template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000223
Nick Kledzike34182f2013-11-06 21:36:55 +0000224 uint32_t pointerAlign(uint32_t value);
225 static StringRef dyldPath();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000226
Nick Kledzike34182f2013-11-06 21:36:55 +0000227 struct SegExtraInfo {
228 uint32_t fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000229 uint32_t fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000230 std::vector<const Section*> sections;
231 };
232 typedef std::map<const Segment*, SegExtraInfo> SegMap;
233 struct SectionExtraInfo {
234 uint32_t fileOffset;
235 };
236 typedef std::map<const Section*, SectionExtraInfo> SectionMap;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000237
Nick Kledzike34182f2013-11-06 21:36:55 +0000238 const NormalizedFile &_file;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000239 std::error_code _ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000240 uint8_t *_buffer;
241 const bool _is64;
242 const bool _swap;
243 const bool _bigEndianArch;
244 uint64_t _seg1addr;
245 uint32_t _startOfLoadCommands;
246 uint32_t _countOfLoadCommands;
247 uint32_t _endOfLoadCommands;
248 uint32_t _startOfRelocations;
Nick Kledzik21921372014-07-24 23:06:56 +0000249 uint32_t _startOfDataInCode;
Nick Kledzike34182f2013-11-06 21:36:55 +0000250 uint32_t _startOfSymbols;
251 uint32_t _startOfIndirectSymbols;
252 uint32_t _startOfSymbolStrings;
253 uint32_t _endOfSymbolStrings;
254 uint32_t _symbolTableLocalsStartIndex;
255 uint32_t _symbolTableGlobalsStartIndex;
256 uint32_t _symbolTableUndefinesStartIndex;
257 uint32_t _symbolStringPoolSize;
258 uint32_t _symbolTableSize;
Nick Kledzik21921372014-07-24 23:06:56 +0000259 uint32_t _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000260 uint32_t _indirectSymbolTableCount;
261 // Used in object file creation only
262 uint32_t _startOfSectionsContent;
263 uint32_t _endOfSectionsContent;
264 // Used in final linked image only
265 uint32_t _startOfLinkEdit;
266 uint32_t _startOfRebaseInfo;
267 uint32_t _endOfRebaseInfo;
268 uint32_t _startOfBindingInfo;
269 uint32_t _endOfBindingInfo;
270 uint32_t _startOfLazyBindingInfo;
271 uint32_t _endOfLazyBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000272 uint32_t _startOfExportTrie;
273 uint32_t _endOfExportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000274 uint32_t _endOfLinkEdit;
275 uint64_t _addressOfLinkEdit;
276 SegMap _segInfo;
277 SectionMap _sectInfo;
278 ByteBuffer _rebaseInfo;
279 ByteBuffer _bindingInfo;
280 ByteBuffer _lazyBindingInfo;
281 ByteBuffer _weakBindingInfo;
Nick Kledzik141330a2014-09-03 19:52:50 +0000282 ByteBuffer _exportTrie;
Nick Kledzike34182f2013-11-06 21:36:55 +0000283};
284
285size_t headerAndLoadCommandsSize(const NormalizedFile &file) {
286 MachOFileLayout layout(file);
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000287 return layout.headerAndLoadCommandsSize();
Nick Kledzike34182f2013-11-06 21:36:55 +0000288}
289
290StringRef MachOFileLayout::dyldPath() {
291 return "/usr/lib/dyld";
292}
293
294uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
Rui Ueyama489a8062016-01-14 20:53:50 +0000295 return llvm::alignTo(value, _is64 ? 8 : 4);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000296}
Nick Kledzike34182f2013-11-06 21:36:55 +0000297
298
Nick Kledzik2fcbe822014-07-30 00:58:06 +0000299size_t MachOFileLayout::headerAndLoadCommandsSize() const {
300 return _endOfLoadCommands;
301}
Nick Kledzike34182f2013-11-06 21:36:55 +0000302
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000303MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
Nick Kledzike34182f2013-11-06 21:36:55 +0000304 : _file(file),
305 _is64(MachOLinkingContext::is64Bit(file.arch)),
306 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
307 _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
308 _seg1addr(INT64_MAX) {
309 _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000310 const size_t segCommandBaseSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000311 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
312 const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
313 if (file.fileType == llvm::MachO::MH_OBJECT) {
314 // object files have just one segment load command containing all sections
315 _endOfLoadCommands = _startOfLoadCommands
316 + segCommandBaseSize
317 + file.sections.size() * sectsSize
318 + sizeof(symtab_command);
319 _countOfLoadCommands = 2;
Pete Cooperceee5de2016-02-04 02:16:08 +0000320 if (file.hasMinVersionLoadCommand) {
321 _endOfLoadCommands += sizeof(version_min_command);
322 _countOfLoadCommands++;
323 }
Nick Kledzik21921372014-07-24 23:06:56 +0000324 if (!_file.dataInCode.empty()) {
325 _endOfLoadCommands += sizeof(linkedit_data_command);
326 _countOfLoadCommands++;
327 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000328 // Assign file offsets to each section.
Nick Kledzike34182f2013-11-06 21:36:55 +0000329 _startOfSectionsContent = _endOfLoadCommands;
Nick Kledzike34182f2013-11-06 21:36:55 +0000330 unsigned relocCount = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000331 uint64_t offset = _startOfSectionsContent;
Nick Kledzike34182f2013-11-06 21:36:55 +0000332 for (const Section &sect : file.sections) {
Lang Hamesac2adce2015-12-11 23:25:09 +0000333 if (isZeroFillSection(sect.type))
334 _sectInfo[&sect].fileOffset = 0;
335 else {
Rui Ueyama489a8062016-01-14 20:53:50 +0000336 offset = llvm::alignTo(offset, sect.alignment);
Nick Kledzikb072c362014-11-18 00:30:29 +0000337 _sectInfo[&sect].fileOffset = offset;
338 offset += sect.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000339 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000340 relocCount += sect.relocations.size();
341 }
Nick Kledzikb072c362014-11-18 00:30:29 +0000342 _endOfSectionsContent = offset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000343
Nick Kledzike34182f2013-11-06 21:36:55 +0000344 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +0000345 computeDataInCodeSize();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000346
Nick Kledzike34182f2013-11-06 21:36:55 +0000347 // Align start of relocations.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000348 _startOfRelocations = pointerAlign(_endOfSectionsContent);
Nick Kledzik21921372014-07-24 23:06:56 +0000349 _startOfDataInCode = _startOfRelocations + relocCount * 8;
350 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000351 // Add Indirect symbol table.
352 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
353 // Align start of symbol table and symbol strings.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000354 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000355 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000356 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000357 + pointerAlign(_symbolStringPoolSize);
358 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000359 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000360 llvm::dbgs() << "MachOFileLayout()\n"
361 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
362 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
363 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
364 << " startOfRelocations=" << _startOfRelocations << "\n"
365 << " startOfSymbols=" << _startOfSymbols << "\n"
366 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
367 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
368 << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
369 << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
370 } else {
371 // Final linked images have one load command per segment.
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000372 _endOfLoadCommands = _startOfLoadCommands
Nick Kledzike34182f2013-11-06 21:36:55 +0000373 + loadCommandsSize(_countOfLoadCommands);
374
375 // Assign section file offsets.
376 buildFileOffsets();
377 buildLinkEditInfo();
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000378
Nick Kledzike34182f2013-11-06 21:36:55 +0000379 // LINKEDIT of final linked images has in order:
380 // rebase info, binding info, lazy binding info, weak binding info,
Nick Kledzik21921372014-07-24 23:06:56 +0000381 // data-in-code, symbol table, indirect symbol table, symbol table strings.
Nick Kledzike34182f2013-11-06 21:36:55 +0000382 _startOfRebaseInfo = _startOfLinkEdit;
383 _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
384 _startOfBindingInfo = _endOfRebaseInfo;
385 _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
386 _startOfLazyBindingInfo = _endOfBindingInfo;
387 _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000388 _startOfExportTrie = _endOfLazyBindingInfo;
389 _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
390 _startOfDataInCode = _endOfExportTrie;
Nick Kledzik21921372014-07-24 23:06:56 +0000391 _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000392 _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000393 _startOfSymbolStrings = _startOfIndirectSymbols
Nick Kledzike34182f2013-11-06 21:36:55 +0000394 + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000395 _endOfSymbolStrings = _startOfSymbolStrings
Nick Kledzike34182f2013-11-06 21:36:55 +0000396 + pointerAlign(_symbolStringPoolSize);
397 _endOfLinkEdit = _endOfSymbolStrings;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000398 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000399 llvm::dbgs() << "MachOFileLayout()\n"
400 << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
401 << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
402 << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
403 << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
404 << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
405 << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
406 << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
407 << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
408 << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
409 << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
Nick Kledzik141330a2014-09-03 19:52:50 +0000410 << " startOfExportTrie=" << _startOfExportTrie << "\n"
411 << " endOfExportTrie=" << _endOfExportTrie << "\n"
Nick Kledzik21921372014-07-24 23:06:56 +0000412 << " startOfDataInCode=" << _startOfDataInCode << "\n"
Nick Kledzike34182f2013-11-06 21:36:55 +0000413 << " startOfSymbols=" << _startOfSymbols << "\n"
414 << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
415 << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
416 << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
417 }
418}
419
420uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
421 uint32_t size = 0;
422 count = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000423
424 const size_t segCommandSize =
Nick Kledzike34182f2013-11-06 21:36:55 +0000425 (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
426 const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
427
428 // Add LC_SEGMENT for each segment.
429 size += _file.segments.size() * segCommandSize;
430 count += _file.segments.size();
431 // Add section record for each section.
432 size += _file.sections.size() * sectionSize;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000433
Tim Northover301c4e62014-07-01 08:15:41 +0000434 // If creating a dylib, add LC_ID_DYLIB.
435 if (_file.fileType == llvm::MachO::MH_DYLIB) {
436 size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
437 ++count;
438 }
439
Nick Kledzike34182f2013-11-06 21:36:55 +0000440 // Add LC_DYLD_INFO
441 size += sizeof(dyld_info_command);
442 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000443
Nick Kledzike34182f2013-11-06 21:36:55 +0000444 // Add LC_SYMTAB
445 size += sizeof(symtab_command);
446 ++count;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000447
Nick Kledzike34182f2013-11-06 21:36:55 +0000448 // Add LC_DYSYMTAB
449 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
450 size += sizeof(dysymtab_command);
451 ++count;
452 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000453
Pete Cooper354809e2016-02-03 22:28:29 +0000454 // If main executable add LC_LOAD_DYLINKER
Nick Kledzike34182f2013-11-06 21:36:55 +0000455 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
456 size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
457 ++count;
Pete Cooper354809e2016-02-03 22:28:29 +0000458 }
459
460 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
461 // LC_VERSION_MIN_TVOS
462 if (_file.hasMinVersionLoadCommand) {
463 size += sizeof(version_min_command);
464 ++count;
465 }
466
Pete Cooper40576fa2016-02-04 02:45:23 +0000467 // Add LC_SOURCE_VERSION
468 size += sizeof(source_version_command);
469 ++count;
470
Pete Cooper354809e2016-02-03 22:28:29 +0000471 // If main executable add LC_MAIN
472 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000473 size += sizeof(entry_point_command);
474 ++count;
475 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000476
Nick Kledzike34182f2013-11-06 21:36:55 +0000477 // Add LC_LOAD_DYLIB for each dependent dylib.
478 for (const DependentDylib &dep : _file.dependentDylibs) {
479 size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
480 ++count;
481 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000482
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000483 // Add LC_RPATH
484 for (const StringRef &path : _file.rpaths) {
Lang Hames2ed3bf92015-10-29 16:50:26 +0000485 size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000486 ++count;
487 }
488
Nick Kledzik54ce29582014-10-28 22:21:10 +0000489 // Add LC_DATA_IN_CODE if needed
490 if (!_file.dataInCode.empty()) {
491 size += sizeof(linkedit_data_command);
492 ++count;
493 }
494
Nick Kledzike34182f2013-11-06 21:36:55 +0000495 return size;
496}
497
498static bool overlaps(const Segment &s1, const Segment &s2) {
499 if (s2.address >= s1.address+s1.size)
500 return false;
501 if (s1.address >= s2.address+s2.size)
502 return false;
503 return true;
504}
505
506static bool overlaps(const Section &s1, const Section &s2) {
507 if (s2.address >= s1.address+s1.content.size())
508 return false;
509 if (s1.address >= s2.address+s2.content.size())
510 return false;
511 return true;
512}
513
514void MachOFileLayout::buildFileOffsets() {
515 // Verify no segments overlap
516 for (const Segment &sg1 : _file.segments) {
517 for (const Segment &sg2 : _file.segments) {
518 if (&sg1 == &sg2)
519 continue;
520 if (overlaps(sg1,sg2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000521 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000522 return;
523 }
524 }
525 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000526
527 // Verify no sections overlap
Nick Kledzike34182f2013-11-06 21:36:55 +0000528 for (const Section &s1 : _file.sections) {
529 for (const Section &s2 : _file.sections) {
530 if (&s1 == &s2)
531 continue;
532 if (overlaps(s1,s2)) {
Rafael Espindola372bc702014-06-13 17:20:48 +0000533 _ec = make_error_code(llvm::errc::executable_format_error);
Nick Kledzike34182f2013-11-06 21:36:55 +0000534 return;
535 }
536 }
537 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000538
Nick Kledzike34182f2013-11-06 21:36:55 +0000539 // Build side table of extra info about segments and sections.
540 SegExtraInfo t;
541 t.fileOffset = 0;
542 for (const Segment &sg : _file.segments) {
543 _segInfo[&sg] = t;
544 }
545 SectionExtraInfo t2;
546 t2.fileOffset = 0;
547 // Assign sections to segments.
548 for (const Section &s : _file.sections) {
549 _sectInfo[&s] = t2;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000550 bool foundSegment = false;
Nick Kledzike34182f2013-11-06 21:36:55 +0000551 for (const Segment &sg : _file.segments) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000552 if (sg.name.equals(s.segmentName)) {
553 if ((s.address >= sg.address)
Nick Kledzike34182f2013-11-06 21:36:55 +0000554 && (s.address+s.content.size() <= sg.address+sg.size)) {
Nick Kledzik1bebb282014-09-09 23:52:59 +0000555 _segInfo[&sg].sections.push_back(&s);
556 foundSegment = true;
557 break;
Nick Kledzike34182f2013-11-06 21:36:55 +0000558 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000559 }
560 }
Nick Kledzik1bebb282014-09-09 23:52:59 +0000561 if (!foundSegment) {
562 _ec = make_error_code(llvm::errc::executable_format_error);
563 return;
564 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000565 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000566
Nick Kledzike34182f2013-11-06 21:36:55 +0000567 // Assign file offsets.
568 uint32_t fileOffset = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000569 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000570 llvm::dbgs() << "buildFileOffsets()\n");
571 for (const Segment &sg : _file.segments) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000572 _segInfo[&sg].fileOffset = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000573 if ((_seg1addr == INT64_MAX) && sg.access)
574 _seg1addr = sg.address;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000575 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000576 llvm::dbgs() << " segment=" << sg.name
577 << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
Tim Northover08d6a7b2014-06-30 09:49:30 +0000578
579 uint32_t segFileSize = 0;
Nick Kledzik761d6542014-10-24 22:19:22 +0000580 // A segment that is not zero-fill must use a least one page of disk space.
581 if (sg.access)
582 segFileSize = _file.pageSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000583 for (const Section *s : _segInfo[&sg].sections) {
Tim Northover08d6a7b2014-06-30 09:49:30 +0000584 uint32_t sectOffset = s->address - sg.address;
585 uint32_t sectFileSize =
Lang Hamesac2adce2015-12-11 23:25:09 +0000586 isZeroFillSection(s->type) ? 0 : s->content.size();
Tim Northover08d6a7b2014-06-30 09:49:30 +0000587 segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
588
589 _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000590 DEBUG_WITH_TYPE("MachOFileLayout",
Nick Kledzike34182f2013-11-06 21:36:55 +0000591 llvm::dbgs() << " section=" << s->sectionName
592 << ", fileOffset=" << fileOffset << "\n");
593 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000594
Pete Cooper353652f2016-02-06 00:14:15 +0000595 // round up all segments to page aligned, except __LINKEDIT
596 if (!sg.name.equals("__LINKEDIT")) {
597 _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
598 fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
599 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000600 _addressOfLinkEdit = sg.address + sg.size;
601 }
Tim Northover08d6a7b2014-06-30 09:49:30 +0000602 _startOfLinkEdit = fileOffset;
Nick Kledzike34182f2013-11-06 21:36:55 +0000603}
604
Nick Kledzike34182f2013-11-06 21:36:55 +0000605size_t MachOFileLayout::size() const {
606 return _endOfSymbolStrings;
607}
608
609void MachOFileLayout::writeMachHeader() {
Pete Cooper8563e5a2016-02-04 20:43:43 +0000610 auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
611 // dynamic x86 executables on newer OS version should also set the
612 // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
613 // FIXME: Check that this is a dynamic executable, not a static one.
614 if (_file.fileType == llvm::MachO::MH_EXECUTE &&
615 cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
616 _file.os == MachOLinkingContext::OS::macOSX) {
617 uint32_t version;
618 bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
619 if (!failed && _file.minOSverson >= version)
620 cpusubtype |= CPU_SUBTYPE_LIB64;
621 }
622
Nick Kledzike34182f2013-11-06 21:36:55 +0000623 mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
624 mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
625 mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
Pete Cooper8563e5a2016-02-04 20:43:43 +0000626 mh->cpusubtype = cpusubtype;
Nick Kledzike34182f2013-11-06 21:36:55 +0000627 mh->filetype = _file.fileType;
628 mh->ncmds = _countOfLoadCommands;
629 mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
630 mh->flags = _file.flags;
631 if (_swap)
632 swapStruct(*mh);
633}
634
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000635uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
Nick Kledzike34182f2013-11-06 21:36:55 +0000636 uint32_t &index) {
637 if (sect.indirectSymbols.empty())
638 return 0;
639 uint32_t result = index;
640 index += sect.indirectSymbols.size();
641 return result;
642}
643
644uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
645 if (sect.indirectSymbols.empty())
646 return 0;
647 if (sect.type != S_SYMBOL_STUBS)
648 return 0;
649 return sect.content.size() / sect.indirectSymbols.size();
650}
651
Nick Kledzik29f749e2013-11-09 00:07:28 +0000652template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000653std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
Nick Kledzik29f749e2013-11-09 00:07:28 +0000654 typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
655 seg->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000656 seg->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000657 + _file.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000658 uint8_t *next = lc + seg->cmdsize;
659 memset(seg->segname, 0, 16);
660 seg->vmaddr = 0;
Nick Kledzikb072c362014-11-18 00:30:29 +0000661 seg->vmsize = _file.sections.back().address
662 + _file.sections.back().content.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000663 seg->fileoff = _endOfLoadCommands;
664 seg->filesize = seg->vmsize;
665 seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
666 seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
667 seg->nsects = _file.sections.size();
668 seg->flags = 0;
669 if (_swap)
670 swapStruct(*seg);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000671 typename T::section *sout = reinterpret_cast<typename T::section*>
672 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000673 uint32_t relOffset = _startOfRelocations;
Nick Kledzike34182f2013-11-06 21:36:55 +0000674 uint32_t indirectSymRunningIndex = 0;
675 for (const Section &sin : _file.sections) {
676 setString16(sin.sectionName, sout->sectname);
677 setString16(sin.segmentName, sout->segname);
678 sout->addr = sin.address;
679 sout->size = sin.content.size();
Nick Kledzikb072c362014-11-18 00:30:29 +0000680 sout->offset = _sectInfo[&sin].fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000681 sout->align = llvm::Log2_32(sin.alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000682 sout->reloff = sin.relocations.empty() ? 0 : relOffset;
683 sout->nreloc = sin.relocations.size();
684 sout->flags = sin.type | sin.attributes;
685 sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
686 sout->reserved2 = indirectSymbolElementSize(sin);
687 relOffset += sin.relocations.size() * sizeof(any_relocation_info);
Nick Kledzike34182f2013-11-06 21:36:55 +0000688 if (_swap)
689 swapStruct(*sout);
690 ++sout;
691 }
692 lc = next;
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000693 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000694}
695
Nick Kledzik29f749e2013-11-09 00:07:28 +0000696template <typename T>
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000697std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000698 uint32_t indirectSymRunningIndex = 0;
699 for (const Segment &seg : _file.segments) {
Pete Cooper353652f2016-02-06 00:14:15 +0000700 // Link edit has no sections and a custom range of address, so handle it
701 // specially.
Nick Kledzike34182f2013-11-06 21:36:55 +0000702 SegExtraInfo &segInfo = _segInfo[&seg];
Pete Cooper353652f2016-02-06 00:14:15 +0000703 if (seg.name.equals("__LINKEDIT")) {
704 size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
705 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
706 cmd->cmd = T::LC;
707 cmd->cmdsize = sizeof(typename T::command);
708 uint8_t *next = lc + cmd->cmdsize;
709 setString16("__LINKEDIT", cmd->segname);
710 cmd->vmaddr = _addressOfLinkEdit;
711 cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
712 cmd->fileoff = _startOfLinkEdit;
713 cmd->filesize = linkeditSize;
714 cmd->initprot = seg.access;
715 cmd->maxprot = seg.access;
716 cmd->nsects = 0;
717 cmd->flags = 0;
718 if (_swap)
719 swapStruct(*cmd);
720 lc = next;
721 continue;
722 }
723 // Write segment command with trailing sections.
Nick Kledzik29f749e2013-11-09 00:07:28 +0000724 typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
725 cmd->cmd = T::LC;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000726 cmd->cmdsize = sizeof(typename T::command)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000727 + segInfo.sections.size() * sizeof(typename T::section);
Nick Kledzike34182f2013-11-06 21:36:55 +0000728 uint8_t *next = lc + cmd->cmdsize;
729 setString16(seg.name, cmd->segname);
730 cmd->vmaddr = seg.address;
731 cmd->vmsize = seg.size;
732 cmd->fileoff = segInfo.fileOffset;
Tim Northover08d6a7b2014-06-30 09:49:30 +0000733 cmd->filesize = segInfo.fileSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000734 cmd->maxprot = seg.access;
735 cmd->initprot = seg.access;
736 cmd->nsects = segInfo.sections.size();
737 cmd->flags = 0;
738 if (_swap)
739 swapStruct(*cmd);
Nick Kledzik29f749e2013-11-09 00:07:28 +0000740 typename T::section *sect = reinterpret_cast<typename T::section*>
741 (lc+sizeof(typename T::command));
Nick Kledzike34182f2013-11-06 21:36:55 +0000742 for (const Section *section : segInfo.sections) {
743 setString16(section->sectionName, sect->sectname);
744 setString16(section->segmentName, sect->segname);
745 sect->addr = section->address;
746 sect->size = section->content.size();
Lang Hamesac2adce2015-12-11 23:25:09 +0000747 if (isZeroFillSection(section->type))
Nick Kledzikb072c362014-11-18 00:30:29 +0000748 sect->offset = 0;
749 else
750 sect->offset = section->address - seg.address + segInfo.fileOffset;
Rui Ueyamaf217ef02015-03-26 02:03:44 +0000751 sect->align = llvm::Log2_32(section->alignment);
Nick Kledzike34182f2013-11-06 21:36:55 +0000752 sect->reloff = 0;
753 sect->nreloc = 0;
754 sect->flags = section->type | section->attributes;
755 sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
756 sect->reserved2 = indirectSymbolElementSize(*section);
757 if (_swap)
758 swapStruct(*sect);
759 ++sect;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000760 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000761 lc = reinterpret_cast<uint8_t*>(next);
762 }
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000763 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +0000764}
765
Pete Cooperceee5de2016-02-04 02:16:08 +0000766static void writeVersionMinLoadCommand(const NormalizedFile &_file,
767 bool _swap,
768 uint8_t *&lc) {
769 if (!_file.hasMinVersionLoadCommand)
770 return;
771 version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
772 switch (_file.os) {
773 case MachOLinkingContext::OS::unknown:
774 vm->cmd = _file.minOSVersionKind;
775 vm->cmdsize = sizeof(version_min_command);
776 vm->version = _file.minOSverson;
777 vm->sdk = 0;
778 break;
779 case MachOLinkingContext::OS::macOSX:
780 vm->cmd = LC_VERSION_MIN_MACOSX;
781 vm->cmdsize = sizeof(version_min_command);
782 vm->version = _file.minOSverson;
783 vm->sdk = _file.sdkVersion;
784 break;
785 case MachOLinkingContext::OS::iOS:
786 case MachOLinkingContext::OS::iOS_simulator:
787 vm->cmd = LC_VERSION_MIN_IPHONEOS;
788 vm->cmdsize = sizeof(version_min_command);
789 vm->version = _file.minOSverson;
790 vm->sdk = _file.sdkVersion;
791 break;
792 }
793 if (_swap)
794 swapStruct(*vm);
795 lc += sizeof(version_min_command);
796}
797
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000798std::error_code MachOFileLayout::writeLoadCommands() {
799 std::error_code ec;
Nick Kledzike34182f2013-11-06 21:36:55 +0000800 uint8_t *lc = &_buffer[_startOfLoadCommands];
801 if (_file.fileType == llvm::MachO::MH_OBJECT) {
802 // Object files have one unnamed segment which holds all sections.
803 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000804 ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000805 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000806 ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000807 // Add LC_SYMTAB with symbol table info
808 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
809 st->cmd = LC_SYMTAB;
810 st->cmdsize = sizeof(symtab_command);
811 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000812 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000813 + _file.undefinedSymbols.size();
814 st->stroff = _startOfSymbolStrings;
815 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
816 if (_swap)
817 swapStruct(*st);
Nick Kledzik21921372014-07-24 23:06:56 +0000818 lc += sizeof(symtab_command);
Pete Cooperceee5de2016-02-04 02:16:08 +0000819
820 // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
821 // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
822 writeVersionMinLoadCommand(_file, _swap, lc);
823
Nick Kledzik21921372014-07-24 23:06:56 +0000824 // Add LC_DATA_IN_CODE if needed.
825 if (_dataInCodeSize != 0) {
826 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
827 dl->cmd = LC_DATA_IN_CODE;
828 dl->cmdsize = sizeof(linkedit_data_command);
829 dl->dataoff = _startOfDataInCode;
830 dl->datasize = _dataInCodeSize;
831 if (_swap)
832 swapStruct(*dl);
833 lc += sizeof(linkedit_data_command);
834 }
Nick Kledzike34182f2013-11-06 21:36:55 +0000835 } else {
836 // Final linked images have sections under segments.
837 if (_is64)
Nick Kledzik29f749e2013-11-09 00:07:28 +0000838 ec = writeSegmentLoadCommands<MachO64Trait>(lc);
Nick Kledzike34182f2013-11-06 21:36:55 +0000839 else
Nick Kledzik29f749e2013-11-09 00:07:28 +0000840 ec = writeSegmentLoadCommands<MachO32Trait>(lc);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000841
Tim Northover301c4e62014-07-01 08:15:41 +0000842 // Add LC_ID_DYLIB command for dynamic libraries.
843 if (_file.fileType == llvm::MachO::MH_DYLIB) {
844 dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
845 StringRef path = _file.installName;
846 uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
847 dc->cmd = LC_ID_DYLIB;
848 dc->cmdsize = size;
849 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000850 // needs to be some constant value different than the one in LC_LOAD_DYLIB
851 dc->dylib.timestamp = 1;
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000852 dc->dylib.current_version = _file.currentVersion;
853 dc->dylib.compatibility_version = _file.compatVersion;
Tim Northover301c4e62014-07-01 08:15:41 +0000854 if (_swap)
855 swapStruct(*dc);
856 memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
857 lc[sizeof(dylib_command) + path.size()] = '\0';
858 lc += size;
859 }
860
Nick Kledzike34182f2013-11-06 21:36:55 +0000861 // Add LC_DYLD_INFO_ONLY.
862 dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
863 di->cmd = LC_DYLD_INFO_ONLY;
864 di->cmdsize = sizeof(dyld_info_command);
865 di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
866 di->rebase_size = _rebaseInfo.size();
867 di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
868 di->bind_size = _bindingInfo.size();
869 di->weak_bind_off = 0;
870 di->weak_bind_size = 0;
871 di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
872 di->lazy_bind_size = _lazyBindingInfo.size();
Nick Kledzik141330a2014-09-03 19:52:50 +0000873 di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
874 di->export_size = _exportTrie.size();
Nick Kledzike34182f2013-11-06 21:36:55 +0000875 if (_swap)
876 swapStruct(*di);
877 lc += sizeof(dyld_info_command);
878
879 // Add LC_SYMTAB with symbol table info.
880 symtab_command* st = reinterpret_cast<symtab_command*>(lc);
881 st->cmd = LC_SYMTAB;
882 st->cmdsize = sizeof(symtab_command);
883 st->symoff = _startOfSymbols;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000884 st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +0000885 + _file.undefinedSymbols.size();
886 st->stroff = _startOfSymbolStrings;
887 st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
888 if (_swap)
889 swapStruct(*st);
890 lc += sizeof(symtab_command);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000891
Nick Kledzike34182f2013-11-06 21:36:55 +0000892 // Add LC_DYSYMTAB
893 if (_file.fileType != llvm::MachO::MH_PRELOAD) {
894 dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
895 dst->cmd = LC_DYSYMTAB;
896 dst->cmdsize = sizeof(dysymtab_command);
897 dst->ilocalsym = _symbolTableLocalsStartIndex;
898 dst->nlocalsym = _file.localSymbols.size();
899 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 {
941 source_version_command* sv = reinterpret_cast<source_version_command*>(lc);
942 sv->cmd = LC_SOURCE_VERSION;
943 sv->cmdsize = sizeof(source_version_command);
944 sv->version = _file.sourceVersion;
945 if (_swap)
946 swapStruct(*sv);
947 lc += sizeof(source_version_command);
948 }
949
Pete Cooper354809e2016-02-03 22:28:29 +0000950 // If main executable, add LC_MAIN.
951 if (_file.fileType == llvm::MachO::MH_EXECUTE) {
Nick Kledzike34182f2013-11-06 21:36:55 +0000952 // Build LC_MAIN load command.
953 entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
954 ep->cmd = LC_MAIN;
955 ep->cmdsize = sizeof(entry_point_command);
956 ep->entryoff = _file.entryAddress - _seg1addr;
Lang Hames65a64c92015-05-20 22:10:50 +0000957 ep->stacksize = _file.stackSize;
Nick Kledzike34182f2013-11-06 21:36:55 +0000958 if (_swap)
959 swapStruct(*ep);
960 lc += sizeof(entry_point_command);
961 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000962
Nick Kledzike34182f2013-11-06 21:36:55 +0000963 // Add LC_LOAD_DYLIB commands
964 for (const DependentDylib &dep : _file.dependentDylibs) {
965 dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
966 uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
Nick Kledzik51720672014-10-16 19:31:28 +0000967 dc->cmd = dep.kind;
Nick Kledzike34182f2013-11-06 21:36:55 +0000968 dc->cmdsize = size;
969 dc->dylib.name = sizeof(dylib_command); // offset
Jean-Daniel Dupasedefccc2014-12-20 09:22:56 +0000970 // needs to be some constant value different than the one in LC_ID_DYLIB
Nick Kledzik5b9e48b2014-11-19 02:21:53 +0000971 dc->dylib.timestamp = 2;
972 dc->dylib.current_version = dep.currentVersion;
973 dc->dylib.compatibility_version = dep.compatVersion;
Nick Kledzike34182f2013-11-06 21:36:55 +0000974 if (_swap)
975 swapStruct(*dc);
976 memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
977 lc[sizeof(dylib_command)+dep.path.size()] = '\0';
978 lc += size;
979 }
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000980
981 // Add LC_RPATH
982 for (const StringRef &path : _file.rpaths) {
983 rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
Lang Hames2ed3bf92015-10-29 16:50:26 +0000984 uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
Jean-Daniel Dupas23dd15e2014-12-18 21:33:38 +0000985 rpc->cmd = LC_RPATH;
986 rpc->cmdsize = size;
987 rpc->path = sizeof(rpath_command); // offset
988 if (_swap)
989 swapStruct(*rpc);
990 memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
991 lc[sizeof(rpath_command)+path.size()] = '\0';
992 lc += size;
993 }
994
Nick Kledzik54ce29582014-10-28 22:21:10 +0000995 // Add LC_DATA_IN_CODE if needed.
996 if (_dataInCodeSize != 0) {
997 linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
998 dl->cmd = LC_DATA_IN_CODE;
999 dl->cmdsize = sizeof(linkedit_data_command);
1000 dl->dataoff = _startOfDataInCode;
1001 dl->datasize = _dataInCodeSize;
1002 if (_swap)
1003 swapStruct(*dl);
1004 lc += sizeof(linkedit_data_command);
1005 }
Nick Kledzike34182f2013-11-06 21:36:55 +00001006 }
1007 return ec;
1008}
1009
Nick Kledzike34182f2013-11-06 21:36:55 +00001010void MachOFileLayout::writeSectionContent() {
1011 for (const Section &s : _file.sections) {
1012 // Copy all section content to output buffer.
Lang Hamesac2adce2015-12-11 23:25:09 +00001013 if (isZeroFillSection(s.type))
Nick Kledzik61fdef62014-05-15 20:59:23 +00001014 continue;
Nick Kledzik1bebb282014-09-09 23:52:59 +00001015 if (s.content.empty())
1016 continue;
Nick Kledzike34182f2013-11-06 21:36:55 +00001017 uint32_t offset = _sectInfo[&s].fileOffset;
1018 uint8_t *p = &_buffer[offset];
1019 memcpy(p, &s.content[0], s.content.size());
1020 p += s.content.size();
1021 }
1022}
1023
1024void MachOFileLayout::writeRelocations() {
1025 uint32_t relOffset = _startOfRelocations;
1026 for (Section sect : _file.sections) {
1027 for (Relocation r : sect.relocations) {
1028 any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
1029 &_buffer[relOffset]);
1030 *rb = packRelocation(r, _swap, _bigEndianArch);
1031 relOffset += sizeof(any_relocation_info);
1032 }
1033 }
1034}
1035
Nick Kledzike34182f2013-11-06 21:36:55 +00001036void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
1037 uint32_t &symOffset, uint32_t &strOffset) {
1038 for (const Symbol &sym : symbols) {
1039 if (_is64) {
1040 nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
1041 nb->n_strx = strOffset - _startOfSymbolStrings;
1042 nb->n_type = sym.type | sym.scope;
1043 nb->n_sect = sym.sect;
1044 nb->n_desc = sym.desc;
1045 nb->n_value = sym.value;
1046 if (_swap)
1047 swapStruct(*nb);
1048 symOffset += sizeof(nlist_64);
1049 } else {
1050 nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
1051 nb->n_strx = strOffset - _startOfSymbolStrings;
1052 nb->n_type = sym.type | sym.scope;
1053 nb->n_sect = sym.sect;
1054 nb->n_desc = sym.desc;
1055 nb->n_value = sym.value;
1056 if (_swap)
1057 swapStruct(*nb);
1058 symOffset += sizeof(nlist);
1059 }
1060 memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
1061 strOffset += sym.name.size();
1062 _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
1063 }
1064}
1065
Nick Kledzik21921372014-07-24 23:06:56 +00001066void MachOFileLayout::writeDataInCodeInfo() {
1067 uint32_t offset = _startOfDataInCode;
1068 for (const DataInCode &entry : _file.dataInCode) {
1069 data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
1070 &_buffer[offset]);
1071 dst->offset = entry.offset;
1072 dst->length = entry.length;
1073 dst->kind = entry.kind;
1074 if (_swap)
1075 swapStruct(*dst);
1076 offset += sizeof(data_in_code_entry);
1077 }
1078}
1079
Nick Kledzike34182f2013-11-06 21:36:55 +00001080void MachOFileLayout::writeSymbolTable() {
1081 // Write symbol table and symbol strings in parallel.
1082 uint32_t symOffset = _startOfSymbols;
1083 uint32_t strOffset = _startOfSymbolStrings;
1084 _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
1085 appendSymbols(_file.localSymbols, symOffset, strOffset);
1086 appendSymbols(_file.globalSymbols, symOffset, strOffset);
1087 appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
1088 // Write indirect symbol table array.
1089 uint32_t *indirects = reinterpret_cast<uint32_t*>
1090 (&_buffer[_startOfIndirectSymbols]);
1091 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1092 // Object files have sections in same order as input normalized file.
1093 for (const Section &section : _file.sections) {
1094 for (uint32_t index : section.indirectSymbols) {
1095 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001096 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001097 else
1098 *indirects++ = index;
1099 }
1100 }
1101 } else {
1102 // Final linked images must sort sections from normalized file.
1103 for (const Segment &seg : _file.segments) {
1104 SegExtraInfo &segInfo = _segInfo[&seg];
1105 for (const Section *section : segInfo.sections) {
1106 for (uint32_t index : section->indirectSymbols) {
1107 if (_swap)
Artyom Skrobov17587fb2014-06-14 12:40:04 +00001108 *indirects++ = llvm::sys::getSwappedBytes(index);
Nick Kledzike34182f2013-11-06 21:36:55 +00001109 else
1110 *indirects++ = index;
1111 }
1112 }
1113 }
1114 }
1115}
1116
1117void MachOFileLayout::writeRebaseInfo() {
1118 memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
1119}
1120
1121void MachOFileLayout::writeBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001122 memcpy(&_buffer[_startOfBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001123 _bindingInfo.bytes(), _bindingInfo.size());
1124}
1125
1126void MachOFileLayout::writeLazyBindingInfo() {
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001127 memcpy(&_buffer[_startOfLazyBindingInfo],
Nick Kledzike34182f2013-11-06 21:36:55 +00001128 _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
1129}
1130
Nick Kledzik141330a2014-09-03 19:52:50 +00001131void MachOFileLayout::writeExportInfo() {
1132 memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
1133}
1134
Nick Kledzike34182f2013-11-06 21:36:55 +00001135void MachOFileLayout::buildLinkEditInfo() {
1136 buildRebaseInfo();
1137 buildBindInfo();
1138 buildLazyBindInfo();
Nick Kledzik141330a2014-09-03 19:52:50 +00001139 buildExportTrie();
Nick Kledzike34182f2013-11-06 21:36:55 +00001140 computeSymbolTableSizes();
Nick Kledzik21921372014-07-24 23:06:56 +00001141 computeDataInCodeSize();
Nick Kledzike34182f2013-11-06 21:36:55 +00001142}
1143
1144void MachOFileLayout::buildSectionRelocations() {
1145
1146}
1147
1148void MachOFileLayout::buildRebaseInfo() {
1149 // TODO: compress rebasing info.
1150 for (const RebaseLocation& entry : _file.rebasingInfo) {
1151 _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001152 _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001153 | entry.segIndex);
1154 _rebaseInfo.append_uleb128(entry.segOffset);
1155 _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
1156 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001157 _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001158 _rebaseInfo.align(_is64 ? 8 : 4);
1159}
1160
1161void MachOFileLayout::buildBindInfo() {
1162 // TODO: compress bind info.
Nick Kledzikf373c772014-11-11 01:31:18 +00001163 uint64_t lastAddend = 0;
Nick Kledzike34182f2013-11-06 21:36:55 +00001164 for (const BindLocation& entry : _file.bindingInfo) {
1165 _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001166 _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001167 | entry.segIndex);
1168 _bindingInfo.append_uleb128(entry.segOffset);
Lang Hames5c692002015-09-28 20:25:14 +00001169 if (entry.ordinal > 0)
1170 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1171 (entry.ordinal & 0xF));
1172 else
1173 _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1174 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001175 _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1176 _bindingInfo.append_string(entry.symbolName);
Nick Kledzikf373c772014-11-11 01:31:18 +00001177 if (entry.addend != lastAddend) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001178 _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1179 _bindingInfo.append_sleb128(entry.addend);
Nick Kledzikf373c772014-11-11 01:31:18 +00001180 lastAddend = entry.addend;
Nick Kledzike34182f2013-11-06 21:36:55 +00001181 }
1182 _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
1183 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001184 _bindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001185 _bindingInfo.align(_is64 ? 8 : 4);
1186}
1187
1188void MachOFileLayout::buildLazyBindInfo() {
1189 for (const BindLocation& entry : _file.lazyBindingInfo) {
1190 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001191 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
Nick Kledzike34182f2013-11-06 21:36:55 +00001192 | entry.segIndex);
Nick Kledzikf373c772014-11-11 01:31:18 +00001193 _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
Lang Hames5c692002015-09-28 20:25:14 +00001194 if (entry.ordinal > 0)
1195 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
1196 (entry.ordinal & 0xF));
1197 else
1198 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
1199 (entry.ordinal & 0xF));
Nick Kledzike34182f2013-11-06 21:36:55 +00001200 _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
1201 _lazyBindingInfo.append_string(entry.symbolName);
1202 _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
Nick Kledzikf373c772014-11-11 01:31:18 +00001203 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001204 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001205 _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
Nick Kledzike34182f2013-11-06 21:36:55 +00001206 _lazyBindingInfo.align(_is64 ? 8 : 4);
1207}
1208
Pete Coopere420dd42016-01-25 21:50:54 +00001209void TrieNode::addSymbol(const Export& entry,
1210 BumpPtrAllocator &allocator,
1211 std::vector<TrieNode*> &allNodes) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001212 StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
1213 for (TrieEdge &edge : _children) {
1214 StringRef edgeStr = edge._subString;
1215 if (partialStr.startswith(edgeStr)) {
1216 // Already have matching edge, go down that path.
1217 edge._child->addSymbol(entry, allocator, allNodes);
1218 return;
1219 }
1220 // See if string has commmon prefix with existing edge.
1221 for (int n=edgeStr.size()-1; n > 0; --n) {
1222 if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
1223 // Splice in new node: was A -> C, now A -> B -> C
1224 StringRef bNodeStr = edge._child->_cummulativeString;
1225 bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
Eugene Zelenko41547942015-11-10 22:37:38 +00001226 auto *bNode = new (allocator) TrieNode(bNodeStr);
Nick Kledzik141330a2014-09-03 19:52:50 +00001227 allNodes.push_back(bNode);
1228 TrieNode* cNode = edge._child;
1229 StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
1230 StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
1231 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1232 << "splice in TrieNode('" << bNodeStr
1233 << "') between edge '"
1234 << abEdgeStr << "' and edge='"
1235 << bcEdgeStr<< "'\n");
1236 TrieEdge& abEdge = edge;
1237 abEdge._subString = abEdgeStr;
1238 abEdge._child = bNode;
Eugene Zelenko41547942015-11-10 22:37:38 +00001239 auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001240 bNode->_children.insert(bNode->_children.end(), bcEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001241 bNode->addSymbol(entry, allocator, allNodes);
1242 return;
1243 }
1244 }
1245 }
1246 if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1247 assert(entry.otherOffset != 0);
1248 }
1249 if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
1250 assert(entry.otherOffset != 0);
1251 }
1252 // No commonality with any existing child, make a new edge.
Eugene Zelenko41547942015-11-10 22:37:38 +00001253 auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
1254 auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
Pete Coopere420dd42016-01-25 21:50:54 +00001255 _children.insert(_children.end(), newEdge);
Nick Kledzik141330a2014-09-03 19:52:50 +00001256 DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
1257 << "new TrieNode('" << entry.name << "') with edge '"
1258 << partialStr << "' from node='"
1259 << _cummulativeString << "'\n");
1260 newNode->_address = entry.offset;
1261 newNode->_flags = entry.flags | entry.kind;
1262 newNode->_other = entry.otherOffset;
1263 if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
1264 newNode->_importedName = entry.otherName.copy(allocator);
1265 newNode->_hasExportInfo = true;
1266 allNodes.push_back(newNode);
1267}
1268
Pete Coopere420dd42016-01-25 21:50:54 +00001269bool TrieNode::updateOffset(uint32_t& offset) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001270 uint32_t nodeSize = 1; // Length when no export info
1271 if (_hasExportInfo) {
1272 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1273 nodeSize = llvm::getULEB128Size(_flags);
1274 nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
1275 nodeSize += _importedName.size();
1276 ++nodeSize; // Trailing zero in imported name.
1277 } else {
1278 nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
1279 if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1280 nodeSize += llvm::getULEB128Size(_other);
1281 }
1282 // Overall node size so far is uleb128 of export info + actual export info.
1283 nodeSize += llvm::getULEB128Size(nodeSize);
1284 }
1285 // Compute size of all child edges.
1286 ++nodeSize; // Byte for number of chidren.
1287 for (TrieEdge &edge : _children) {
1288 nodeSize += edge._subString.size() + 1 // String length.
1289 + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
1290 }
1291 // On input, 'offset' is new prefered location for this node.
1292 bool result = (_trieOffset != offset);
1293 // Store new location in node object for use by parents.
1294 _trieOffset = offset;
1295 // Update offset for next iteration.
1296 offset += nodeSize;
1297 // Return true if _trieOffset was changed.
1298 return result;
1299}
1300
Pete Coopere420dd42016-01-25 21:50:54 +00001301void TrieNode::appendToByteBuffer(ByteBuffer &out) {
Nick Kledzik141330a2014-09-03 19:52:50 +00001302 if (_hasExportInfo) {
1303 if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
1304 if (!_importedName.empty()) {
1305 // nodes with re-export info: size, flags, ordinal, import-name
1306 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1307 + llvm::getULEB128Size(_other)
1308 + _importedName.size() + 1;
1309 assert(nodeSize < 256);
1310 out.append_byte(nodeSize);
1311 out.append_uleb128(_flags);
1312 out.append_uleb128(_other);
1313 out.append_string(_importedName);
1314 } else {
1315 // nodes without re-export info: size, flags, ordinal, empty-string
1316 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1317 + llvm::getULEB128Size(_other) + 1;
1318 assert(nodeSize < 256);
1319 out.append_byte(nodeSize);
1320 out.append_uleb128(_flags);
1321 out.append_uleb128(_other);
1322 out.append_byte(0);
1323 }
1324 } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
1325 // Nodes with export info: size, flags, address, other
1326 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1327 + llvm::getULEB128Size(_address)
1328 + llvm::getULEB128Size(_other);
1329 assert(nodeSize < 256);
1330 out.append_byte(nodeSize);
1331 out.append_uleb128(_flags);
1332 out.append_uleb128(_address);
1333 out.append_uleb128(_other);
1334 } else {
1335 // Nodes with export info: size, flags, address
1336 uint32_t nodeSize = llvm::getULEB128Size(_flags)
1337 + llvm::getULEB128Size(_address);
1338 assert(nodeSize < 256);
1339 out.append_byte(nodeSize);
1340 out.append_uleb128(_flags);
1341 out.append_uleb128(_address);
1342 }
1343 } else {
1344 // Node with no export info.
1345 uint32_t nodeSize = 0;
1346 out.append_byte(nodeSize);
1347 }
1348 // Add number of children.
1349 assert(_children.size() < 256);
1350 out.append_byte(_children.size());
1351 // Append each child edge substring and node offset.
1352 for (TrieEdge &edge : _children) {
1353 out.append_string(edge._subString);
1354 out.append_uleb128(edge._child->_trieOffset);
1355 }
1356}
1357
1358void MachOFileLayout::buildExportTrie() {
1359 if (_file.exportInfo.empty())
1360 return;
1361
1362 // For all temporary strings and objects used building trie.
1363 BumpPtrAllocator allocator;
1364
1365 // Build trie of all exported symbols.
Eugene Zelenko41547942015-11-10 22:37:38 +00001366 auto *rootNode = new (allocator) TrieNode(StringRef());
Nick Kledzik141330a2014-09-03 19:52:50 +00001367 std::vector<TrieNode*> allNodes;
1368 allNodes.reserve(_file.exportInfo.size()*2);
1369 allNodes.push_back(rootNode);
1370 for (const Export& entry : _file.exportInfo) {
1371 rootNode->addSymbol(entry, allocator, allNodes);
1372 }
1373
1374 // Assign each node in the vector an offset in the trie stream, iterating
1375 // until all uleb128 sizes have stabilized.
1376 bool more;
1377 do {
1378 uint32_t offset = 0;
1379 more = false;
1380 for (TrieNode* node : allNodes) {
1381 if (node->updateOffset(offset))
1382 more = true;
1383 }
1384 } while (more);
1385
1386 // Serialize trie to ByteBuffer.
1387 for (TrieNode* node : allNodes) {
1388 node->appendToByteBuffer(_exportTrie);
1389 }
1390 _exportTrie.align(_is64 ? 8 : 4);
1391}
1392
Nick Kledzike34182f2013-11-06 21:36:55 +00001393void MachOFileLayout::computeSymbolTableSizes() {
1394 // MachO symbol tables have three ranges: locals, globals, and undefines
1395 const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001396 _symbolTableSize = nlistSize * (_file.localSymbols.size()
Nick Kledzike34182f2013-11-06 21:36:55 +00001397 + _file.globalSymbols.size()
1398 + _file.undefinedSymbols.size());
Lang Hames201c08f2015-12-10 00:12:24 +00001399 _symbolStringPoolSize = 1; // Always reserve 1-byte for the empty string.
Nick Kledzike34182f2013-11-06 21:36:55 +00001400 for (const Symbol &sym : _file.localSymbols) {
1401 _symbolStringPoolSize += (sym.name.size()+1);
1402 }
1403 for (const Symbol &sym : _file.globalSymbols) {
1404 _symbolStringPoolSize += (sym.name.size()+1);
1405 }
1406 for (const Symbol &sym : _file.undefinedSymbols) {
1407 _symbolStringPoolSize += (sym.name.size()+1);
1408 }
1409 _symbolTableLocalsStartIndex = 0;
1410 _symbolTableGlobalsStartIndex = _file.localSymbols.size();
Shankar Easwaran3d8de472014-01-27 03:09:26 +00001411 _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
Nick Kledzike34182f2013-11-06 21:36:55 +00001412 + _file.globalSymbols.size();
1413
1414 _indirectSymbolTableCount = 0;
1415 for (const Section &sect : _file.sections) {
1416 _indirectSymbolTableCount += sect.indirectSymbols.size();
1417 }
1418}
1419
Nick Kledzik21921372014-07-24 23:06:56 +00001420void MachOFileLayout::computeDataInCodeSize() {
1421 _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
1422}
Nick Kledzike34182f2013-11-06 21:36:55 +00001423
1424void MachOFileLayout::writeLinkEditContent() {
1425 if (_file.fileType == llvm::MachO::MH_OBJECT) {
1426 writeRelocations();
Nick Kledzik21921372014-07-24 23:06:56 +00001427 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001428 writeSymbolTable();
1429 } else {
1430 writeRebaseInfo();
1431 writeBindingInfo();
1432 writeLazyBindingInfo();
1433 // TODO: add weak binding info
Nick Kledzik141330a2014-09-03 19:52:50 +00001434 writeExportInfo();
Nick Kledzik54ce29582014-10-28 22:21:10 +00001435 writeDataInCodeInfo();
Nick Kledzike34182f2013-11-06 21:36:55 +00001436 writeSymbolTable();
1437 }
1438}
1439
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001440std::error_code MachOFileLayout::writeBinary(StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001441 // Check for pending error from constructor.
1442 if (_ec)
1443 return _ec;
1444 // Create FileOutputBuffer with calculated size.
Nick Kledzike34182f2013-11-06 21:36:55 +00001445 unsigned flags = 0;
1446 if (_file.fileType != llvm::MachO::MH_OBJECT)
1447 flags = llvm::FileOutputBuffer::F_executable;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001448 ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
1449 llvm::FileOutputBuffer::create(path, size(), flags);
1450 if (std::error_code ec = fobOrErr.getError())
Nick Kledzike34182f2013-11-06 21:36:55 +00001451 return ec;
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001452 std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
Nick Kledzike34182f2013-11-06 21:36:55 +00001453 // Write content.
1454 _buffer = fob->getBufferStart();
1455 writeMachHeader();
Rafael Espindolabdc8f2f2015-08-13 00:31:46 +00001456 std::error_code ec = writeLoadCommands();
Nick Kledzike34182f2013-11-06 21:36:55 +00001457 if (ec)
1458 return ec;
1459 writeSectionContent();
1460 writeLinkEditContent();
1461 fob->commit();
1462
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001463 return std::error_code();
Nick Kledzike34182f2013-11-06 21:36:55 +00001464}
1465
Nick Kledzike34182f2013-11-06 21:36:55 +00001466/// Takes in-memory normalized view and writes a mach-o object file.
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +00001467std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
Nick Kledzike34182f2013-11-06 21:36:55 +00001468 MachOFileLayout layout(file);
1469 return layout.writeBinary(path);
1470}
1471
Nick Kledzike34182f2013-11-06 21:36:55 +00001472} // namespace normalized
1473} // namespace mach_o
1474} // namespace lld